diff --git a/Cargo.lock b/Cargo.lock index 0470736e..daebe993 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -507,12 +507,6 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" -[[package]] -name = "dyn-clone" -version = "1.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" - [[package]] name = "ed25519" version = "2.2.3" @@ -551,7 +545,6 @@ dependencies = [ "epiphany-model-adapter", "epiphany-openai-adapter", "epiphany-release-construction", - "epiphany-state-model", "epiphany-tool-adapter", "ghostlight-persona-projection", "ignore", @@ -649,15 +642,6 @@ dependencies = [ "uuid", ] -[[package]] -name = "epiphany-state-model" -version = "0.1.0" -dependencies = [ - "schemars", - "serde", - "ts-rs", -] - [[package]] name = "epiphany-tool-adapter" version = "0.1.0" @@ -1867,30 +1851,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "schemars" -version = "0.8.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fbf2ae1b8bc8e02df939598064d22402220cd5bbcca1c76f7d6a310974d5615" -dependencies = [ - "dyn-clone", - "schemars_derive", - "serde", - "serde_json", -] - -[[package]] -name = "schemars_derive" -version = "0.8.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32e265784ad618884abaea0600a9adf15393368d840e0222d101a072f3f7534d" -dependencies = [ - "proc-macro2", - "quote", - "serde_derive_internals", - "syn 2.0.119", -] - [[package]] name = "security-framework" version = "3.7.0" @@ -1964,17 +1924,6 @@ dependencies = [ "syn 3.0.3", ] -[[package]] -name = "serde_derive_internals" -version = "0.29.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.119", -] - [[package]] name = "serde_json" version = "1.0.151" @@ -2177,15 +2126,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "termcolor" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" -dependencies = [ - "winapi-util", -] - [[package]] name = "thiserror" version = "2.0.20" @@ -2414,30 +2354,6 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" -[[package]] -name = "ts-rs" -version = "11.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4994acea2522cd2b3b85c1d9529a55991e3ad5e25cdcd3de9d505972c4379424" -dependencies = [ - "serde_json", - "thiserror", - "ts-rs-macros", - "uuid", -] - -[[package]] -name = "ts-rs-macros" -version = "11.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee6ff59666c9cbaec3533964505d39154dc4e0a56151fdea30a09ed0301f62e2" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.119", - "termcolor", -] - [[package]] name = "typenum" version = "1.20.1" @@ -3047,18 +2963,3 @@ name = "zmij" version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" - -[[patch.unused]] -name = "tungstenite" -version = "0.27.0" -source = "git+https://github.com/openai-oss-forks/tungstenite-rs?rev=9200079d3b54a1ff51072e24d81fd354f085156f#9200079d3b54a1ff51072e24d81fd354f085156f" - -[[patch.unused]] -name = "tokio-tungstenite" -version = "0.28.0" -source = "git+https://github.com/openai-oss-forks/tokio-tungstenite?rev=132f5b39c862e3a970f731d709608b3e6276d5f6#132f5b39c862e3a970f731d709608b3e6276d5f6" - -[[patch.unused]] -name = "tungstenite" -version = "0.27.0" -source = "git+https://github.com/openai-oss-forks/tungstenite-rs?rev=9200079d3b54a1ff51072e24d81fd354f085156f#9200079d3b54a1ff51072e24d81fd354f085156f" diff --git a/Cargo.toml b/Cargo.toml index 6618cf68..f208bbc6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,6 @@ members = [ "epiphany-openai-adapter", "epiphany-openai-runtime", "epiphany-release-construction", - "epiphany-state-model", "epiphany-tool-adapter", "epiphany-tool-mcp-runtime", ] @@ -54,13 +53,6 @@ incremental = true [dev-dependencies] tempfile = "3" -[patch.crates-io] -tokio-tungstenite = { git = "https://github.com/openai-oss-forks/tokio-tungstenite", rev = "132f5b39c862e3a970f731d709608b3e6276d5f6" } -tungstenite = { git = "https://github.com/openai-oss-forks/tungstenite-rs", rev = "9200079d3b54a1ff51072e24d81fd354f085156f" } - -[patch."ssh://git@github.com/openai-oss-forks/tungstenite-rs.git"] -tungstenite = { git = "https://github.com/openai-oss-forks/tungstenite-rs", rev = "9200079d3b54a1ff51072e24d81fd354f085156f" } - [[bin]] name = "epiphany-release" path = "epiphany-core/src/bin/epiphany-release.rs" diff --git a/README.md b/README.md index 5c05bc1e..259a8c36 100644 --- a/README.md +++ b/README.md @@ -120,15 +120,15 @@ Epiphany is a native GameCult runtime that began as an opinionated Codex fork. Her body is made of: -- typed Rust domain organs in `epiphany-core` and `epiphany-state-model` +- typed Rust domain organs owned by `epiphany-core` - CultCache `.cc` stores for runtime, heartbeat, agent state, local Verse, memory graph, and thread state - CultMesh and CultNet contracts for local and distributed state - provider-neutral model and tool request/receipt documents - Mind, Substrate Gate, Eyes, Hands, Soul, Continuity, Persona, and heartbeat authority surfaces -- Codex retained only for honest OpenAI subscription auth and model transport; - Epiphany does not publish a Codex-owned project-state surface +- a narrow standalone CodexConnector process for OpenAI subscription auth and + model transport; Epiphany compiles no Codex crate and keeps cognition local That last clause matters. Codex and other frontier agents can be excellent workers. They do not decide which organizational state is authoritative, who diff --git a/docs/epiphany_body_whitepaper.tex b/docs/epiphany_body_whitepaper.tex index a857393c..05046be2 100644 --- a/docs/epiphany_body_whitepaper.tex +++ b/docs/epiphany_body_whitepaper.tex @@ -48,7 +48,7 @@ The practical definition in this repository is: \begin{itemize} \item the root checkout at \code{F:\Projects\Epiphany}; - \item Epiphany Rust crates such as \code{epiphany-core}, \code{epiphany-state-model}, model/tool adapters, and OpenAI transport crates; + \item Epiphany Rust crates such as \code{epiphany-core}, model/tool adapters, and provider runtimes; \item vendored substrate in \code{vendor/codex}, \code{vendor/cultcache-rs}, \code{vendor/cultnet-rs}, and \code{vendor/cultmesh-rs}; \item typed state stores under \code{state/}; \item schemas under \code{schemas/cultnet/}; @@ -59,20 +59,19 @@ The practical definition in this repository is: \section{Executive Map} -Epiphany's current Body is a hybrid machine in transition. Its center of gravity -has moved into typed Rust/CultCache organs, but compatibility arteries still -run through vendored Codex. The live target is not a cleaner pile of Codex -routes. The target is an Epiphany-native CultCache/CultMesh/CultNet body with a -relatively vanilla Codex-derived reliquary retained for OpenAI subscription -auth and model transport. +Epiphany's current Body is a typed Rust/CultCache organism with provider +transport outside its cognition boundary. Codex requests cross a lean client +ABI into the independent CodexConnector daemon, which owns subscription +credential refresh, transport, and replay. Epiphany owns prompts, tools, +reasoning context, decisions, and Mind admission; it compiles no Codex crate. \begin{longtable}{>{\raggedright\arraybackslash}p{0.23\linewidth}>{\raggedright\arraybackslash}p{0.32\linewidth}>{\raggedright\arraybackslash}p{0.35\linewidth}} \textbf{Body Region} & \textbf{Current Owner} & \textbf{Invariant} \\ \hline Durable Mind state & keyed CultCache documents assembled by \code{epiphany-core} & Prompt rendering consumes sealed typed projections; no persisted thread aggregate or global authority revision exists. \\ Domain policy & \code{epiphany-core} & Verdicts, launch policy, acceptance rules, runtime lifecycle, and mutation law live here, not in bridge DTOs. \\ -Vendored Codex & \code{vendor/codex} & Retain host/app-server/auth/model compatibility where useful; do not let Codex own Epiphany prompts, scheduler, or state. \\ -Runtime spine & \code{epiphany-core/src/runtime_spine.rs} and \code{state/runtime-spine.cc} & Runtime identity, jobs, events, receipts, tool/model documents are typed CultCache records. \\ +Codex transport & independent \code{GameCult/CodexConnector} daemon & Own subscription credentials, provider transport, and exact replay only; never own Epiphany prompts, scheduler, decisions, or state. \\ +Runtime spine & \code{epiphany-core/src/runtime_spine.rs} and \code{state/runtime-spine.cc} & Runtime identity, jobs, receipts, and tool/model documents are typed CultCache records. \\ Persona memory & keyed Mind Persona-memory documents & Persona decisions admit bounded memories by semantic identity; no parallel role-memory aggregate or generation head exists. \\ Resident Self physiology & Resident Self CultCache documents via \code{epiphany-swarm} & Typed pressure, exact grant creation, launch exclusion, leases, terminal receipts, retry, and bounded retention have one owner. No scheduler singleton or acknowledgement loop exists. \\ Local Verse & CultMesh over \code{state/local-verse.cc} & Local Verse context is compact prompt/operator context; private state does not become public by flipping a flag. \\ @@ -82,27 +81,21 @@ Operator artifacts & \code{.epiphany-*}, \code{tools/epiphany_local_run.ps1} & A \section{Repository Body} -The checkout has nine primary Epiphany Rust crates: +The checkout has eight primary Epiphany Rust packages: \begin{itemize} - \item \code{epiphany-core}: the main domain organ. It owns state-update - validation, launch documents, runtime spine, Resident Self, Persona - projection, Substrate Gate, Mind, Eyes, Hands, Soul, Continuity, CultMesh - integration, surface derivation, smokes, and local operator binaries. - \item \code{epiphany-state-model}: the durable \code{EpiphanyThreadState} - type plus \code{render_epiphany_state}. This is the typed Mind surface that - prompt fragments and views read. + \item \code{epiphany-core}: the main domain organ. It owns semantic state + contracts, keyed Mind admission, launch documents, runtime spine, Resident + Self, Persona projection, Substrate Gate, Eyes, Hands, Soul, Continuity, + CultMesh integration, and surface derivation. \item \code{epiphany-model-adapter}: provider-neutral model request, stream event, receipt, and status documents. \item \code{epiphany-openai-adapter}: OpenAI-shaped request/event/receipt and status documents. - \item \code{epiphany-openai-auth-spine}: Codex-derived auth boundary over - \code{codex-login}. It preserves honest Codex-compatible credential and token - behavior rather than impersonating it from scratch. - \item \code{epiphany-openai-codex-spine}: model transport over vendored Codex - client machinery. \item \code{epiphany-openai-runtime}: executable model runtime, including \code{epiphany-model-runtime}. + \item \code{epiphany-release-construction}: exact package construction and + release-witness verification. \item \code{epiphany-tool-adapter}: typed tool capability, invocation intent, and invocation receipt documents. \item \code{epiphany-tool-mcp-runtime}: first-party tool executor. Native @@ -114,8 +107,8 @@ The checkout has nine primary Epiphany Rust crates: The vendored region contains: \begin{itemize} - \item \code{vendor/codex}: the Codex-derived host and compatibility substrate. - It is tracked directly, not as a submodule. + \item \code{vendor/codex}: retained Codex-fork source history. It is not in + Epiphany's compiled runtime graph. \item \code{vendor/cultcache-rs}, \code{vendor/cultnet-rs}, and \code{vendor/cultmesh-rs}: repo-contained Rust Cult substrate. \end{itemize} diff --git a/docs/epiphany_investor_brief.md b/docs/epiphany_investor_brief.md index b5ab23f2..cbd5c556 100644 --- a/docs/epiphany_investor_brief.md +++ b/docs/epiphany_investor_brief.md @@ -77,7 +77,7 @@ conflicts, or a consequential judgment cannot be derived honestly. The current native Epiphany body includes: -- typed Rust domain organs in `epiphany-core` and `epiphany-state-model` +- typed Rust domain organs owned by `epiphany-core` - keyed Mind state with typed projection and promotion paths - RepoModel and Model Atlas surfaces for source-grounded architectural belief - CultCache `.cc` state and CultMesh/CultNet contracts @@ -86,7 +86,7 @@ The current native Epiphany body includes: - runtime-spine job and worker-result documents - Mind, Modeling, Substrate Gate, Eyes, Hands, Soul, Continuity, Persona, and heartbeat authority surfaces -- local operator status, coordinator, smoke, and Verse-context commands +- local operator status, coordinator, and Verse-context commands Codex is retained only for OpenAI authentication and model transport. Epiphany does not publish Codex app-server state as its project Mind. diff --git a/epiphany-core/Cargo.toml b/epiphany-core/Cargo.toml index 891efb46..b9b06b31 100644 --- a/epiphany-core/Cargo.toml +++ b/epiphany-core/Cargo.toml @@ -21,7 +21,6 @@ epiphany-openai-adapter = { path = "../epiphany-openai-adapter" } epiphany-release-construction = { path = "../epiphany-release-construction" } epiphany-model-adapter = { path = "../epiphany-model-adapter" } epiphany-tool-adapter = { path = "../epiphany-tool-adapter" } -epiphany-state-model = { path = "../epiphany-state-model" } ghostlight-persona-projection = { git = "https://github.com/GameCult/Ghostlight.git", rev = "22281891cbf9258db80c15a9fd465e6fa251e7dd", package = "ghostlight-persona-projection" } ed25519-dalek = "2" ignore = "0.4.23" diff --git a/epiphany-core/src/current_work.rs b/epiphany-core/src/current_work.rs index 3b26c232..8f3d637a 100644 --- a/epiphany-core/src/current_work.rs +++ b/epiphany-core/src/current_work.rs @@ -3406,7 +3406,7 @@ fn resolve_body_modeling_work( #[cfg(test)] mod tests { use super::*; - use epiphany_state_model::{ + use crate::state_model::{ EpiphanyMemoryDomain, EpiphanyMemoryLifecycle, EpiphanyMemoryNode, EpiphanyMemoryNodeKind, RepoFrontierItem, RepoFrontierStatus, }; @@ -5792,12 +5792,12 @@ mod tests { research_cache.put(&research_context.context_id, &research_context)?; let stale_research_store = temp.path().join("stale-research-output.cc"); std::fs::copy(&store, &stale_research_store)?; - let evidence = epiphany_state_model::EpiphanyEvidenceRecord { + let evidence = crate::EpiphanyEvidenceRecord { id: "research-evidence-1".into(), kind: "external-source".into(), status: "ok".into(), summary: "The bounded external claim is supported.".into(), - code_refs: vec![epiphany_state_model::EpiphanyCodeRef { + code_refs: vec![crate::EpiphanyCodeRef { path: "epiphany-core/src/current_work.rs".into(), start_line: Some(1), end_line: None, @@ -5805,7 +5805,7 @@ mod tests { note: None, }], }; - let observation = epiphany_state_model::EpiphanyObservation { + let observation = crate::EpiphanyObservation { id: "research-observation-1".into(), summary: "External evidence answers the exact frontier question.".into(), source_kind: "research".into(), diff --git a/epiphany-core/src/lib.rs b/epiphany-core/src/lib.rs index 64e07e45..d9b4dc9c 100644 --- a/epiphany-core/src/lib.rs +++ b/epiphany-core/src/lib.rs @@ -32,6 +32,7 @@ mod runtime_spine; mod runtime_store_backend; mod runtime_worker_attempt; mod soul_gateway; +mod state_model; mod state_ledger; mod substrate_gate; mod surfaces; @@ -99,11 +100,6 @@ pub use cultmesh_integration::{ }; pub use current_work::*; -pub use epiphany_state_model::EpiphanyMemoryAnchor; -pub use epiphany_state_model::EpiphanyMemoryDomain; -pub use epiphany_state_model::EpiphanyMemoryEdge; -pub use epiphany_state_model::EpiphanyMemoryLifecycle; -pub use epiphany_state_model::EpiphanyMemoryNode; pub use hands_gateway::*; pub use idunn_provider_health::{ EPIPHANY_IDUNN_PROVIDER_HEALTH_ADMISSION_SCHEMA, EPIPHANY_IDUNN_PROVIDER_HEALTH_ADMISSION_TYPE, @@ -133,13 +129,7 @@ pub use imagination_consideration::{ validate_candidate as validate_imagination_consideration_candidate, validate_current_request as validate_current_imagination_consideration_request, }; -pub use memory_graph::EpiphanyMemoryEdgeKind; -pub use memory_graph::EpiphanyMemoryGraphSnapshot; pub use memory_graph::EpiphanyMemoryGraphValidationError; -pub use memory_graph::EpiphanyMemoryNodeKind; -pub use memory_graph::RepoFrontierAdoptedPlan; -pub use memory_graph::RepoFrontierItem; -pub use memory_graph::RepoFrontierStatus; pub use memory_graph::validate_memory_graph_snapshot; pub use mind_documents::*; pub use packaged_release::{ @@ -301,6 +291,7 @@ pub use runtime_spine::select_and_commit_repo_frontier_route; pub use runtime_spine::terminalize_model_pass_failure_session; pub(crate) use runtime_worker_attempt::{RuntimeTypedRequestRef, WorkerProcessStatus}; pub use soul_gateway::*; +pub use state_model::*; pub use state_ledger::EpiphanyBranchRecord; pub use state_ledger::EpiphanyLedgerEvidenceRecord; pub use state_ledger::EpiphanyStateLedgerEntry; diff --git a/epiphany-core/src/memory_graph/mod.rs b/epiphany-core/src/memory_graph/mod.rs index 3a4d5073..d1620351 100644 --- a/epiphany-core/src/memory_graph/mod.rs +++ b/epiphany-core/src/memory_graph/mod.rs @@ -1,16 +1,5 @@ pub mod validation; -pub use epiphany_state_model::EpiphanyMemoryDomain; -pub use epiphany_state_model::EpiphanyMemoryEdge; -pub use epiphany_state_model::EpiphanyMemoryEdgeKind; -pub use epiphany_state_model::EpiphanyMemoryGraphSnapshot; -pub use epiphany_state_model::EpiphanyMemoryLifecycle; -pub use epiphany_state_model::EpiphanyMemoryNode; -pub use epiphany_state_model::EpiphanyMemoryNodeKind; -pub use epiphany_state_model::RepoFrontierAdoptedPlan; -pub use epiphany_state_model::RepoFrontierItem; -pub use epiphany_state_model::RepoFrontierStatus; - pub use validation::EpiphanyMemoryGraphValidationError; pub(crate) use validation::frontier_item_has_routeable_repository_scope; pub(crate) use validation::repo_paths_are_canonical_and_safe; diff --git a/epiphany-core/src/memory_graph/validation.rs b/epiphany-core/src/memory_graph/validation.rs index 10e4ad8b..e064e708 100644 --- a/epiphany-core/src/memory_graph/validation.rs +++ b/epiphany-core/src/memory_graph/validation.rs @@ -1,9 +1,9 @@ -use super::EpiphanyMemoryDomain; -use super::EpiphanyMemoryEdge; -use super::EpiphanyMemoryGraphSnapshot; -use super::EpiphanyMemoryLifecycle; -use super::EpiphanyMemoryNode; -use super::RepoFrontierStatus; +use crate::EpiphanyMemoryDomain; +use crate::EpiphanyMemoryEdge; +use crate::EpiphanyMemoryGraphSnapshot; +use crate::EpiphanyMemoryLifecycle; +use crate::EpiphanyMemoryNode; +use crate::RepoFrontierStatus; use std::collections::{HashMap, HashSet}; pub(crate) fn repo_paths_are_canonical_and_safe(paths: &[String]) -> bool { @@ -23,7 +23,7 @@ pub(crate) fn repo_paths_are_canonical_and_safe(paths: &[String]) -> bool { } pub(crate) fn frontier_item_has_routeable_repository_scope( - item: &epiphany_state_model::RepoFrontierItem, + item: &crate::RepoFrontierItem, ) -> bool { !item.repository_scope.is_empty() && repo_paths_are_canonical_and_safe(&item.repository_scope) } diff --git a/epiphany-core/src/mind_documents.rs b/epiphany-core/src/mind_documents.rs index 3167cbe1..63857eed 100644 --- a/epiphany-core/src/mind_documents.rs +++ b/epiphany-core/src/mind_documents.rs @@ -2,7 +2,7 @@ use std::path::Path; use anyhow::{Result, anyhow}; use cultcache_rs::{CultCache, CultCacheEnvelope, DatabaseEntry}; -use epiphany_state_model::{ +use crate::state_model::{ EpiphanyEvidenceRecord, EpiphanyInvariant, EpiphanyInvestigationCheckpoint, EpiphanyModeState, EpiphanyObservation, EpiphanySubgoal, }; diff --git a/epiphany-core/src/reasoning_context.rs b/epiphany-core/src/reasoning_context.rs index 4078bbfe..51a2ea4c 100644 --- a/epiphany-core/src/reasoning_context.rs +++ b/epiphany-core/src/reasoning_context.rs @@ -68,10 +68,10 @@ impl From for EpiphanyRolePassAuthorityProject pub struct EpiphanyRepoModelPromptProjection { pub identity: crate::EpiphanyRepoModelIdentityDocument, pub projection_digest: String, - pub domains: Vec, - pub nodes: Vec, - pub edges: Vec, - pub frontier: Vec, + pub domains: Vec, + pub nodes: Vec, + pub edges: Vec, + pub frontier: Vec, pub claim_obligations: Vec, pub surface_offers: Vec, pub dependency_claims: Vec, @@ -104,16 +104,16 @@ pub struct EpiphanyMindPromptProjection { pub projection_digest: String, pub objective: Option, pub active_subgoal_id: Option, - pub subgoals: Vec, - pub invariants: Vec, - pub observations: Vec, - pub evidence: Vec, + pub subgoals: Vec, + pub invariants: Vec, + pub observations: Vec, + pub evidence: Vec, pub verification_audits: Vec, pub reorientation_decisions: Vec, pub reorientation_failures: Vec, pub agent_pass_admission_refusals: Vec, - pub investigation_checkpoint: Option, - pub mode: Option, + pub investigation_checkpoint: Option, + pub mode: Option, pub repository_body_observation: Option, pub repo_model: Option, } @@ -2627,7 +2627,7 @@ mod tests { let make = |key: &str, summary: &str| -> Result { let cache = runtime_spine_cache(&store)?; let document = crate::EpiphanyMindObservationDocument { - value: epiphany_state_model::EpiphanyObservation { + value: crate::EpiphanyObservation { id: key.into(), summary: summary.into(), source_kind: "test".into(), diff --git a/epiphany-core/src/reorientation_work.rs b/epiphany-core/src/reorientation_work.rs index 09fa74e2..2e7a80bc 100644 --- a/epiphany-core/src/reorientation_work.rs +++ b/epiphany-core/src/reorientation_work.rs @@ -19,10 +19,10 @@ pub struct EpiphanyReorientationStateProjection { pub runtime_id: String, pub objective: Option, pub active_subgoal_id: Option, - pub investigation_checkpoint: Option, - pub mode: Option, + pub investigation_checkpoint: Option, + pub mode: Option, pub repository_body_observation: Option, - pub frontier: Vec, + pub frontier: Vec, pub projection_digest: String, } @@ -1060,7 +1060,7 @@ mod tests { cache.put( "unrelated-observation", &crate::EpiphanyMindObservationDocument { - value: epiphany_state_model::EpiphanyObservation { + value: crate::EpiphanyObservation { id: "unrelated-observation".into(), summary: "Persona observed an unrelated social fact.".into(), ..Default::default() diff --git a/epiphany-core/src/repo_model_documents.rs b/epiphany-core/src/repo_model_documents.rs index 32703de1..5b66ca6e 100644 --- a/epiphany-core/src/repo_model_documents.rs +++ b/epiphany-core/src/repo_model_documents.rs @@ -3,7 +3,7 @@ use std::path::Path; use anyhow::{Result, anyhow}; use cultcache_rs::{CultCache, CultCacheEnvelope, DatabaseEntry}; -use epiphany_state_model::{ +use crate::state_model::{ EpiphanyMemoryDomain, EpiphanyMemoryEdge, EpiphanyMemoryGraphSnapshot, EpiphanyMemoryNode, RepoFrontierItem, }; @@ -835,7 +835,7 @@ pub fn plan_repo_model_mutation( { insert_strong_envelope(&mut strong, existing)?; } - node.lifecycle = epiphany_state_model::EpiphanyMemoryLifecycle::Retired; + node.lifecycle = crate::EpiphanyMemoryLifecycle::Retired; nodes.insert(node_id.clone(), node.clone()); insert_envelope( &mut writes, @@ -879,7 +879,7 @@ pub fn plan_repo_model_mutation( .get_envelope::(edge_id)? .ok_or_else(|| anyhow!("RepoModel edge lost its envelope"))?; insert_strong_envelope(&mut strong, existing)?; - edge.lifecycle = epiphany_state_model::EpiphanyMemoryLifecycle::Retired; + edge.lifecycle = crate::EpiphanyMemoryLifecycle::Retired; edges.insert(edge_id.clone(), edge.clone()); insert_envelope( &mut writes, @@ -1319,9 +1319,9 @@ fn require_semantic_id(value: &str, label: &str) -> Result<()> { fn frontier_is_unresolved(item: &RepoFrontierItem) -> bool { matches!( item.status, - epiphany_state_model::RepoFrontierStatus::Proposed - | epiphany_state_model::RepoFrontierStatus::Active - | epiphany_state_model::RepoFrontierStatus::Blocked + crate::RepoFrontierStatus::Proposed + | crate::RepoFrontierStatus::Active + | crate::RepoFrontierStatus::Blocked ) } @@ -1509,9 +1509,9 @@ fn validate_claim_obligations( if !item.target_claim_ids.contains(&obligation.node_id) || !matches!( item.status, - epiphany_state_model::RepoFrontierStatus::Proposed - | epiphany_state_model::RepoFrontierStatus::Active - | epiphany_state_model::RepoFrontierStatus::Blocked + crate::RepoFrontierStatus::Proposed + | crate::RepoFrontierStatus::Active + | crate::RepoFrontierStatus::Blocked ) { return Err(anyhow!("RepoModel claim obligation is not live")); @@ -1521,9 +1521,9 @@ fn validate_claim_obligations( for item in frontier.iter().filter(|item| { matches!( item.status, - epiphany_state_model::RepoFrontierStatus::Proposed - | epiphany_state_model::RepoFrontierStatus::Active - | epiphany_state_model::RepoFrontierStatus::Blocked + crate::RepoFrontierStatus::Proposed + | crate::RepoFrontierStatus::Active + | crate::RepoFrontierStatus::Blocked ) }) { for node_id in &item.target_claim_ids { @@ -1542,7 +1542,7 @@ fn validate_claim_obligations( mod tests { use super::*; use crate::{RuntimeSpineInitOptions, initialize_runtime_spine}; - use epiphany_state_model::{ + use crate::state_model::{ EpiphanyMemoryEdgeKind, EpiphanyMemoryLifecycle, EpiphanyMemoryNodeKind, RepoFrontierStatus, }; diff --git a/epiphany-core/src/repo_model_gateway.rs b/epiphany-core/src/repo_model_gateway.rs index fcbd9370..9193d843 100644 --- a/epiphany-core/src/repo_model_gateway.rs +++ b/epiphany-core/src/repo_model_gateway.rs @@ -418,7 +418,7 @@ pub struct RepoFrontierRoute { #[cultcache(key = 11)] pub authorized_paths: Vec, #[cultcache(key = 12, default)] - pub adopted_plan: Option, + pub adopted_plan: Option, #[cultcache(key = 13)] pub selected_at: String, } diff --git a/epiphany-state-model/src/lib.rs b/epiphany-core/src/state_model.rs similarity index 74% rename from epiphany-state-model/src/lib.rs rename to epiphany-core/src/state_model.rs index 4fb147a5..4e893012 100644 --- a/epiphany-state-model/src/lib.rs +++ b/epiphany-core/src/state_model.rs @@ -1,83 +1,70 @@ +//! Core-owned semantic state contracts. + use std::path::PathBuf; -use schemars::JsonSchema; use serde::Deserialize; use serde::Serialize; -use ts_rs::TS; -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema, TS, Default)] +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Default)] pub struct EpiphanySubgoal { pub id: String, pub title: String, pub status: String, #[serde(default, skip_serializing_if = "Option::is_none")] - #[ts(type = "string | null")] pub summary: Option, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema, TS, Default)] +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Default)] pub struct EpiphanyInvariant { pub id: String, pub description: String, pub status: String, #[serde(default, skip_serializing_if = "Option::is_none")] - #[ts(type = "string | null")] pub rationale: Option, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema, TS, Default)] +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Default)] pub struct EpiphanyCodeRef { pub path: PathBuf, #[serde(default, skip_serializing_if = "Option::is_none")] - #[ts(type = "number | null")] pub start_line: Option, #[serde(default, skip_serializing_if = "Option::is_none")] - #[ts(type = "number | null")] pub end_line: Option, #[serde(default, skip_serializing_if = "Option::is_none")] - #[ts(type = "string | null")] pub symbol: Option, #[serde(default, skip_serializing_if = "Option::is_none")] - #[ts(type = "string | null")] pub note: Option, } -#[derive(Serialize, Deserialize, Clone, Copy, Debug, PartialEq, Eq, JsonSchema, TS, Default)] +#[derive(Serialize, Deserialize, Clone, Copy, Debug, PartialEq, Eq, Default)] #[serde(rename_all = "snake_case")] -#[ts(rename_all = "snake_case")] pub enum EpiphanyInvestigationDisposition { #[default] ResumeReady, RegatherRequired, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema, TS, Default)] +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Default)] pub struct EpiphanyInvestigationCheckpoint { pub checkpoint_id: String, pub kind: String, pub disposition: EpiphanyInvestigationDisposition, pub focus: String, #[serde(default, skip_serializing_if = "Option::is_none")] - #[ts(type = "string | null")] pub summary: Option, #[serde(default, skip_serializing_if = "Option::is_none")] - #[ts(type = "string | null")] pub next_action: Option, #[serde(default, skip_serializing_if = "Option::is_none")] - #[ts(type = "string | null")] pub captured_at_turn_id: Option, #[serde(default, skip_serializing_if = "Vec::is_empty")] - #[ts(type = "Array")] pub open_questions: Vec, #[serde(default, skip_serializing_if = "Vec::is_empty")] - #[ts(type = "Array")] pub code_refs: Vec, #[serde(default, skip_serializing_if = "Vec::is_empty")] - #[ts(type = "Array")] pub evidence_ids: Vec, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema, TS, Default)] +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Default)] pub struct EpiphanyObservation { pub id: String, pub summary: String, @@ -89,7 +76,7 @@ pub struct EpiphanyObservation { pub evidence_ids: Vec, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema, TS, Default)] +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Default)] pub struct EpiphanyEvidenceRecord { pub id: String, pub kind: String, @@ -99,16 +86,15 @@ pub struct EpiphanyEvidenceRecord { pub code_refs: Vec, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema, TS, Default)] +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Default)] pub struct EpiphanyModeState { pub name: String, #[serde(default, skip_serializing_if = "Option::is_none")] - #[ts(type = "ModeKind | null")] pub kind: Option, } #[derive( - Serialize, Deserialize, Clone, Copy, Debug, PartialEq, Eq, Hash, JsonSchema, TS, Default, + Serialize, Deserialize, Clone, Copy, Debug, PartialEq, Eq, Hash, Default, )] #[serde(rename_all = "snake_case")] pub enum EpiphanyModeKind { @@ -123,36 +109,30 @@ pub enum EpiphanyModeKind { Default, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema, TS, Default)] +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Default)] pub struct EpiphanyMemoryGraphSnapshot { pub graph_id: String, #[serde(default, skip_serializing_if = "Vec::is_empty")] - #[ts(type = "Array")] pub domains: Vec, #[serde(default, skip_serializing_if = "Vec::is_empty")] - #[ts(type = "Array")] pub nodes: Vec, #[serde(default, skip_serializing_if = "Vec::is_empty")] - #[ts(type = "Array")] pub edges: Vec, #[serde(default, skip_serializing_if = "Vec::is_empty")] - #[ts(type = "Array")] pub frontier: Vec, } /// A durable piece of unfinished repository anatomy. This is Modeling-owned state, /// not a scheduler job or a presentation card. -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema, TS, Default)] +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Default)] pub struct RepoFrontierItem { pub id: String, pub migration_body: String, pub question: String, pub gap: String, #[serde(default, skip_serializing_if = "Vec::is_empty")] - #[ts(type = "Array")] pub target_claim_ids: Vec, #[serde(default, skip_serializing_if = "Vec::is_empty")] - #[ts(type = "Array")] /// Canonical repository-relative path ceiling for this wound. This is the /// scope that downstream Planning may narrow and Hands may eventually /// change; inspected files and evidence provenance belong elsewhere. @@ -162,36 +142,28 @@ pub struct RepoFrontierItem { /// propose this payload, but only the dedicated model transition may make /// it part of Modeling-owned truth. #[serde(default, skip_serializing_if = "Option::is_none")] - #[ts(type = "RepoFrontierAdoptedPlan | null")] pub adopted_plan: Option, #[serde(default, skip_serializing_if = "Vec::is_empty")] - #[ts(type = "Array")] pub dependency_item_ids: Vec, #[serde(default)] pub status: RepoFrontierStatus, #[serde(default, skip_serializing_if = "Vec::is_empty")] - #[ts(type = "Array")] pub evidence_refs: Vec, /// Exact immutable public sources selected upstream for Eyes. These are /// causal retrieval inputs, not evidence produced by Modeling. #[serde(default, skip_serializing_if = "Vec::is_empty")] - #[ts(type = "Array")] pub public_source_refs: Vec, #[serde(default, skip_serializing_if = "Option::is_none")] - #[ts(type = "string | null")] pub created_at: Option, #[serde(default, skip_serializing_if = "Option::is_none")] - #[ts(type = "string | null")] pub updated_at: Option, #[serde(default, skip_serializing_if = "Option::is_none")] - #[ts(type = "string | null")] pub retired_at: Option, #[serde(default, skip_serializing_if = "Option::is_none")] - #[ts(type = "string | null")] pub superseded_by: Option, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema, TS, Default)] +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Default)] pub struct RepoFrontierAdoptedPlan { pub planning_request_id: String, pub result_id: String, @@ -199,18 +171,14 @@ pub struct RepoFrontierAdoptedPlan { pub candidate_id: String, pub candidate_sha256: String, #[serde(default, skip_serializing_if = "Vec::is_empty")] - #[ts(type = "Array")] pub safe_paths: Vec, pub action: String, pub command: String, #[serde(default, skip_serializing_if = "Vec::is_empty")] - #[ts(type = "Array")] pub checks: Vec, #[serde(default, skip_serializing_if = "Vec::is_empty")] - #[ts(type = "Array")] pub stop_conditions: Vec, #[serde(default, skip_serializing_if = "Vec::is_empty")] - #[ts(type = "Array")] pub rollback_steps: Vec, pub commit_message: String, } @@ -225,9 +193,8 @@ impl RepoFrontierAdoptedPlan { } } -#[derive(Serialize, Deserialize, Clone, Copy, Debug, PartialEq, Eq, JsonSchema, TS, Default)] +#[derive(Serialize, Deserialize, Clone, Copy, Debug, PartialEq, Eq, Default)] #[serde(rename_all = "snake_case")] -#[ts(rename_all = "snake_case")] pub enum RepoFrontierStatus { #[default] Proposed, @@ -238,22 +205,20 @@ pub enum RepoFrontierStatus { Superseded, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema, TS, Default)] +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Default)] pub struct EpiphanyMemoryDomain { pub id: String, pub title: String, #[serde(default, skip_serializing_if = "Option::is_none")] - #[ts(type = "string | null")] pub description: Option, #[serde(default)] pub lifecycle: EpiphanyMemoryLifecycle, } #[derive( - Serialize, Deserialize, Clone, Copy, Debug, PartialEq, Eq, Hash, JsonSchema, TS, Default, + Serialize, Deserialize, Clone, Copy, Debug, PartialEq, Eq, Hash, Default, )] #[serde(rename_all = "snake_case")] -#[ts(rename_all = "snake_case")] pub enum EpiphanyMemoryLifecycle { #[default] Observed, @@ -264,10 +229,9 @@ pub enum EpiphanyMemoryLifecycle { } #[derive( - Serialize, Deserialize, Clone, Copy, Debug, PartialEq, Eq, Hash, JsonSchema, TS, Default, + Serialize, Deserialize, Clone, Copy, Debug, PartialEq, Eq, Hash, Default, )] #[serde(rename_all = "snake_case")] -#[ts(rename_all = "snake_case")] pub enum EpiphanyMemoryNodeKind { #[default] Domain, @@ -283,7 +247,7 @@ pub enum EpiphanyMemoryNodeKind { Other, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema, TS, Default)] +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Default)] pub struct EpiphanyMemoryNode { pub id: String, pub domain_id: String, @@ -294,26 +258,21 @@ pub struct EpiphanyMemoryNode { pub tension: String, pub action_implication: String, #[serde(default, skip_serializing_if = "Vec::is_empty")] - #[ts(type = "Array")] pub anchors: Vec, #[serde(default, skip_serializing_if = "Vec::is_empty")] - #[ts(type = "Array")] pub source_hashes: Vec, #[serde(default)] pub lifecycle: EpiphanyMemoryLifecycle, #[serde(default, skip_serializing_if = "Option::is_none")] - #[ts(type = "string | null")] pub created_at: Option, #[serde(default, skip_serializing_if = "Option::is_none")] - #[ts(type = "string | null")] pub updated_at: Option, } #[derive( - Serialize, Deserialize, Clone, Copy, Debug, PartialEq, Eq, Hash, JsonSchema, TS, Default, + Serialize, Deserialize, Clone, Copy, Debug, PartialEq, Eq, Hash, Default, )] #[serde(rename_all = "snake_case")] -#[ts(rename_all = "snake_case")] pub enum EpiphanyMemoryEdgeKind { #[default] Owns, @@ -332,7 +291,7 @@ pub enum EpiphanyMemoryEdgeKind { Other, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema, TS, Default)] +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Default)] pub struct EpiphanyMemoryEdge { pub id: String, pub source_id: String, @@ -340,27 +299,22 @@ pub struct EpiphanyMemoryEdge { pub kind: EpiphanyMemoryEdgeKind, pub claim: String, #[serde(default, skip_serializing_if = "Vec::is_empty")] - #[ts(type = "Array")] pub anchors: Vec, #[serde(default)] pub lifecycle: EpiphanyMemoryLifecycle, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema, TS, Default)] +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Default)] pub struct EpiphanyMemoryAnchor { pub id: String, pub kind: String, pub target: String, #[serde(default, skip_serializing_if = "Option::is_none")] - #[ts(type = "EpiphanyCodeRef | null")] pub code_ref: Option, #[serde(default, skip_serializing_if = "Option::is_none")] - #[ts(type = "string | null")] pub evidence_id: Option, #[serde(default, skip_serializing_if = "Option::is_none")] - #[ts(type = "string | null")] pub source_hash: Option, #[serde(default, skip_serializing_if = "Option::is_none")] - #[ts(type = "string | null")] pub note: Option, } diff --git a/epiphany-core/src/surfaces/research_decision.rs b/epiphany-core/src/surfaces/research_decision.rs index b4030934..119c1d07 100644 --- a/epiphany-core/src/surfaces/research_decision.rs +++ b/epiphany-core/src/surfaces/research_decision.rs @@ -1,7 +1,7 @@ use anyhow::{Result, anyhow}; -use epiphany_state_model::EpiphanyEvidenceRecord; -use epiphany_state_model::EpiphanyInvestigationCheckpoint; -use epiphany_state_model::EpiphanyObservation; +use crate::state_model::EpiphanyEvidenceRecord; +use crate::state_model::EpiphanyInvestigationCheckpoint; +use crate::state_model::EpiphanyObservation; use serde::{Deserialize, Serialize}; use std::collections::BTreeSet; diff --git a/epiphany-state-model/Cargo.toml b/epiphany-state-model/Cargo.toml deleted file mode 100644 index 5d48d99a..00000000 --- a/epiphany-state-model/Cargo.toml +++ /dev/null @@ -1,19 +0,0 @@ -[package] -name = "epiphany-state-model" -version = "0.1.0" -edition = "2024" -publish = false -license-file = "../LICENSE" - -[lib] -name = "epiphany_state_model" -path = "src/lib.rs" - -[dependencies] -schemars = "0.8" -serde = { version = "1", features = ["derive"] } -ts-rs = { version = "11", features = [ - "uuid-impl", - "serde-json-impl", - "no-serde-warnings", -] } diff --git a/notes/codex-auth-spine-inventory.md b/notes/codex-auth-spine-inventory.md index 606fb4c2..4393641f 100644 --- a/notes/codex-auth-spine-inventory.md +++ b/notes/codex-auth-spine-inventory.md @@ -188,11 +188,11 @@ application. `codex-core` re-exports the contract only as a compatibility alias, and `CodexThread` now calls native state-update functions around its remaining revision check, persistence validation, and rollout/session writeback. -The credential extraction overcut has been corrected. Codex file/keyring/auto -auth, env API key handling, ChatGPT token refresh, account metadata parsing, -and header-client setup remain in vendored `codex-login`. The redundant -Epiphany re-export crate is gone; the root workspace carries the Codex -`tokio-tungstenite` / `tungstenite` patches required for standalone builds. +This paragraph describes the superseded embedded-auth phase. Exact `ed7357a2` +later removed Codex credential and transport anatomy from Epiphany entirely; +the independent CodexConnector owns that boundary. The unused root +`tokio-tungstenite` / `tungstenite` patches are gone with the compiled Codex +graph. The point is ownership: Epiphany calls a model adapter; it does not live inside the Codex host brain. diff --git a/notes/epiphany-fork-implementation-plan.md b/notes/epiphany-fork-implementation-plan.md index ef05b5b6..304d018e 100644 --- a/notes/epiphany-fork-implementation-plan.md +++ b/notes/epiphany-fork-implementation-plan.md @@ -7,14 +7,13 @@ of app-server routes. ## Objective Build an inspectable native organism whose typed state, runtime, organ gates, -memory, scheduling, interfaces, and social crossings can operate without Codex -owning Epiphany cognition. Retain Codex-derived code only where it provides an -earned OpenAI-compatible authentication or model-transport capability. +memory, scheduling, interfaces, and social crossings operate without Codex +owning Epiphany cognition. OpenAI subscription authentication and model +transport belong to the independent CodexConnector daemon, not Epiphany's body. ## Current Mechanism -- `epiphany-state-model` owns shared typed semantic contracts; durable Mind is keyed CultCache owned by `epiphany-core`. -- `epiphany-core` owns keyed Mind admission, runtime spine, organ gates, +- `epiphany-core` owns the semantic contracts, keyed Mind admission, runtime spine, organ gates, Resident Self physiology, Persona, and CultMesh integration. Coordinator policy, status, and every migrated work family consume keyed Mind plus exact runtime receipts. Persisted `EpiphanyThreadStateEntry`, the in-memory