diff --git a/epiphany-codex-bridge/src/mutation.rs b/epiphany-codex-bridge/src/mutation.rs index 6b5b0ef2..561f9bdf 100644 --- a/epiphany-codex-bridge/src/mutation.rs +++ b/epiphany-codex-bridge/src/mutation.rs @@ -3,6 +3,8 @@ use std::path::PathBuf; use codex_app_server_protocol::ThreadEpiphanyReorientFinding; use codex_app_server_protocol::ThreadEpiphanyRoleFinding; use codex_app_server_protocol::ThreadEpiphanyRoleId; +use codex_app_server_protocol::ThreadEpiphanyStateUpdatedNotification; +use codex_app_server_protocol::ThreadEpiphanyStateUpdatedSource; use codex_app_server_protocol::ThreadEpiphanyStateUpdatedField; use codex_app_server_protocol::ThreadEpiphanyUpdatePatch; use codex_core::EpiphanyStateUpdate; @@ -99,6 +101,22 @@ pub fn state_update_from_thread_patch( } } +pub fn epiphany_state_updated_notification( + thread_id: String, + source: ThreadEpiphanyStateUpdatedSource, + revision: u64, + changed_fields: Vec, + epiphany_state: codex_protocol::protocol::EpiphanyThreadState, +) -> ThreadEpiphanyStateUpdatedNotification { + ThreadEpiphanyStateUpdatedNotification { + thread_id, + source, + revision, + changed_fields, + epiphany_state, + } +} + pub fn imagination_role_accept_patch_errors(patch: &ThreadEpiphanyUpdatePatch) -> Vec { imagination_role_state_patch_policy_errors(&core_state_patch_from_protocol(patch)) } diff --git a/notes/fresh-workspace-handoff.md b/notes/fresh-workspace-handoff.md index eb6979a0..8f323e30 100644 --- a/notes/fresh-workspace-handoff.md +++ b/notes/fresh-workspace-handoff.md @@ -535,6 +535,10 @@ The twenty-eighth cut made reorient acceptance return its core `EpiphanyStateUpdate` from the bridge, so the route no longer assembles the scratch/checkpoint/receipt/evidence update fields after receiving the bridge bundle. `epiphany_mutation_routes.rs` is about 1,070 lines. +The twenty-ninth cut moved repeated Epiphany state-updated notification shaping +into `epiphany-codex-bridge/src/mutation.rs`. This did not materially shrink +the route file, but it removed another duplicated protocol-shape authority from +the mutation handlers. `epiphany_mutation_routes.rs` is about 1,071 lines. Also: MCP itself is allowed to be JSON. The target is not "replace MCP JSON"; the target is an Epiphany-owned boundary that speaks typed Epiphany @@ -542,7 +546,8 @@ intent/result/receipt documents internally and normal MCP JSON-RPC externally. Continue with the actual whale-carcass cut: carve remaining route-level mutation orchestration into explicit typed bridge/service calls, starting with launch -response/notification shaping and interrupt result projection. Success is a +response shaping and then reassessing whether the next clean cut is worth +making or whether the remaining code is honest Codex edge glue. Success is a visibly smaller processor and less mutation authority in Codex, not merely nicer payload names or another adapter reliquary. Do not resume Rider, Unity, Aquarium, Face, dogfood, planning, app, skill, marketplace, or bridge expansion diff --git a/state/ledgers.msgpack b/state/ledgers.msgpack index a8a8c018..3d4fe99f 100644 Binary files a/state/ledgers.msgpack and b/state/ledgers.msgpack differ diff --git a/state/map.yaml b/state/map.yaml index 2e7a1072..7d6e39ca 100644 --- a/state/map.yaml +++ b/state/map.yaml @@ -278,5 +278,5 @@ rejected_paths: reason: making Epiphany cleaner inside Codex still preserves the wrong organ; Codex must be starved down to OpenAI subscription auth/model transport, while Epiphany data and subsystem communication move to typed CultCache/CultNet. current_status: - summary: The Codex starvation pass has five typing receipts, seventeen processor cuts, and now a real physical extraction: `epiphany-codex-bridge` lives outside `vendor/codex` and owns the Codex-facing Epiphany adapters for scene, jobs, context/planning/graph query, retrieval, result projection, runtime-spine result adaptation, launch/prompt doctrine, mutation document mechanics, live-state projection, pressure/pre-compaction rendering, freshness/reorientation projection, CRRC/coordinator/role-board projection, and acceptance/evidence signal helpers. Vendored app-server now retains only `epiphany_invalidation.rs` as a root Epiphany module because watcher lifecycle is still app-server machinery; `codex_message_processor.rs` still contains route dispatch and mutation orchestration. The processor is about 10,339 lines, `epiphany_mutation_routes.rs` is about 1,070 lines, and `epiphany_state_helpers.rs` is down to a 19-line rollout-state loader after moving typed mutation helpers, reviewability checks, completed runtime-result acceptance loading, live-state projection, launched/interrupted job fallback projection, role/reorient acceptance update bundle construction including its core state update, and protocol patch-to-core state-update projection out to the bridge. This is progress, not absolution: the bridge is still Codex-facing compatibility, not the final CultNet runtime, and route-level launch/update/promote/interrupt orchestration still lives inside the Codex processor. MCP itself is correctly JSON at its protocol edge; the target is typed Epiphany intent/result/receipt wrappers around MCP, not replacing MCP JSON. - next_action: Continue Codex starvation by carving remaining route-level mutation orchestration into explicit outside-vendor service calls, starting with launch response/notification shaping and interrupt result projection. Do not resume app/skill/marketplace expansion. + summary: The Codex starvation pass has five typing receipts, seventeen processor cuts, and now a real physical extraction: `epiphany-codex-bridge` lives outside `vendor/codex` and owns the Codex-facing Epiphany adapters for scene, jobs, context/planning/graph query, retrieval, result projection, runtime-spine result adaptation, launch/prompt doctrine, mutation document mechanics, live-state projection, pressure/pre-compaction rendering, freshness/reorientation projection, CRRC/coordinator/role-board projection, and acceptance/evidence signal helpers. Vendored app-server now retains only `epiphany_invalidation.rs` as a root Epiphany module because watcher lifecycle is still app-server machinery; `codex_message_processor.rs` still contains route dispatch and mutation orchestration. The processor is about 10,339 lines, `epiphany_mutation_routes.rs` is about 1,071 lines, and `epiphany_state_helpers.rs` is down to a 19-line rollout-state loader after moving typed mutation helpers, reviewability checks, completed runtime-result acceptance loading, live-state projection, launched/interrupted job fallback projection, role/reorient acceptance update bundle construction including its core state update, protocol patch-to-core state-update projection, and state-updated notification shaping out to the bridge. This is progress, not absolution: the bridge is still Codex-facing compatibility, not the final CultNet runtime, and route-level launch/update/promote/interrupt orchestration still lives inside the Codex processor. MCP itself is correctly JSON at its protocol edge; the target is typed Epiphany intent/result/receipt wrappers around MCP, not replacing MCP JSON. + next_action: Continue Codex starvation by carving remaining route-level mutation orchestration into explicit outside-vendor service calls, starting with launch response shaping and then reassessing whether the next clean cut is worth making or whether the remaining code is honest Codex edge glue. Do not resume app/skill/marketplace expansion. 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 4fce1d6f..a4eb457e 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 @@ -22,6 +22,7 @@ use epiphany_codex_bridge::mutation::build_reorient_acceptance_update; use epiphany_codex_bridge::mutation::build_role_acceptance_update; use epiphany_codex_bridge::mutation::epiphany_job_launch_changed_fields; use epiphany_codex_bridge::mutation::epiphany_promote_changed_fields; +use epiphany_codex_bridge::mutation::epiphany_state_updated_notification; use epiphany_codex_bridge::mutation::epiphany_update_patch_changed_fields; use epiphany_codex_bridge::mutation::state_update_from_thread_patch; use epiphany_codex_bridge::mutation::thread_epiphany_patch_has_state_replacements; @@ -144,13 +145,13 @@ impl CodexMessageProcessor { .await; self.outgoing .send_server_notification(ServerNotification::ThreadEpiphanyStateUpdated( - ThreadEpiphanyStateUpdatedNotification { - thread_id: thread_uuid.to_string(), - source: ThreadEpiphanyStateUpdatedSource::JobLaunch, - revision: epiphany_state.revision, + epiphany_state_updated_notification( + thread_uuid.to_string(), + ThreadEpiphanyStateUpdatedSource::JobLaunch, + epiphany_state.revision, changed_fields, epiphany_state, - }, + ), )) .await; } @@ -306,13 +307,13 @@ impl CodexMessageProcessor { .await; self.outgoing .send_server_notification(ServerNotification::ThreadEpiphanyStateUpdated( - ThreadEpiphanyStateUpdatedNotification { - thread_id: thread_uuid.to_string(), - source: ThreadEpiphanyStateUpdatedSource::RoleAccept, - revision: epiphany_state.revision, + epiphany_state_updated_notification( + thread_uuid.to_string(), + ThreadEpiphanyStateUpdatedSource::RoleAccept, + epiphany_state.revision, changed_fields, epiphany_state, - }, + ), )) .await; } @@ -469,13 +470,13 @@ impl CodexMessageProcessor { .await; self.outgoing .send_server_notification(ServerNotification::ThreadEpiphanyStateUpdated( - ThreadEpiphanyStateUpdatedNotification { - thread_id: thread_uuid.to_string(), - source: ThreadEpiphanyStateUpdatedSource::JobLaunch, - revision: epiphany_state.revision, + epiphany_state_updated_notification( + thread_uuid.to_string(), + ThreadEpiphanyStateUpdatedSource::JobLaunch, + epiphany_state.revision, changed_fields, epiphany_state, - }, + ), )) .await; } @@ -631,13 +632,13 @@ impl CodexMessageProcessor { .await; self.outgoing .send_server_notification(ServerNotification::ThreadEpiphanyStateUpdated( - ThreadEpiphanyStateUpdatedNotification { - thread_id: thread_uuid.to_string(), - source: ThreadEpiphanyStateUpdatedSource::ReorientAccept, - revision: epiphany_state.revision, + epiphany_state_updated_notification( + thread_uuid.to_string(), + ThreadEpiphanyStateUpdatedSource::ReorientAccept, + epiphany_state.revision, changed_fields, epiphany_state, - }, + ), )) .await; } @@ -788,13 +789,13 @@ impl CodexMessageProcessor { self.outgoing.send_response(request_id, response).await; self.outgoing .send_server_notification(ServerNotification::ThreadEpiphanyStateUpdated( - ThreadEpiphanyStateUpdatedNotification { - thread_id: thread_uuid.to_string(), - source: ThreadEpiphanyStateUpdatedSource::Promote, - revision: epiphany_state.revision, + epiphany_state_updated_notification( + thread_uuid.to_string(), + ThreadEpiphanyStateUpdatedSource::Promote, + epiphany_state.revision, changed_fields, epiphany_state, - }, + ), )) .await; } @@ -859,13 +860,13 @@ impl CodexMessageProcessor { self.outgoing.send_response(request_id, response).await; self.outgoing .send_server_notification(ServerNotification::ThreadEpiphanyStateUpdated( - ThreadEpiphanyStateUpdatedNotification { - thread_id: thread_uuid.to_string(), - source: ThreadEpiphanyStateUpdatedSource::Update, - revision: epiphany_state.revision, + epiphany_state_updated_notification( + thread_uuid.to_string(), + ThreadEpiphanyStateUpdatedSource::Update, + epiphany_state.revision, changed_fields, epiphany_state, - }, + ), )) .await; } @@ -970,13 +971,13 @@ impl CodexMessageProcessor { .await; self.outgoing .send_server_notification(ServerNotification::ThreadEpiphanyStateUpdated( - ThreadEpiphanyStateUpdatedNotification { - thread_id: thread_uuid.to_string(), - source: ThreadEpiphanyStateUpdatedSource::JobLaunch, - revision: epiphany_state.revision, + epiphany_state_updated_notification( + thread_uuid.to_string(), + ThreadEpiphanyStateUpdatedSource::JobLaunch, + epiphany_state.revision, changed_fields, epiphany_state, - }, + ), )) .await; } @@ -1057,13 +1058,13 @@ impl CodexMessageProcessor { .await; self.outgoing .send_server_notification(ServerNotification::ThreadEpiphanyStateUpdated( - ThreadEpiphanyStateUpdatedNotification { - thread_id: thread_uuid.to_string(), - source: ThreadEpiphanyStateUpdatedSource::JobInterrupt, - revision: epiphany_state.revision, + epiphany_state_updated_notification( + thread_uuid.to_string(), + ThreadEpiphanyStateUpdatedSource::JobInterrupt, + epiphany_state.revision, changed_fields, epiphany_state, - }, + ), )) .await; }