diff --git a/epiphany-codex-bridge/src/lib.rs b/epiphany-codex-bridge/src/lib.rs index 8e701458..15e84a82 100644 --- a/epiphany-codex-bridge/src/lib.rs +++ b/epiphany-codex-bridge/src/lib.rs @@ -15,6 +15,7 @@ pub mod protocol_edge; pub mod reorient; pub mod results; pub mod retrieve; +pub mod retrieve_protocol; pub mod runtime_results; pub mod scene; pub mod scene_protocol; diff --git a/epiphany-codex-bridge/src/retrieve.rs b/epiphany-codex-bridge/src/retrieve.rs index 55446e0c..d7961848 100644 --- a/epiphany-codex-bridge/src/retrieve.rs +++ b/epiphany-codex-bridge/src/retrieve.rs @@ -1,14 +1,5 @@ -use codex_app_server_protocol::ThreadEpiphanyIndexResponse; -use codex_app_server_protocol::ThreadEpiphanyRetrieveIndexSummary; -use codex_app_server_protocol::ThreadEpiphanyRetrieveResponse; -use codex_app_server_protocol::ThreadEpiphanyRetrieveResult; -use codex_app_server_protocol::ThreadEpiphanyRetrieveResultKind; -use codex_app_server_protocol::ThreadEpiphanyRetrieveShardSummary; -use codex_utils_absolute_path::AbsolutePathBuf; use epiphany_core::EpiphanyRetrieveQuery; use epiphany_core::EpiphanyRetrieveResponse as CoreEpiphanyRetrieveResponse; -use epiphany_core::EpiphanyRetrieveResult as CoreEpiphanyRetrieveResult; -use epiphany_core::EpiphanyRetrieveResultKind as CoreEpiphanyRetrieveResultKind; use epiphany_core::index_workspace; use epiphany_core::normalize_epiphany_retrieve_query; use epiphany_core::retrieval_state_for_workspace; @@ -16,30 +7,12 @@ use epiphany_core::retrieve_workspace; use epiphany_state_model::EpiphanyRetrievalState; use std::path::PathBuf; -pub fn map_epiphany_retrieve_response( - response: CoreEpiphanyRetrieveResponse, -) -> anyhow::Result { - Ok(ThreadEpiphanyRetrieveResponse { - query: response.query, - index_summary: map_epiphany_retrieve_index_summary(response.index_summary)?, - results: response - .results - .into_iter() - .map(map_epiphany_retrieve_result) - .collect(), - }) -} - pub async fn index_epiphany_retrieval_for_paths( workspace_root: PathBuf, codex_home: PathBuf, force_full_rebuild: bool, -) -> anyhow::Result { - let index_summary = - index_epiphany_retrieval_state_for_paths(workspace_root, codex_home, force_full_rebuild) - .await - .and_then(map_epiphany_retrieve_index_summary)?; - Ok(ThreadEpiphanyIndexResponse { index_summary }) +) -> anyhow::Result { + index_epiphany_retrieval_state_for_paths(workspace_root, codex_home, force_full_rebuild).await } pub fn normalize_thread_epiphany_retrieve_query( @@ -88,55 +61,3 @@ pub async fn retrieve_epiphany_for_paths( .await .map_err(|err| anyhow::anyhow!("epiphany retrieval worker failed: {err}"))? } - -pub fn map_epiphany_retrieve_index_summary( - summary: EpiphanyRetrievalState, -) -> anyhow::Result { - Ok(ThreadEpiphanyRetrieveIndexSummary { - workspace_root: AbsolutePathBuf::from_absolute_path(summary.workspace_root) - .map_err(anyhow::Error::from)?, - index_revision: summary.index_revision, - status: summary.status, - semantic_available: summary.semantic_available, - last_indexed_at_unix_seconds: summary.last_indexed_at_unix_seconds, - indexed_file_count: summary.indexed_file_count, - indexed_chunk_count: summary.indexed_chunk_count, - shards: summary - .shards - .into_iter() - .map(|shard| ThreadEpiphanyRetrieveShardSummary { - shard_id: shard.shard_id, - path_prefix: shard.path_prefix, - indexed_file_count: shard.indexed_file_count, - indexed_chunk_count: shard.indexed_chunk_count, - status: shard.status, - exact_available: shard.exact_available, - semantic_available: shard.semantic_available, - }) - .collect(), - dirty_paths: summary.dirty_paths, - }) -} - -fn map_epiphany_retrieve_result( - result: CoreEpiphanyRetrieveResult, -) -> ThreadEpiphanyRetrieveResult { - ThreadEpiphanyRetrieveResult { - kind: match result.kind { - CoreEpiphanyRetrieveResultKind::ExactFile => { - ThreadEpiphanyRetrieveResultKind::ExactFile - } - CoreEpiphanyRetrieveResultKind::ExactDirectory => { - ThreadEpiphanyRetrieveResultKind::ExactDirectory - } - CoreEpiphanyRetrieveResultKind::SemanticChunk => { - ThreadEpiphanyRetrieveResultKind::SemanticChunk - } - }, - path: result.path, - score: result.score, - line_start: result.line_start, - line_end: result.line_end, - excerpt: result.excerpt, - } -} diff --git a/epiphany-codex-bridge/src/retrieve_protocol.rs b/epiphany-codex-bridge/src/retrieve_protocol.rs new file mode 100644 index 00000000..a23ca566 --- /dev/null +++ b/epiphany-codex-bridge/src/retrieve_protocol.rs @@ -0,0 +1,83 @@ +use codex_app_server_protocol::ThreadEpiphanyIndexResponse; +use codex_app_server_protocol::ThreadEpiphanyRetrieveIndexSummary; +use codex_app_server_protocol::ThreadEpiphanyRetrieveResponse; +use codex_app_server_protocol::ThreadEpiphanyRetrieveResult; +use codex_app_server_protocol::ThreadEpiphanyRetrieveResultKind; +use codex_app_server_protocol::ThreadEpiphanyRetrieveShardSummary; +use codex_utils_absolute_path::AbsolutePathBuf; +use epiphany_core::EpiphanyRetrieveResponse as CoreEpiphanyRetrieveResponse; +use epiphany_core::EpiphanyRetrieveResult as CoreEpiphanyRetrieveResult; +use epiphany_core::EpiphanyRetrieveResultKind as CoreEpiphanyRetrieveResultKind; +use epiphany_state_model::EpiphanyRetrievalState; + +pub fn protocol_retrieve_response( + response: CoreEpiphanyRetrieveResponse, +) -> anyhow::Result { + Ok(ThreadEpiphanyRetrieveResponse { + query: response.query, + index_summary: protocol_retrieve_index_summary(response.index_summary)?, + results: response + .results + .into_iter() + .map(protocol_retrieve_result) + .collect(), + }) +} + +pub fn protocol_index_response( + index_summary: EpiphanyRetrievalState, +) -> anyhow::Result { + Ok(ThreadEpiphanyIndexResponse { + index_summary: protocol_retrieve_index_summary(index_summary)?, + }) +} + +pub fn protocol_retrieve_index_summary( + summary: EpiphanyRetrievalState, +) -> anyhow::Result { + Ok(ThreadEpiphanyRetrieveIndexSummary { + workspace_root: AbsolutePathBuf::from_absolute_path(summary.workspace_root) + .map_err(anyhow::Error::from)?, + index_revision: summary.index_revision, + status: summary.status, + semantic_available: summary.semantic_available, + last_indexed_at_unix_seconds: summary.last_indexed_at_unix_seconds, + indexed_file_count: summary.indexed_file_count, + indexed_chunk_count: summary.indexed_chunk_count, + shards: summary + .shards + .into_iter() + .map(|shard| ThreadEpiphanyRetrieveShardSummary { + shard_id: shard.shard_id, + path_prefix: shard.path_prefix, + indexed_file_count: shard.indexed_file_count, + indexed_chunk_count: shard.indexed_chunk_count, + status: shard.status, + exact_available: shard.exact_available, + semantic_available: shard.semantic_available, + }) + .collect(), + dirty_paths: summary.dirty_paths, + }) +} + +fn protocol_retrieve_result(result: CoreEpiphanyRetrieveResult) -> ThreadEpiphanyRetrieveResult { + ThreadEpiphanyRetrieveResult { + kind: match result.kind { + CoreEpiphanyRetrieveResultKind::ExactFile => { + ThreadEpiphanyRetrieveResultKind::ExactFile + } + CoreEpiphanyRetrieveResultKind::ExactDirectory => { + ThreadEpiphanyRetrieveResultKind::ExactDirectory + } + CoreEpiphanyRetrieveResultKind::SemanticChunk => { + ThreadEpiphanyRetrieveResultKind::SemanticChunk + } + }, + path: result.path, + score: result.score, + line_start: result.line_start, + line_end: result.line_end, + excerpt: result.excerpt, + } +} diff --git a/notes/fresh-workspace-handoff.md b/notes/fresh-workspace-handoff.md index 297f6c39..fe8995f9 100644 --- a/notes/fresh-workspace-handoff.md +++ b/notes/fresh-workspace-handoff.md @@ -90,6 +90,7 @@ remembers doctrine; the branch remembers the blade. - Coordinator projection is split out too. `coordinator.rs` no longer imports app-server protocol DTOs; it owns typed coordinator status, CRRC input shaping, role-board derivation, automation verdict selection, and note rendering. `coordinator_protocol.rs` owns Codex JSON-RPC projection for coordinator, CRRC, and role-board response payloads. - Context/planning/graph projection is split out too. `context.rs` returns typed `epiphany-core` view documents; `context_protocol.rs` owns Codex JSON-RPC tuple/projection cargo for context, planning, and graph-query responses. - Scene projection is split out too. `scene.rs` returns the typed core `EpiphanyScene`; `scene_protocol.rs` owns `ThreadEpiphanyScene` and scene-action response projection. +- Retrieval projection is split out too. `retrieve.rs` normalizes, indexes, looks up state, and retrieves typed core results; `retrieve_protocol.rs` owns Codex JSON-RPC retrieve/index response projection and absolute-path DTO validation. - 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 3a05b5f1..64f5c4b7 100644 Binary files a/state/ledgers.msgpack and b/state/ledgers.msgpack differ diff --git a/state/map.yaml b/state/map.yaml index 05ffa377..7be5f5be 100644 --- a/state/map.yaml +++ b/state/map.yaml @@ -439,6 +439,10 @@ current_status: Scene derivation follows that boundary too: `scene.rs` now returns the typed core `EpiphanyScene`, and `scene_protocol.rs` owns projection into `ThreadEpiphanyScene` plus scene-action DTOs for view responses. + Retrieval follows the boundary too: `retrieve.rs` executes normalization, + indexing, state lookup, and typed retrieval responses; `retrieve_protocol.rs` + owns Codex JSON-RPC retrieve/index response projection and absolute-path DTO + validation. The bridge still depends on vendored Codex for app-server protocol DTOs and absolute path validation, so the purification is not done. next_action: Continue Codex starvation and CultNet liberation by cutting bridge-internal response/projection authority. Prioritize the next coordinator/view seam that still composes policy-shaped facts instead of merely loading host facts and projecting core surfaces; keep MCP/OpenAI JSON only at their true protocol/text edges. Do not add compatibility adapters unless they protect a named ownership invariant. 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 8ecfaf55..e79285ad 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 @@ -32,6 +32,7 @@ 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; @@ -440,6 +441,7 @@ impl CodexMessageProcessor { force_full_rebuild, ) .await + .and_then(protocol_index_response) { Ok(response) => response, Err(err) => { 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 30740361..0f202885 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 @@ -18,9 +18,9 @@ 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::map_epiphany_retrieve_response; 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::EpiphanyFreshnessResponseInput; use epiphany_codex_bridge::view::EpiphanyReorientResultResponseInput; use epiphany_codex_bridge::view::EpiphanyRoleResultResponseInput; @@ -460,7 +460,7 @@ impl CodexMessageProcessor { let response = match retrieve_epiphany_for_paths(config.cwd.to_path_buf(), codex_home, query) .await - .and_then(map_epiphany_retrieve_response) + .and_then(protocol_retrieve_response) { Ok(response) => response, Err(err) => {