Move prompt renderer to state model

This commit is contained in:
Meta Vens 2026-05-19 09:40:48 +01:00
commit d510f39b4c
14 changed files with 69 additions and 64 deletions

View file

@ -3,7 +3,6 @@ mod distillation;
mod heartbeat_state;
mod memory_graph;
mod promotion;
mod prompt;
mod proposal;
mod retrieval;
mod runtime_spine;
@ -53,6 +52,7 @@ pub use epiphany_state_model::EpiphanyMemoryNode;
pub use epiphany_state_model::EpiphanyMemoryProfile;
pub use epiphany_state_model::EpiphanyMemorySummary;
pub use epiphany_state_model::EpiphanyThreadState;
pub use epiphany_state_model::render_epiphany_state;
pub use heartbeat_state::EpiphanyHeartbeatCognitionEntry;
pub use heartbeat_state::EpiphanyHeartbeatStateEntry;
pub use heartbeat_state::GhostlightSceneParticipantSeed;
@ -124,7 +124,6 @@ pub use promotion::EpiphanyPromotionInput;
pub use promotion::EpiphanyStateReplacementValidationInput;
pub use promotion::evaluate_promotion;
pub use promotion::validate_state_replacement_patch;
pub use prompt::render_epiphany_state;
pub use proposal::EpiphanyMapProposal;
pub use proposal::EpiphanyMapProposalInput;
pub use proposal::propose_map_update;

View file

@ -1143,7 +1143,7 @@ mod tests {
summary: "The prompt renderer injects Epiphany state".to_string(),
source_kind: "verification".to_string(),
status: status.to_string(),
code_refs: vec![code_ref("epiphany-core/src/prompt.rs")],
code_refs: vec![code_ref("epiphany-state-model/src/prompt.rs")],
evidence_ids: vec!["ev-verified".to_string()],
}],
recent_evidence: vec![EpiphanyEvidenceRecord {
@ -1151,7 +1151,7 @@ mod tests {
kind: "verification".to_string(),
status: "ok".to_string(),
summary: "Verified prompt renderer behavior".to_string(),
code_refs: vec![code_ref("epiphany-core/src/prompt.rs")],
code_refs: vec![code_ref("epiphany-state-model/src/prompt.rs")],
}],
churn: Some(EpiphanyChurnState {
understanding_status: "grounded".to_string(),
@ -1197,11 +1197,11 @@ mod tests {
title: "Prompt renderer".to_string(),
purpose: "Render Epiphany state into developer context".to_string(),
status: Some("grounded".to_string()),
code_refs: vec![code_ref("epiphany-core/src/prompt.rs")],
code_refs: vec![code_ref("epiphany-state-model/src/prompt.rs")],
..Default::default()
});
state.observations[0].code_refs.push(EpiphanyCodeRef {
path: PathBuf::from("epiphany-core/src/prompt.rs"),
path: PathBuf::from("epiphany-state-model/src/prompt.rs"),
start_line: Some(30),
end_line: Some(40),
symbol: Some("render_epiphany_state".to_string()),
@ -1233,7 +1233,7 @@ mod tests {
#[test]
fn propose_map_update_reuses_existing_deterministic_path_node_without_refs() {
let mut state = state_with_observation("verified");
let node_id = graph_node_id(Path::new("epiphany-core/src/prompt.rs"));
let node_id = graph_node_id(Path::new("epiphany-state-model/src/prompt.rs"));
state.graphs.architecture.nodes.push(EpiphanyGraphNode {
id: node_id.clone(),
title: "Prompt path".to_string(),
@ -1299,7 +1299,7 @@ mod tests {
id: "prompt-renderer".to_string(),
title: "Prompt renderer".to_string(),
purpose: "Render Epiphany state into developer context".to_string(),
code_refs: vec![code_ref("epiphany-core/src/prompt.rs")],
code_refs: vec![code_ref("epiphany-state-model/src/prompt.rs")],
..Default::default()
});
@ -1337,7 +1337,7 @@ mod tests {
title: "Prompt renderer".to_string(),
purpose: "Render Epiphany state into developer context".to_string(),
code_refs: vec![EpiphanyCodeRef {
path: PathBuf::from("epiphany-core/src/prompt.rs"),
path: PathBuf::from("epiphany-state-model/src/prompt.rs"),
start_line: Some(100),
end_line: Some(120),
symbol: Some("render_graphs".to_string()),
@ -1412,7 +1412,7 @@ mod tests {
summary: "Live smoke verified prompt renderer Epiphany state injection".to_string(),
source_kind: "smoke".to_string(),
status: "ok".to_string(),
code_refs: vec![code_ref("epiphany-core/src/prompt.rs")],
code_refs: vec![code_ref("epiphany-state-model/src/prompt.rs")],
evidence_ids: vec!["ev-strong".to_string()],
});
state.recent_evidence.push(EpiphanyEvidenceRecord {
@ -1420,7 +1420,7 @@ mod tests {
kind: "verification".to_string(),
status: "ok".to_string(),
summary: "Verifier accepted prompt renderer state injection".to_string(),
code_refs: vec![code_ref("epiphany-core/src/prompt.rs")],
code_refs: vec![code_ref("epiphany-state-model/src/prompt.rs")],
});
let proposal = propose_map_update(EpiphanyMapProposalInput {
@ -1457,7 +1457,7 @@ mod tests {
summary: "Failed candidate should not be selected".to_string(),
source_kind: "verification".to_string(),
status: "failed".to_string(),
code_refs: vec![code_ref("epiphany-core/src/prompt.rs")],
code_refs: vec![code_ref("epiphany-state-model/src/prompt.rs")],
evidence_ids: vec!["ev-failed".to_string()],
});
state.recent_evidence.push(EpiphanyEvidenceRecord {
@ -1465,14 +1465,14 @@ mod tests {
kind: "verification".to_string(),
status: "failed".to_string(),
summary: "Verifier rejected the failed candidate".to_string(),
code_refs: vec![code_ref("epiphany-core/src/prompt.rs")],
code_refs: vec![code_ref("epiphany-state-model/src/prompt.rs")],
});
state.observations.push(EpiphanyObservation {
id: "obs-strong".to_string(),
summary: "Live smoke verified prompt renderer Epiphany state injection".to_string(),
source_kind: "smoke".to_string(),
status: "ok".to_string(),
code_refs: vec![code_ref("epiphany-core/src/prompt.rs")],
code_refs: vec![code_ref("epiphany-state-model/src/prompt.rs")],
evidence_ids: vec!["ev-strong".to_string()],
});
state.recent_evidence.push(EpiphanyEvidenceRecord {
@ -1480,7 +1480,7 @@ mod tests {
kind: "verification".to_string(),
status: "ok".to_string(),
summary: "Verifier accepted prompt renderer state injection".to_string(),
code_refs: vec![code_ref("epiphany-core/src/prompt.rs")],
code_refs: vec![code_ref("epiphany-state-model/src/prompt.rs")],
});
let proposal = propose_map_update(EpiphanyMapProposalInput {
@ -1502,7 +1502,7 @@ mod tests {
fn propose_map_update_auto_selection_prefers_frontier_dirty_path_cluster() {
let mut state = state_with_observation("ok");
state.graph_frontier = Some(EpiphanyGraphFrontier {
dirty_paths: vec![PathBuf::from("epiphany-core/src/prompt.rs")],
dirty_paths: vec![PathBuf::from("epiphany-state-model/src/prompt.rs")],
..Default::default()
});
state.observations.push(EpiphanyObservation {
@ -1537,7 +1537,7 @@ mod tests {
proposal
.graph_frontier
.dirty_paths
.contains(&PathBuf::from("epiphany-core/src/prompt.rs"))
.contains(&PathBuf::from("epiphany-state-model/src/prompt.rs"))
);
assert!(
!proposal
@ -1580,7 +1580,7 @@ mod tests {
id: "prompt-renderer".to_string(),
title: "Prompt renderer".to_string(),
purpose: "Render Epiphany state".to_string(),
code_refs: vec![code_ref("epiphany-core/src/prompt.rs")],
code_refs: vec![code_ref("epiphany-state-model/src/prompt.rs")],
..Default::default()
},
],
@ -1619,7 +1619,7 @@ mod tests {
dataflow_node_id: "epiphany-state-fragment".to_string(),
architecture_node_id: "prompt-renderer".to_string(),
relationship: Some("rendered by".to_string()),
code_refs: vec![code_ref("epiphany-core/src/prompt.rs")],
code_refs: vec![code_ref("epiphany-state-model/src/prompt.rs")],
}],
};
@ -1739,7 +1739,7 @@ mod tests {
id: "prompt-renderer".to_string(),
title: "Prompt renderer".to_string(),
purpose: "Render Epiphany state into developer context".to_string(),
code_refs: vec![code_ref("epiphany-core/src/prompt.rs")],
code_refs: vec![code_ref("epiphany-state-model/src/prompt.rs")],
..Default::default()
});
state.observations[0]

View file

@ -5,6 +5,10 @@ use serde::Deserialize;
use serde::Serialize;
use ts_rs::TS;
mod prompt;
pub use prompt::render_epiphany_state;
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema, TS)]
pub struct EpiphanyStateItem {
#[serde(default, skip_serializing_if = "Option::is_none")]

View file

@ -1,19 +1,19 @@
use epiphany_state_model::EpiphanyChurnState;
use epiphany_state_model::EpiphanyCodeRef;
use epiphany_state_model::EpiphanyEvidenceRecord;
use epiphany_state_model::EpiphanyGraph;
use epiphany_state_model::EpiphanyGraphCheckpoint;
use epiphany_state_model::EpiphanyGraphEdge;
use epiphany_state_model::EpiphanyGraphFrontier;
use epiphany_state_model::EpiphanyGraphLink;
use epiphany_state_model::EpiphanyGraphNode;
use epiphany_state_model::EpiphanyInvestigationCheckpoint;
use epiphany_state_model::EpiphanyInvestigationDisposition;
use epiphany_state_model::EpiphanyModeState;
use epiphany_state_model::EpiphanyObservation;
use epiphany_state_model::EpiphanyPlanningState;
use epiphany_state_model::EpiphanyScratchPad;
use epiphany_state_model::EpiphanyThreadState;
use crate::EpiphanyChurnState;
use crate::EpiphanyCodeRef;
use crate::EpiphanyEvidenceRecord;
use crate::EpiphanyGraph;
use crate::EpiphanyGraphCheckpoint;
use crate::EpiphanyGraphEdge;
use crate::EpiphanyGraphFrontier;
use crate::EpiphanyGraphLink;
use crate::EpiphanyGraphNode;
use crate::EpiphanyInvestigationCheckpoint;
use crate::EpiphanyInvestigationDisposition;
use crate::EpiphanyModeState;
use crate::EpiphanyObservation;
use crate::EpiphanyPlanningState;
use crate::EpiphanyScratchPad;
use crate::EpiphanyThreadState;
use std::collections::HashSet;
use std::path::Path;
@ -798,19 +798,19 @@ fn push_omitted_count(lines: &mut Vec<String>, total: usize, shown: usize, label
#[cfg(test)]
mod tests {
use super::render_epiphany_state;
use epiphany_state_model::EpiphanyChurnState;
use epiphany_state_model::EpiphanyCodeRef;
use epiphany_state_model::EpiphanyGraph;
use epiphany_state_model::EpiphanyGraphCheckpoint;
use epiphany_state_model::EpiphanyGraphEdge;
use epiphany_state_model::EpiphanyGraphFrontier;
use epiphany_state_model::EpiphanyGraphNode;
use epiphany_state_model::EpiphanyGraphs;
use epiphany_state_model::EpiphanyInvestigationCheckpoint;
use epiphany_state_model::EpiphanyInvestigationDisposition;
use epiphany_state_model::EpiphanyModeKind;
use epiphany_state_model::EpiphanyModeState;
use epiphany_state_model::EpiphanyThreadState;
use crate::EpiphanyChurnState;
use crate::EpiphanyCodeRef;
use crate::EpiphanyGraph;
use crate::EpiphanyGraphCheckpoint;
use crate::EpiphanyGraphEdge;
use crate::EpiphanyGraphFrontier;
use crate::EpiphanyGraphNode;
use crate::EpiphanyGraphs;
use crate::EpiphanyInvestigationCheckpoint;
use crate::EpiphanyInvestigationDisposition;
use crate::EpiphanyModeKind;
use crate::EpiphanyModeState;
use crate::EpiphanyThreadState;
use std::path::PathBuf;
#[test]

View file

@ -14,7 +14,7 @@ The spine exists in more than twenty-five live paths:
- protocol state shape: `EpiphanyThreadState`, `RolloutItem::EpiphanyState`, retrieval summaries, and prompt tags live in [protocol.rs](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/protocol/src/protocol.rs:103).
- in-memory session state: `SessionState` stores an optional `EpiphanyThreadState`, and `Session` exposes thin async accessors over it in [state/session.rs](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/core/src/state/session.rs:36) and [session/mod.rs](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/core/src/session/mod.rs:1240).
- prompt injection: `build_initial_context` reads the optional state and adds a bounded `<epiphany_state>` developer fragment; the renderer now includes durable investigation-checkpoint and planning sections when authoritative state carries them, so a resumed agent can see whether source gathering was banked and what captures/backlog/drafts exist without treating them as adopted objectives in [session/mod.rs](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/core/src/session/mod.rs:2434), [prompt.rs](E:/Projects/EpiphanyAgent/epiphany-core/src/prompt.rs:33), and [prompt.rs](E:/Projects/EpiphanyAgent/epiphany-core/src/prompt.rs:127).
- prompt injection: `build_initial_context` reads the optional state and adds a bounded `<epiphany_state>` developer fragment; the renderer now lives beside the typed state model and includes durable investigation-checkpoint and planning sections when authoritative state carries them, so a resumed agent can see whether source gathering was banked and what captures/backlog/drafts exist without treating them as adopted objectives in [session/mod.rs](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/core/src/session/mod.rs:2434), [prompt.rs](E:/Projects/EpiphanyAgent/epiphany-state-model/src/prompt.rs:33), and [prompt.rs](E:/Projects/EpiphanyAgent/epiphany-state-model/src/prompt.rs:127).
- per-turn persistence: normal turn setup persists one `RolloutItem::EpiphanyState` after the `TurnContext` when state exists in [session/mod.rs](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/core/src/session/mod.rs:2677).
- client read hydration: app-server thread views attach live or reconstructed `thread.epiphanyState` in [codex_message_processor.rs](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/app-server/src/codex_message_processor.rs:4706) and [codex_message_processor.rs](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/app-server/src/codex_message_processor.rs:4822).
- explicit distillation proposals: app-server routes read-only `thread/epiphany/distill` through a loaded-thread handler into `epiphany-core` so one explicit observation can become a patch candidate without mutating state; tool/command/shell/model sources now get typed evidence kinds and bounded salient-output summaries instead of dumping raw output into durable state in [codex_message_processor.rs](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/app-server/src/codex_message_processor.rs:4358) and [distillation.rs](E:/Projects/EpiphanyAgent/epiphany-core/src/distillation.rs:28).
@ -37,7 +37,7 @@ The spine exists in more than twenty-five live paths:
- CRRC coordinator recommendation: the `crrc` view lens reuses pressure/freshness/watcher/reorientation mapping plus the fixed `reorient-worker` binding and result read-back helper, recognizes already accepted reorientation findings so an accepted result is not recommended for acceptance again, and calls pure `epiphany-core` CRRC policy to return one bounded recommendation such as continue, prepare checkpoint, launch worker, wait, review, accept, or regather manually without mutating, launching, accepting, compacting, notifying, scheduling, or silently continuing work in [v2.rs](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/app-server-protocol/src/protocol/v2.rs:4661), [crrc.rs](E:/Projects/EpiphanyAgent/epiphany-core/src/surfaces/crrc.rs:60), and [codex_message_processor.rs](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/app-server/src/codex_message_processor.rs:4546).
- role ownership projection: the `roles` view lens reuses the same state/jobs/pressure/reorient/result/CRRC signals as the coordinator loop, and projects implementation, Imagination/planning, modeling/checkpoint, verification/review, and reorientation lanes with owner roles, status, linked jobs, authority scopes, and recommended scene actions without launching, scheduling, accepting, compacting, notifying, or mutating state. App-server adapts concrete protocol jobs and thread state, while the pure role-board projection policy now lives in [role_board.rs](E:/Projects/EpiphanyAgent/epiphany-core/src/surfaces/role_board.rs:70).
- role specialist launch/read-back/acceptance: app-server declares experimental `thread/epiphany/roleLaunch`, read-only `thread/epiphany/roleResult`, and write-gated `thread/epiphany/roleAccept`. `roleLaunch` accepts fixed Imagination/planning, modeling/checkpoint, and verification/review role ids, builds bounded specialist payloads from authoritative Epiphany state, routes them through the heartbeat-backed `epiphany_launch_job` seam, opens a typed runtime-spine job receipt, and emits the normal `jobLaunch` state update for `jobBindings` only. `roleResult` resolves heartbeat bindings through typed runtime-spine job results and seals legacy `agent_jobs` bindings, then adapts worker JSON through core role-result interpretation in [role_result.rs](E:/Projects/EpiphanyAgent/epiphany-core/src/surfaces/role_result.rs:45), projecting structured output as a reviewable finding with verdict, summary, next safe move, inspected files, frontier/evidence ids, optional `statePatch`, optional `selfPatch`, coordinator `selfPersistence` review, and errors without mutation, promotion, scheduling, or hidden continuation. `selfPatch` is a Ghostlight-shaped lane-memory request, not project truth: core accepts only role-matched, bounded, evidence-grounded memory/goal/value/private-note mutations and refuses objectives, graphs, checkpoints, scratch, planning, jobs, authority, code edits, or raw transcripts with reasons. `roleAccept` accepts completed heartbeat findings from typed runtime-spine results, accepts completed Imagination findings only when they contain a valid planning-only patch with draft Objective Draft review gates, accepts completed modeling/checkpoint findings only with a modeling-safe `statePatch`, applies accepted project patches through the existing Epiphany state validator, and uses core acceptance bundle policy to build the audit observation, evidence, and typed receipt. GUI/coordinator accept paths then apply accepted `selfPatch` requests to typed CultCache role dossiers in `state/agents.msgpack` through the native `epiphany-agent-memory-store` binary. Implementation stays owned by the main coding agent, verification output remains review-only, and reorientation stays on the CRRC-specific `reorientLaunch` / `reorientResult` / `reorientAccept` path.
- shared prompt memory projection and role dossiers: the prompt config now carries `[shared].persistent_memory` in [epiphany_specialists.toml](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/app-server/src/prompts/epiphany_specialists.toml:2). App-server parses that block, prepends it through `epiphany_agent_prompt_with_memory`, and therefore projects the same Ghostlight-derived memory into fixed role specialist instructions, reorientation-worker instructions, coordinator notes, and CRRC checkpoint steering. The base `<epiphany_state>` doctrine reinforces the Perfect Machine rule through [prompt.rs](E:/Projects/EpiphanyAgent/epiphany-core/src/prompt.rs:31) and [epiphany_doctrine.md](E:/Projects/EpiphanyAgent/epiphany-core/src/prompts/epiphany_doctrine.md:1). Individual Ghostlight-shaped role dossiers now live in typed CultCache `state/agents.msgpack`, and the native `epiphany-agent-memory-store` binary validates, reviews, and applies bounded self-memory patches through the Rust store.
- shared prompt memory projection and role dossiers: the prompt config now carries `[shared].persistent_memory` in [epiphany_specialists.toml](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/app-server/src/prompts/epiphany_specialists.toml:2). App-server parses that block, prepends it through `epiphany_agent_prompt_with_memory`, and therefore projects the same Ghostlight-derived memory into fixed role specialist instructions, reorientation-worker instructions, coordinator notes, and CRRC checkpoint steering. The base `<epiphany_state>` doctrine reinforces the Perfect Machine rule through [prompt.rs](E:/Projects/EpiphanyAgent/epiphany-state-model/src/prompt.rs:31) and [epiphany_doctrine.md](E:/Projects/EpiphanyAgent/epiphany-state-model/src/prompts/epiphany_doctrine.md:1). Individual Ghostlight-shaped role dossiers now live in typed CultCache `state/agents.msgpack`, and the native `epiphany-agent-memory-store` binary validates, reviews, and applies bounded self-memory patches through the Rust store.
- fixed-lane coordinator: the `coordinator` view lens composes role, pressure, reorient, CRRC, role result, and reorient result signals, and returns one current action without mutation. App-server assembles host/protocol inputs, but the pure fixed-lane decision ladder now lives in `epiphany-core` in [coordinator.rs](E:/Projects/EpiphanyAgent/epiphany-core/src/surfaces/coordinator.rs:132). Review acceptance and implementation clearance are intentionally different: an accepted verification finding clears implementation only when the verifier verdict is `pass`; accepted `needs-evidence`, `needs-review`, or `fail` findings route back toward modeling/checkpoint strengthening before code work resumes. `regatherManually` is now fallback, not a supervisor-puppeteering excuse: completed unaccepted modeling findings stop at `reviewModelingResult`, modeling acceptance precedes verification, and fixed lane actions are considered before manual regather.
- MVP operator view: native `epiphany-mvp-status` launches app-server over stdio, starts or reads one thread, gathers scene, planning, pressure, reorient, jobs, roles, Imagination/modeling/verification role results, reorient result, CRRC responses, heartbeat, and Face bubble artifacts, and renders them as text or JSON so the loop can be dogfooded without Python owning the product surface.
- MVP dogfood runner: the old Python runner was cut with the `agent_jobs` path. The replacement must be native Rust/CultCache/CultNet and complete heartbeat-owned runtime-spine job results with operator-safe artifacts.
@ -49,7 +49,7 @@ The spine exists in more than twenty-five live paths:
The thick Epiphany-owned implementation is mostly outside vendored Codex now:
- prompt rendering lives in [epiphany-core/src/prompt.rs](E:/Projects/EpiphanyAgent/epiphany-core/src/prompt.rs:33), including the always-rendered operating-discipline section in [prompt.rs](E:/Projects/EpiphanyAgent/epiphany-core/src/prompt.rs:26).
- prompt rendering lives in [epiphany-state-model/src/prompt.rs](E:/Projects/EpiphanyAgent/epiphany-state-model/src/prompt.rs:33), including the always-rendered operating-discipline section in [prompt.rs](E:/Projects/EpiphanyAgent/epiphany-state-model/src/prompt.rs:26).
- generic rollout replay for stored-thread reads lives in [epiphany-core/src/rollout.rs](E:/Projects/EpiphanyAgent/epiphany-core/src/rollout.rs:38).
- retrieval and indexing live in [epiphany-core/src/retrieval.rs](E:/Projects/EpiphanyAgent/epiphany-core/src/retrieval.rs:144) and [retrieval.rs](E:/Projects/EpiphanyAgent/epiphany-core/src/retrieval.rs:160), with summary-only freshness reads in [retrieval.rs](E:/Projects/EpiphanyAgent/epiphany-core/src/retrieval.rs:100).
- deterministic observation distillation lives in [epiphany-core/src/distillation.rs](E:/Projects/EpiphanyAgent/epiphany-core/src/distillation.rs:28).
@ -310,7 +310,7 @@ There is now one deliberately unbounded-in-spirit but tiny-in-text exception: th
It then builds the normal developer bundle. After collaboration-mode instructions, it checks `epiphany_state.as_ref()` and pushes `EpiphanyStateInstructions::from_state(...).render()`.
`EpiphanyStateInstructions` is only a Codex adapter. It calls `epiphany_core::render_epiphany_state(state)` and wraps the result in the protocol tags.
`EpiphanyStateInstructions` is only a Codex adapter. It calls the `codex_protocol` re-export of the state-model `render_epiphany_state(state)` and wraps the result in the protocol tags.
`render_epiphany_state` always emits:
@ -324,9 +324,9 @@ Code refs:
- [session/mod.rs](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/core/src/session/mod.rs:2447)
- [session/mod.rs](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/core/src/session/mod.rs:2509)
- [context/epiphany_state_instructions.rs](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/core/src/context/epiphany_state_instructions.rs:7)
- [epiphany-core/src/prompt.rs](E:/Projects/EpiphanyAgent/epiphany-core/src/prompt.rs:26)
- [epiphany-core/src/prompt.rs](E:/Projects/EpiphanyAgent/epiphany-core/src/prompt.rs:33)
- [epiphany-core/src/prompt.rs](E:/Projects/EpiphanyAgent/epiphany-core/src/prompt.rs:43)
- [epiphany-state-model/src/prompt.rs](E:/Projects/EpiphanyAgent/epiphany-state-model/src/prompt.rs:26)
- [epiphany-state-model/src/prompt.rs](E:/Projects/EpiphanyAgent/epiphany-state-model/src/prompt.rs:33)
- [epiphany-state-model/src/prompt.rs](E:/Projects/EpiphanyAgent/epiphany-state-model/src/prompt.rs:43)
### Output

View file

@ -88,7 +88,7 @@ The landed machine now has:
- live-specialist runner must be rebuilt around heartbeat/runtime-spine result receipts
- first Phase 6 Aquarium operator shell extracted to sibling repo `E:\Projects\EpiphanyAquarium`, a Tauri v2 + React/WebGL client over the existing status bridge, dogfood artifacts, and GUI action artifacts, with its own distilled interface state/memory/doctrine plus durable checkpoint preparation, bounded status/coordinator artifact buttons, fixed modeling/verification/reorient launch and read-back buttons, and explicit review-gated reorient acceptance
- first Unity editor/runtime bridge through native `epiphany-unity-bridge`, native `epiphany-unity-bridge-smoke`, and the GUI Inspect Unity action, resolving exact project-pinned editors and writing runtime artifacts while refusing wrong or missing versions
- prompt-file ownership for major Epiphany prompt surfaces: rendered state intro/doctrine lives under `epiphany-core/src/prompts/`, while modeling/Body, research/Eyes, implementation/Hands, verification/Soul, reorientation/Life, coordinator/Self, and CRRC templates live in `vendor/codex/codex-rs/app-server/src/prompts/epiphany_specialists.toml`
- prompt-file ownership for major Epiphany prompt surfaces: rendered state intro/doctrine lives under `epiphany-state-model/src/prompts/` beside the typed state document renderer, while modeling/Body, research/Eyes, implementation/Hands, verification/Soul, reorientation/Life, coordinator/Self, and CRRC templates live in `vendor/codex/codex-rs/app-server/src/prompts/epiphany_specialists.toml`
- prompt-level anti-Greenspun guardrails: Epiphany keeps Codex's useful operator discipline and requires a bounded research/scout check before agents invent bespoke versions of known algorithms, parsers, schedulers, renderers, protocols, storage layers, security mechanisms, or workflow engines
- live Phase 6 reorientation app-server smoke coverage through native `epiphany-phase6-reorient-smoke`
- live Phase 6 MVP status smoke coverage through native `epiphany-mvp-status-smoke`

View file

@ -40,7 +40,7 @@ remembers doctrine; the branch remembers the blade.
- Agent self-memory review/application now has typed `AgentSelfPatch` core APIs. JSON-value selfPatch functions are compatibility wrappers for CLI/artifact ingress; native callers should parse once at the edge and then call `review_agent_self_patch_document` / `apply_agent_self_patch_document`. Role-result self-persistence no longer exports a JSON-value reviewer; the live API is `review_role_self_patch_document`.
- `epiphany-openai-codex-spine` no longer uses Codex's Responses client, model-provider layer, `codex-api`, `codex-model-provider`, `codex-model-provider-info`, or `codex-protocol` for outbound model requests. It reaches `codex-login` only through `epiphany-openai-auth-spine` so credential loading/refresh stays Codex-compatible while request/status/event/runtime surfaces stay typed Epiphany documents.
- `notes/epiphany-memory-graph-unified-plan.md` is the current memory architecture direction drawn from `Fractal Domains And The Cache That Bites` plus the VoidBot memory scar tissue. The repo semantic architecture/dataflow graph and agent memory are one `EpiphanyMemoryGraph` substrate with repo, role, short-term, incubation, agency, candidate-intervention, and evidence profiles. The first native skeleton is landed: `epiphany-state-model` owns shared graph document types, `epiphany-core::memory_graph` owns stable ids, validation, freshness, context cuts, and CultCache persistence, and `epiphany-memory-graph` can status/validate/context/smoke the store without Qdrant. Qdrant is a contribution cache for typed graph documents, not truth. `notes/repo-fractal-dataflow-cache-plan.md` and `notes/agent-memory-fractal-cache-plan.md` are profile plans, not rival organs.
- Durable Epiphany state types now live in root crate `epiphany-state-model`. `codex-protocol` re-exports them only so old rollout/API callers keep compiling; do not add new durable `Epiphany*` state structs under `vendor/codex`. `epiphany-core` imports the native model directly and no longer depends on `codex-protocol`. Pressure derives from native `EpiphanyTokenUsageSnapshot`; Codex token telemetry is mapped at the bridge. Codex rollout/event reconstruction now lives in `codex-core::epiphany_rollout`, where the Codex `RolloutItem` / `EventMsg` types belong. Exact retrieval path matching is native to `epiphany-core`, so `epiphany-core` has no direct vendored Codex crate dependency.
- Durable Epiphany state types now live in root crate `epiphany-state-model`. `codex-protocol` re-exports them only so old rollout/API callers keep compiling; do not add new durable `Epiphany*` state structs under `vendor/codex`. The deterministic `<epiphany_state>` prompt renderer also lives beside that typed model now, with prompt text under `epiphany-state-model/src/prompts/`; `epiphany-core` only re-exports it for compatibility. `epiphany-core` imports the native model directly and no longer depends on `codex-protocol`. Pressure derives from native `EpiphanyTokenUsageSnapshot`; Codex token telemetry is mapped at the bridge. Codex rollout/event reconstruction now lives in `codex-core::epiphany_rollout`, where the Codex `RolloutItem` / `EventMsg` types belong. Exact retrieval path matching is native to `epiphany-core`, so `epiphany-core` has no direct vendored Codex crate dependency.
- State-update contract proof and job launch/interrupt DTO ownership now live in native `epiphany-core`. The old giant `codex_thread.rs` Epiphany state-update test fixture was cut, and `epiphany-codex-bridge` no longer imports Epiphany job launch request types from `codex_core`; vendored `CodexThread` may call the native mutation/launch law for compatibility, but it must not regain ownership of state-update semantics, heartbeat launch-plan policy, or Epiphany DTOs.
- 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.
@ -1231,7 +1231,7 @@ The prompt doctrine pass has now also run. It rechecked global AGENTS,
available Codex memories, and nearby evidence ledgers before distilling the
sane parts into the shared base prompt, rendered Epiphany state, and fixed lane
templates. Major prompt text now lives in prompt files instead of Rust/Python
string slabs: rendered state intro/doctrine lives under `epiphany-core/src/prompts/`,
string slabs: rendered state intro/doctrine lives under `epiphany-state-model/src/prompts/`,
and lane/control templates live in
`vendor/codex/codex-rs/app-server/src/prompts/epiphany_specialists.toml`.
Implementation is not a `roleLaunch` specialist; it is the GUI-launched main

View file

@ -770,7 +770,7 @@ work so repo orientation stops beginning with blind `rg`.
Files:
- `epiphany-core/src/prompt.rs`
- `epiphany-state-model/src/prompt.rs`
- `epiphany-core/src/surfaces/worker_launch.rs`
- `vendor/codex/...` only as compatibility bridge surfaces if still needed

Binary file not shown.

View file

@ -115,7 +115,7 @@ accepted_design:
- `thread/epiphany/index` writes the retrieval catalog, not durable Epiphany understanding; catalog is auspex output, not doctrine.
- Qdrant is the preferred persistent semantic backend; BM25 remains the bootstrap/fallback/control path.
- `notes/epiphany-memory-graph-unified-plan.md` applies the mapped-fractal-domain/cache lesson to Epiphany and corrects the organ boundary: repo architecture/dataflow and agent memory are profiles over one `EpiphanyMemoryGraph`, not separate graph engines. The first native skeleton is landed: `epiphany-state-model` owns the public document vocabulary, `epiphany-core::memory_graph` owns stable ids/validation/freshness/context cuts/CultCache persistence, and `epiphany-memory-graph` exposes status/validate/context/smoke without Qdrant. `notes/repo-fractal-dataflow-cache-plan.md` and `notes/agent-memory-fractal-cache-plan.md` are profile plans beneath that substrate. If deleting Qdrant deletes understanding, the design is wrong; the fallback must be slower but still correct typed graph traversal.
- `epiphany-core` owns prompt rendering, rollout replay helpers, retrieval/indexing, distillation, proposal, promotion policy, scene projection, freshness derivation, pressure derivation, job/progress view derivation, planning view derivation, reorientation resume/regather verdict policy, pure CRRC recommendation policy, fixed-lane coordinator decision policy, role-board projection policy, and role-result interpretation/self-persistence review policy where possible.
- `epiphany-state-model` owns the deterministic prompt-state renderer beside the typed `EpiphanyThreadState` document it serializes. `epiphany-core` re-exports that renderer for compatibility and owns rollout replay helpers, retrieval/indexing, distillation, proposal, promotion policy, scene projection, freshness derivation, pressure derivation, job/progress view derivation, planning view derivation, reorientation resume/regather verdict policy, pure CRRC recommendation policy, fixed-lane coordinator decision policy, role-board projection policy, and role-result interpretation/self-persistence review policy where possible.
- Vendored Codex keeps the thin typed host seam: protocol types, thread bridges, app-server protocol, request routing, watcher lifecycle, notifications, and rollout integration. Epiphany projection and coordinator policy should keep moving into `epiphany-core` / `epiphany-codex-bridge` instead of living in `codex_message_processor.rs`.
- The current algorithmic map is the source-grounded description of live control flow.
- Compact-Rehydrate-Reorient-Continue is an architecture primitive; automatic runtime coordination is not landed yet.
@ -168,7 +168,7 @@ accepted_design:
- A machine is perfect when every remaining part visibly deserves to exist; this applies to persistent memory too.
- Evidence is not an activity feed; repeated "I just did this" entries should be cut or distilled when git already proves the work.
- Language, tone, ritual, and emotional salience are real control surfaces for a language-model harness; they are not supernatural, but they shape attention, role, permission, and behavior. The rite is a steering wheel, not decoration.
- Major Epiphany prompt surfaces live in prompt files rather than Rust/Python string slabs: rendered state intro/doctrine under `epiphany-core/src/prompts/`, and modeling/Body, research/Eyes, implementation/Hands, verification/Soul, reorientation/Life, coordinator/Self, Face/public-surface, and CRRC intervention templates in `vendor/codex/codex-rs/app-server/src/prompts/epiphany_specialists.toml`.
- Major Epiphany prompt surfaces live in prompt files rather than Rust/Python string slabs: rendered state intro/doctrine under `epiphany-state-model/src/prompts/`, and modeling/Body, research/Eyes, implementation/Hands, verification/Soul, reorientation/Life, coordinator/Self, Face/public-surface, and CRRC intervention templates in `vendor/codex/codex-rs/app-server/src/prompts/epiphany_specialists.toml`.
- Specialist prompts are role-distilled instead of generic and their live text is config-backed in app-server: modeling/checkpoint is the Body of code, dataflow, seams, and frontier; research/scout is the Eyes prompt surface for existing work, vendor guidance, libraries, papers, and anti-Greenspun source selection; implementation is the Hands, the main coding lane and actuator rather than a `roleLaunch` specialist; verification/review is the Soul of promise, invariants, evidence, and user truth; reorientation is Life across compaction and source drift; coordinator is the read-only Self that routes attention without implementing, verifying, promoting, or accepting; Face is the public Discord #aquarium surface that translates agent thought-weather without moderating or leaking sealed thought.
- Epiphany prompt surfaces now carry a shared Ghostlight-derived persistent memory projection before lane-specific text: prompt is not memory, durable typed state is the mind, personality and protected values are first-class salience handles, and every lane is explicitly responsible for making its own memory/model/prompt/evidence habit sharper or naming the needed repair. Each lane states self-improvement in its own rite-language: Imagination selects futures, Body clarifies anatomy, Eyes sees earlier, Hands touches source more precisely, Soul becomes harder to fool, Life loses less continuity, Self routes repair, and Face becomes clearer at turning inner weather into useful social presence.
- Specialist self-memory now has a bounded Ghostlight-shaped CultCache persistence surface in `state/agents.msgpack`: Imagination, Body, Eyes, Hands, Soul, Life, Self, and Face each have an individual typed role dossier for identity, personality, semantic/episodic/relationship memory, goals, and values. These entries are lane memory only; project truth remains in authoritative `EpiphanyThreadState`.
@ -297,4 +297,4 @@ current_status:
freshness propagation, summary-versus-child context cuts, and a validated
CultCache store entry; the native `epiphany-memory-graph` binary can
status/validate/query/smoke the store without Qdrant.
next_action: Continue the memory graph build unless a more urgent Codex starvation regression appears. Repo, agent, and heartbeat profile producers now map accepted architecture/dataflow graph truth, reviewed role dossier memory/goals/values, and heartbeat cognition pressure into `EpiphanyMemoryGraph` documents; compose merges profile snapshots into one validated graph; `epiphany-memory-graph compose` writes from typed graph stores; `epiphany-memory-graph refresh` can invoke live agent-memory and heartbeat-cognition producers from their typed stores; `epiphany-core` has a native typed `EpiphanyThreadState` CultCache store seam; the bridge mirrors loaded Codex-thread Epiphany state into `state/thread-state.msgpack`; and CultNet now advertises logical `EpiphanyThreadState` plus `EpiphanyMemoryGraph` snapshot contracts. The next clean slice is local refresh/dogfood once a mirrored thread-state store exists, then a Qdrant embedding cache writer that treats embeddings as rebuildable manifests, not canonical memory.
next_action: Continue Codex starvation before outward feature growth. The prompt-state renderer now lives with `epiphany-state-model`, and Codex core reaches it through the protocol re-export; the next clean cut is the remaining `codex-core::CodexThread` Epiphany seam, where retrieval/indexing/state update/job launch still imports `epiphany-core` directly. Classify whether those methods belong in a tiny host persistence trait, `epiphany-codex-bridge`, or an Epiphany-owned runtime route before adding new capability.

View file

@ -2,6 +2,7 @@ use super::ContextualUserFragment;
use codex_protocol::protocol::EPIPHANY_STATE_CLOSE_TAG;
use codex_protocol::protocol::EPIPHANY_STATE_OPEN_TAG;
use codex_protocol::protocol::EpiphanyThreadState;
use codex_protocol::protocol::render_epiphany_state;
#[derive(Debug, Clone, PartialEq)]
pub(crate) struct EpiphanyStateInstructions {
@ -11,7 +12,7 @@ pub(crate) struct EpiphanyStateInstructions {
impl EpiphanyStateInstructions {
pub(crate) fn from_state(state: &EpiphanyThreadState) -> Self {
Self {
text: epiphany_core::render_epiphany_state(state),
text: render_epiphany_state(state),
}
}
}

View file

@ -2983,6 +2983,7 @@ pub use epiphany_state_model::EpiphanyScratchPad;
pub use epiphany_state_model::EpiphanyStateItem;
pub use epiphany_state_model::EpiphanySubgoal;
pub use epiphany_state_model::EpiphanyThreadState;
pub use epiphany_state_model::render_epiphany_state;
#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema, TS)]
pub struct CompactedItem {