From c45cd1bf468010d883f81637bf04cc6dc00c4f56 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Tue, 19 May 2026 21:51:42 +0100 Subject: [PATCH] Keep coordinator decisions core-shaped --- epiphany-codex-bridge/src/coordinator.rs | 271 +++++++++++++--------- epiphany-codex-bridge/src/view.rs | 41 ++-- epiphany-core/src/surfaces/coordinator.rs | 32 ++- epiphany-core/src/surfaces/crrc.rs | 21 +- notes/fresh-workspace-handoff.md | 1 + state/ledgers.msgpack | Bin 133627 -> 133989 bytes state/map.yaml | 2 +- 7 files changed, 216 insertions(+), 152 deletions(-) diff --git a/epiphany-codex-bridge/src/coordinator.rs b/epiphany-codex-bridge/src/coordinator.rs index cf21ae90..c53f84f0 100644 --- a/epiphany-codex-bridge/src/coordinator.rs +++ b/epiphany-codex-bridge/src/coordinator.rs @@ -38,6 +38,7 @@ use epiphany_core::EpiphanyCrrcResultStatus as CoreEpiphanyCrrcResultStatus; use epiphany_core::EpiphanyCrrcSceneAction as CoreEpiphanyCrrcSceneAction; use epiphany_core::EpiphanyCrrcStateStatus as CoreEpiphanyCrrcStateStatus; use epiphany_core::EpiphanyJobLaunchRequest; +use epiphany_core::EpiphanyReorientAction as CoreEpiphanyReorientAction; use epiphany_core::EpiphanyRoleBoardCheckpointSummary; use epiphany_core::EpiphanyRoleBoardInput; use epiphany_core::EpiphanyRoleBoardJob; @@ -80,7 +81,7 @@ use std::path::Path; pub fn map_epiphany_crrc_recommendation( loaded: bool, state_status: ThreadEpiphanyReorientStateStatus, - pressure: &ThreadEpiphanyPressure, + pressure: &epiphany_core::EpiphanyPressure, decision: &ThreadEpiphanyReorientDecision, result_status: ThreadEpiphanyReorientResultStatus, checkpoint_present: bool, @@ -117,6 +118,15 @@ fn map_core_crrc_reorient_action( } } +fn map_core_reorient_action_from_protocol( + action: ThreadEpiphanyReorientAction, +) -> CoreEpiphanyReorientAction { + match action { + ThreadEpiphanyReorientAction::Resume => CoreEpiphanyReorientAction::Resume, + ThreadEpiphanyReorientAction::Regather => CoreEpiphanyReorientAction::Regather, + } +} + fn map_core_crrc_result_status( status: ThreadEpiphanyReorientResultStatus, ) -> CoreEpiphanyCrrcResultStatus { @@ -141,6 +151,79 @@ fn map_core_crrc_result_status( } } +fn map_protocol_coordinator_source_signals( + signals: EpiphanyCoordinatorSourceSignals, +) -> ThreadEpiphanyCoordinatorSignals { + ThreadEpiphanyCoordinatorSignals { + pressure_level: map_protocol_pressure_level(signals.pressure_level), + should_prepare_compaction: signals.should_prepare_compaction, + reorient_action: map_protocol_reorient_action(signals.reorient_action), + crrc_action: map_core_crrc_action(signals.crrc_action), + modeling_result_status: map_protocol_coordinator_role_result_status( + signals.modeling_result_status, + ), + verification_result_status: map_protocol_coordinator_role_result_status( + signals.verification_result_status, + ), + reorient_result_status: map_protocol_crrc_result_status(signals.reorient_result_status), + } +} + +fn map_protocol_pressure_level( + level: epiphany_core::EpiphanyPressureLevel, +) -> codex_app_server_protocol::ThreadEpiphanyPressureLevel { + match level { + epiphany_core::EpiphanyPressureLevel::Unknown => { + codex_app_server_protocol::ThreadEpiphanyPressureLevel::Unknown + } + epiphany_core::EpiphanyPressureLevel::Low => { + codex_app_server_protocol::ThreadEpiphanyPressureLevel::Low + } + epiphany_core::EpiphanyPressureLevel::Elevated => { + codex_app_server_protocol::ThreadEpiphanyPressureLevel::Elevated + } + epiphany_core::EpiphanyPressureLevel::High => { + codex_app_server_protocol::ThreadEpiphanyPressureLevel::High + } + epiphany_core::EpiphanyPressureLevel::Critical => { + codex_app_server_protocol::ThreadEpiphanyPressureLevel::Critical + } + } +} + +fn map_protocol_reorient_action( + action: CoreEpiphanyReorientAction, +) -> ThreadEpiphanyReorientAction { + match action { + CoreEpiphanyReorientAction::Resume => ThreadEpiphanyReorientAction::Resume, + CoreEpiphanyReorientAction::Regather => ThreadEpiphanyReorientAction::Regather, + } +} + +fn map_protocol_crrc_result_status( + status: CoreEpiphanyCrrcResultStatus, +) -> ThreadEpiphanyReorientResultStatus { + match status { + CoreEpiphanyCrrcResultStatus::MissingState => { + ThreadEpiphanyReorientResultStatus::MissingState + } + CoreEpiphanyCrrcResultStatus::MissingBinding => { + ThreadEpiphanyReorientResultStatus::MissingBinding + } + CoreEpiphanyCrrcResultStatus::BackendUnavailable => { + ThreadEpiphanyReorientResultStatus::BackendUnavailable + } + CoreEpiphanyCrrcResultStatus::BackendMissing => { + ThreadEpiphanyReorientResultStatus::BackendMissing + } + CoreEpiphanyCrrcResultStatus::Pending => ThreadEpiphanyReorientResultStatus::Pending, + CoreEpiphanyCrrcResultStatus::Running => ThreadEpiphanyReorientResultStatus::Running, + CoreEpiphanyCrrcResultStatus::Completed => ThreadEpiphanyReorientResultStatus::Completed, + CoreEpiphanyCrrcResultStatus::Failed => ThreadEpiphanyReorientResultStatus::Failed, + CoreEpiphanyCrrcResultStatus::Cancelled => ThreadEpiphanyReorientResultStatus::Cancelled, + } +} + fn map_core_crrc_action(action: CoreEpiphanyCrrcAction) -> ThreadEpiphanyCrrcAction { match action { CoreEpiphanyCrrcAction::Continue => ThreadEpiphanyCrrcAction::Continue, @@ -183,18 +266,21 @@ fn map_core_crrc_recommendation( } } -pub struct EpiphanyCoordinatorDecision { - pub action: ThreadEpiphanyCoordinatorAction, - pub target_role: Option, - pub recommended_scene_action: Option, - pub requires_review: bool, - pub can_auto_run: bool, - pub reason: String, +pub type EpiphanyCoordinatorDecision = CoreEpiphanyCoordinatorDecision; + +pub struct EpiphanyCoordinatorSourceSignals { + pub pressure_level: epiphany_core::EpiphanyPressureLevel, + pub should_prepare_compaction: bool, + pub reorient_action: CoreEpiphanyReorientAction, + pub crrc_action: CoreEpiphanyCrrcAction, + pub modeling_result_status: CoreEpiphanyCoordinatorRoleResultStatus, + pub verification_result_status: CoreEpiphanyCoordinatorRoleResultStatus, + pub reorient_result_status: CoreEpiphanyCrrcResultStatus, } pub struct EpiphanyCoordinatorStatus { pub decision: EpiphanyCoordinatorDecision, - pub source_signals: ThreadEpiphanyCoordinatorSignals, + pub source_signals: EpiphanyCoordinatorSourceSignals, pub roles: Vec, pub note: String, pub modeling_result_accepted: bool, @@ -206,7 +292,7 @@ pub async fn derive_epiphany_coordinator_status( state: Option<&EpiphanyThreadState>, runtime_store_path: Option<&Path>, state_status: ThreadEpiphanyReorientStateStatus, - pressure: &ThreadEpiphanyPressure, + pressure: &epiphany_core::EpiphanyPressure, recommendation: &ThreadEpiphanyCrrcRecommendation, roles: Vec, reorient_decision: Option<&ThreadEpiphanyReorientDecision>, @@ -285,16 +371,19 @@ pub async fn derive_epiphany_coordinator_status( let reorient_finding_accepted = reorient_finding.is_some_and(|finding| { state.is_some_and(|state| epiphany_reorient_finding_already_accepted(state, finding)) }); - let source_signals = ThreadEpiphanyCoordinatorSignals { + let source_signals = EpiphanyCoordinatorSourceSignals { pressure_level: pressure.level, should_prepare_compaction: pressure.should_prepare_compaction, reorient_action: reorient_decision .map(|decision| decision.action) - .unwrap_or(ThreadEpiphanyReorientAction::Resume), - crrc_action: recommendation.action, - modeling_result_status, - verification_result_status, - reorient_result_status, + .map(map_core_reorient_action_from_protocol) + .unwrap_or(CoreEpiphanyReorientAction::Resume), + crrc_action: map_core_crrc_action_from_protocol(recommendation.action), + modeling_result_status: map_core_coordinator_role_result_status(modeling_result_status), + verification_result_status: map_core_coordinator_role_result_status( + verification_result_status, + ), + reorient_result_status: map_core_crrc_result_status(reorient_result_status), }; let decision = map_epiphany_coordinator( state_status, @@ -316,11 +405,11 @@ pub async fn derive_epiphany_coordinator_status( ); let note = render_epiphany_coordinator_note( recommendation.action, - pressure.level, + map_protocol_pressure_level(pressure.level), modeling_result_status, verification_result_status, reorient_result_status, - decision.action, + map_protocol_coordinator_action(decision.action), ); EpiphanyCoordinatorStatus { @@ -350,13 +439,19 @@ pub fn map_epiphany_coordinator_view( }, state_status, state_revision, - action: status.decision.action, - target_role: status.decision.target_role, - recommended_scene_action: status.decision.recommended_scene_action, + action: map_protocol_coordinator_action(status.decision.action), + target_role: status + .decision + .target_role + .map(map_protocol_coordinator_role_id), + recommended_scene_action: status + .decision + .recommended_scene_action + .map(map_protocol_coordinator_scene_action), requires_review: status.decision.requires_review, can_auto_run: status.decision.can_auto_run, reason: status.decision.reason, - source_signals: status.source_signals, + source_signals: map_protocol_coordinator_source_signals(status.source_signals), roles: status.roles, note: status.note, } @@ -372,9 +467,7 @@ pub enum EpiphanyCoordinatorAutomationAction { pub fn map_epiphany_coordinator_automation_action( decision: &EpiphanyCoordinatorDecision, ) -> EpiphanyCoordinatorAutomationAction { - map_protocol_coordinator_automation_action(coordinator_automation_action( - &map_core_coordinator_decision_from_protocol(decision), - )) + map_protocol_coordinator_automation_action(coordinator_automation_action(decision)) } pub fn select_epiphany_coordinator_automation_action( @@ -382,7 +475,7 @@ pub fn select_epiphany_coordinator_automation_action( force_checkpoint_compaction: bool, ) -> EpiphanyCoordinatorAutomationAction { map_protocol_coordinator_automation_action(select_coordinator_automation_action( - &map_core_coordinator_decision_from_protocol(decision), + decision, force_checkpoint_compaction, )) } @@ -450,7 +543,7 @@ pub async fn select_epiphany_coordinator_automation( let crrc_recommendation = map_epiphany_crrc_recommendation( true, state_status, - &pressure, + &core_pressure, &reorient_decision, reorient_result_status, input.state.investigation_checkpoint.as_ref().is_some(), @@ -470,7 +563,7 @@ pub async fn select_epiphany_coordinator_automation( Some(input.state), Some(input.runtime_store_path), state_status, - &pressure, + &core_pressure, &crrc_recommendation, roles, Some(&reorient_decision), @@ -521,10 +614,10 @@ pub async fn select_epiphany_coordinator_automation( pub fn map_epiphany_coordinator( state_status: ThreadEpiphanyReorientStateStatus, checkpoint_present: bool, - pressure: &ThreadEpiphanyPressure, + pressure: &epiphany_core::EpiphanyPressure, recommendation: &ThreadEpiphanyCrrcRecommendation, roles: &[ThreadEpiphanyRoleLane], - signals: &ThreadEpiphanyCoordinatorSignals, + signals: &EpiphanyCoordinatorSourceSignals, modeling_result_accepted: bool, modeling_result_reviewable: bool, modeling_result_accepted_after_verification: bool, @@ -536,19 +629,15 @@ pub fn map_epiphany_coordinator( verification_result_needs_evidence: bool, reorient_finding_accepted: bool, ) -> EpiphanyCoordinatorDecision { - map_core_coordinator_decision(recommend_coordinator_action(EpiphanyCoordinatorInput { + recommend_coordinator_action(EpiphanyCoordinatorInput { state_status: map_core_crrc_state_status(state_status), checkpoint_present, should_prepare_compaction: pressure.should_prepare_compaction, recommendation: map_core_coordinator_crrc_recommendation(recommendation), roles: roles.iter().map(map_core_coordinator_role_lane).collect(), signals: EpiphanyCoordinatorSignals { - modeling_result_status: map_core_coordinator_role_result_status( - signals.modeling_result_status, - ), - verification_result_status: map_core_coordinator_role_result_status( - signals.verification_result_status, - ), + modeling_result_status: signals.modeling_result_status, + verification_result_status: signals.verification_result_status, }, modeling_result_accepted, modeling_result_reviewable, @@ -560,7 +649,7 @@ pub fn map_epiphany_coordinator( verification_result_allows_implementation, verification_result_needs_evidence, reorient_finding_accepted, - })) + }) } fn map_core_coordinator_crrc_recommendation( @@ -625,12 +714,6 @@ fn map_protocol_coordinator_role_id( } } -fn map_core_coordinator_role_id_from_protocol( - role_id: ThreadEpiphanyRoleId, -) -> CoreEpiphanyCoordinatorRoleId { - map_core_coordinator_role_id(role_id) -} - fn map_core_coordinator_role_status( status: ThreadEpiphanyRoleStatus, ) -> CoreEpiphanyCoordinatorRoleStatus { @@ -674,6 +757,34 @@ fn map_core_coordinator_role_result_status( } } +fn map_protocol_coordinator_role_result_status( + status: CoreEpiphanyCoordinatorRoleResultStatus, +) -> ThreadEpiphanyRoleResultStatus { + match status { + CoreEpiphanyCoordinatorRoleResultStatus::MissingState => { + ThreadEpiphanyRoleResultStatus::MissingState + } + CoreEpiphanyCoordinatorRoleResultStatus::MissingBinding => { + ThreadEpiphanyRoleResultStatus::MissingBinding + } + CoreEpiphanyCoordinatorRoleResultStatus::BackendUnavailable => { + ThreadEpiphanyRoleResultStatus::BackendUnavailable + } + CoreEpiphanyCoordinatorRoleResultStatus::BackendMissing => { + ThreadEpiphanyRoleResultStatus::BackendMissing + } + CoreEpiphanyCoordinatorRoleResultStatus::Pending => ThreadEpiphanyRoleResultStatus::Pending, + CoreEpiphanyCoordinatorRoleResultStatus::Running => ThreadEpiphanyRoleResultStatus::Running, + CoreEpiphanyCoordinatorRoleResultStatus::Completed => { + ThreadEpiphanyRoleResultStatus::Completed + } + CoreEpiphanyCoordinatorRoleResultStatus::Failed => ThreadEpiphanyRoleResultStatus::Failed, + CoreEpiphanyCoordinatorRoleResultStatus::Cancelled => { + ThreadEpiphanyRoleResultStatus::Cancelled + } + } +} + fn map_core_coordinator_scene_action_from_protocol( action: ThreadEpiphanySceneAction, ) -> CoreEpiphanyCoordinatorSceneAction { @@ -733,46 +844,6 @@ fn map_protocol_coordinator_scene_action( } } -fn map_core_coordinator_action_from_protocol( - action: ThreadEpiphanyCoordinatorAction, -) -> CoreEpiphanyCoordinatorAction { - match action { - ThreadEpiphanyCoordinatorAction::PrepareCheckpoint => { - CoreEpiphanyCoordinatorAction::PrepareCheckpoint - } - ThreadEpiphanyCoordinatorAction::CompactRehydrateReorient => { - CoreEpiphanyCoordinatorAction::CompactRehydrateReorient - } - ThreadEpiphanyCoordinatorAction::LaunchReorientWorker => { - CoreEpiphanyCoordinatorAction::LaunchReorientWorker - } - ThreadEpiphanyCoordinatorAction::WaitForReorientWorker => { - CoreEpiphanyCoordinatorAction::WaitForReorientWorker - } - ThreadEpiphanyCoordinatorAction::ReviewReorientResult => { - CoreEpiphanyCoordinatorAction::ReviewReorientResult - } - ThreadEpiphanyCoordinatorAction::RegatherManually => { - CoreEpiphanyCoordinatorAction::RegatherManually - } - ThreadEpiphanyCoordinatorAction::LaunchModeling => { - CoreEpiphanyCoordinatorAction::LaunchModeling - } - ThreadEpiphanyCoordinatorAction::ReviewModelingResult => { - CoreEpiphanyCoordinatorAction::ReviewModelingResult - } - ThreadEpiphanyCoordinatorAction::LaunchVerification => { - CoreEpiphanyCoordinatorAction::LaunchVerification - } - ThreadEpiphanyCoordinatorAction::ReviewVerificationResult => { - CoreEpiphanyCoordinatorAction::ReviewVerificationResult - } - ThreadEpiphanyCoordinatorAction::ContinueImplementation => { - CoreEpiphanyCoordinatorAction::ContinueImplementation - } - } -} - fn map_protocol_coordinator_action( action: CoreEpiphanyCoordinatorAction, ) -> ThreadEpiphanyCoordinatorAction { @@ -813,38 +884,6 @@ fn map_protocol_coordinator_action( } } -fn map_core_coordinator_decision_from_protocol( - decision: &EpiphanyCoordinatorDecision, -) -> CoreEpiphanyCoordinatorDecision { - CoreEpiphanyCoordinatorDecision { - action: map_core_coordinator_action_from_protocol(decision.action), - target_role: decision - .target_role - .map(map_core_coordinator_role_id_from_protocol), - recommended_scene_action: decision - .recommended_scene_action - .map(map_core_coordinator_scene_action_from_protocol), - requires_review: decision.requires_review, - can_auto_run: decision.can_auto_run, - reason: decision.reason.clone(), - } -} - -fn map_core_coordinator_decision( - decision: CoreEpiphanyCoordinatorDecision, -) -> EpiphanyCoordinatorDecision { - EpiphanyCoordinatorDecision { - action: map_protocol_coordinator_action(decision.action), - target_role: decision.target_role.map(map_protocol_coordinator_role_id), - recommended_scene_action: decision - .recommended_scene_action - .map(map_protocol_coordinator_scene_action), - requires_review: decision.requires_review, - can_auto_run: decision.can_auto_run, - reason: decision.reason, - } -} - fn map_protocol_coordinator_automation_action( action: CoreEpiphanyCoordinatorAutomationAction, ) -> EpiphanyCoordinatorAutomationAction { diff --git a/epiphany-codex-bridge/src/view.rs b/epiphany-codex-bridge/src/view.rs index 7d2dc268..57938419 100644 --- a/epiphany-codex-bridge/src/view.rs +++ b/epiphany-codex-bridge/src/view.rs @@ -228,21 +228,22 @@ pub async fn map_epiphany_view_response( let reorient_finding_accepted = reorient_finding.as_ref().is_some_and(|finding| { state.is_some_and(|state| epiphany_reorient_finding_already_accepted(state, finding)) }); - let recommendation = - if let (Some(pressure), Some(decision)) = (pressure.as_ref(), reorient_decision.as_ref()) { - Some(map_epiphany_crrc_recommendation( - loaded, - reorient_state_status, - pressure, - decision, - reorient_result_status, - checkpoint_present, - reorient_finding.is_some(), - reorient_finding_accepted, - )) - } else { - None - }; + let recommendation = if let (Some(core_pressure), Some(decision)) = + (core_pressure.as_ref(), reorient_decision.as_ref()) + { + Some(map_epiphany_crrc_recommendation( + loaded, + reorient_state_status, + core_pressure, + decision, + reorient_result_status, + checkpoint_present, + reorient_finding.is_some(), + reorient_finding_accepted, + )) + } else { + None + }; let roles = if let (Some(pressure), Some(decision), Some(recommendation)) = ( pressure.as_ref(), reorient_decision.as_ref(), @@ -261,14 +262,16 @@ pub async fn map_epiphany_view_response( None }; let coordinator_response = if lenses.contains(&ThreadEpiphanyViewLens::Coordinator) { - if let (Some(pressure), Some(recommendation), Some(roles)) = - (pressure.as_ref(), recommendation.as_ref(), roles.clone()) - { + if let (Some(core_pressure), Some(recommendation), Some(roles)) = ( + core_pressure.as_ref(), + recommendation.as_ref(), + roles.clone(), + ) { let status = derive_epiphany_coordinator_status( state, runtime_store_path, reorient_state_status, - pressure, + core_pressure, recommendation, roles, reorient_decision.as_ref(), diff --git a/epiphany-core/src/surfaces/coordinator.rs b/epiphany-core/src/surfaces/coordinator.rs index b0479823..53dc9ba2 100644 --- a/epiphany-core/src/surfaces/coordinator.rs +++ b/epiphany-core/src/surfaces/coordinator.rs @@ -1,8 +1,11 @@ use super::EpiphanyCrrcAction; use super::EpiphanyCrrcSceneAction; use super::EpiphanyCrrcStateStatus; +use serde::Deserialize; +use serde::Serialize; -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] pub enum EpiphanyCoordinatorRoleId { Implementation, Imagination, @@ -11,7 +14,8 @@ pub enum EpiphanyCoordinatorRoleId { Reorientation, } -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] pub enum EpiphanyCoordinatorRoleStatus { Ready, Needed, @@ -23,7 +27,8 @@ pub enum EpiphanyCoordinatorRoleStatus { Completed, } -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] pub enum EpiphanyCoordinatorRoleResultStatus { MissingState, MissingBinding, @@ -36,7 +41,8 @@ pub enum EpiphanyCoordinatorRoleResultStatus { Cancelled, } -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] pub enum EpiphanyCoordinatorAction { PrepareCheckpoint, CompactRehydrateReorient, @@ -51,7 +57,8 @@ pub enum EpiphanyCoordinatorAction { ContinueImplementation, } -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] pub enum EpiphanyCoordinatorSceneAction { Update, Reorient, @@ -62,26 +69,30 @@ pub enum EpiphanyCoordinatorSceneAction { RoleResult, } -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] pub enum EpiphanyCoordinatorAutomationAction { None, CompactRehydrateReorient, LaunchReorientWorker, } -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] pub struct EpiphanyCoordinatorCrrcRecommendation { pub action: EpiphanyCrrcAction, pub recommended_scene_action: Option, } -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] pub struct EpiphanyCoordinatorSignals { pub modeling_result_status: EpiphanyCoordinatorRoleResultStatus, pub verification_result_status: EpiphanyCoordinatorRoleResultStatus, } -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] pub struct EpiphanyCoordinatorRoleLane { pub id: EpiphanyCoordinatorRoleId, pub status: EpiphanyCoordinatorRoleStatus, @@ -107,7 +118,8 @@ pub struct EpiphanyCoordinatorInput { pub reorient_finding_accepted: bool, } -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] pub struct EpiphanyCoordinatorDecision { pub action: EpiphanyCoordinatorAction, pub target_role: Option, diff --git a/epiphany-core/src/surfaces/crrc.rs b/epiphany-core/src/surfaces/crrc.rs index ca9b91ff..528c5110 100644 --- a/epiphany-core/src/surfaces/crrc.rs +++ b/epiphany-core/src/surfaces/crrc.rs @@ -1,16 +1,22 @@ -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +use serde::Deserialize; +use serde::Serialize; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] pub enum EpiphanyCrrcStateStatus { Missing, Ready, } -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] pub enum EpiphanyCrrcReorientAction { Resume, Regather, } -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] pub enum EpiphanyCrrcResultStatus { MissingState, MissingBinding, @@ -23,7 +29,8 @@ pub enum EpiphanyCrrcResultStatus { Cancelled, } -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] pub enum EpiphanyCrrcAction { Continue, PrepareCheckpoint, @@ -34,7 +41,8 @@ pub enum EpiphanyCrrcAction { RegatherManually, } -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] pub enum EpiphanyCrrcSceneAction { Update, Reorient, @@ -43,7 +51,8 @@ pub enum EpiphanyCrrcSceneAction { ReorientAccept, } -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] pub struct EpiphanyCrrcRecommendation { pub action: EpiphanyCrrcAction, pub recommended_scene_action: Option, diff --git a/notes/fresh-workspace-handoff.md b/notes/fresh-workspace-handoff.md index 7f886445..9ce1323e 100644 --- a/notes/fresh-workspace-handoff.md +++ b/notes/fresh-workspace-handoff.md @@ -48,6 +48,7 @@ remembers doctrine; the branch remembers the blade. - `epiphany-codex-bridge` no longer depends on vendored `codex-core` at all. Retrieval takes workspace/Codex-home paths, invalidation owns a native `notify` watcher, runtime-result acceptance takes typed state plus runtime-store path, live rollout/thread reads moved into app-server `epiphany_thread_host`, and mutation policy depends on the small `EpiphanyMutationHost` trait implemented by app-server's `EpiphanyCodexThreadHost` wrapper. The bridge owns Epiphany law; vendored app-server owns CodexThread access. - `epiphany-codex-bridge` also no longer depends on `codex-protocol`. Bridge durable-state imports point at `epiphany-state-model`, token pressure takes native `EpiphanyTokenUsageSnapshot`, app-server maps Codex token telemetry at the host wall, Codex token usage rollout replay lives in `codex_message_processor/token_usage_replay.rs`, and bridge errors are `EpiphanyBridgeError`. The only remaining vendored bridge dependencies are app-server protocol DTOs and absolute path validation. - The first bridge JSON-RPC starvation cuts are landed. Freshness now returns a serializable `EpiphanyFreshnessSurface`, job launch/interrupt mutation results carry typed `EpiphanyJobView` plus separate host-edge launcher/backend ids, reorient/pre-compaction decisions consume typed `EpiphanyPressure`, reorient policy consumes typed freshness directly, and reorient launch documents/results use typed core reorient decisions/status before app-server projects them into legacy JSON-RPC DTOs. Continue by cutting the full view/coordinator board into typed surfaces, not by inventing adapters with nicer uniforms. +- Coordinator decision/status is less contaminated now: `epiphany-codex-bridge` stores coordinator decisions and source signals as core-shaped types, core CRRC/coordinator surfaces serialize natively, and `ThreadEpiphany*` projection happens at the legacy view emission boundary. Keep cutting remaining role-board/result/reorient inputs until Aquarium/CultNet can read coordinator surfaces without JSON-RPC DTO authority. - MCP remains JSON because MCP is a JSON protocol. The latest processor cut only moved MCP refresh/OAuth/status/resource/tool-call route handling into `codex_message_processor/mcp_routes.rs`, reducing the root processor to about 8,977 lines; it did not claim MCP payloads are CultNet or make MCP an Epiphany-owned runtime contract. - Codex account auth route handling remains in vendored Codex but now lives in `codex_message_processor/auth_routes.rs`: API-key login, ChatGPT browser/device-code/external-token login, logout, auth status, account, rate limits, and add-credits nudge handling. This preserves Codex ownership of subscription auth while cutting the root processor to about 8,094 lines. - One-off command execution and command stream write/resize/terminate route handling now live in `codex_message_processor/command_routes.rs`; `CommandExecManager` remains the lifecycle owner, while the root processor is about 7,800 lines. diff --git a/state/ledgers.msgpack b/state/ledgers.msgpack index 6185d7529dca1b41635f58829eb47991e694da9b..59f383af7b13045ce0ce0ecbec09e1a7bea906ed 100644 GIT binary patch delta 325 zcmZvYy-LGS6vw%piq2IOhXdjyH8E(>xCpU07D^_!ONIyA$H!sTR+*5TCW^jJmzoufPumegC+B zcp3+Ocyto_gZVPv-U%aPY@#$eV}Tvo5}h&{sjEcH3Xf)YTTfYDh6IW}^aQVz~QoLa(USg0aJUBN{>Vn7EOO;A=)Dw+Z1 zid*+HkbdI_(RdtrtMNRwHz