diff --git a/notes/epiphany-app-server-client-matrix.md b/notes/epiphany-app-server-client-matrix.md index 5226081f..7e7b0a3c 100644 --- a/notes/epiphany-app-server-client-matrix.md +++ b/notes/epiphany-app-server-client-matrix.md @@ -22,20 +22,20 @@ These are retained only while the named compatibility binaries remain. They do not justify route-local policy, implicit triggers, Codex state ownership, or new clients. -## Unconsumed advertised routes +## Removed unconsumed routes -| Route | Finding | Deletion owner | +| Route | Finding | Result | |---|---|---| -| `roleLaunch` | no executable caller | remove request registration, dispatch, handler, tests/docs | -| `roleAccept` | no executable caller | remove request registration, dispatch, handler, tests/docs | -| `reorientLaunch` | no executable caller | remove request registration, dispatch, handler, tests/docs | -| `reorientAccept` | no executable caller | remove request registration, dispatch, handler, tests/docs | -| `index` | no executable caller | remove request registration, dispatch, handler, tests/docs | -| `distill` | no executable caller | remove request registration, dispatch, handler, tests/docs | -| `propose` | no executable caller | remove request registration, dispatch, handler, tests/docs | -| `promote` | no executable caller | remove request registration, dispatch, handler, tests/docs | -| `jobLaunch` | no executable caller | remove request registration, dispatch, handler, tests/docs | -| `retrieve` | no executable caller | remove request registration, dispatch, handler, tests/docs | +| `roleLaunch` | no executable caller | request surface deleted | +| `roleAccept` | no executable caller | request surface deleted | +| `reorientLaunch` | no executable caller | request surface deleted | +| `reorientAccept` | no executable caller | request surface deleted | +| `index` | no executable caller | request surface deleted | +| `distill` | no executable caller | request surface deleted | +| `propose` | no executable caller | request surface deleted | +| `promote` | no executable caller | request surface deleted | +| `jobLaunch` | no executable caller | request surface deleted | +| `retrieve` | no executable caller | request surface deleted | Protocol DTOs may remain temporarily only when retained response projections or bridge conversion tests still compile against them. A DTO is not authority and diff --git a/notes/fresh-workspace-handoff.md b/notes/fresh-workspace-handoff.md index 84bc8f6e..97b7f62e 100644 --- a/notes/fresh-workspace-handoff.md +++ b/notes/fresh-workspace-handoff.md @@ -1952,8 +1952,12 @@ compatibility API with no named living client. The client matrix now lives at `notes/epiphany-app-server-client-matrix.md`: eight routes have named phase-6 smoke or `epiphany-mvp-status --codex` consumers; ten advertised routes have no executable caller beyond definitions/tests/docs and are marked for deletion. -Cut those ten request registrations, dispatch arms, handlers, tests, and README -claims next; do not let generated bindings count as clients. +Those ten request registrations, dispatch arms, handlers, protocol tests, and +README claims are now deleted. A source guard fixes registration to the eight +named-client routes and explicitly rejects the removed names. Protocol compile, +app-server compile, and four compatibility-architecture tests pass. Next audit +zero-caller protocol DTOs and bridge conversion helpers left by this cut, then +migrate or retire the phase-6 smoke and `epiphany-mvp-status --codex` clients. ## Immediate Re-entry Instruction diff --git a/notes/native-coordinator-liberation-map.md b/notes/native-coordinator-liberation-map.md index 6f8cb39b..d7bd11f4 100644 --- a/notes/native-coordinator-liberation-map.md +++ b/notes/native-coordinator-liberation-map.md @@ -365,9 +365,8 @@ routes, notifications, and read projection only. A source guard rejects renewed automation authority in the event loop, processor module list, or thread state. The remaining app-server surface is now mechanically classified and guarded. -Mutation routes must call one of nine explicit bridge delegates for role launch, -role acceptance, reorientation launch/acceptance, indexing, promotion, update, -job launch, or interruption; forbidden local receipt/binding/runtime writes, +Mutation routes may call only the explicit update or interruption bridge +delegate; forbidden local receipt/binding/runtime writes, prompt steering, compaction submission, and automation selection fail the source test. Read routes reject every mutation, launch, interruption, indexing, prompt-steering, compaction, or scheduler symbol. Migration, read projection, @@ -382,5 +381,6 @@ in-repo consumers, all explicit phase-6 smokes or unconsumed: role/reorientation launch and accept, index, distill, propose, promote, job launch, and retrieve. Definitions, generated bindings, README claims, and serialization tests do not count as clients. Those ten request -registrations, dispatch arms, handlers, tests, and docs are the next deletion -line. +registrations, dispatch arms, handlers, tests, and README claims are deleted. +The registration guard now fixes the compatibility surface at the eight named +client routes and rejects restoration of the unconsumed methods. diff --git a/state/ledgers.msgpack b/state/ledgers.msgpack index 4569f6d8..cec94a95 100644 Binary files a/state/ledgers.msgpack and b/state/ledgers.msgpack differ diff --git a/state/map.yaml b/state/map.yaml index aff97ac7..969f8647 100644 --- a/state/map.yaml +++ b/state/map.yaml @@ -659,4 +659,4 @@ current_status: - Service lifecycle receipt history is now event-only: `load_epiphany_cultmesh_daemon_service_lifecycle_receipts` filters out the `epiphany-local/daemon-service-lifecycle-receipt/latest` mirror, while `load_latest_epiphany_cultmesh_daemon_service_lifecycle_receipt` remains the latest-state reader. Focused unit test `service_lifecycle_receipt_history_excludes_latest_mirror` proves two per-receipt writes return exactly two history records and latest points at the second. Fresh smoke `verse-query-lifecycle-history-filter-smoke` and live overview/triage `local-20260618-145632-497-efac6f0d` / `local-20260618-145632-321-867947af` prove compact swarm sights still expose service lifecycle attention plus the present elevated runbook artifact without daemon pokes or service mutation. Do not use a broad unscoped cargo test filter for this check on Windows; it fans out across bin harnesses and hit a broken pipe during this pass. - `epiphany-verse-query seed-compact` is the compact seed receipt for wrappers and read-only rites. The older `seed` command still prints the full local Verse context for explicit debugging, but compact wrapper modes now avoid full `seed`/final `query` readback after the combined overview proof exposed Windows debug stack overflow from full-context serialization pressure. last_completed_repo_swarm_cut: Huginn live-fire has crossed the first real repo Body from Persona pressure to branch-local Hands commit and Soul/Mind closure, and now has repeatable closure and redacted-public-proof mouths. On `E:\Projects\Huginn` branch `epiphany/huginn/first-awakening`, `tools/epiphany_local_run.ps1 -Mode repo-persona-intake` accepted item `huginn-inspection-readback-livefire`, Weksa/Persona intake remained sealed, and `epiphany-work derive-plan` lowered it to model-authored safe family `repo.status_section` for `README.md` only. `tools/epiphany_local_run.ps1 -Mode repo-swarm-run` advanced four bounded pulses: run-from-plan, adopt-from-plan, execute-from-plan, and close-from-execute. Huginn commit `e9b07c38fceabbdc89ea35c2156326c80c0393a2` updated only `README.md`; closure receipt `.epiphany\work\work-close-huginn-inspection-readback-livefire.json` records status `closed`, Soul verdict `passed`, Mind state commit `repo-work-close-huginn-inspection-readback-livefire-mind-commit`, safe family `repo.status_section`, path scope `README.md`, Bifrost publication gate, and `privateStateExposed=false`. Verification also ran Huginn's TypeScript compiler through concrete Node path: `C:\Program Files\nodejs\node.exe E:\Projects\Huginn\node_modules\typescript\bin\tsc -p tsconfig.json` passed. Native verifier `epiphany-repo-livefire-closure-smoke --workspace E:\Projects\Huginn --item huginn-inspection-readback-livefire --expected-path README.md --expected-family repo.status_section --expected-gate awaiting-publication --expected-blocker bifrost-publication-missing` checks closure receipt, Mind map entry, overview gate/blocker, authority seals, and `git show` changed paths, returning `status=ok`, `soulVerdict=passed`, `publicationGate=Bifrost`, and `privateStateExposed=false`. Wrapper `tools/epiphany_local_run.ps1 -Mode repo-livefire-closure -Workspace E:\Projects\Huginn -RepoWorkItem huginn-inspection-readback-livefire -SkipBuild` exposes the same read-only proof through the local operator mouth; artifact `local-20260621-190156-803-2f85ba15` printed commit, path, gate, blocker, Soul verdict, Mind commit receipt, and `privateStateExposed=False` without push, merge, publication, or target mutation. New wrapper `tools/epiphany_local_run.ps1 -Mode repo-work-public-proof -Workspace E:\Projects\Huginn -RepoWorkItem huginn-inspection-readback-livefire -SkipBuild` exports the redacted proof bundle and repo-local Verse index without publishing; artifact `local-20260621-190645-345-4555b1dc` wrote `.epiphany\public\proof-bundles\repo-work-public-proof-huginn-inspection-readback-livefire.json`, proof id `repo-work-public-proof-huginn-inspection-readback-livefire`, SHA-256 `857545b199f3e37eb06c2e757e5cfc201958e46667bb1f8403fd333a22620f63`, nine artifact rows, zero publication rows, and `privateStateExposed=False`. Gjallar readback `local-20260621-190701-140-b9519ec6` sees the `REPO-WORK-PUBLIC-PROOF` row and action row from Huginn's repo-local Verse with the same SHA-256 while Bifrost publication remains missing. Launcher compact modes are now named compact operator-context modes instead of read-only modes, and `bifrost-public-proof` summaries print item, target public Verse, room, proof SHA-256, review receipts, and credit receipts so publication receipts are auditable without claiming upstream sync. - next_action: Use `notes/epiphany-app-server-client-matrix.md` to delete the ten unconsumed advertised routes: roleLaunch, roleAccept, reorientLaunch, reorientAccept, index, distill, propose, promote, jobLaunch, and retrieve. Remove request registration, dispatch, handlers, route tests, and README claims; retain DTOs only where a living retained projection still needs them. Keep the eight named smoke/`--codex` fallback routes guarded as compatibility-only. + next_action: Audit protocol DTOs and bridge conversion helpers left behind by the ten deleted app-server request methods; delete zero-caller shapes without disturbing the eight guarded compatibility routes. Then migrate or retire the phase-6 smoke and `epiphany-mvp-status --codex` consumers so the remaining compatibility surface can contract again. diff --git a/vendor/codex/codex-rs/app-server-protocol/src/protocol/common.rs b/vendor/codex/codex-rs/app-server-protocol/src/protocol/common.rs index ed2a03dc..2de0adb6 100644 --- a/vendor/codex/codex-rs/app-server-protocol/src/protocol/common.rs +++ b/vendor/codex/codex-rs/app-server-protocol/src/protocol/common.rs @@ -341,21 +341,11 @@ client_request_definitions! { params: v2::ThreadEpiphanyViewParams, response: v2::ThreadEpiphanyViewResponse, }, - #[experimental("thread/epiphany/roleLaunch")] - ThreadEpiphanyRoleLaunch => "thread/epiphany/roleLaunch" { - params: v2::ThreadEpiphanyRoleLaunchParams, - response: v2::ThreadEpiphanyRoleLaunchResponse, - }, #[experimental("thread/epiphany/roleResult")] ThreadEpiphanyRoleResult => "thread/epiphany/roleResult" { params: v2::ThreadEpiphanyRoleResultParams, response: v2::ThreadEpiphanyRoleResultResponse, }, - #[experimental("thread/epiphany/roleAccept")] - ThreadEpiphanyRoleAccept => "thread/epiphany/roleAccept" { - params: v2::ThreadEpiphanyRoleAcceptParams, - response: v2::ThreadEpiphanyRoleAcceptResponse, - }, #[experimental("thread/epiphany/freshness")] ThreadEpiphanyFreshness => "thread/epiphany/freshness" { params: v2::ThreadEpiphanyFreshnessParams, @@ -371,46 +361,11 @@ client_request_definitions! { params: v2::ThreadEpiphanyGraphQueryParams, response: v2::ThreadEpiphanyGraphQueryResponse, }, - #[experimental("thread/epiphany/reorientLaunch")] - ThreadEpiphanyReorientLaunch => "thread/epiphany/reorientLaunch" { - params: v2::ThreadEpiphanyReorientLaunchParams, - response: v2::ThreadEpiphanyReorientLaunchResponse, - }, #[experimental("thread/epiphany/reorientResult")] ThreadEpiphanyReorientResult => "thread/epiphany/reorientResult" { params: v2::ThreadEpiphanyReorientResultParams, response: v2::ThreadEpiphanyReorientResultResponse, }, - #[experimental("thread/epiphany/reorientAccept")] - ThreadEpiphanyReorientAccept => "thread/epiphany/reorientAccept" { - params: v2::ThreadEpiphanyReorientAcceptParams, - response: v2::ThreadEpiphanyReorientAcceptResponse, - }, - #[experimental("thread/epiphany/index")] - ThreadEpiphanyIndex => "thread/epiphany/index" { - params: v2::ThreadEpiphanyIndexParams, - response: v2::ThreadEpiphanyIndexResponse, - }, - #[experimental("thread/epiphany/distill")] - ThreadEpiphanyDistill => "thread/epiphany/distill" { - params: v2::ThreadEpiphanyDistillParams, - response: v2::ThreadEpiphanyDistillResponse, - }, - #[experimental("thread/epiphany/propose")] - ThreadEpiphanyPropose => "thread/epiphany/propose" { - params: v2::ThreadEpiphanyProposeParams, - response: v2::ThreadEpiphanyProposeResponse, - }, - #[experimental("thread/epiphany/promote")] - ThreadEpiphanyPromote => "thread/epiphany/promote" { - params: v2::ThreadEpiphanyPromoteParams, - response: v2::ThreadEpiphanyPromoteResponse, - }, - #[experimental("thread/epiphany/jobLaunch")] - ThreadEpiphanyJobLaunch => "thread/epiphany/jobLaunch" { - params: v2::ThreadEpiphanyJobLaunchParams, - response: v2::ThreadEpiphanyJobLaunchResponse, - }, #[experimental("thread/epiphany/jobInterrupt")] ThreadEpiphanyJobInterrupt => "thread/epiphany/jobInterrupt" { params: v2::ThreadEpiphanyJobInterruptParams, @@ -421,11 +376,6 @@ client_request_definitions! { params: v2::ThreadEpiphanyUpdateParams, response: v2::ThreadEpiphanyUpdateResponse, }, - #[experimental("thread/epiphany/retrieve")] - ThreadEpiphanyRetrieve => "thread/epiphany/retrieve" { - params: v2::ThreadEpiphanyRetrieveParams, - response: v2::ThreadEpiphanyRetrieveResponse, - }, ThreadTurnsList => "thread/turns/list" { params: v2::ThreadTurnsListParams, response: v2::ThreadTurnsListResponse, @@ -1661,96 +1611,6 @@ mod tests { Ok(()) } - #[test] - fn serialize_thread_epiphany_role_launch_response() -> Result<()> { - let response = ClientResponse::ThreadEpiphanyRoleLaunch { - request_id: RequestId::Integer(8), - response: v2::ThreadEpiphanyRoleLaunchResponse { - thread_id: "thr_123".to_string(), - role_id: v2::ThreadEpiphanyRoleId::Modeling, - revision: 4, - changed_fields: vec![v2::ThreadEpiphanyStateUpdatedField::JobBindings], - epiphany_state: epiphany_state_model::EpiphanyThreadState { - revision: 4, - job_bindings: vec![epiphany_state_model::EpiphanyJobBinding { - id: "modeling-checkpoint-worker".to_string(), - kind: epiphany_state_model::EpiphanyJobKind::Specialist, - scope: "role-scoped modeling/checkpoint maintenance".to_string(), - owner_role: "epiphany-modeler".to_string(), - authority_scope: Some("epiphany.role.modeling".to_string()), - linked_subgoal_ids: vec!["phase-6".to_string()], - linked_graph_node_ids: vec!["state-spine".to_string()], - blocking_reason: None, - }], - ..Default::default() - }, - job: v2::ThreadEpiphanyJob { - id: "modeling-checkpoint-worker".to_string(), - kind: v2::ThreadEpiphanyJobKind::Specialist, - scope: "role-scoped modeling/checkpoint maintenance".to_string(), - owner_role: "epiphany-modeler".to_string(), - launcher_job_id: Some("epiphany-launch-1".to_string()), - authority_scope: Some("epiphany.role.modeling".to_string()), - backend_job_id: Some("backend-1".to_string()), - status: v2::ThreadEpiphanyJobStatus::Pending, - items_processed: None, - items_total: None, - progress_note: Some( - "Explicitly launched through the Epiphany authority surface onto the heartbeat backend." - .to_string(), - ), - last_checkpoint_at_unix_seconds: None, - blocking_reason: None, - active_thread_ids: Vec::new(), - linked_subgoal_ids: vec!["phase-6".to_string()], - linked_graph_node_ids: vec!["state-spine".to_string()], - }, - }, - }; - - assert_eq!(response.id(), &RequestId::Integer(8)); - assert_eq!(response.method(), "thread/epiphany/roleLaunch"); - assert_eq!( - json!({ - "method": "thread/epiphany/roleLaunch", - "id": 8, - "response": { - "threadId": "thr_123", - "roleId": "modeling", - "revision": 4, - "changedFields": ["jobBindings"], - "epiphanyState": { - "revision": 4, - "job_bindings": [{ - "id": "modeling-checkpoint-worker", - "kind": "specialist", - "scope": "role-scoped modeling/checkpoint maintenance", - "owner_role": "epiphany-modeler", - "authority_scope": "epiphany.role.modeling", - "linked_subgoal_ids": ["phase-6"], - "linked_graph_node_ids": ["state-spine"] - }] - }, - "job": { - "id": "modeling-checkpoint-worker", - "kind": "specialist", - "scope": "role-scoped modeling/checkpoint maintenance", - "ownerRole": "epiphany-modeler", - "launcherJobId": "epiphany-launch-1", - "authorityScope": "epiphany.role.modeling", - "backendJobId": "backend-1", - "status": "pending", - "progressNote": "Explicitly launched through the Epiphany authority surface onto the heartbeat backend.", - "linkedSubgoalIds": ["phase-6"], - "linkedGraphNodeIds": ["state-spine"] - } - } - }), - serde_json::to_value(&response)?, - ); - Ok(()) - } - #[test] fn serialize_thread_epiphany_role_result_response() -> Result<()> { let response = ClientResponse::ThreadEpiphanyRoleResult { @@ -1856,105 +1716,6 @@ mod tests { Ok(()) } - #[test] - fn serialize_thread_epiphany_role_accept_response() -> Result<()> { - let patch = v2::ThreadEpiphanyUpdatePatch { - graph_frontier: Some(epiphany_state_model::EpiphanyGraphFrontier { - active_node_ids: vec!["state-spine".to_string()], - ..Default::default() - }), - ..Default::default() - }; - let finding = v2::ThreadEpiphanyRoleFinding { - role_id: v2::ThreadEpiphanyRoleId::Modeling, - verdict: Some("checkpoint-update-needed".to_string()), - summary: Some("Graph frontier should keep state-spine active.".to_string()), - next_safe_move: Some("Accept the reviewed modeling patch.".to_string()), - checkpoint_summary: None, - scratch_summary: None, - files_inspected: vec!["src/lib.rs".to_string()], - frontier_node_ids: vec!["state-spine".to_string()], - evidence_ids: Vec::new(), - artifact_refs: Vec::new(), - runtime_result_id: Some("result-modeling-1".to_string()), - runtime_job_id: Some("backend-1".to_string()), - open_questions: Vec::new(), - evidence_gaps: Vec::new(), - risks: Vec::new(), - state_patch: Some(patch.clone()), - self_patch: None, - self_persistence: None, - job_error: None, - item_error: None, - }; - let response = ClientResponse::ThreadEpiphanyRoleAccept { - request_id: RequestId::Integer(10), - response: v2::ThreadEpiphanyRoleAcceptResponse { - revision: 5, - changed_fields: vec![ - v2::ThreadEpiphanyStateUpdatedField::AcceptanceReceipts, - v2::ThreadEpiphanyStateUpdatedField::GraphFrontier, - v2::ThreadEpiphanyStateUpdatedField::Observations, - v2::ThreadEpiphanyStateUpdatedField::Evidence, - ], - epiphany_state: epiphany_state_model::EpiphanyThreadState { - revision: 5, - ..Default::default() - }, - role_id: v2::ThreadEpiphanyRoleId::Modeling, - binding_id: "modeling-checkpoint-worker".to_string(), - accepted_receipt_id: "accept-modeling-1".to_string(), - accepted_observation_id: "obs-modeling-1".to_string(), - accepted_evidence_id: "ev-modeling-1".to_string(), - applied_patch: patch, - finding, - }, - }; - - assert_eq!(response.id(), &RequestId::Integer(10)); - assert_eq!(response.method(), "thread/epiphany/roleAccept"); - assert_eq!( - json!({ - "method": "thread/epiphany/roleAccept", - "id": 10, - "response": { - "revision": 5, - "changedFields": ["acceptanceReceipts", "graphFrontier", "observations", "evidence"], - "epiphanyState": { - "revision": 5 - }, - "roleId": "modeling", - "bindingId": "modeling-checkpoint-worker", - "acceptedReceiptId": "accept-modeling-1", - "acceptedObservationId": "obs-modeling-1", - "acceptedEvidenceId": "ev-modeling-1", - "appliedPatch": { - "graphFrontier": { - "active_node_ids": ["state-spine"] - } - }, - "finding": { - "roleId": "modeling", - "verdict": "checkpoint-update-needed", - "summary": "Graph frontier should keep state-spine active.", - "nextSafeMove": "Accept the reviewed modeling patch.", - "filesInspected": ["src/lib.rs"], - "frontierNodeIds": ["state-spine"], - "runtimeResultId": "result-modeling-1", - "runtimeJobId": "backend-1", - "statePatch": { - "graphFrontier": { - "active_node_ids": ["state-spine"] - } - } - } - } - }), - serde_json::to_value(&response)?, - ); - Ok(()) - } - #[test] fn serialize_thread_epiphany_freshness_response() -> Result<()> { let response = ClientResponse::ThreadEpiphanyFreshness { @@ -2274,137 +2035,6 @@ mod tests { Ok(()) } - #[test] - fn serialize_thread_epiphany_reorient_launch_response() -> Result<()> { - let response = ClientResponse::ThreadEpiphanyReorientLaunch { - request_id: RequestId::Integer(8), - response: v2::ThreadEpiphanyReorientLaunchResponse { - thread_id: "thr_123".to_string(), - source: v2::ThreadEpiphanyReorientSource::Live, - state_status: v2::ThreadEpiphanyReorientStateStatus::Ready, - state_revision: Some(4), - decision: v2::ThreadEpiphanyReorientDecision { - action: v2::ThreadEpiphanyReorientAction::Regather, - checkpoint_status: v2::ThreadEpiphanyReorientCheckpointStatus::ResumeReady, - checkpoint_id: Some("ix-1".to_string()), - pressure_level: v2::ThreadEpiphanyPressureLevel::High, - retrieval_status: v2::ThreadEpiphanyRetrievalFreshnessStatus::Stale, - graph_status: v2::ThreadEpiphanyGraphFreshnessStatus::Ready, - watcher_status: v2::ThreadEpiphanyInvalidationStatus::Changed, - reasons: vec![ - v2::ThreadEpiphanyReorientReason::CheckpointPathsChanged, - v2::ThreadEpiphanyReorientReason::FrontierChanged, - ], - checkpoint_dirty_paths: vec![PathBuf::from("src/lib.rs")], - checkpoint_changed_paths: vec![PathBuf::from("src/lib.rs")], - active_frontier_node_ids: vec!["state-spine".to_string()], - next_action: "Re-gather source before editing.".to_string(), - note: "Resume-ready checkpoint was invalidated by watcher/frontier drift." - .to_string(), - }, - revision: 5, - changed_fields: vec![v2::ThreadEpiphanyStateUpdatedField::JobBindings], - epiphany_state: epiphany_state_model::EpiphanyThreadState { - revision: 5, - job_bindings: vec![epiphany_state_model::EpiphanyJobBinding { - id: "reorient-worker".to_string(), - kind: epiphany_state_model::EpiphanyJobKind::Specialist, - scope: "reorient-guided checkpoint regather".to_string(), - owner_role: "epiphany-reorient".to_string(), - authority_scope: Some("epiphany.reorient.regather".to_string()), - linked_subgoal_ids: vec!["phase-6".to_string()], - linked_graph_node_ids: vec!["state-spine".to_string()], - blocking_reason: None, - }], - ..Default::default() - }, - job: v2::ThreadEpiphanyJob { - id: "reorient-worker".to_string(), - kind: v2::ThreadEpiphanyJobKind::Specialist, - scope: "reorient-guided checkpoint regather".to_string(), - owner_role: "epiphany-reorient".to_string(), - launcher_job_id: Some("epiphany-launch-1".to_string()), - authority_scope: Some("epiphany.reorient.regather".to_string()), - backend_job_id: Some("backend-1".to_string()), - status: v2::ThreadEpiphanyJobStatus::Pending, - items_processed: None, - items_total: None, - progress_note: Some( - "Explicitly launched through the Epiphany authority surface onto the heartbeat backend." - .to_string(), - ), - last_checkpoint_at_unix_seconds: None, - blocking_reason: None, - active_thread_ids: Vec::new(), - linked_subgoal_ids: vec!["phase-6".to_string()], - linked_graph_node_ids: vec!["state-spine".to_string()], - }, - }, - }; - - assert_eq!(response.id(), &RequestId::Integer(8)); - assert_eq!(response.method(), "thread/epiphany/reorientLaunch"); - assert_eq!( - json!({ - "method": "thread/epiphany/reorientLaunch", - "id": 8, - "response": { - "threadId": "thr_123", - "source": "live", - "stateStatus": "ready", - "stateRevision": 4, - "decision": { - "action": "regather", - "checkpointStatus": "resumeReady", - "checkpointId": "ix-1", - "pressureLevel": "high", - "retrievalStatus": "stale", - "graphStatus": "ready", - "watcherStatus": "changed", - "reasons": [ - "checkpointPathsChanged", - "frontierChanged" - ], - "checkpointDirtyPaths": ["src/lib.rs"], - "checkpointChangedPaths": ["src/lib.rs"], - "activeFrontierNodeIds": ["state-spine"], - "nextAction": "Re-gather source before editing.", - "note": "Resume-ready checkpoint was invalidated by watcher/frontier drift." - }, - "revision": 5, - "changedFields": ["jobBindings"], - "epiphanyState": { - "revision": 5, - "job_bindings": [{ - "id": "reorient-worker", - "kind": "specialist", - "scope": "reorient-guided checkpoint regather", - "owner_role": "epiphany-reorient", - "authority_scope": "epiphany.reorient.regather", - "linked_subgoal_ids": ["phase-6"], - "linked_graph_node_ids": ["state-spine"] - }] - }, - "job": { - "id": "reorient-worker", - "kind": "specialist", - "scope": "reorient-guided checkpoint regather", - "ownerRole": "epiphany-reorient", - "launcherJobId": "epiphany-launch-1", - "authorityScope": "epiphany.reorient.regather", - "backendJobId": "backend-1", - "status": "pending", - "progressNote": "Explicitly launched through the Epiphany authority surface onto the heartbeat backend.", - "linkedSubgoalIds": ["phase-6"], - "linkedGraphNodeIds": ["state-spine"] - } - } - }), - serde_json::to_value(&response)?, - ); - Ok(()) - } - #[test] fn serialize_thread_epiphany_reorient_result_response() -> Result<()> { let response = ClientResponse::ThreadEpiphanyReorientResult { @@ -2502,477 +2132,6 @@ mod tests { Ok(()) } - #[test] - fn serialize_thread_epiphany_reorient_accept_response() -> Result<()> { - let response = ClientResponse::ThreadEpiphanyReorientAccept { - request_id: RequestId::Integer(10), - response: v2::ThreadEpiphanyReorientAcceptResponse { - revision: 6, - changed_fields: vec![ - v2::ThreadEpiphanyStateUpdatedField::AcceptanceReceipts, - v2::ThreadEpiphanyStateUpdatedField::Observations, - v2::ThreadEpiphanyStateUpdatedField::Evidence, - v2::ThreadEpiphanyStateUpdatedField::Scratch, - ], - epiphany_state: epiphany_state_model::EpiphanyThreadState { - revision: 6, - observations: vec![epiphany_state_model::EpiphanyObservation { - id: "obs-reorient-1".to_string(), - summary: "Accepted resume reorientation result.".to_string(), - source_kind: "reorient_result".to_string(), - status: "accepted".to_string(), - evidence_ids: vec!["ev-reorient-1".to_string()], - ..Default::default() - }], - recent_evidence: vec![epiphany_state_model::EpiphanyEvidenceRecord { - id: "ev-reorient-1".to_string(), - kind: "reorient_result".to_string(), - status: "accepted".to_string(), - summary: "Checkpoint remains source-grounded.".to_string(), - ..Default::default() - }], - ..Default::default() - }, - binding_id: "reorient-worker".to_string(), - accepted_receipt_id: "accept-reorient-1".to_string(), - accepted_observation_id: "obs-reorient-1".to_string(), - accepted_evidence_id: "ev-reorient-1".to_string(), - finding: v2::ThreadEpiphanyReorientFinding { - mode: Some("resume".to_string()), - summary: Some("Checkpoint remains source-grounded.".to_string()), - next_safe_move: Some("Continue the bounded slice.".to_string()), - checkpoint_still_valid: Some(true), - files_inspected: Vec::new(), - frontier_node_ids: Vec::new(), - evidence_ids: Vec::new(), - artifact_refs: Vec::new(), - runtime_result_id: Some("result-reorient-1".to_string()), - runtime_job_id: Some("backend-1".to_string()), - job_error: None, - item_error: None, - }, - }, - }; - - assert_eq!(response.id(), &RequestId::Integer(10)); - assert_eq!(response.method(), "thread/epiphany/reorientAccept"); - assert_eq!( - json!({ - "method": "thread/epiphany/reorientAccept", - "id": 10, - "response": { - "revision": 6, - "changedFields": ["acceptanceReceipts", "observations", "evidence", "scratch"], - "epiphanyState": { - "revision": 6, - "observations": [{ - "id": "obs-reorient-1", - "summary": "Accepted resume reorientation result.", - "source_kind": "reorient_result", - "status": "accepted", - "evidence_ids": ["ev-reorient-1"] - }], - "recent_evidence": [{ - "id": "ev-reorient-1", - "kind": "reorient_result", - "status": "accepted", - "summary": "Checkpoint remains source-grounded." - }] - }, - "bindingId": "reorient-worker", - "acceptedReceiptId": "accept-reorient-1", - "acceptedObservationId": "obs-reorient-1", - "acceptedEvidenceId": "ev-reorient-1", - "finding": { - "mode": "resume", - "summary": "Checkpoint remains source-grounded.", - "nextSafeMove": "Continue the bounded slice.", - "checkpointStillValid": true, - "runtimeResultId": "result-reorient-1", - "runtimeJobId": "backend-1" - } - } - }), - serde_json::to_value(&response)?, - ); - Ok(()) - } - - #[test] - fn serialize_thread_epiphany_retrieve_response() -> Result<()> { - let response = ClientResponse::ThreadEpiphanyRetrieve { - request_id: RequestId::Integer(8), - response: v2::ThreadEpiphanyRetrieveResponse { - query: "checkpoint frontier".to_string(), - index_summary: v2::ThreadEpiphanyRetrieveIndexSummary { - workspace_root: absolute_path("/workspace"), - index_revision: Some("query-time-bm25-v1".to_string()), - status: epiphany_state_model::EpiphanyRetrievalStatus::Ready, - semantic_available: true, - last_indexed_at_unix_seconds: Some(1_744_500_000), - indexed_file_count: Some(12), - indexed_chunk_count: Some(34), - shards: vec![v2::ThreadEpiphanyRetrieveShardSummary { - shard_id: "workspace".to_string(), - path_prefix: PathBuf::from("."), - indexed_file_count: Some(12), - indexed_chunk_count: Some(34), - status: epiphany_state_model::EpiphanyRetrievalStatus::Ready, - exact_available: true, - semantic_available: true, - }], - dirty_paths: vec![PathBuf::from("src/session/mod.rs")], - }, - results: vec![v2::ThreadEpiphanyRetrieveResult { - kind: v2::ThreadEpiphanyRetrieveResultKind::SemanticChunk, - path: PathBuf::from("notes/design.md"), - score: 2.5, - line_start: Some(3), - line_end: Some(9), - excerpt: Some("checkpoint frontier".to_string()), - }], - }, - }; - - assert_eq!(response.id(), &RequestId::Integer(8)); - assert_eq!(response.method(), "thread/epiphany/retrieve"); - assert_eq!( - json!({ - "method": "thread/epiphany/retrieve", - "id": 8, - "response": { - "query": "checkpoint frontier", - "indexSummary": { - "workspaceRoot": absolute_path_string("workspace"), - "indexRevision": "query-time-bm25-v1", - "status": "ready", - "semanticAvailable": true, - "lastIndexedAtUnixSeconds": 1744500000, - "indexedFileCount": 12, - "indexedChunkCount": 34, - "shards": [ - { - "shardId": "workspace", - "pathPrefix": ".", - "indexedFileCount": 12, - "indexedChunkCount": 34, - "status": "ready", - "exactAvailable": true, - "semanticAvailable": true - } - ], - "dirtyPaths": ["src/session/mod.rs"] - }, - "results": [ - { - "kind": "semanticChunk", - "path": "notes/design.md", - "score": 2.5, - "lineStart": 3, - "lineEnd": 9, - "excerpt": "checkpoint frontier" - } - ] - } - }), - serde_json::to_value(&response)?, - ); - Ok(()) - } - - #[test] - fn serialize_thread_epiphany_index_response() -> Result<()> { - let response = ClientResponse::ThreadEpiphanyIndex { - request_id: RequestId::Integer(9), - response: v2::ThreadEpiphanyIndexResponse { - index_summary: v2::ThreadEpiphanyRetrieveIndexSummary { - workspace_root: absolute_path("/workspace"), - index_revision: Some("qdrant-ollama-v1:qwen3-embedding:0.6b".to_string()), - status: epiphany_state_model::EpiphanyRetrievalStatus::Ready, - semantic_available: true, - last_indexed_at_unix_seconds: Some(1_744_500_100), - indexed_file_count: Some(12), - indexed_chunk_count: Some(34), - shards: vec![v2::ThreadEpiphanyRetrieveShardSummary { - shard_id: "workspace".to_string(), - path_prefix: PathBuf::from("."), - indexed_file_count: Some(12), - indexed_chunk_count: Some(34), - status: epiphany_state_model::EpiphanyRetrievalStatus::Ready, - exact_available: true, - semantic_available: true, - }], - dirty_paths: Vec::new(), - }, - }, - }; - - assert_eq!(response.id(), &RequestId::Integer(9)); - assert_eq!(response.method(), "thread/epiphany/index"); - assert_eq!( - json!({ - "method": "thread/epiphany/index", - "id": 9, - "response": { - "indexSummary": { - "workspaceRoot": absolute_path_string("workspace"), - "indexRevision": "qdrant-ollama-v1:qwen3-embedding:0.6b", - "status": "ready", - "semanticAvailable": true, - "lastIndexedAtUnixSeconds": 1744500100, - "indexedFileCount": 12, - "indexedChunkCount": 34, - "shards": [ - { - "shardId": "workspace", - "pathPrefix": ".", - "indexedFileCount": 12, - "indexedChunkCount": 34, - "status": "ready", - "exactAvailable": true, - "semanticAvailable": true - } - ], - "dirtyPaths": [] - } - } - }), - serde_json::to_value(&response)?, - ); - Ok(()) - } - - #[test] - fn serialize_thread_epiphany_distill_response() -> Result<()> { - let response = ClientResponse::ThreadEpiphanyDistill { - request_id: RequestId::Integer(10), - response: v2::ThreadEpiphanyDistillResponse { - expected_revision: 7, - patch: v2::ThreadEpiphanyUpdatePatch { - observations: vec![epiphany_state_model::EpiphanyObservation { - id: "obs-123".to_string(), - summary: "Smoke passed".to_string(), - source_kind: "smoke".to_string(), - status: "ok".to_string(), - code_refs: Vec::new(), - evidence_ids: vec!["ev-123".to_string()], - }], - evidence: vec![epiphany_state_model::EpiphanyEvidenceRecord { - id: "ev-123".to_string(), - kind: "verification".to_string(), - status: "ok".to_string(), - summary: "Smoke passed".to_string(), - code_refs: Vec::new(), - }], - ..Default::default() - }, - }, - }; - - assert_eq!(response.id(), &RequestId::Integer(10)); - assert_eq!(response.method(), "thread/epiphany/distill"); - assert_eq!( - json!({ - "method": "thread/epiphany/distill", - "id": 10, - "response": { - "expectedRevision": 7, - "patch": { - "observations": [ - { - "id": "obs-123", - "summary": "Smoke passed", - "source_kind": "smoke", - "status": "ok", - "evidence_ids": ["ev-123"] - } - ], - "evidence": [ - { - "id": "ev-123", - "kind": "verification", - "status": "ok", - "summary": "Smoke passed" - } - ] - } - } - }), - serde_json::to_value(&response)?, - ); - Ok(()) - } - - #[test] - fn serialize_thread_epiphany_propose_response() -> Result<()> { - let response = ClientResponse::ThreadEpiphanyPropose { - request_id: RequestId::Integer(12), - response: v2::ThreadEpiphanyProposeResponse { - expected_revision: 7, - patch: v2::ThreadEpiphanyUpdatePatch { - churn: Some(epiphany_state_model::EpiphanyChurnState { - understanding_status: "proposal_ready".to_string(), - diff_pressure: "low".to_string(), - graph_freshness: Some("proposal".to_string()), - ..Default::default() - }), - ..Default::default() - }, - }, - }; - - assert_eq!(response.id(), &RequestId::Integer(12)); - assert_eq!(response.method(), "thread/epiphany/propose"); - assert_eq!( - json!({ - "method": "thread/epiphany/propose", - "id": 12, - "response": { - "expectedRevision": 7, - "patch": { - "churn": { - "understanding_status": "proposal_ready", - "diff_pressure": "low", - "graph_freshness": "proposal" - } - } - } - }), - serde_json::to_value(&response)?, - ); - Ok(()) - } - - #[test] - fn serialize_thread_epiphany_promote_response() -> Result<()> { - let response = ClientResponse::ThreadEpiphanyPromote { - request_id: RequestId::Integer(11), - response: v2::ThreadEpiphanyPromoteResponse { - accepted: false, - reasons: vec!["verifierEvidence.status must be accepting".to_string()], - revision: None, - changed_fields: Vec::new(), - epiphany_state: None, - }, - }; - - assert_eq!(response.id(), &RequestId::Integer(11)); - assert_eq!(response.method(), "thread/epiphany/promote"); - assert_eq!( - json!({ - "method": "thread/epiphany/promote", - "id": 11, - "response": { - "accepted": false, - "reasons": ["verifierEvidence.status must be accepting"], - "epiphanyState": null - } - }), - serde_json::to_value(&response)?, - ); - Ok(()) - } - - #[test] - fn serialize_thread_epiphany_job_launch_response() -> Result<()> { - let response = ClientResponse::ThreadEpiphanyJobLaunch { - request_id: RequestId::Integer(12), - response: v2::ThreadEpiphanyJobLaunchResponse { - revision: 3, - changed_fields: vec![ - v2::ThreadEpiphanyStateUpdatedField::JobBindings, - v2::ThreadEpiphanyStateUpdatedField::RuntimeLinks, - ], - epiphany_state: epiphany_state_model::EpiphanyThreadState { - revision: 3, - job_bindings: vec![epiphany_state_model::EpiphanyJobBinding { - id: "specialist-work".to_string(), - kind: epiphany_state_model::EpiphanyJobKind::Specialist, - scope: "role-scoped specialist work".to_string(), - owner_role: "epiphany-harness".to_string(), - authority_scope: Some("epiphany.specialist".to_string()), - linked_subgoal_ids: Vec::new(), - linked_graph_node_ids: Vec::new(), - blocking_reason: None, - }], - runtime_links: vec![epiphany_state_model::EpiphanyRuntimeLink { - id: "runtime-link-specialist-work-job-123".to_string(), - binding_id: "specialist-work".to_string(), - surface: "jobLaunch".to_string(), - role_id: "epiphany-harness".to_string(), - authority_scope: "epiphany.specialist".to_string(), - runtime_job_id: "job-123".to_string(), - runtime_result_id: None, - linked_subgoal_ids: Vec::new(), - linked_graph_node_ids: Vec::new(), - }], - ..Default::default() - }, - job: v2::ThreadEpiphanyJob { - id: "specialist-work".to_string(), - kind: v2::ThreadEpiphanyJobKind::Specialist, - scope: "role-scoped specialist work".to_string(), - owner_role: "epiphany-harness".to_string(), - launcher_job_id: None, - authority_scope: Some("epiphany.specialist".to_string()), - backend_job_id: Some("job-123".to_string()), - status: v2::ThreadEpiphanyJobStatus::Pending, - items_processed: None, - items_total: None, - progress_note: Some("Runtime agent job is pending.".to_string()), - last_checkpoint_at_unix_seconds: None, - blocking_reason: None, - active_thread_ids: Vec::new(), - linked_subgoal_ids: Vec::new(), - linked_graph_node_ids: Vec::new(), - }, - }, - }; - - assert_eq!(response.id(), &RequestId::Integer(12)); - assert_eq!(response.method(), "thread/epiphany/jobLaunch"); - assert_eq!( - json!({ - "method": "thread/epiphany/jobLaunch", - "id": 12, - "response": { - "revision": 3, - "changedFields": ["jobBindings", "runtimeLinks"], - "epiphanyState": { - "revision": 3, - "job_bindings": [{ - "id": "specialist-work", - "kind": "specialist", - "scope": "role-scoped specialist work", - "owner_role": "epiphany-harness", - "authority_scope": "epiphany.specialist" - }], - "runtime_links": [{ - "id": "runtime-link-specialist-work-job-123", - "binding_id": "specialist-work", - "surface": "jobLaunch", - "role_id": "epiphany-harness", - "authority_scope": "epiphany.specialist", - "runtime_job_id": "job-123" - }] - }, - "job": { - "id": "specialist-work", - "kind": "specialist", - "scope": "role-scoped specialist work", - "ownerRole": "epiphany-harness", - "authorityScope": "epiphany.specialist", - "backendJobId": "job-123", - "status": "pending", - "progressNote": "Runtime agent job is pending." - } - } - }), - serde_json::to_value(&response)?, - ); - Ok(()) - } - #[test] fn serialize_thread_epiphany_job_interrupt_response() -> Result<()> { let response = ClientResponse::ThreadEpiphanyJobInterrupt { @@ -3696,36 +2855,6 @@ mod tests { assert_eq!(reason, Some("mock/experimentalMethod")); } - #[test] - fn thread_epiphany_retrieve_is_marked_experimental() { - let request = ClientRequest::ThreadEpiphanyRetrieve { - request_id: RequestId::Integer(1), - params: v2::ThreadEpiphanyRetrieveParams { - thread_id: "thr_123".to_string(), - query: "checkpoint frontier".to_string(), - limit: Some(5), - path_prefixes: vec![PathBuf::from("notes")], - }, - }; - let reason = crate::experimental_api::ExperimentalApi::experimental_reason(&request); - assert_eq!(reason, Some("thread/epiphany/retrieve")); - } - - #[test] - fn thread_epiphany_role_launch_is_marked_experimental() { - let request = ClientRequest::ThreadEpiphanyRoleLaunch { - request_id: RequestId::Integer(1), - params: v2::ThreadEpiphanyRoleLaunchParams { - thread_id: "thr_123".to_string(), - role_id: v2::ThreadEpiphanyRoleId::Modeling, - expected_revision: Some(1), - max_runtime_seconds: Some(60), - }, - }; - let reason = crate::experimental_api::ExperimentalApi::experimental_reason(&request); - assert_eq!(reason, Some("thread/epiphany/roleLaunch")); - } - #[test] fn thread_epiphany_role_result_is_marked_experimental() { let request = ClientRequest::ThreadEpiphanyRoleResult { @@ -3740,21 +2869,6 @@ mod tests { assert_eq!(reason, Some("thread/epiphany/roleResult")); } - #[test] - fn thread_epiphany_role_accept_is_marked_experimental() { - let request = ClientRequest::ThreadEpiphanyRoleAccept { - request_id: RequestId::Integer(1), - params: v2::ThreadEpiphanyRoleAcceptParams { - thread_id: "thr_123".to_string(), - role_id: v2::ThreadEpiphanyRoleId::Modeling, - expected_revision: Some(2), - binding_id: None, - }, - }; - let reason = crate::experimental_api::ExperimentalApi::experimental_reason(&request); - assert_eq!(reason, Some("thread/epiphany/roleAccept")); - } - #[test] fn thread_epiphany_freshness_is_marked_experimental() { let request = ClientRequest::ThreadEpiphanyFreshness { @@ -3785,20 +2899,6 @@ mod tests { assert_eq!(reason, Some("thread/epiphany/context")); } - #[test] - fn thread_epiphany_reorient_launch_is_marked_experimental() { - let request = ClientRequest::ThreadEpiphanyReorientLaunch { - request_id: RequestId::Integer(1), - params: v2::ThreadEpiphanyReorientLaunchParams { - thread_id: "thr_123".to_string(), - expected_revision: Some(4), - max_runtime_seconds: Some(90), - }, - }; - let reason = crate::experimental_api::ExperimentalApi::experimental_reason(&request); - assert_eq!(reason, Some("thread/epiphany/reorientLaunch")); - } - #[test] fn thread_epiphany_reorient_result_is_marked_experimental() { let request = ClientRequest::ThreadEpiphanyReorientResult { @@ -3812,134 +2912,6 @@ mod tests { assert_eq!(reason, Some("thread/epiphany/reorientResult")); } - #[test] - fn thread_epiphany_reorient_accept_is_marked_experimental() { - let request = ClientRequest::ThreadEpiphanyReorientAccept { - request_id: RequestId::Integer(1), - params: v2::ThreadEpiphanyReorientAcceptParams { - thread_id: "thr_123".to_string(), - expected_revision: Some(5), - binding_id: Some("reorient-worker".to_string()), - update_scratch: true, - update_investigation_checkpoint: false, - }, - }; - let reason = crate::experimental_api::ExperimentalApi::experimental_reason(&request); - assert_eq!(reason, Some("thread/epiphany/reorientAccept")); - } - - #[test] - fn thread_epiphany_index_is_marked_experimental() { - let request = ClientRequest::ThreadEpiphanyIndex { - request_id: RequestId::Integer(1), - params: v2::ThreadEpiphanyIndexParams { - thread_id: "thr_123".to_string(), - force_full_rebuild: true, - }, - }; - let reason = crate::experimental_api::ExperimentalApi::experimental_reason(&request); - assert_eq!(reason, Some("thread/epiphany/index")); - } - - #[test] - fn thread_epiphany_distill_is_marked_experimental() { - let request = ClientRequest::ThreadEpiphanyDistill { - request_id: RequestId::Integer(1), - params: v2::ThreadEpiphanyDistillParams { - thread_id: "thr_123".to_string(), - source_kind: "smoke".to_string(), - status: "ok".to_string(), - text: "smoke passed".to_string(), - subject: Some("thread/epiphany/distill".to_string()), - evidence_kind: None, - code_refs: Vec::new(), - }, - }; - let reason = crate::experimental_api::ExperimentalApi::experimental_reason(&request); - assert_eq!(reason, Some("thread/epiphany/distill")); - } - - #[test] - fn thread_epiphany_propose_is_marked_experimental() { - let request = ClientRequest::ThreadEpiphanyPropose { - request_id: RequestId::Integer(1), - params: v2::ThreadEpiphanyProposeParams { - thread_id: "thr_123".to_string(), - observation_ids: vec!["obs-123".to_string()], - }, - }; - let reason = crate::experimental_api::ExperimentalApi::experimental_reason(&request); - assert_eq!(reason, Some("thread/epiphany/propose")); - } - - #[test] - fn thread_epiphany_promote_is_marked_experimental() { - let request = ClientRequest::ThreadEpiphanyPromote { - request_id: RequestId::Integer(1), - params: v2::ThreadEpiphanyPromoteParams { - thread_id: "thr_123".to_string(), - expected_revision: Some(1), - patch: v2::ThreadEpiphanyUpdatePatch { - objective: Some("Keep the map honest".to_string()), - ..Default::default() - }, - verifier_evidence: epiphany_state_model::EpiphanyEvidenceRecord { - id: "ev-verifier".to_string(), - kind: "verification".to_string(), - status: "ok".to_string(), - summary: "Verifier accepted promotion".to_string(), - code_refs: Vec::new(), - }, - }, - }; - let reason = crate::experimental_api::ExperimentalApi::experimental_reason(&request); - assert_eq!(reason, Some("thread/epiphany/promote")); - } - - #[test] - fn thread_epiphany_job_launch_is_marked_experimental() { - let request = ClientRequest::ThreadEpiphanyJobLaunch { - request_id: RequestId::Integer(1), - params: v2::ThreadEpiphanyJobLaunchParams { - thread_id: "thr_123".to_string(), - expected_revision: Some(2), - binding_id: "specialist-work".to_string(), - kind: epiphany_state_model::EpiphanyJobKind::Specialist, - scope: "role-scoped specialist work".to_string(), - owner_role: "epiphany-harness".to_string(), - authority_scope: "epiphany.specialist".to_string(), - linked_subgoal_ids: vec!["phase6".to_string()], - linked_graph_node_ids: vec!["job-surface".to_string()], - instruction: "Summarize the bound specialist task.".to_string(), - launch_document: v2::ThreadEpiphanyWorkerLaunchDocument::Role( - v2::ThreadEpiphanyRoleWorkerLaunchDocument { - thread_id: "thr_123".to_string(), - role_id: "modeling".to_string(), - state_revision: 2, - objective: Some("Keep the map honest".to_string()), - active_subgoal_id: Some("phase6".to_string()), - active_subgoals: Vec::new(), - active_graph_node_ids: vec!["job-surface".to_string()], - investigation_checkpoint: None, - scratch: None, - invariants: Vec::new(), - graphs: None, - recent_evidence: Vec::new(), - recent_observations: Vec::new(), - graph_frontier: None, - graph_checkpoint: None, - planning: None, - churn: None, - }, - ), - output_contract_id: "epiphany.role_worker_result.v0".to_string(), - max_runtime_seconds: Some(30), - }, - }; - let reason = crate::experimental_api::ExperimentalApi::experimental_reason(&request); - assert_eq!(reason, Some("thread/epiphany/jobLaunch")); - } - #[test] fn thread_epiphany_job_interrupt_is_marked_experimental() { let request = ClientRequest::ThreadEpiphanyJobInterrupt { diff --git a/vendor/codex/codex-rs/app-server/README.md b/vendor/codex/codex-rs/app-server/README.md index 438de25e..0a62caea 100644 --- a/vendor/codex/codex-rs/app-server/README.md +++ b/vendor/codex/codex-rs/app-server/README.md @@ -136,16 +136,12 @@ Example with notification opt-out: Hydrated thread responses such as `thread/start`, `thread/resume`, `thread/fork`, `thread/read`, and `thread/unarchive` may include `thread.epiphanyState` when the thread has persisted Epiphany state. When the thread is currently loaded, app-server prefers the live in-memory value; otherwise it reconstructs the latest surviving snapshot from rollout items using the same rollback/compaction semantics as core session replay. For live threads with Epiphany state but no persisted retrieval summary yet, app-server backfills a lightweight query-time retrieval summary instead of pretending the retrieval field is absent. -Experimental Epiphany retrieval: +Experimental Epiphany state access: -- `thread/epiphany/index` runs an explicit loaded-thread-only semantic indexing pass that writes a Qdrant-backed workspace index under Codex home metadata, using local Ollama embeddings by default. It is the write path for persistent semantic retrieval and keeps `thread/epiphany/retrieve` read-only. -- `thread/epiphany/retrieve` runs a loaded-thread-only hybrid repo query that combines `codex_file_search` path hits with BM25 chunk retrieval and returns typed result metadata plus an Epiphany retrieval summary. -- `thread/epiphany/distill` is a loaded-thread-only read surface that turns one explicit observation input into a deterministic observation/evidence patch plus the current `expectedRevision`. It does not mutate thread state; callers must pass the returned patch to `thread/epiphany/update` to promote it. - `thread/epiphany/context` is a targeted read-only state-shard surface. It selects graph nodes/edges, active frontier, checkpoint, observations, and evidence from authoritative typed state without mutating or notifying. - `thread/epiphany/graphQuery` is a read-only graph traversal surface over authoritative typed state. It can return explicit nodes, path/symbol matches, one-to-three-hop neighbors, and the current frontier neighborhood while preserving architecture/dataflow links; it does not mutate, index, schedule, or promote. -- `thread/epiphany/promote` is an explicit loaded-thread-only promotion gate. It evaluates a patch plus verifier evidence, rejects with reasons without mutating state when policy fails, and applies the patch through the durable update path when accepted. Accepted responses include the landed `revision` and `changedFields`. - `thread/epiphany/update` is the explicit loaded-thread-only control-plane write path for Epiphany state. It can append observations/evidence and replace bounded typed state fields such as objective, subgoals, graph frontier/checkpoint, scratch, churn, and mode; it bumps the Epiphany revision, returns `revision` plus `changedFields`, and persists a rollout snapshot immediately. -- `thread/epiphany/stateUpdated` is an experimental server notification emitted after successful `thread/epiphany/update` and accepted `thread/epiphany/promote`. It carries the updated typed `epiphanyState`, a `source` of `update` or `promote`, event-level `revision`, and typed `changedFields`; rejected promotions do not emit it. +- `thread/epiphany/stateUpdated` is an experimental server notification emitted after successful `thread/epiphany/update`. It carries the updated typed `epiphanyState`, an `update` source, event-level `revision`, and typed `changedFields`. - `thread/epiphany/jobsUpdated` is a sealed legacy notification shape. Epiphany no longer emits it from Codex batch-job progress; heartbeat/runtime-spine owns live activation telemetry, while the `jobs` lens on `thread/epiphany/view` remains a read-only projection over current typed state. - `thread/epiphany/freshness` is a read-only reflection surface for retrieval and graph staleness. It reports revision/source identity, retrieval freshness, graph freshness, and exact dirty-path pressure, and for loaded threads now also reports watcher-backed invalidation inputs with watched root, changed paths, mapped graph-node hits, and active-frontier hits. It still does not mutate state, schedule refresh work, or perform automatic watcher-driven semantic invalidation. - `thread/epiphany/reorient` is a read-only CRRC policy surface. It consumes the durable investigation checkpoint plus freshness, watcher, and pressure signals to return a bounded `resume` versus `regather` verdict with explicit checkpoint-path/frontier reasons. It does not mutate state, compact, notify, schedule, or silently continue work on the caller's behalf. diff --git a/vendor/codex/codex-rs/app-server/src/codex_message_processor.rs b/vendor/codex/codex-rs/app-server/src/codex_message_processor.rs index 32aeba88..eb9ba295 100644 --- a/vendor/codex/codex-rs/app-server/src/codex_message_processor.rs +++ b/vendor/codex/codex-rs/app-server/src/codex_message_processor.rs @@ -641,18 +641,10 @@ impl CodexMessageProcessor { self.thread_epiphany_view(to_connection_request_id(request_id), params) .await; } - ClientRequest::ThreadEpiphanyRoleLaunch { request_id, params } => { - self.thread_epiphany_role_launch(to_connection_request_id(request_id), params) - .await; - } ClientRequest::ThreadEpiphanyRoleResult { request_id, params } => { self.thread_epiphany_role_result(to_connection_request_id(request_id), params) .await; } - ClientRequest::ThreadEpiphanyRoleAccept { request_id, params } => { - self.thread_epiphany_role_accept(to_connection_request_id(request_id), params) - .await; - } ClientRequest::ThreadEpiphanyFreshness { request_id, params } => { self.thread_epiphany_freshness(to_connection_request_id(request_id), params) .await; @@ -665,38 +657,10 @@ impl CodexMessageProcessor { self.thread_epiphany_graph_query(to_connection_request_id(request_id), params) .await; } - ClientRequest::ThreadEpiphanyReorientLaunch { request_id, params } => { - self.thread_epiphany_reorient_launch(to_connection_request_id(request_id), params) - .await; - } ClientRequest::ThreadEpiphanyReorientResult { request_id, params } => { self.thread_epiphany_reorient_result(to_connection_request_id(request_id), params) .await; } - ClientRequest::ThreadEpiphanyReorientAccept { request_id, params } => { - self.thread_epiphany_reorient_accept(to_connection_request_id(request_id), params) - .await; - } - ClientRequest::ThreadEpiphanyIndex { request_id, params } => { - self.thread_epiphany_index(to_connection_request_id(request_id), params) - .await; - } - ClientRequest::ThreadEpiphanyDistill { request_id, params } => { - self.thread_epiphany_distill(to_connection_request_id(request_id), params) - .await; - } - ClientRequest::ThreadEpiphanyPropose { request_id, params } => { - self.thread_epiphany_propose(to_connection_request_id(request_id), params) - .await; - } - ClientRequest::ThreadEpiphanyPromote { request_id, params } => { - self.thread_epiphany_promote(to_connection_request_id(request_id), params) - .await; - } - ClientRequest::ThreadEpiphanyJobLaunch { request_id, params } => { - self.thread_epiphany_job_launch(to_connection_request_id(request_id), params) - .await; - } ClientRequest::ThreadEpiphanyJobInterrupt { request_id, params } => { self.thread_epiphany_job_interrupt(to_connection_request_id(request_id), params) .await; @@ -705,10 +669,6 @@ impl CodexMessageProcessor { self.thread_epiphany_update(to_connection_request_id(request_id), params) .await; } - ClientRequest::ThreadEpiphanyRetrieve { request_id, params } => { - self.thread_epiphany_retrieve(to_connection_request_id(request_id), params) - .await; - } ClientRequest::ThreadTurnsList { request_id, params } => { self.thread_turns_list(to_connection_request_id(request_id), params) .await; diff --git a/vendor/codex/codex-rs/app-server/src/codex_message_processor/epiphany_compatibility_architecture.rs b/vendor/codex/codex-rs/app-server/src/codex_message_processor/epiphany_compatibility_architecture.rs index 80c6e0d0..5320ac58 100644 --- a/vendor/codex/codex-rs/app-server/src/codex_message_processor/epiphany_compatibility_architecture.rs +++ b/vendor/codex/codex-rs/app-server/src/codex_message_processor/epiphany_compatibility_architecture.rs @@ -2,14 +2,7 @@ fn mutation_routes_are_explicit_compatibility_delegates() { let source = include_str!("epiphany_mutation_routes.rs"); for delegate in [ - "launch_thread_epiphany_role(", - "apply_thread_epiphany_role_accept(", - "launch_thread_epiphany_reorient(", - "apply_thread_epiphany_reorient_accept(", - "index_epiphany_retrieval_for_paths(", - "apply_thread_epiphany_promote(", "apply_thread_epiphany_update(", - "launch_thread_epiphany_job(", "interrupt_thread_epiphany_job(", ] { assert!(source.contains(delegate), "missing compatibility delegate {delegate}"); @@ -30,6 +23,41 @@ fn mutation_routes_are_explicit_compatibility_delegates() { } } +#[test] +fn only_named_client_routes_remain_registered() { + let protocol = include_str!("../../../app-server-protocol/src/protocol/common.rs"); + let registrations = protocol + .split("ThreadTurnsList =>") + .next() + .expect("client request registration section"); + for retained in [ + "thread/epiphany/view", + "thread/epiphany/roleResult", + "thread/epiphany/freshness", + "thread/epiphany/context", + "thread/epiphany/graphQuery", + "thread/epiphany/reorientResult", + "thread/epiphany/jobInterrupt", + "thread/epiphany/update", + ] { + assert!(registrations.contains(retained), "missing retained client route {retained}"); + } + for removed in [ + "thread/epiphany/roleLaunch", + "thread/epiphany/roleAccept", + "thread/epiphany/reorientLaunch", + "thread/epiphany/reorientAccept", + "thread/epiphany/index", + "thread/epiphany/distill", + "thread/epiphany/propose", + "thread/epiphany/promote", + "thread/epiphany/jobLaunch", + "thread/epiphany/retrieve", + ] { + assert!(!registrations.contains(removed), "unconsumed route remains registered: {removed}"); + } +} + #[test] fn read_routes_have_no_mutation_or_scheduler_authority() { let source = include_str!("epiphany_read_routes.rs"); diff --git a/vendor/codex/codex-rs/app-server/src/codex_message_processor/epiphany_mutation_routes.rs b/vendor/codex/codex-rs/app-server/src/codex_message_processor/epiphany_mutation_routes.rs index b819d0f9..e4205609 100644 --- a/vendor/codex/codex-rs/app-server/src/codex_message_processor/epiphany_mutation_routes.rs +++ b/vendor/codex/codex-rs/app-server/src/codex_message_processor/epiphany_mutation_routes.rs @@ -1,45 +1,20 @@ use codex_app_server_protocol::*; use codex_core::CodexThread; use codex_protocol::ThreadId; -use epiphany_state_model::EpiphanyRetrievalState; use epiphany_state_model::EpiphanyThreadState; use epiphany_codex_bridge::cultnet::EpiphanyStateUpdatedField; use epiphany_codex_bridge::error::EpiphanyBridgeError; -use epiphany_codex_bridge::invalidation::epiphany_freshness_watcher_snapshot; -use epiphany_codex_bridge::launch::EPIPHANY_REORIENT_LAUNCH_BINDING_ID; -use epiphany_codex_bridge::launch::build_epiphany_job_launch_request; -use epiphany_codex_bridge::launch::epiphany_role_binding_id; -use epiphany_codex_bridge::mutation_service::EpiphanyThreadPromoteApplied; -use epiphany_codex_bridge::mutation_service::apply_thread_epiphany_promote; -use epiphany_codex_bridge::mutation_service::apply_thread_epiphany_reorient_accept; -use epiphany_codex_bridge::mutation_service::apply_thread_epiphany_role_accept; use epiphany_codex_bridge::mutation_service::apply_thread_epiphany_update; use epiphany_codex_bridge::mutation_service::interrupt_thread_epiphany_job; -use epiphany_codex_bridge::mutation_service::launch_thread_epiphany_job; -use epiphany_codex_bridge::mutation_service::launch_thread_epiphany_reorient; -use epiphany_codex_bridge::mutation_service::launch_thread_epiphany_role; use epiphany_codex_bridge::protocol_edge::protocol_job_from_surface; -use epiphany_codex_bridge::protocol_edge::protocol_patch_from_core; -use epiphany_codex_bridge::protocol_edge::protocol_reorient_decision; -use epiphany_codex_bridge::protocol_edge::protocol_reorient_finding; -use epiphany_codex_bridge::protocol_edge::protocol_reorient_source; -use epiphany_codex_bridge::protocol_edge::protocol_reorient_state_status; -use epiphany_codex_bridge::protocol_edge::protocol_role_finding; -use epiphany_codex_bridge::protocol_edge::protocol_role_id_to_core; use epiphany_codex_bridge::protocol_edge::protocol_state_updated_fields; use epiphany_codex_bridge::protocol_edge::protocol_state_updated_notification; use epiphany_codex_bridge::protocol_edge::protocol_update_patch_to_core; -use epiphany_codex_bridge::protocol_edge::protocol_worker_launch_document_to_core; -use epiphany_codex_bridge::retrieve::epiphany_retrieval_state_for_paths; -use epiphany_codex_bridge::retrieve::index_epiphany_retrieval_for_paths; -use epiphany_codex_bridge::retrieve_protocol::protocol_index_response; use std::sync::Arc; use super::CodexMessageProcessor; use super::ConnectionRequestId; -use super::ThreadReadViewError; use super::epiphany_thread_host::EpiphanyCodexThreadHost; -use super::epiphany_thread_host::epiphany_token_usage_snapshot; impl CodexMessageProcessor { async fn load_epiphany_thread( @@ -94,450 +69,6 @@ impl CodexMessageProcessor { .await; } - pub(super) async fn thread_epiphany_role_launch( - &self, - request_id: ConnectionRequestId, - params: ThreadEpiphanyRoleLaunchParams, - ) { - let ThreadEpiphanyRoleLaunchParams { - thread_id, - role_id, - expected_revision, - max_runtime_seconds, - } = params; - let core_role_id = protocol_role_id_to_core(role_id); - - let (thread_uuid, loaded_thread) = - match self.load_epiphany_thread(&request_id, &thread_id).await { - Some(thread) => thread, - None => return, - }; - let host = EpiphanyCodexThreadHost::new(loaded_thread.as_ref()); - let applied = match launch_thread_epiphany_role( - &host, - &thread_id, - core_role_id, - expected_revision, - max_runtime_seconds, - ) - .await - { - Ok(applied) => applied, - Err(EpiphanyBridgeError::InvalidRequest(message)) => { - self.send_invalid_request_error(request_id, message).await; - return; - } - Err(err) => { - self.send_internal_error( - request_id, - format!("failed to launch Epiphany role specialist for {thread_uuid}: {err}"), - ) - .await; - return; - } - }; - let changed_fields = applied.changed_fields; - let protocol_changed_fields = protocol_state_updated_fields(changed_fields.clone()); - let epiphany_state = applied.epiphany_state; - - self.outgoing - .send_response( - request_id, - ThreadEpiphanyRoleLaunchResponse { - thread_id: thread_uuid.to_string(), - role_id, - revision: applied.revision, - changed_fields: protocol_changed_fields, - epiphany_state: epiphany_state.clone(), - job: protocol_job_from_surface( - applied.job, - Some(applied.launcher_job_id), - Some(applied.backend_job_id), - ), - }, - ) - .await; - self.send_epiphany_state_updated( - thread_uuid, - ThreadEpiphanyStateUpdatedSource::JobLaunch, - changed_fields, - epiphany_state, - ) - .await; - } - - pub(super) async fn thread_epiphany_role_accept( - &self, - request_id: ConnectionRequestId, - params: ThreadEpiphanyRoleAcceptParams, - ) { - let ThreadEpiphanyRoleAcceptParams { - thread_id, - role_id, - expected_revision, - binding_id, - } = params; - let core_role_id = protocol_role_id_to_core(role_id); - - let default_binding_id = match epiphany_role_binding_id(core_role_id) { - Ok(binding_id) => binding_id, - Err(message) => { - self.send_invalid_request_error(request_id, message).await; - return; - } - }; - let binding_id = binding_id.unwrap_or_else(|| default_binding_id.into()); - - let (thread_uuid, loaded_thread) = - match self.load_epiphany_thread(&request_id, &thread_id).await { - Some(thread) => thread, - None => return, - }; - let host = EpiphanyCodexThreadHost::new(loaded_thread.as_ref()); - let applied = match apply_thread_epiphany_role_accept( - &host, - core_role_id, - expected_revision, - &binding_id, - ) - .await - { - Ok(applied) => applied, - Err(EpiphanyBridgeError::InvalidRequest(message)) => { - self.send_invalid_request_error(request_id, message).await; - return; - } - Err(err) => { - self.send_internal_error( - request_id, - format!("failed to apply Epiphany role finding: {err}"), - ) - .await; - return; - } - }; - let changed_fields = applied.changed_fields; - let protocol_changed_fields = protocol_state_updated_fields(changed_fields.clone()); - let epiphany_state = applied.epiphany_state; - - self.outgoing - .send_response( - request_id, - ThreadEpiphanyRoleAcceptResponse { - revision: applied.revision, - changed_fields: protocol_changed_fields, - epiphany_state: epiphany_state.clone(), - role_id, - binding_id: binding_id.clone(), - accepted_receipt_id: applied.accepted_receipt_id, - accepted_observation_id: applied.accepted_observation_id, - accepted_evidence_id: applied.accepted_evidence_id, - applied_patch: protocol_patch_from_core(applied.applied_patch), - finding: protocol_role_finding(role_id, applied.finding), - }, - ) - .await; - self.send_epiphany_state_updated( - thread_uuid, - ThreadEpiphanyStateUpdatedSource::RoleAccept, - changed_fields, - epiphany_state, - ) - .await; - } - - pub(super) async fn thread_epiphany_reorient_launch( - &self, - request_id: ConnectionRequestId, - params: ThreadEpiphanyReorientLaunchParams, - ) { - let ThreadEpiphanyReorientLaunchParams { - thread_id, - expected_revision, - max_runtime_seconds, - } = params; - - let (thread_uuid, loaded_thread) = - match self.load_epiphany_thread(&request_id, &thread_id).await { - Some(thread) => thread, - None => return, - }; - let thread = match self.read_thread_view(thread_uuid, false).await { - Ok(thread) => thread, - Err(ThreadReadViewError::InvalidRequest(message)) => { - self.send_invalid_request_error(request_id, message).await; - return; - } - Err(ThreadReadViewError::Internal(message)) => { - self.send_internal_error(request_id, message).await; - return; - } - }; - - let retrieval_override = thread_epiphany_retrieval_state(loaded_thread.as_ref()).await; - let config_snapshot = loaded_thread.config_snapshot().await; - self.epiphany_invalidation_manager - .ensure_thread_watch(&thread_id, &config_snapshot.cwd) - .await; - let watcher_snapshot = self - .epiphany_invalidation_manager - .snapshot(&thread_id) - .await; - let token_usage_info = loaded_thread.token_usage_info().await; - let host = EpiphanyCodexThreadHost::new(loaded_thread.as_ref()); - let token_usage_snapshot = epiphany_token_usage_snapshot(token_usage_info.as_ref()); - let applied = match launch_thread_epiphany_reorient( - &host, - &thread_id, - expected_revision, - max_runtime_seconds, - thread.epiphany_state.as_ref(), - Some(&retrieval_override), - Some(epiphany_freshness_watcher_snapshot(&watcher_snapshot)), - token_usage_snapshot.as_ref(), - ) - .await - { - Ok(applied) => applied, - Err(EpiphanyBridgeError::InvalidRequest(message)) => { - self.send_invalid_request_error(request_id, message).await; - return; - } - Err(err) => { - self.send_internal_error( - request_id, - format!( - "failed to launch Epiphany reorientation worker for {thread_uuid}: {err}" - ), - ) - .await; - return; - } - }; - let changed_fields = applied.changed_fields; - let protocol_changed_fields = protocol_state_updated_fields(changed_fields.clone()); - let epiphany_state = applied.epiphany_state; - - self.outgoing - .send_response( - request_id, - ThreadEpiphanyReorientLaunchResponse { - thread_id: thread_uuid.to_string(), - source: protocol_reorient_source(applied.source), - state_status: protocol_reorient_state_status(applied.state_status), - state_revision: applied.state_revision, - decision: protocol_reorient_decision(applied.decision), - revision: applied.revision, - changed_fields: protocol_changed_fields, - epiphany_state: epiphany_state.clone(), - job: protocol_job_from_surface( - applied.job, - Some(applied.launcher_job_id), - Some(applied.backend_job_id), - ), - }, - ) - .await; - self.send_epiphany_state_updated( - thread_uuid, - ThreadEpiphanyStateUpdatedSource::JobLaunch, - changed_fields, - epiphany_state, - ) - .await; - } - - pub(super) async fn thread_epiphany_reorient_accept( - &self, - request_id: ConnectionRequestId, - params: ThreadEpiphanyReorientAcceptParams, - ) { - let ThreadEpiphanyReorientAcceptParams { - thread_id, - expected_revision, - binding_id, - update_scratch, - update_investigation_checkpoint, - } = params; - let binding_id = binding_id.unwrap_or_else(|| EPIPHANY_REORIENT_LAUNCH_BINDING_ID.into()); - - let (thread_uuid, loaded_thread) = - match self.load_epiphany_thread(&request_id, &thread_id).await { - Some(thread) => thread, - None => return, - }; - let host = EpiphanyCodexThreadHost::new(loaded_thread.as_ref()); - let applied = match apply_thread_epiphany_reorient_accept( - &host, - expected_revision, - binding_id.as_str(), - update_scratch, - update_investigation_checkpoint, - ) - .await - { - Ok(applied) => applied, - Err(EpiphanyBridgeError::InvalidRequest(message)) => { - self.send_invalid_request_error(request_id, message).await; - return; - } - Err(err) => { - self.send_internal_error( - request_id, - format!("failed to accept Epiphany reorientation finding: {err}"), - ) - .await; - return; - } - }; - let changed_fields = applied.changed_fields; - let protocol_changed_fields = protocol_state_updated_fields(changed_fields.clone()); - let epiphany_state = applied.epiphany_state; - - self.outgoing - .send_response( - request_id, - ThreadEpiphanyReorientAcceptResponse { - revision: applied.revision, - changed_fields: protocol_changed_fields, - epiphany_state: epiphany_state.clone(), - binding_id: binding_id.clone(), - accepted_receipt_id: applied.accepted_receipt_id, - accepted_observation_id: applied.accepted_observation_id, - accepted_evidence_id: applied.accepted_evidence_id, - finding: protocol_reorient_finding(applied.finding), - }, - ) - .await; - self.send_epiphany_state_updated( - thread_uuid, - ThreadEpiphanyStateUpdatedSource::ReorientAccept, - changed_fields, - epiphany_state, - ) - .await; - } - - pub(super) async fn thread_epiphany_index( - &self, - request_id: ConnectionRequestId, - params: ThreadEpiphanyIndexParams, - ) { - let ThreadEpiphanyIndexParams { - thread_id, - force_full_rebuild, - } = params; - - let (thread_uuid, thread) = match self.load_epiphany_thread(&request_id, &thread_id).await { - Some(thread) => thread, - None => return, - }; - - let config = thread.config_snapshot().await; - let codex_home = thread.codex_home().await; - let response = match index_epiphany_retrieval_for_paths( - config.cwd.to_path_buf(), - codex_home, - force_full_rebuild, - ) - .await - .and_then(protocol_index_response) - { - Ok(response) => response, - Err(err) => { - self.send_internal_error( - request_id, - format!("failed to index Epiphany retrieval state for {thread_uuid}: {err}"), - ) - .await; - return; - } - }; - - self.outgoing.send_response(request_id, response).await; - } - - pub(super) async fn thread_epiphany_promote( - &self, - request_id: ConnectionRequestId, - params: ThreadEpiphanyPromoteParams, - ) { - let ThreadEpiphanyPromoteParams { - thread_id, - expected_revision, - patch, - verifier_evidence, - } = params; - - let (thread_uuid, thread) = match self.load_epiphany_thread(&request_id, &thread_id).await { - Some(thread) => thread, - None => return, - }; - - let host = EpiphanyCodexThreadHost::new(thread.as_ref()); - let core_patch = protocol_update_patch_to_core(&patch); - let applied = match apply_thread_epiphany_promote( - &host, - expected_revision, - core_patch, - verifier_evidence, - ) - .await - { - Ok(applied) => applied, - Err(EpiphanyBridgeError::InvalidRequest(message)) => { - self.send_invalid_request_error(request_id, message).await; - return; - } - Err(err) => { - self.send_internal_error( - request_id, - format!("failed to promote Epiphany state update: {err}"), - ) - .await; - return; - } - }; - - let applied = match applied { - EpiphanyThreadPromoteApplied::Accepted(applied) => applied, - EpiphanyThreadPromoteApplied::Rejected { reasons } => { - self.outgoing - .send_response( - request_id, - ThreadEpiphanyPromoteResponse { - accepted: false, - reasons, - revision: None, - changed_fields: Vec::new(), - epiphany_state: None, - }, - ) - .await; - return; - } - }; - let changed_fields = applied.changed_fields; - let protocol_changed_fields = protocol_state_updated_fields(changed_fields.clone()); - let epiphany_state = applied.epiphany_state; - let response = ThreadEpiphanyPromoteResponse { - accepted: true, - reasons: Vec::new(), - revision: Some(applied.revision), - changed_fields: protocol_changed_fields, - epiphany_state: Some(epiphany_state.clone()), - }; - - self.outgoing.send_response(request_id, response).await; - self.send_epiphany_state_updated( - thread_uuid, - ThreadEpiphanyStateUpdatedSource::Promote, - changed_fields, - epiphany_state, - ) - .await; - } - pub(super) async fn thread_epiphany_update( &self, request_id: ConnectionRequestId, @@ -591,97 +122,6 @@ impl CodexMessageProcessor { .await; } - pub(super) async fn thread_epiphany_job_launch( - &self, - request_id: ConnectionRequestId, - params: ThreadEpiphanyJobLaunchParams, - ) { - let ThreadEpiphanyJobLaunchParams { - thread_id, - expected_revision, - binding_id, - kind, - scope, - owner_role, - authority_scope, - linked_subgoal_ids, - linked_graph_node_ids, - instruction, - launch_document, - output_contract_id, - max_runtime_seconds, - } = params; - - let (thread_uuid, thread) = match self.load_epiphany_thread(&request_id, &thread_id).await { - Some(thread) => thread, - None => return, - }; - - let host = EpiphanyCodexThreadHost::new(thread.as_ref()); - let core_launch_document = protocol_worker_launch_document_to_core(launch_document); - let applied = match launch_thread_epiphany_job( - &host, - build_epiphany_job_launch_request( - expected_revision, - binding_id.clone(), - kind, - scope, - owner_role, - authority_scope, - linked_subgoal_ids, - linked_graph_node_ids, - instruction, - core_launch_document, - output_contract_id, - max_runtime_seconds, - ), - kind, - "missing launched job projection", - ) - .await - { - Ok(applied) => applied, - Err(EpiphanyBridgeError::InvalidRequest(message)) => { - self.send_invalid_request_error(request_id, message).await; - return; - } - Err(err) => { - self.send_internal_error( - request_id, - format!("failed to launch Epiphany job for {thread_uuid}: {err}"), - ) - .await; - return; - } - }; - let changed_fields = applied.changed_fields; - let protocol_changed_fields = protocol_state_updated_fields(changed_fields.clone()); - let epiphany_state = applied.epiphany_state; - - self.outgoing - .send_response( - request_id, - ThreadEpiphanyJobLaunchResponse { - revision: applied.revision, - changed_fields: protocol_changed_fields, - epiphany_state: epiphany_state.clone(), - job: protocol_job_from_surface( - applied.job, - Some(applied.launcher_job_id), - Some(applied.backend_job_id), - ), - }, - ) - .await; - self.send_epiphany_state_updated( - thread_uuid, - ThreadEpiphanyStateUpdatedSource::JobLaunch, - changed_fields, - epiphany_state, - ) - .await; - } - pub(super) async fn thread_epiphany_job_interrupt( &self, request_id: ConnectionRequestId, @@ -748,9 +188,3 @@ impl CodexMessageProcessor { .await; } } - -async fn thread_epiphany_retrieval_state(thread: &CodexThread) -> EpiphanyRetrievalState { - let config = thread.config_snapshot().await; - let codex_home = thread.codex_home().await; - epiphany_retrieval_state_for_paths(config.cwd.to_path_buf(), codex_home).await -} diff --git a/vendor/codex/codex-rs/app-server/src/codex_message_processor/epiphany_read_routes.rs b/vendor/codex/codex-rs/app-server/src/codex_message_processor/epiphany_read_routes.rs index 401747f7..4e238af4 100644 --- a/vendor/codex/codex-rs/app-server/src/codex_message_processor/epiphany_read_routes.rs +++ b/vendor/codex/codex-rs/app-server/src/codex_message_processor/epiphany_read_routes.rs @@ -2,7 +2,6 @@ use codex_app_server_protocol::*; use codex_core::CodexThread; use codex_protocol::ThreadId; use epiphany_state_model::EpiphanyRetrievalState; -use super::epiphany_thread_host::load_authoritative_epiphany_state; use super::epiphany_thread_host::runtime_spine_store_path; use epiphany_codex_bridge::cultnet::EpiphanySurfaceSource; use epiphany_codex_bridge::invalidation::epiphany_freshness_watcher_snapshot; @@ -14,24 +13,18 @@ use epiphany_codex_bridge::protocol_edge::core_epiphany_view_needs_reorientation use epiphany_codex_bridge::protocol_edge::core_epiphany_view_needs_runtime_store; use epiphany_codex_bridge::protocol_edge::default_core_epiphany_view_lenses; use epiphany_codex_bridge::protocol_edge::protocol_context_params_to_core; -use epiphany_codex_bridge::protocol_edge::protocol_distill_params_to_core; use epiphany_codex_bridge::protocol_edge::protocol_freshness_response_from_surface; use epiphany_codex_bridge::protocol_edge::protocol_graph_query_to_core; use epiphany_codex_bridge::protocol_edge::protocol_role_id_to_core; use epiphany_codex_bridge::protocol_edge::protocol_view_lenses_to_core; use epiphany_codex_bridge::retrieve::epiphany_retrieval_state_for_paths; -use epiphany_codex_bridge::retrieve::normalize_thread_epiphany_retrieve_query; -use epiphany_codex_bridge::retrieve::retrieve_epiphany_for_paths; -use epiphany_codex_bridge::retrieve_protocol::protocol_retrieve_response; use epiphany_codex_bridge::view_protocol::EpiphanyFreshnessResponseInput; use epiphany_codex_bridge::view_protocol::EpiphanyReorientResultResponseInput; use epiphany_codex_bridge::view_protocol::EpiphanyRoleResultResponseInput; use epiphany_codex_bridge::view_protocol::EpiphanyViewResponseInput; use epiphany_codex_bridge::view_protocol::derive_epiphany_freshness_surface; use epiphany_codex_bridge::view_protocol::map_epiphany_context_response; -use epiphany_codex_bridge::view_protocol::map_epiphany_distill_response; use epiphany_codex_bridge::view_protocol::map_epiphany_graph_query_response; -use epiphany_codex_bridge::view_protocol::map_epiphany_propose_response; use epiphany_codex_bridge::view_protocol::map_epiphany_reorient_result_response; use epiphany_codex_bridge::view_protocol::map_epiphany_role_result_response; use epiphany_codex_bridge::view_protocol::map_epiphany_view_response; @@ -415,171 +408,7 @@ impl CodexMessageProcessor { self.outgoing.send_response(request_id, response).await; } - pub(super) async fn thread_epiphany_retrieve( - &self, - request_id: ConnectionRequestId, - params: ThreadEpiphanyRetrieveParams, - ) { - let ThreadEpiphanyRetrieveParams { - thread_id, - query, - limit, - path_prefixes, - } = params; - let thread_uuid = match ThreadId::from_string(&thread_id) { - Ok(id) => id, - Err(err) => { - self.send_invalid_request_error(request_id, format!("invalid thread id: {err}")) - .await; - return; - } - }; - - let query = match normalize_thread_epiphany_retrieve_query(query, limit, path_prefixes) { - Ok(query) => query, - Err(message) => { - self.send_invalid_request_error(request_id, message.to_string()) - .await; - return; - } - }; - - let thread = match self.thread_manager.get_thread(thread_uuid).await { - Ok(thread) => thread, - Err(_) => { - self.send_invalid_request_error( - request_id, - format!("thread not loaded: {thread_uuid}"), - ) - .await; - return; - } - }; - - let config = thread.config_snapshot().await; - let codex_home = thread.codex_home().await; - let response = - match retrieve_epiphany_for_paths(config.cwd.to_path_buf(), codex_home, query) - .await - .and_then(protocol_retrieve_response) - { - Ok(response) => response, - Err(err) => { - self.send_internal_error( - request_id, - format!("failed to retrieve Epiphany results for {thread_uuid}: {err}"), - ) - .await; - return; - } - }; - - self.outgoing.send_response(request_id, response).await; - } - - pub(super) async fn thread_epiphany_distill( - &self, - request_id: ConnectionRequestId, - params: ThreadEpiphanyDistillParams, - ) { - let thread_id = params.thread_id.clone(); - - let thread_uuid = match ThreadId::from_string(&thread_id) { - Ok(id) => id, - Err(err) => { - self.send_invalid_request_error(request_id, format!("invalid thread id: {err}")) - .await; - return; - } - }; - - let thread = match self.thread_manager.get_thread(thread_uuid).await { - Ok(thread) => thread, - Err(_) => { - self.send_invalid_request_error( - request_id, - format!("thread not loaded: {thread_uuid}"), - ) - .await; - return; - } - }; - - let expected_revision = load_authoritative_epiphany_state(&thread) - .await - .map(|state| state.revision) - .unwrap_or(0); - let input = protocol_distill_params_to_core(params); - let response = match map_epiphany_distill_response(expected_revision, input) { - Ok(response) => response, - Err(err) => { - self.send_invalid_request_error( - request_id, - format!("failed to distill Epiphany observation: {err}"), - ) - .await; - return; - } - }; - - self.outgoing.send_response(request_id, response).await; - } - - pub(super) async fn thread_epiphany_propose( - &self, - request_id: ConnectionRequestId, - params: ThreadEpiphanyProposeParams, - ) { - let ThreadEpiphanyProposeParams { thread_id, .. } = ¶ms; - let thread_id = thread_id.clone(); - - let thread_uuid = match ThreadId::from_string(&thread_id) { - Ok(id) => id, - Err(err) => { - self.send_invalid_request_error(request_id, format!("invalid thread id: {err}")) - .await; - return; - } - }; - - let thread = match self.thread_manager.get_thread(thread_uuid).await { - Ok(thread) => thread, - Err(_) => { - self.send_invalid_request_error( - request_id, - format!("thread not loaded: {thread_uuid}"), - ) - .await; - return; - } - }; - - let state = match load_authoritative_epiphany_state(&thread).await { - Some(state) => state, - None => { - self.send_invalid_request_error( - request_id, - format!("thread has no Epiphany state: {thread_uuid}"), - ) - .await; - return; - } - }; - let response = match map_epiphany_propose_response(state, params.observation_ids) { - Ok(response) => response, - Err(err) => { - self.send_invalid_request_error( - request_id, - format!("failed to propose Epiphany map update: {err}"), - ) - .await; - return; - } - }; - - self.outgoing.send_response(request_id, response).await; - } } async fn thread_epiphany_retrieval_state(thread: &CodexThread) -> EpiphanyRetrievalState {