Add Epiphany investigation checkpoints

This commit is contained in:
Meta Vens 2026-04-26 05:12:51 +01:00
commit 71ea1ed2ea
17 changed files with 578 additions and 40 deletions

View file

@ -1646,6 +1646,20 @@ mod tests {
shard_count: 1,
dirty_path_count: 0,
}),
investigation_checkpoint: Some(
v2::ThreadEpiphanySceneInvestigationCheckpoint {
checkpoint_id: "ix-1".to_string(),
kind: "slice_planning".to_string(),
disposition: codex_protocol::protocol::EpiphanyInvestigationDisposition::ResumeReady,
focus: "Keep the durable resume packet visible.".to_string(),
summary: Some("Checkpointed the bounded planning slice.".to_string()),
next_action: Some("Patch one typed field next.".to_string()),
captured_at_turn_id: Some("turn-7".to_string()),
open_question_count: 1,
code_ref_count: 2,
evidence_count: 1,
},
),
observations: v2::ThreadEpiphanySceneRecords {
total_count: 1,
latest: vec![v2::ThreadEpiphanySceneRecord {
@ -1724,6 +1738,18 @@ mod tests {
"shardCount": 1,
"dirtyPathCount": 0
},
"investigationCheckpoint": {
"checkpointId": "ix-1",
"kind": "slice_planning",
"disposition": "resume_ready",
"focus": "Keep the durable resume packet visible.",
"summary": "Checkpointed the bounded planning slice.",
"nextAction": "Patch one typed field next.",
"capturedAtTurnId": "turn-7",
"openQuestionCount": 1,
"codeRefCount": 2,
"evidenceCount": 1
},
"observations": {
"totalCount": 1,
"latest": [
@ -1851,6 +1877,17 @@ mod tests {
..Default::default()
}),
checkpoint: None,
investigation_checkpoint: Some(
codex_protocol::protocol::EpiphanyInvestigationCheckpoint {
checkpoint_id: "ix-1".to_string(),
kind: "source_gathering".to_string(),
focus: "Audit the compaction seam.".to_string(),
next_action: Some(
"Re-gather source if this packet is stale.".to_string(),
),
..Default::default()
},
),
observations: vec![codex_protocol::protocol::EpiphanyObservation {
id: "obs-1".to_string(),
summary: "Context shard is read-only.".to_string(),
@ -1906,6 +1943,13 @@ mod tests {
"frontier": {
"active_node_ids": ["state-spine"]
},
"investigationCheckpoint": {
"checkpoint_id": "ix-1",
"kind": "source_gathering",
"disposition": "resume_ready",
"focus": "Audit the compaction seam.",
"next_action": "Re-gather source if this packet is stale."
},
"observations": [
{
"id": "obs-1",

View file

@ -67,6 +67,8 @@ use codex_protocol::protocol::EpiphanyGraphLink as CoreEpiphanyGraphLink;
use codex_protocol::protocol::EpiphanyGraphNode as CoreEpiphanyGraphNode;
use codex_protocol::protocol::EpiphanyGraphs as CoreEpiphanyGraphs;
use codex_protocol::protocol::EpiphanyInvariant as CoreEpiphanyInvariant;
use codex_protocol::protocol::EpiphanyInvestigationCheckpoint as CoreEpiphanyInvestigationCheckpoint;
use codex_protocol::protocol::EpiphanyInvestigationDisposition as CoreEpiphanyInvestigationDisposition;
use codex_protocol::protocol::EpiphanyModeState as CoreEpiphanyModeState;
use codex_protocol::protocol::EpiphanyObservation as CoreEpiphanyObservation;
use codex_protocol::protocol::EpiphanyRetrievalStatus as CoreEpiphanyRetrievalStatus;
@ -3956,6 +3958,9 @@ pub struct ThreadEpiphanyScene {
#[serde(default, skip_serializing_if = "Option::is_none")]
#[ts(optional = nullable)]
pub retrieval: Option<ThreadEpiphanySceneRetrieval>,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[ts(optional = nullable)]
pub investigation_checkpoint: Option<ThreadEpiphanySceneInvestigationCheckpoint>,
pub observations: ThreadEpiphanySceneRecords,
pub evidence: ThreadEpiphanySceneRecords,
#[serde(default, skip_serializing_if = "Option::is_none")]
@ -4062,6 +4067,28 @@ pub struct ThreadEpiphanySceneRetrieval {
pub dirty_path_count: u32,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub struct ThreadEpiphanySceneInvestigationCheckpoint {
pub checkpoint_id: String,
pub kind: String,
pub disposition: CoreEpiphanyInvestigationDisposition,
pub focus: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[ts(optional = nullable)]
pub summary: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[ts(optional = nullable)]
pub next_action: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[ts(optional = nullable)]
pub captured_at_turn_id: Option<String>,
pub open_question_count: u32,
pub code_ref_count: u32,
pub evidence_count: u32,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS, Default)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
@ -4242,6 +4269,9 @@ pub struct ThreadEpiphanyContext {
#[serde(default, skip_serializing_if = "Option::is_none")]
#[ts(optional = nullable)]
pub checkpoint: Option<CoreEpiphanyGraphCheckpoint>,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[ts(optional = nullable)]
pub investigation_checkpoint: Option<CoreEpiphanyInvestigationCheckpoint>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub observations: Vec<CoreEpiphanyObservation>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
@ -4480,6 +4510,9 @@ pub struct ThreadEpiphanyUpdatePatch {
#[serde(default, skip_serializing_if = "Option::is_none")]
#[ts(optional = nullable)]
pub scratch: Option<CoreEpiphanyScratchPad>,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[ts(optional = nullable)]
pub investigation_checkpoint: Option<CoreEpiphanyInvestigationCheckpoint>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub observations: Vec<CoreEpiphanyObservation>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
@ -4532,6 +4565,7 @@ pub enum ThreadEpiphanyStateUpdatedField {
GraphFrontier,
GraphCheckpoint,
Scratch,
InvestigationCheckpoint,
Observations,
Evidence,
Churn,