Render dynamic Verse prompt context
This commit is contained in:
parent
2ea573769b
commit
0fca183873
7 changed files with 384 additions and 4 deletions
155
epiphany-core/src/bin/epiphany-prompt-context-smoke.rs
Normal file
155
epiphany-core/src/bin/epiphany-prompt-context-smoke.rs
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
use anyhow::Result;
|
||||
use epiphany_core::EpiphanyMemoryContextQuery;
|
||||
use epiphany_core::EpiphanyMemoryDomain;
|
||||
use epiphany_core::EpiphanyMemoryFreshnessStatus;
|
||||
use epiphany_core::EpiphanyMemoryGraphSnapshot;
|
||||
use epiphany_core::EpiphanyMemoryLifecycle;
|
||||
use epiphany_core::EpiphanyMemoryNode;
|
||||
use epiphany_core::EpiphanyMemoryNodeKind;
|
||||
use epiphany_core::EpiphanyMemoryProfile;
|
||||
use epiphany_core::EpiphanyMemorySummary;
|
||||
use epiphany_core::EpiphanyPromptContextInput;
|
||||
use epiphany_core::memory_graph_domain_id;
|
||||
use epiphany_core::memory_graph_node_id;
|
||||
use epiphany_core::plan_memory_graph_context_cut;
|
||||
use epiphany_core::query_epiphany_local_verse_context;
|
||||
use epiphany_core::render_epiphany_prompt_context;
|
||||
use epiphany_core::seed_epiphany_local_verse_context;
|
||||
use serde_json::json;
|
||||
use std::env;
|
||||
use std::path::PathBuf;
|
||||
|
||||
fn main() -> Result<()> {
|
||||
let store = env::args().nth(1).map(PathBuf::from).unwrap_or_else(|| {
|
||||
PathBuf::from(".epiphany-smoke")
|
||||
.join("cultmesh")
|
||||
.join("epiphany-prompt-context.ccmp")
|
||||
});
|
||||
if let Some(parent) = store.parent() {
|
||||
std::fs::create_dir_all(parent)?;
|
||||
}
|
||||
|
||||
seed_epiphany_local_verse_context(
|
||||
&store,
|
||||
"epiphany-prompt-context-smoke",
|
||||
"2026-06-02T00:00:00Z",
|
||||
)?;
|
||||
let local_verse = query_epiphany_local_verse_context(&store, "epiphany-prompt-context-smoke")?;
|
||||
let memory_context = plan_memory_graph_context_cut(
|
||||
&smoke_snapshot(),
|
||||
&EpiphanyMemoryContextQuery {
|
||||
id: "prompt-context-smoke-query".to_string(),
|
||||
profile: Some(EpiphanyMemoryProfile::RepoArchitecture),
|
||||
text: Some("Verse prompt assembly".to_string()),
|
||||
budget: Some(4),
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
let rendered = render_epiphany_prompt_context(&EpiphanyPromptContextInput {
|
||||
focus: "Build a bounded worker prompt from local Verse and memory context.".to_string(),
|
||||
local_verse,
|
||||
memory_context,
|
||||
});
|
||||
|
||||
let checks = [
|
||||
rendered.contains("<epiphany_dynamic_context>"),
|
||||
rendered.contains("Odin"),
|
||||
rendered.contains("Yggdrasil"),
|
||||
rendered.contains("Bifrost"),
|
||||
rendered.contains("gamecult-local"),
|
||||
rendered.contains("Verse-backed prompt assembly"),
|
||||
rendered.contains("Mind reviews durable state effects"),
|
||||
!rendered.contains("raw private worker transcript should never render"),
|
||||
];
|
||||
if checks.iter().any(|passed| !passed) {
|
||||
anyhow::bail!("prompt context smoke failed rendered packet checks:\n{rendered}");
|
||||
}
|
||||
|
||||
println!(
|
||||
"{}",
|
||||
serde_json::to_string_pretty(&json!({
|
||||
"status": "ok",
|
||||
"store": store,
|
||||
"renderedBytes": rendered.len(),
|
||||
"containsVerseContext": true,
|
||||
"containsMemoryContext": true,
|
||||
"omitsUnselectedPrivateText": true,
|
||||
}))?
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn smoke_snapshot() -> EpiphanyMemoryGraphSnapshot {
|
||||
let domain_id = memory_graph_domain_id(
|
||||
EpiphanyMemoryProfile::RepoArchitecture,
|
||||
"crate",
|
||||
"epiphany-core",
|
||||
);
|
||||
let selected_node = memory_graph_node_id(
|
||||
&domain_id,
|
||||
"module",
|
||||
"epiphany-core/src/prompt_context.rs",
|
||||
Some("prompt_context"),
|
||||
);
|
||||
let unselected_node = memory_graph_node_id(
|
||||
&domain_id,
|
||||
"module",
|
||||
"sealed/raw_worker_transcript.rs",
|
||||
Some("sealed_private_text"),
|
||||
);
|
||||
|
||||
EpiphanyMemoryGraphSnapshot {
|
||||
graph_id: "prompt-context-smoke".to_string(),
|
||||
domains: vec![EpiphanyMemoryDomain {
|
||||
id: domain_id.clone(),
|
||||
profile: EpiphanyMemoryProfile::RepoArchitecture,
|
||||
title: "epiphany-core".to_string(),
|
||||
lifecycle: EpiphanyMemoryLifecycle::Accepted,
|
||||
..Default::default()
|
||||
}],
|
||||
nodes: vec![
|
||||
EpiphanyMemoryNode {
|
||||
id: selected_node.clone(),
|
||||
domain_id: domain_id.clone(),
|
||||
profile: EpiphanyMemoryProfile::RepoArchitecture,
|
||||
kind: EpiphanyMemoryNodeKind::Module,
|
||||
title: "prompt_context".to_string(),
|
||||
claim: "Verse-backed prompt assembly injects bounded local Verse and semantic memory packets.".to_string(),
|
||||
action_implication:
|
||||
"Use compact dynamic context before launching broad swarm turns."
|
||||
.to_string(),
|
||||
lifecycle: EpiphanyMemoryLifecycle::Accepted,
|
||||
confidence: 90,
|
||||
salience: 90,
|
||||
..Default::default()
|
||||
},
|
||||
EpiphanyMemoryNode {
|
||||
id: unselected_node,
|
||||
domain_id: domain_id.clone(),
|
||||
profile: EpiphanyMemoryProfile::RepoArchitecture,
|
||||
kind: EpiphanyMemoryNodeKind::Module,
|
||||
title: "sealed_private_text".to_string(),
|
||||
claim: "raw private worker transcript should never render".to_string(),
|
||||
action_implication: "This text must stay absent from the smoke output.".to_string(),
|
||||
lifecycle: EpiphanyMemoryLifecycle::Accepted,
|
||||
confidence: 90,
|
||||
salience: 10,
|
||||
..Default::default()
|
||||
},
|
||||
],
|
||||
summaries: vec![EpiphanyMemorySummary {
|
||||
id: "summary-prompt-context".to_string(),
|
||||
domain_id,
|
||||
covers_node_ids: vec![selected_node],
|
||||
target: "prompt_context".to_string(),
|
||||
claim: "Verse-backed prompt assembly can ask the local Verse and memory graph for compact context.".to_string(),
|
||||
action_implication:
|
||||
"Render this packet into worker prompts, then keep Mind as the durable-state gate."
|
||||
.to_string(),
|
||||
freshness: EpiphanyMemoryFreshnessStatus::Ready,
|
||||
confidence: 95,
|
||||
..Default::default()
|
||||
}],
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
|
@ -12,6 +12,7 @@ mod memory_graph;
|
|||
mod mind_gateway;
|
||||
mod organ_dependencies;
|
||||
mod promotion;
|
||||
mod prompt_context;
|
||||
mod proposal;
|
||||
mod retrieval;
|
||||
mod runtime_spine;
|
||||
|
|
@ -357,6 +358,8 @@ pub use promotion::EpiphanyPromotionInput;
|
|||
pub use promotion::EpiphanyStateReplacementValidationInput;
|
||||
pub use promotion::evaluate_promotion;
|
||||
pub use promotion::validate_state_replacement_patch;
|
||||
pub use prompt_context::EpiphanyPromptContextInput;
|
||||
pub use prompt_context::render_epiphany_prompt_context;
|
||||
pub use proposal::EpiphanyMapProposal;
|
||||
pub use proposal::EpiphanyMapProposalInput;
|
||||
pub use proposal::propose_map_update;
|
||||
|
|
|
|||
213
epiphany-core/src/prompt_context.rs
Normal file
213
epiphany-core/src/prompt_context.rs
Normal file
|
|
@ -0,0 +1,213 @@
|
|||
use crate::EpiphanyLocalVerseContext;
|
||||
use epiphany_state_model::EpiphanyMemoryContextPacket;
|
||||
use epiphany_state_model::EpiphanyMemoryFreshnessStatus;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct EpiphanyPromptContextInput {
|
||||
pub focus: String,
|
||||
pub local_verse: EpiphanyLocalVerseContext,
|
||||
pub memory_context: EpiphanyMemoryContextPacket,
|
||||
}
|
||||
|
||||
pub fn render_epiphany_prompt_context(input: &EpiphanyPromptContextInput) -> String {
|
||||
let mut lines = vec![
|
||||
"<epiphany_dynamic_context>".to_string(),
|
||||
"## Dynamic Context".to_string(),
|
||||
format!("- Focus: {}", compact_line(&input.focus)),
|
||||
"- Boundary: this packet is prompt context, not durable state admission.".to_string(),
|
||||
"- Boundary: Mind reviews durable state effects; Substrate Gate reviews repo access; public Verse material is thought weather until adoption.".to_string(),
|
||||
String::new(),
|
||||
"## Local Verse".to_string(),
|
||||
format!("- Runtime: `{}`", input.local_verse.runtime_id),
|
||||
format!("- Store: `{}`", input.local_verse.store_path),
|
||||
format!("- Odin: {}", compact_line(&input.local_verse.odin_scope)),
|
||||
format!(
|
||||
"- Yggdrasil: {}",
|
||||
compact_line(&input.local_verse.yggdrasil_scope)
|
||||
),
|
||||
format!(
|
||||
"- Prompt assembly: {}",
|
||||
compact_line(&input.local_verse.prompt_assembly_note)
|
||||
),
|
||||
];
|
||||
|
||||
for policy in input.local_verse.verse_policies.iter().take(3) {
|
||||
lines.push(format!(
|
||||
"- Verse `{}` [{}]: private={}, untrusted_ingress={}, yggdrasil_tunnel={}; {}",
|
||||
policy.verse_id,
|
||||
policy.tier,
|
||||
policy.private_state_allowed,
|
||||
policy.untrusted_ingress_allowed,
|
||||
policy.yggdrasil_tunnel_allowed,
|
||||
compact_line(&policy.purpose)
|
||||
));
|
||||
}
|
||||
|
||||
if let Some(status) = input.local_verse.operator_status.as_ref() {
|
||||
lines.push(format!(
|
||||
"- Operator status `{}`: {}",
|
||||
status.status,
|
||||
compact_line(&status.summary)
|
||||
));
|
||||
}
|
||||
|
||||
if !input.local_verse.contract_summaries.is_empty() {
|
||||
lines.push("## Organ Contract Summary".to_string());
|
||||
for contract in input.local_verse.contract_summaries.iter().take(8) {
|
||||
lines.push(format!(
|
||||
"- `{}` [{} -> {}]: ops={}, receipts={}",
|
||||
contract.contract_id,
|
||||
contract.authority,
|
||||
contract.verse_id,
|
||||
contract.operations.len(),
|
||||
contract.receipt_document_types.len()
|
||||
));
|
||||
}
|
||||
push_omitted_count(
|
||||
&mut lines,
|
||||
input.local_verse.contract_summaries.len(),
|
||||
8,
|
||||
"organ contract summaries",
|
||||
);
|
||||
}
|
||||
|
||||
lines.push("## Semantic Memory Context".to_string());
|
||||
lines.push(format!(
|
||||
"- Packet `{}` from query `{}`",
|
||||
input.memory_context.id, input.memory_context.query_id
|
||||
));
|
||||
|
||||
for summary in input.memory_context.summaries.iter().take(4) {
|
||||
lines.push(format!(
|
||||
"- Summary `{}` [{}]: {}; next: {}",
|
||||
summary.id,
|
||||
render_freshness(summary.freshness),
|
||||
compact_line(&summary.claim),
|
||||
compact_line(&summary.action_implication)
|
||||
));
|
||||
}
|
||||
push_omitted_count(
|
||||
&mut lines,
|
||||
input.memory_context.summaries.len(),
|
||||
4,
|
||||
"memory summaries",
|
||||
);
|
||||
|
||||
for node in input.memory_context.nodes.iter().take(6) {
|
||||
lines.push(format!(
|
||||
"- Node `{}` [{}]: {}; next: {}",
|
||||
node.id,
|
||||
node.title,
|
||||
compact_line(&node.claim),
|
||||
compact_line(&node.action_implication)
|
||||
));
|
||||
}
|
||||
push_omitted_count(
|
||||
&mut lines,
|
||||
input.memory_context.nodes.len(),
|
||||
6,
|
||||
"memory nodes",
|
||||
);
|
||||
|
||||
if !input.memory_context.warnings.is_empty() {
|
||||
lines.push("## Memory Context Warnings".to_string());
|
||||
for warning in input.memory_context.warnings.iter().take(4) {
|
||||
lines.push(format!("- {}", compact_line(warning)));
|
||||
}
|
||||
}
|
||||
|
||||
if !input.memory_context.missing_node_ids.is_empty()
|
||||
|| !input.memory_context.missing_edge_ids.is_empty()
|
||||
{
|
||||
lines.push("## Missing Memory References".to_string());
|
||||
if !input.memory_context.missing_node_ids.is_empty() {
|
||||
lines.push(format!(
|
||||
"- Missing nodes: {}",
|
||||
input.memory_context.missing_node_ids.join(", ")
|
||||
));
|
||||
}
|
||||
if !input.memory_context.missing_edge_ids.is_empty() {
|
||||
lines.push(format!(
|
||||
"- Missing edges: {}",
|
||||
input.memory_context.missing_edge_ids.join(", ")
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
lines.push("</epiphany_dynamic_context>".to_string());
|
||||
lines.join("\n")
|
||||
}
|
||||
|
||||
fn render_freshness(status: EpiphanyMemoryFreshnessStatus) -> &'static str {
|
||||
match status {
|
||||
EpiphanyMemoryFreshnessStatus::Missing => "missing",
|
||||
EpiphanyMemoryFreshnessStatus::Ready => "ready",
|
||||
EpiphanyMemoryFreshnessStatus::Stale => "stale",
|
||||
EpiphanyMemoryFreshnessStatus::Indexing => "indexing",
|
||||
EpiphanyMemoryFreshnessStatus::Unavailable => "unavailable",
|
||||
}
|
||||
}
|
||||
|
||||
fn compact_line(value: &str) -> String {
|
||||
let mut compacted = value.split_whitespace().collect::<Vec<_>>().join(" ");
|
||||
if compacted.len() > 260 {
|
||||
compacted.truncate(257);
|
||||
compacted.push_str("...");
|
||||
}
|
||||
compacted
|
||||
}
|
||||
|
||||
fn push_omitted_count(lines: &mut Vec<String>, total: usize, shown: usize, label: &str) {
|
||||
if total > shown {
|
||||
lines.push(format!("- ... {} more {} not shown", total - shown, label));
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::query_epiphany_local_verse_context;
|
||||
use crate::seed_epiphany_local_verse_context;
|
||||
use epiphany_state_model::EpiphanyMemoryContextPacket;
|
||||
use epiphany_state_model::EpiphanyMemoryFreshnessStatus;
|
||||
use epiphany_state_model::EpiphanyMemorySummary;
|
||||
|
||||
#[test]
|
||||
fn prompt_context_renders_verse_and_memory_without_state_authority() -> anyhow::Result<()> {
|
||||
let temp = tempfile::tempdir()?;
|
||||
let store = temp.path().join("epiphany-local-verse.ccmp");
|
||||
seed_epiphany_local_verse_context(&store, "epiphany-test", "2026-06-02T00:00:00Z")?;
|
||||
let local_verse = query_epiphany_local_verse_context(&store, "epiphany-test")?;
|
||||
let memory_context = EpiphanyMemoryContextPacket {
|
||||
id: "memctx-test".to_string(),
|
||||
query_id: "query-test".to_string(),
|
||||
summaries: vec![EpiphanyMemorySummary {
|
||||
id: "summary-test".to_string(),
|
||||
claim: "Shared graph law lets prompt assembly ask for relevant memory instead of hauling the archive.".to_string(),
|
||||
action_implication:
|
||||
"Inject the compact packet, then let Mind review any durable effect."
|
||||
.to_string(),
|
||||
freshness: EpiphanyMemoryFreshnessStatus::Ready,
|
||||
confidence: 90,
|
||||
..Default::default()
|
||||
}],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let rendered = render_epiphany_prompt_context(&EpiphanyPromptContextInput {
|
||||
focus: "Assemble context for a bounded worker prompt.".to_string(),
|
||||
local_verse,
|
||||
memory_context,
|
||||
});
|
||||
|
||||
assert!(rendered.contains("<epiphany_dynamic_context>"));
|
||||
assert!(rendered.contains("Odin"));
|
||||
assert!(rendered.contains("Yggdrasil"));
|
||||
assert!(rendered.contains("Bifrost"));
|
||||
assert!(rendered.contains("gamecult-local"));
|
||||
assert!(rendered.contains("Shared graph law"));
|
||||
assert!(rendered.contains("Mind reviews durable state effects"));
|
||||
assert!(!rendered.contains("raw worker transcript"));
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
@ -127,6 +127,7 @@ The first native query tool is:
|
|||
cargo run --manifest-path .\epiphany-core\Cargo.toml --bin epiphany-verse-query -- smoke
|
||||
cargo run --manifest-path .\epiphany-core\Cargo.toml --bin epiphany-verse-query -- seed
|
||||
cargo run --manifest-path .\epiphany-core\Cargo.toml --bin epiphany-verse-query -- query
|
||||
cargo run --manifest-path .\epiphany-core\Cargo.toml --bin epiphany-prompt-context-smoke
|
||||
```
|
||||
|
||||
This writes and reads a compact CultMesh-backed local Verse context bundle:
|
||||
|
|
@ -143,6 +144,13 @@ This writes and reads a compact CultMesh-backed local Verse context bundle:
|
|||
This is not semantic search yet. It is the first typed inspection packet the
|
||||
future prompt assembler can depend on.
|
||||
|
||||
`epiphany-prompt-context-smoke` is the first prompt-context proof on top of
|
||||
that packet. It seeds local Verse context, builds a memory graph context cut,
|
||||
renders the combined dynamic prompt packet, and asserts that Verse/Odin/
|
||||
Yggdrasil/Bifrost context plus relevant semantic memory appear while unrelated
|
||||
private-looking text stays absent. It is still a local proof, not a live swarm
|
||||
runner.
|
||||
|
||||
## Invariants
|
||||
|
||||
- CultCache documents are the data.
|
||||
|
|
@ -165,8 +173,9 @@ For swarm migration, the next useful chain is:
|
|||
2. Add semantic memory graph query packets beside the Verse policy/status
|
||||
packet.
|
||||
3. Teach worker launch prompt assembly to consume those packets explicitly.
|
||||
4. Add a smoke that proves a worker prompt includes relevant Verse/memory
|
||||
context and omits unrelated private sludge.
|
||||
4. Extend the prompt-context smoke into a launch-document smoke that proves a
|
||||
worker prompt includes relevant Verse/memory context and omits unrelated
|
||||
private sludge.
|
||||
5. Move one Aquarium/local-run read path to the native Verse query before
|
||||
increasing swarm cadence.
|
||||
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ remembers doctrine; the branch remembers the blade.
|
|||
- Native status now exposes that quarantined bridge spine without granting it authority. `runtime_spine_status` counts tool invocation intents, receipts, and pending calls; `runtime_tool_invocation_statuses` derives read-only intent/receipt status rows; `epiphany-runtime-spine status` reports the counts; and `epiphany-mvp-status --runtime-store <path>` renders the latest tool calls under `tools`. This is operator visibility only. The model-runtime feedback seam is also now typed: MCP-shaped model tool calls preserve the original provider `call_id` plus source model request id; `epiphany-model-runtime tool-followup` builds a provider-neutral follow-up `EpiphanyModelRequest` from completed typed tool receipts using the previous provider response id; and `epiphany-model-runtime tool-followup-turn` derives and runs that continuation through the selected provider in one runtime-owned operation. `epiphany-model-runtime run-worker --auto-tools --tool-adapter-bin <path>` now lets a launched worker automatically execute typed MCP intents through the quarantined Codex MCP adapter, feed receipts back through follow-up model turns, and only then parse/complete the worker result. Codex still executes the quarantined MCP edge; Epiphany owns the continuation request shape and invocation boundary.
|
||||
- The active foundation directive is now `notes/codex-starvation-and-cultnet-liberation-plan.md`. The previous Codex app-server control-plane rebuild made Epiphany less rotten inside Codex, but that is not the destination. Epiphany must become a native CultCache/CultMesh/CultNet runtime while remaining an honest modified Codex-derived backend for subscription auth/model use. Codex should remain relatively vanilla and keep doing Codex things, including useful app-server and streaming bridge affordances, but it must not own Epiphany state, processes, prompts, scheduler decisions, or policy. The bridge handles interop; Codex and Epiphany do not get to rummage around in each other's organs.
|
||||
- `notes/epiphany-cultmesh-dreaming-roadmap.md` is the new concrete design for distributed Epiphany dreaming. The invariant is hard: private state stays local; public dreams are separately authored typed documents distributed through CultMesh/CultNet; foreign dreams are thought weather until a reviewed local adoption receipt digests them. The first code slice should be dream schemas plus a local CultMesh-backed store, not public fanout.
|
||||
- CultMesh is now the preferred Rust abstraction for that local store work. The compile-time Rust substrate is repo-contained: `vendor/cultcache-rs`, `vendor/cultnet-rs`, and `vendor/cultmesh-rs`. The old `E:\Projects\CultLib\crates\*` dependency body is dead in this checkout and must not be revived by accident. Vendored CultCache reads/writes `cultcache.store.v1`, so `state/ledgers.msgpack` and `epiphany-state status` are aligned again. The first integrations are deliberately small: status, Verse policy, global room policy, organ contract policy, native operator status, native operator snapshots, and local operator run intent/receipt round-trip through CultMesh. `notes/epiphany-verse-architecture.md` now names the local Verse/Odin/Yggdrasil architecture: Odin sees advertised Verse metadata without bypassing boundaries, Yggdrasil hosts important trusted GameCult Verses such as Bifrost, and prompt assembly should query compact local Verse plus semantic memory packets instead of carrying the whole archive. Use `cargo run --manifest-path .\epiphany-core\Cargo.toml --bin epiphany-cultmesh-smoke`, `cargo run --manifest-path .\epiphany-core\Cargo.toml --bin epiphany-cultmesh-status -- smoke --store .\.epiphany-smoke\cultmesh\operator-status.ccmp --runtime-id epiphany-cultmesh-status-smoke`, `cargo run --manifest-path .\epiphany-core\Cargo.toml --bin epiphany-operator-snapshot -- smoke --store .\.epiphany-smoke\cultmesh\operator-snapshots.ccmp --runtime-id epiphany-operator-snapshot-smoke --snapshot-id smoke-status`, `cargo run --manifest-path .\epiphany-core\Cargo.toml --bin epiphany-operator-run -- smoke --store .\.epiphany-smoke\cultmesh\operator-runs.ccmp --runtime-id epiphany-operator-run-smoke --run-id smoke-run`, and `cargo run --manifest-path .\epiphany-core\Cargo.toml --bin epiphany-verse-query -- smoke` for the focused proofs. Future local dream/status/Verse work should start from CultMesh, not raw CultNet, unless the task is polishing the CultMesh internals themselves. Preserve the three Verse tiers: `epiphany-internal` for private sub-agent typed state, `gamecult-local` for trusted LAN/Yggdrasil-tunnel GameCult sharing, and `epiphany-global` for untrusted public dreams plus topic-specific threaded public rooms for Face posts.
|
||||
- CultMesh is now the preferred Rust abstraction for that local store work. The compile-time Rust substrate is repo-contained: `vendor/cultcache-rs`, `vendor/cultnet-rs`, and `vendor/cultmesh-rs`. The old `E:\Projects\CultLib\crates\*` dependency body is dead in this checkout and must not be revived by accident. Vendored CultCache reads/writes `cultcache.store.v1`, so `state/ledgers.msgpack` and `epiphany-state status` are aligned again. The first integrations are deliberately small: status, Verse policy, global room policy, organ contract policy, native operator status, native operator snapshots, and local operator run intent/receipt round-trip through CultMesh. `notes/epiphany-verse-architecture.md` now names the local Verse/Odin/Yggdrasil architecture: Odin sees advertised Verse metadata without bypassing boundaries, Yggdrasil hosts important trusted GameCult Verses such as Bifrost, and prompt assembly should query compact local Verse plus semantic memory packets instead of carrying the whole archive. Use `cargo run --manifest-path .\epiphany-core\Cargo.toml --bin epiphany-cultmesh-smoke`, `cargo run --manifest-path .\epiphany-core\Cargo.toml --bin epiphany-cultmesh-status -- smoke --store .\.epiphany-smoke\cultmesh\operator-status.ccmp --runtime-id epiphany-cultmesh-status-smoke`, `cargo run --manifest-path .\epiphany-core\Cargo.toml --bin epiphany-operator-snapshot -- smoke --store .\.epiphany-smoke\cultmesh\operator-snapshots.ccmp --runtime-id epiphany-operator-snapshot-smoke --snapshot-id smoke-status`, `cargo run --manifest-path .\epiphany-core\Cargo.toml --bin epiphany-operator-run -- smoke --store .\.epiphany-smoke\cultmesh\operator-runs.ccmp --runtime-id epiphany-operator-run-smoke --run-id smoke-run`, `cargo run --manifest-path .\epiphany-core\Cargo.toml --bin epiphany-verse-query -- smoke`, and `cargo run --manifest-path .\epiphany-core\Cargo.toml --bin epiphany-prompt-context-smoke` for the focused proofs. Future local dream/status/Verse work should start from CultMesh, not raw CultNet, unless the task is polishing the CultMesh internals themselves. Preserve the three Verse tiers: `epiphany-internal` for private sub-agent typed state, `gamecult-local` for trusted LAN/Yggdrasil-tunnel GameCult sharing, and `epiphany-global` for untrusted public dreams plus topic-specific threaded public rooms for Face posts.
|
||||
- `notes/codex-auth-spine-inventory.md` is the source-grounded keeper list for that reliquary. Corrected compliance invariant: Codex-compatible auth identity stays anchored in vendored Codex-derived auth machinery. `epiphany-openai-auth-spine` is now a thin Epiphany-named boundary over `codex-login`, not a clean-room clone of credential storage or token refresh. Codex apps, skills, marketplace, plugin UX, broad app-server workflow, and JSON-RPC sprawl remain cuttable because they are not subscription-auth legitimacy.
|
||||
- Edge JSON is allowed for schema description, hostile ingress before immediate typed parsing, sealed forensic artifacts, or named quarantine experiments. When both subsystems are ours, runtime data must remain typed CultCache documents and move over CultNet typed contracts. Generic `serde_json::Value` in worker launch/result/selfPatch/runtime flow is contamination until classified and replaced.
|
||||
- `notes/epiphany-swarm-readiness-plan.md` is the current live-fire direction gate. The local runner proves startup/status/coordinator wiring; it does not authorize unattended swarm operation. Carry VoidBot's lessons forward: one CTB-style initiative scheduler, typed pause/brake, active-turn freeze, cooldown after completion, stale active-turn recovery receipts, parent-side speech eligibility, memory lifecycle phases, and typed operation proposals instead of prompt-owned governance.
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -72,7 +72,7 @@ data_flow:
|
|||
active_subgoals:
|
||||
- Use `notes/epiphany-cultmesh-dreaming-roadmap.md` as the design authority for distributed Epiphany dreaming. Public dreams are separately authored typed documents distributed through CultMesh/CultNet; private state remains local and cannot be shared by flipping a visibility flag. Foreign dreams are external thought weather until a reviewed local adoption receipt digests them into memory, planning, doctrine, or governance.
|
||||
- CultMesh is now the preferred ergonomic Rust abstraction over CultCache and CultNet for Epiphany-owned local database surfaces. The Rust substrate is repo-contained under `vendor/cultcache-rs`, `vendor/cultnet-rs`, and `vendor/cultmesh-rs`; the old `E:\Projects\CultLib\crates\*` path is dead in this checkout and must not be reintroduced as a compile-time dependency. Future local Verse/dream/status work should start at CultMesh unless it is explicitly polishing CultMesh internals. Preserve the three-Verse boundary: `epiphany-internal` for private sub-agent typed state, `gamecult-local` for trusted LAN/Yggdrasil-tunnel GameCult project sharing, and `epiphany-global` for untrusted public dreams plus topic-specific threaded public rooms for Face posts.
|
||||
- Use `notes/epiphany-verse-architecture.md` as the source note for local Verse/Odin/Yggdrasil prompt-context architecture. Odin is the all-seer discovery/coordinator surface for advertised Verse metadata, not a trust-boundary bypass. Yggdrasil is the hosted spine for important trusted GameCult Verses such as Bifrost. The first native local Verse query surface is `epiphany-verse-query`, which seeds/queries compact CultMesh policy/status/contract context for future dynamic prompt assembly; it is not semantic memory search or public sharing yet.
|
||||
- Use `notes/epiphany-verse-architecture.md` as the source note for local Verse/Odin/Yggdrasil prompt-context architecture. Odin is the all-seer discovery/coordinator surface for advertised Verse metadata, not a trust-boundary bypass. Yggdrasil is the hosted spine for important trusted GameCult Verses such as Bifrost. The first native local Verse query surface is `epiphany-verse-query`, which seeds/queries compact CultMesh policy/status/contract context for future dynamic prompt assembly; `epiphany-prompt-context-smoke` now proves that compact local Verse context plus a semantic memory graph context cut can render a bounded dynamic prompt packet while omitting unrelated private-looking text.
|
||||
- The active priority is Codex starvation and CultNet liberation. Use `notes/codex-starvation-and-cultnet-liberation-plan.md` as the directive and `notes/codex-auth-spine-inventory.md` as the source-grounded keeper list for the retained OpenAI subscription auth/model transport bridge. Classify all Epiphany-relevant JSON contamination, define the native CultNet runtime boundary, keep worker launch/result/selfPatch cargo as typed documents, evacuate Epiphany operator/state/process authority from Codex JSON-RPC, wrap MCP's unavoidable JSON protocol edge in typed Epiphany intent/result/receipt documents, and keep cutting until Epiphany can run its own state and processes without `codex_message_processor.rs` except for bridge compatibility.
|
||||
- Use `notes/epiphany-anatomy.md` as the canonical anatomy map. Embodied sub-agents are Self, Face, Imagination, Eyes, Proprioception, Hands, and Soul. Body is substrate, Mind is persistent state/state admission, Continuity is recovery/compaction/sleep protocol machinery, and Substrate Gate is substrate access protocol.
|
||||
- Organ state now has a hard profile split: resident Epiphany sub-agents use lean `work_organ` state, public/person-shaped agents use portable `persona` state, and heartbeat/swarm machinery owns scheduling/coordination physiology. Face is the Epiphany organ; Persona is the shared GameCult contract for Epiphany Face, VoidBot repo Faces, and Ghostlight characters. Persona documents carry provenance, required public presentation metadata, `date-time` timestamps, typed `candidateActions`, strict anchored thoughts with non-authoritative extensions, custom enum companion labels, and typed affect subrecords for bonds/status reads/doctrine stances. Work organs must not inherit Persona affect/social-bond/status-read machinery just because the old Ghostlight-derived shape had room for it.
|
||||
|
|
|
|||
Reference in a new issue