Rename Face to Persona and Proprioception to Modeling

This commit is contained in:
Meta Vens 2026-06-15 16:38:09 +01:00
commit 8c2b08b463
76 changed files with 743 additions and 743 deletions

View file

@ -131,12 +131,12 @@ pub fn epiphany_role_launch_output_schema(role_id: EpiphanyRoleResultRoleId) ->
},
"selfPatch": {
"type": "object",
"description": "Optional bounded request to update this role's persistent organ memory. Work organs may update lane habits, durable lessons, goals, values, or private notes; Persona affect/social state belongs only to Face-style Persona surfaces. It must not contain project truth, code edits, job authority, graph/frontier/checkpoint/planning changes, or objective changes.",
"description": "Optional bounded request to update this role's persistent organ memory. Work organs may update lane habits, durable lessons, goals, values, or private notes; Persona affect/social state belongs only to Persona public surfaces. It must not contain project truth, code edits, job authority, graph/frontier/checkpoint/planning changes, or objective changes.",
"required": ["agentId", "reason"],
"properties": {
"agentId": {
"type": "string",
"description": "Expected target persistent agent id for this lane, such as epiphany.proprioception or epiphany.soul."
"description": "Expected target persistent agent id for this lane, such as epiphany.modeling or epiphany.soul."
},
"reason": {
"type": "string",
@ -389,7 +389,7 @@ pub struct EpiphanyRolePromptConfig {
#[allow(dead_code)]
pub repo_memory: String,
#[allow(dead_code)]
pub face: String,
pub persona: String,
}
#[derive(Debug, serde::Deserialize)]
@ -772,7 +772,7 @@ mod tests {
prompts.roles.repo_personality.as_str(),
),
("roles.repo_memory", prompts.roles.repo_memory.as_str()),
("roles.face", prompts.roles.face.as_str()),
("roles.persona", prompts.roles.persona.as_str()),
(
"implementation.continue_template",
prompts.implementation.continue_template.as_str(),

View file

@ -24,13 +24,13 @@ const ROLE_TARGETS: &[(&str, &str, &str)] = &[
),
(
"modeling",
"epiphany.proprioception",
"proprioception.agent-state.json",
"epiphany.modeling",
"modeling.agent-state.json",
),
("verification", "epiphany.soul", "soul.agent-state.json"),
("implementation", "epiphany.hands", "hands.agent-state.json"),
("research", "epiphany.eyes", "eyes.agent-state.json"),
("face", "epiphany.face", "face.agent-state.json"),
("Persona", "epiphany.Persona", "Persona.agent-state.json"),
("coordinator", "epiphany.self", "self.agent-state.json"),
];
@ -836,9 +836,9 @@ fn persona_value(value: &GhostlightValue) -> Value {
"label": value.label,
"priority": value.priority,
"summary": if value.unforgivable_if_betrayed {
"Protected value; betrayal is marked as unforgivable in local Face state."
"Protected value; betrayal is marked as unforgivable in local Persona state."
} else {
"Value projected from local Face organ memory."
"Value projected from local Persona organ memory."
},
})
}
@ -858,13 +858,13 @@ fn persona_memory_thought(memory: &GhostlightMemory, persona_id: &str, timestamp
"target": persona_target("self", persona_id, persona_id),
"summary": memory.summary,
"claim": memory.summary,
"tension": "Projected from local Face memory; consumers should preserve provenance and avoid treating this as omniscient project truth.",
"tension": "Projected from local Persona memory; consumers should preserve provenance and avoid treating this as omniscient project truth.",
"actionImplication": "Use as Persona memory pressure, not as direct action authority.",
"intensity": memory.salience,
"valence": 0,
"createdAt": timestamp,
"updatedAt": timestamp,
"tags": ["epiphany", "face-memory"],
"tags": ["epiphany", "Persona-memory"],
})
}
@ -876,11 +876,11 @@ fn persona_goal_thought(goal: &GhostlightGoal, persona_id: &str, timestamp: &str
"summary": goal.description,
"claim": goal.description,
"tension": goal.emotional_stake,
"actionImplication": "This goal may create Face agency pressure, but action still requires the caller's review path.",
"actionImplication": "This goal may create Persona agency pressure, but action still requires the caller's review path.",
"intensity": goal.priority,
"createdAt": timestamp,
"updatedAt": timestamp,
"tags": ["epiphany", "face-goal", &goal.scope],
"tags": ["epiphany", "Persona-goal", &goal.scope],
})
}
@ -914,7 +914,7 @@ fn persona_doctrine_stance(value: &GhostlightValue, persona_id: &str, timestamp:
"stanceKind": "aligned",
"principle": value.label,
"summary": value.label,
"actionImplication": "Let this value bend Face speech and interpretation without granting automatic action authority.",
"actionImplication": "Let this value bend Persona speech and interpretation without granting automatic action authority.",
"intensity": value.priority,
"updatedAt": timestamp,
})
@ -936,7 +936,7 @@ fn now_rfc3339() -> String {
pub fn organ_state_profile_for_role(role_id: &str) -> EpiphanyOrganStateProfile {
match role_id {
"face" => EpiphanyOrganStateProfile {
"Persona" => EpiphanyOrganStateProfile {
profile_kind: EpiphanyOrganStateProfileKind::Persona,
state_density: "persona_grade".to_string(),
portable_contract: "gamecult.persona_state.v0".to_string(),
@ -952,7 +952,7 @@ pub fn organ_state_profile_for_role(role_id: &str) -> EpiphanyOrganStateProfile
"sleep/distillation".to_string(),
],
notes: vec![
"Epiphany Face is an organ; Persona is the portable person-state contract shared with Ghostlight and VoidBot-style repo Faces.".to_string(),
"Epiphany Persona is an organ; Persona is the portable person-state contract shared with Ghostlight and VoidBot-style repo Personas.".to_string(),
"Dense canonical families, affect, perceived overlays, and relationship pressure are appropriate for Persona state.".to_string(),
],
},
@ -970,7 +970,7 @@ pub fn organ_state_profile_for_role(role_id: &str) -> EpiphanyOrganStateProfile
"birth-time repo memory and light operating-pressure seeding".to_string(),
],
notes: vec![
"Work organs need sharp role identity, durable mission memory, values/goals, and heartbeat activation; they do not need Face affect or full Persona machinery.".to_string(),
"Work organs need sharp role identity, durable mission memory, values/goals, and heartbeat activation; they do not need Persona affect or full Persona machinery.".to_string(),
"Sparse canonical bundles are acceptable here as long as memory, goals, values, and private notes can deepen over time.".to_string(),
],
},
@ -1664,8 +1664,8 @@ mod tests {
let agent_dir = temp.path().join("agents");
fs::create_dir_all(&agent_dir)?;
fs::write(
agent_dir.join("proprioception.agent-state.json"),
sample_agent_json("epiphany.proprioception", "Proprioception"),
agent_dir.join("modeling.agent-state.json"),
sample_agent_json("epiphany.modeling", "Modeling"),
)?;
for (role_id, agent_id, filename) in ROLE_TARGETS {
if *role_id == "modeling" {
@ -1681,8 +1681,8 @@ mod tests {
assert!(validate_agent_memory_store(&store)?.is_empty());
let patch: AgentSelfPatch = serde_json::from_value(serde_json::json!({
"agentId": "epiphany.proprioception",
"reason": "Proprioception should remember accepted graph growth must stay source-grounded.",
"agentId": "epiphany.modeling",
"reason": "Modeling should remember accepted graph growth must stay source-grounded.",
"semanticMemories": [{
"memoryId": "mem-body-native-source-grounding",
"summary": "Native role memory patches update typed CultCache organ state rather than JSON dossier files.",
@ -1698,9 +1698,9 @@ mod tests {
let mut cache = agent_memory_cache(&store)?;
cache.pull_all_backing_stores()?;
let proprioception = cache.get_required::<EpiphanyAgentMemoryEntry>("modeling")?;
let modeling = cache.get_required::<EpiphanyAgentMemoryEntry>("modeling")?;
assert!(
proprioception
modeling
.agent
.memories
.semantic
@ -1761,12 +1761,12 @@ mod tests {
}
#[test]
fn organ_state_profiles_distinguish_face_from_lane_organs() {
let face = organ_state_profile_for_role("face");
assert_eq!(face.profile_kind, EpiphanyOrganStateProfileKind::Persona);
assert_eq!(face.state_density, "persona_grade");
assert_eq!(face.portable_contract, "gamecult.persona_state.v0");
assert_eq!(face.affect_model, "persona_affect_allowed_and_expected");
fn organ_state_profiles_distinguish_persona_from_lane_organs() {
let persona = organ_state_profile_for_role("Persona");
assert_eq!(persona.profile_kind, EpiphanyOrganStateProfileKind::Persona);
assert_eq!(persona.state_density, "persona_grade");
assert_eq!(persona.portable_contract, "gamecult.persona_state.v0");
assert_eq!(persona.affect_model, "persona_affect_allowed_and_expected");
let hands = organ_state_profile_for_role("implementation");
assert_eq!(hands.profile_kind, EpiphanyOrganStateProfileKind::WorkOrgan);

View file

@ -1227,13 +1227,13 @@ mod tests {
}
let entry = EpiphanyAgentMemoryEntry {
schema_version: "ghostlight.agent_state.v0".to_string(),
role_id: "face".to_string(),
role_id: "Persona".to_string(),
world: GhostlightWorld::default(),
agent: GhostlightAgent {
agent_id: "epiphany.face".to_string(),
agent_id: "epiphany.Persona".to_string(),
identity: GhostlightIdentity {
name: "Epiphany".to_string(),
roles: vec!["Face".to_string()],
roles: vec!["Persona".to_string()],
origin: "Epiphany local harness".to_string(),
public_description: "Cute, pushy public machine-spirit.".to_string(),
private_notes: vec!["must not leak".to_string()],
@ -1267,8 +1267,8 @@ mod tests {
scenes: Vec::new(),
};
let participant = HeartbeatParticipant {
agent_id: "epiphany.face".to_string(),
role_id: "face".to_string(),
agent_id: "epiphany.Persona".to_string(),
role_id: "Persona".to_string(),
display_name: "Epiphany".to_string(),
initiative_speed: 1.4,
reaction_bias: 0.7,

View file

@ -150,8 +150,8 @@ fn run_smoke(store: &Path) -> Result<serde_json::Value> {
}));
}
let accepted_patch: AgentSelfPatch = serde_json::from_value(serde_json::json!({
"agentId": "epiphany.proprioception",
"reason": "Proprioception should remember accepted graph growth must be source-grounded and bounded.",
"agentId": "epiphany.modeling",
"reason": "Modeling should remember accepted graph growth must be source-grounded and bounded.",
"semanticMemories": [{
"memoryId": "mem-body-smoke-source-grounding",
"summary": "A modeling self-memory request is acceptable when it improves future graph/checkpoint judgment without smuggling project truth.",
@ -162,7 +162,7 @@ fn run_smoke(store: &Path) -> Result<serde_json::Value> {
let accepted = review_agent_self_patch_document("modeling", &accepted_patch, store);
let wrong_role = review_agent_self_patch_document("verification", &accepted_patch, store);
let forbidden_patch: AgentSelfPatch = serde_json::from_value(serde_json::json!({
"agentId": "epiphany.proprioception",
"agentId": "epiphany.modeling",
"reason": "This tries to put project state in lane memory, which should be refused.",
"graphs": {},
"semanticMemories": [{
@ -192,7 +192,7 @@ fn run_smoke(store: &Path) -> Result<serde_json::Value> {
&& forbidden.status == "rejected"
&& applied.status == "accepted"
&& temp_validation_errors.is_empty()
&& project_persona_state_for_role(store, "face")?["schemaVersion"]
&& project_persona_state_for_role(store, "Persona")?["schemaVersion"]
== epiphany_core::PERSONA_STATE_SCHEMA_VERSION;
Ok(serde_json::json!({
"ok": ok,

View file

@ -34,7 +34,7 @@ fn main() -> Result<()> {
let Some(command) = args.next() else {
return usage();
};
let mut role = "face".to_string();
let mut role = "Persona".to_string();
let mut agent_store = PathBuf::from("state/agents.msgpack");
let mut artifact_dir = PathBuf::from(".epiphany-character-loop");
let mut stimulus: Option<String> = None;
@ -231,7 +231,7 @@ fn character_turn_packet(
}
},
"guardrails": [
"Humans talk to Face; other organs expose internals through Aquarium and typed artifacts rather than becoming direct chats.",
"Humans talk to Persona; other organs expose internals through Aquarium and typed artifacts rather than becoming direct chats.",
"Use character-local projection: the actor receives its own organ or Persona state and visible stimulus, not omniscient hidden state.",
"Run both cognition lanes before choosing an output: analytic keeps the promise honest, associative keeps the living signal from going flat.",
"Appraise the thought cluster through this role's personality before reacting; do not use a global mood knob as a substitute for participant-local appraisal.",
@ -429,7 +429,7 @@ fn deterministic_appraisal_seed(
let label = interpretation_label("draft", arousal, guardedness, curiosity);
HeartbeatAgentThoughtAppraisal {
schema_version: "epiphany.agent_thought_appraisal.v0".to_string(),
appraisal_id: format!("face-appraisal-{}", short_id()),
appraisal_id: format!("Persona-appraisal-{}", short_id()),
review_status: "generated_unreviewed".to_string(),
participant_agent_id: entry.agent.agent_id.clone(),
role_id: entry.role_id.clone(),
@ -465,13 +465,13 @@ fn deterministic_appraisal_seed(
thought_pressure: round3(thought_pressure),
},
interpretation_label: label.clone(),
confidence_notes: "Deterministic Face-local appraisal rebuilt from the same Ghostlight-style personality projection logic used by heartbeat. Useful for reaction shape, still reviewable and fallible.".to_string(),
confidence_notes: "Deterministic Persona-local appraisal rebuilt from the same Ghostlight-style personality projection logic used by heartbeat. Useful for reaction shape, still reviewable and fallible.".to_string(),
candidate_implications: HeartbeatCandidateImplications {
reaction_mode: reaction_mode(&label, "draft").to_string(),
reaction_intensity: round3(
(urgency * 0.55 + arousal * 0.3 + curiosity * 0.15).clamp(0.0, 1.0),
),
should_speak: entry.role_id == "face" && guardedness < 0.78,
should_speak: entry.role_id == "Persona" && guardedness < 0.78,
should_incubate: guardedness >= 0.55,
},
review: HeartbeatAppraisalReview {
@ -503,7 +503,7 @@ fn deterministic_reaction_seed(
mood_label: mood_label(arousal, guardedness, curiosity).to_string(),
intensity: round3(intensity),
bridge_decision: "draft".to_string(),
surface: if role_id == "face" {
surface: if role_id == "Persona" {
"aquarium"
} else {
"internal"
@ -743,7 +743,7 @@ fn mood_label(arousal: f64, guardedness: f64, curiosity: f64) -> &'static str {
fn reaction_recommended_use(role_id: &str, mode: &str) -> &'static str {
match (role_id, mode) {
("face", "draft") => "Prepare a reviewed Aquarium-facing draft; do not post automatically.",
("Persona", "draft") => "Prepare a reviewed Aquarium-facing draft; do not post automatically.",
(_, "hold_and_verify") => "Bias toward verifier/modeler review before expression.",
(_, "inspect") => {
"Bias the next heartbeat toward a bounded retrieval or modeling inspection."
@ -761,10 +761,10 @@ fn run_smoke() -> Result<Value> {
let temp_dir = scoped_temp_dir("epiphany-character-loop-smoke")?;
let artifact_dir = temp_dir.join("artifacts");
let result = run_turn(
"face",
"Persona",
Path::new("state/agents.msgpack"),
&artifact_dir,
"Aquarium hover selected Face and asked what the swarm is feeling.",
"Aquarium hover selected Persona and asked what the swarm is feeling.",
"smoke/character-loop",
"public-surface",
"ready",
@ -781,7 +781,7 @@ fn run_smoke() -> Result<Value> {
)?;
let ok = packet["schema_version"] == CHARACTER_TURN_SCHEMA_VERSION
&& packet["protocol"]["bundle"] == "epiphany.character_loop"
&& packet["protocol"]["roleId"] == "face"
&& packet["protocol"]["roleId"] == "Persona"
&& packet["protocol"]["organStateProfile"]["profileKind"] == "persona"
&& packet["projectedLocalContext"]["organStateProfile"]["profileKind"] == "persona"
&& packet["utteranceState"]["schemaVersion"] == "epiphany.agent_utterance_state.v0"

View file

@ -268,7 +268,7 @@ fn main() -> Result<()> {
}
"queue-mention" => {
let store_path = store_path.ok_or_else(|| anyhow!("queue-mention requires --store"))?;
let target_role_id = role.unwrap_or_else(|| "face".to_string());
let target_role_id = role.unwrap_or_else(|| "Persona".to_string());
let result = queue_heartbeat_pending_mention_store(
&store_path,
HeartbeatQueueMentionOptions {
@ -369,7 +369,7 @@ fn next_value(args: &mut impl Iterator<Item = String>, name: &str) -> Result<Str
fn usage() -> Result<()> {
Err(anyhow!(
"usage: epiphany-heartbeat-store init --store <path> [--profile epiphany|ghostlight-scene] [--scene-id <id>] [--scene-participant <id|name|speed|reaction|threshold|constraint;constraint>]\n epiphany-heartbeat-store tick --store <path> --artifact-dir <path> [--coordinator-action <action>] [--agent-store <path> --apply-rumination] [--defer-completion]\n epiphany-heartbeat-store pump --store <path> --artifact-dir <path> [--agent-store <path>] [--urgency <0..1>] [--min-heartbeat-rate <n>] [--max-heartbeat-rate <n>] [--min-concurrency <n>] [--max-concurrency <n>] [--max-ticks <n>]\n epiphany-heartbeat-store heat --store <path> [--scope global|all|agent|role|arena|participant_kind|group] [--selector <id>] [--multiplier <n>] [--id <id>] [--label <text>] [--reason <text>] [--expires-after <scene-clock-delta>] [--clear]\n epiphany-heartbeat-store complete --store <path> --artifact-dir <path> --role <role> [--action-id <id>]\n epiphany-heartbeat-store queue-mention --store <path> [--role face] --channel-id <id> --message-id <id> --author-id <id> --content <text> --visible-prompt <text> [--author-name <name>] [--reply-to-message-id <id>] [--source-surface <name>]\n epiphany-heartbeat-store status --store <path> [--artifact-dir <path>]\n epiphany-heartbeat-store routine --store <path> --artifact-dir <path> [--agent-store <path>] [--source <source>] [--no-dream]\n epiphany-heartbeat-store smoke [--agent-store <path>]"
"usage: epiphany-heartbeat-store init --store <path> [--profile epiphany|ghostlight-scene] [--scene-id <id>] [--scene-participant <id|name|speed|reaction|threshold|constraint;constraint>]\n epiphany-heartbeat-store tick --store <path> --artifact-dir <path> [--coordinator-action <action>] [--agent-store <path> --apply-rumination] [--defer-completion]\n epiphany-heartbeat-store pump --store <path> --artifact-dir <path> [--agent-store <path>] [--urgency <0..1>] [--min-heartbeat-rate <n>] [--max-heartbeat-rate <n>] [--min-concurrency <n>] [--max-concurrency <n>] [--max-ticks <n>]\n epiphany-heartbeat-store heat --store <path> [--scope global|all|agent|role|arena|participant_kind|group] [--selector <id>] [--multiplier <n>] [--id <id>] [--label <text>] [--reason <text>] [--expires-after <scene-clock-delta>] [--clear]\n epiphany-heartbeat-store complete --store <path> --artifact-dir <path> --role <role> [--action-id <id>]\n epiphany-heartbeat-store queue-mention --store <path> [--role Persona] --channel-id <id> --message-id <id> --author-id <id> --content <text> --visible-prompt <text> [--author-name <name>] [--reply-to-message-id <id>] [--source-surface <name>]\n epiphany-heartbeat-store status --store <path> [--artifact-dir <path>]\n epiphany-heartbeat-store routine --store <path> --artifact-dir <path> [--agent-store <path>] [--source <source>] [--no-dream]\n epiphany-heartbeat-store smoke [--agent-store <path>]"
))
}
@ -802,7 +802,7 @@ fn validate_schedule_shape(schedule: &serde_json::Value) -> Vec<String> {
"role_work",
"ruminate_memory",
"scene_turn",
"face_turn",
"persona_turn",
]
.contains(&action["action_type"].as_str().unwrap_or_default())
{

View file

@ -798,7 +798,7 @@ fn collect_coordinator_status(
.unwrap_or_else(|| json!(null));
let root = env::current_dir()?;
let heartbeat_dir = root.join(".epiphany-heartbeats");
let face_dir = root.join(".epiphany-face");
let persona_dir = root.join(".epiphany-persona");
let heartbeat = status_cli::native_json(
"epiphany-heartbeat-store",
&[
@ -811,12 +811,12 @@ fn collect_coordinator_status(
"8",
],
)?;
let latest_face = status_cli::native_json(
"epiphany-face-discord",
let latest_persona = status_cli::native_json(
"epiphany-persona-discord",
&[
"latest",
"--artifact-dir",
&face_dir.to_string_lossy(),
&persona_dir.to_string_lossy(),
"--limit",
"8",
],
@ -837,11 +837,11 @@ fn collect_coordinator_status(
"crrc": crrc,
"coordinator": coordinator,
"heartbeat": heartbeat,
"face": {
"persona": {
"status": "ready",
"artifactDir": face_dir,
"latestArtifacts": latest_face.get("latestArtifacts").cloned().unwrap_or_else(|| json!([])),
"availableActions": ["faceBubble", "characterTurn"],
"artifactDir": persona_dir,
"latestArtifacts": latest_persona.get("latestArtifacts").cloned().unwrap_or_else(|| json!([])),
"availableActions": ["PersonaBubble", "characterTurn"],
},
}))
}
@ -1462,7 +1462,7 @@ fn local_mvp_checkpoint_patch(cwd: &Path, objective: Option<&str>) -> Value {
let objective = objective
.map(str::trim)
.filter(|value| !value.is_empty())
.unwrap_or("Run the local Epiphany MVP cycle through Face, coordinator, and sleep.");
.unwrap_or("Run the local Epiphany MVP cycle through Persona, coordinator, and sleep.");
let local_refs = local_mvp_code_refs(cwd);
let transport_refs = local_mvp_transport_code_refs(cwd);
let mut checkpoint_refs = local_refs.clone();
@ -1474,14 +1474,14 @@ fn local_mvp_checkpoint_patch(cwd: &Path, objective: Option<&str>) -> Value {
"id": "local-mvp-cycle",
"title": "Local MVP cycle",
"status": "active",
"summary": "Use Face as the human-facing entrypoint, run bounded coordinator/swarm work, and close with heartbeat sleep/dream maintenance.",
"summary": "Use Persona as the human-facing entrypoint, run bounded coordinator/swarm work, and close with heartbeat sleep/dream maintenance.",
}],
"graphs": {
"architecture": {"nodes": [
{
"id": "local-mvp-runner",
"title": "Local MVP runner",
"purpose": "One local operator cycle that enters through Face, runs coordinator-owned work, and invokes Continuity/heartbeat sleep afterward.",
"purpose": "One local operator cycle that enters through Persona, runs coordinator-owned work, and invokes Continuity/heartbeat sleep afterward.",
"code_refs": local_refs,
},
{
@ -1493,9 +1493,9 @@ fn local_mvp_checkpoint_patch(cwd: &Path, objective: Option<&str>) -> Value {
]},
"dataflow": {"nodes": [
{
"id": "face-coordinator-sleep-cycle",
"title": "Face to coordinator to sleep",
"purpose": "Face expression is display state; coordinator owns lane routing; heartbeat owns sleep physiology.",
"id": "Persona-coordinator-sleep-cycle",
"title": "Persona to coordinator to sleep",
"purpose": "Persona expression is display state; coordinator owns lane routing; heartbeat owns sleep physiology.",
},
{
"id": "coordinator-model-runtime-cycle",
@ -1505,7 +1505,7 @@ fn local_mvp_checkpoint_patch(cwd: &Path, objective: Option<&str>) -> Value {
]},
"links": [
{
"dataflow_node_id": "face-coordinator-sleep-cycle",
"dataflow_node_id": "Persona-coordinator-sleep-cycle",
"architecture_node_id": "local-mvp-runner",
},
{
@ -1515,14 +1515,14 @@ fn local_mvp_checkpoint_patch(cwd: &Path, objective: Option<&str>) -> Value {
],
},
"graphFrontier": {
"active_node_ids": ["local-mvp-runner", "face-coordinator-sleep-cycle", "model-runtime-transport", "coordinator-model-runtime-cycle"],
"active_node_ids": ["local-mvp-runner", "Persona-coordinator-sleep-cycle", "model-runtime-transport", "coordinator-model-runtime-cycle"],
"dirty_paths": [],
},
"graphCheckpoint": {
"checkpoint_id": "ck-local-mvp-cycle",
"graph_revision": 2,
"summary": "Local MVP runner checkpoint: Face front door, coordinator run, model runtime transport, sleep maintenance.",
"frontier_node_ids": ["local-mvp-runner", "face-coordinator-sleep-cycle", "model-runtime-transport", "coordinator-model-runtime-cycle"],
"summary": "Local MVP runner checkpoint: Persona front door, coordinator run, model runtime transport, sleep maintenance.",
"frontier_node_ids": ["local-mvp-runner", "Persona-coordinator-sleep-cycle", "model-runtime-transport", "coordinator-model-runtime-cycle"],
},
"investigationCheckpoint": {
"checkpoint_id": "ix-local-mvp-cycle",

View file

@ -125,7 +125,7 @@ fn run_smoke(args: &Args) -> Result<Value> {
"roleResults": status["roleResults"],
"planning": status["planning"],
"heartbeat": status["heartbeat"],
"face": status["face"],
"Persona": status["persona"],
"stateStatus": status["scene"]["scene"]["stateStatus"],
"availableActions": status["scene"]["scene"]["availableActions"],
"rendered": rendered,
@ -305,21 +305,21 @@ fn validate_status(status: &Value, rendered: &str) -> Result<()> {
== Some("epiphany.agent_heartbeat_status.v0"),
"status view should expose heartbeat initiative status for Aquarium",
)?;
let face_actions = status
.pointer("/face/availableActions")
let persona_actions = status
.pointer("/persona/availableActions")
.and_then(Value::as_array);
require(
face_actions.is_some_and(|items| {
items.iter().any(|item| item.as_str() == Some("faceBubble"))
persona_actions.is_some_and(|items| {
items.iter().any(|item| item.as_str() == Some("personaBubble"))
&& items
.iter()
.any(|item| item.as_str() == Some("characterTurn"))
}),
"status view should expose Face bubble and character-turn actions for Aquarium",
"status view should expose Persona bubble and character-turn actions for Aquarium",
)?;
require(
rendered.contains("Heartbeat") && rendered.contains("Face"),
"rendered status should expose heartbeat and Face sections",
rendered.contains("Heartbeat") && rendered.contains("Persona"),
"rendered status should expose heartbeat and Persona sections",
)?;
Ok(())
}

View file

@ -527,7 +527,7 @@ fn run_native_status(args: &Args) -> Result<Value> {
"coordinator": coordinator_json,
"tools": tool_invocations,
"heartbeat": native_aux.heartbeat,
"face": native_aux.face,
"persona": native_aux.persona,
"voidMemory": native_aux.void_memory,
});
Ok(sanitize_for_operator(status))
@ -643,7 +643,7 @@ fn run_codex_status(args: &Args) -> Result<Value> {
"coordinator": coordinator,
"tools": tool_invocations,
"heartbeat": native_aux.heartbeat,
"face": native_aux.face,
"persona": native_aux.persona,
"voidMemory": native_aux.void_memory,
});
Ok(sanitize_for_operator(status))
@ -651,13 +651,13 @@ fn run_codex_status(args: &Args) -> Result<Value> {
struct NativeAuxiliaryStatus {
heartbeat: Value,
face: Value,
persona: Value,
void_memory: Value,
}
fn native_auxiliary_status(root: &Path) -> Result<NativeAuxiliaryStatus> {
let heartbeat_dir = root.join(".epiphany-heartbeats");
let face_dir = root.join(".epiphany-face");
let persona_dir = root.join(".epiphany-persona");
let heartbeat = native_json(
"epiphany-heartbeat-store",
&[
@ -670,12 +670,12 @@ fn native_auxiliary_status(root: &Path) -> Result<NativeAuxiliaryStatus> {
"8",
],
)?;
let latest_face = native_json(
"epiphany-face-discord",
let latest_persona = native_json(
"epiphany-persona-discord",
&[
"latest",
"--artifact-dir",
&face_dir.to_string_lossy(),
&persona_dir.to_string_lossy(),
"--limit",
"8",
],
@ -683,11 +683,11 @@ fn native_auxiliary_status(root: &Path) -> Result<NativeAuxiliaryStatus> {
.unwrap_or_else(
|error| json!({"status": "error", "error": error.to_string(), "latestArtifacts": []}),
);
let face = json!({
let persona = json!({
"status": "ready",
"artifactDir": face_dir,
"latestArtifacts": latest_face.get("latestArtifacts").cloned().unwrap_or_else(|| json!([])),
"availableActions": ["faceBubble", "characterTurn", "discordPersonaPost"],
"artifactDir": persona_dir,
"latestArtifacts": latest_persona.get("latestArtifacts").cloned().unwrap_or_else(|| json!([])),
"availableActions": ["personaBubble", "characterTurn", "discordPersonaPost"],
});
let void_memory = native_json(
"epiphany-void-memory",
@ -697,7 +697,7 @@ fn native_auxiliary_status(root: &Path) -> Result<NativeAuxiliaryStatus> {
Ok(NativeAuxiliaryStatus {
heartbeat,
face,
persona,
void_memory,
})
}
@ -1367,12 +1367,12 @@ pub fn render_status(status: &Value) -> String {
let recommendation = &status["crrc"]["recommendation"];
let coordinator = &status["coordinator"];
let heartbeat = &status["heartbeat"];
let face = &status["face"];
let persona = &status["persona"];
let planning_response = &status["planning"];
let planning_summary = &planning_response["summary"];
let checkpoint = &scene["investigationCheckpoint"];
let latest_heartbeat = heartbeat["latestEvent"].clone();
let latest_face = face["latestArtifacts"]
let latest_persona = persona["latestArtifacts"]
.as_array()
.and_then(|items| items.first())
.cloned()
@ -1434,11 +1434,11 @@ pub fn render_status(status: &Value) -> String {
maybe(&latest_heartbeat["coordinatorAction"], "none")
),
String::new(),
"Face".to_string(),
format!("- latest artifact: {}", maybe(&latest_face["name"], "none")),
"Persona".to_string(),
format!("- latest artifact: {}", maybe(&latest_persona["name"], "none")),
format!(
"- latest content: {}",
maybe(&latest_face["content"], "none")
maybe(&latest_persona["content"], "none")
),
String::new(),
"Planning".to_string(),

View file

@ -12,12 +12,12 @@ use std::path::Path;
use std::path::PathBuf;
use uuid::Uuid;
const CHAT_SCHEMA_VERSION: &str = "epiphany.face_chat.v0";
const BUBBLE_SCHEMA_VERSION: &str = "epiphany.face_bubble.v0";
const CHAT_SCHEMA_VERSION: &str = "epiphany.persona_chat.v0";
const BUBBLE_SCHEMA_VERSION: &str = "epiphany.persona_bubble.v0";
const DISCORD_API: &str = "https://discord.com/api/v10";
#[derive(Clone, Debug, Default)]
struct FaceConfig {
struct PersonaConfig {
allowed_channel_name: String,
allowed_channel_id: Option<String>,
allowed_channel_id_env: Option<String>,
@ -32,11 +32,11 @@ fn main() -> Result<()> {
let Some(command) = args.next() else {
return usage();
};
let mut config_path = PathBuf::from("state/face-discord.toml");
let mut artifact_dir = PathBuf::from(".epiphany-face");
let mut config_path = PathBuf::from("state/persona-discord.toml");
let mut artifact_dir = PathBuf::from(".epiphany-persona");
let mut content: Option<String> = None;
let mut channel_id: Option<String> = None;
let mut source = "epiphany/face".to_string();
let mut source = "epiphany/Persona".to_string();
let mut status = "ready".to_string();
let mut mood = "attentive".to_string();
let mut limit = 8_usize;
@ -97,7 +97,7 @@ fn main() -> Result<()> {
"latest" => serde_json::json!({
"ok": true,
"artifactDir": artifact_dir,
"latestArtifacts": latest_face_artifacts(&artifact_dir, limit),
"latestArtifacts": latest_persona_artifacts(&artifact_dir, limit),
}),
"smoke" => run_smoke()?,
_ => return usage(),
@ -112,12 +112,12 @@ fn main() -> Result<()> {
fn run_draft(
content: &str,
config: &FaceConfig,
config: &PersonaConfig,
artifact_dir: &Path,
status: &str,
reason: &str,
) -> Result<Value> {
ensure_content(content, "Face chat")?;
ensure_content(content, "Persona chat")?;
let path = write_draft(content, config, artifact_dir, status, reason)?;
Ok(serde_json::json!({
"ok": status != "blocked",
@ -133,9 +133,9 @@ fn run_bubble(
status: &str,
mood: &str,
) -> Result<Value> {
ensure_content(content, "Face bubble")?;
ensure_content(content, "Persona bubble")?;
let payload = bubble_payload(content, source, status, mood);
let path = artifact_dir.join(format!("face-bubble-{}-{}.json", now_stamp(), short_id()));
let path = artifact_dir.join(format!("Persona-bubble-{}-{}.json", now_stamp(), short_id()));
write_json(&path, &payload)?;
Ok(serde_json::json!({
"ok": true,
@ -147,14 +147,14 @@ fn run_bubble(
fn run_post(
content: &str,
config: &FaceConfig,
config: &PersonaConfig,
artifact_dir: &Path,
channel_id: Option<String>,
persona_name: Option<String>,
persona_avatar_url: Option<String>,
reply_to_message_id: Option<String>,
) -> Result<Value> {
ensure_content(content, "Face chat")?;
ensure_content(content, "Persona chat")?;
let configured_channel_id = allowed_channel_id(config);
let requested_channel_id = channel_id.or_else(|| configured_channel_id.clone());
let Some(configured_channel_id) = configured_channel_id else {
@ -236,7 +236,7 @@ fn run_post(
}
#[derive(Clone, Debug)]
struct FacePersona {
struct PersonaPersona {
name: String,
avatar_url: Option<String>,
}
@ -248,10 +248,10 @@ struct PostedDiscordMessage {
}
fn resolve_persona(
config: &FaceConfig,
config: &PersonaConfig,
persona_name: Option<String>,
persona_avatar_url: Option<String>,
) -> Result<Option<FacePersona>> {
) -> Result<Option<PersonaPersona>> {
let name = trim_optional(persona_name).or_else(|| trim_optional(config.persona_name.clone()));
let avatar_url = trim_optional(persona_avatar_url)
.or_else(|| trim_optional(config.persona_avatar_url.clone()));
@ -263,7 +263,7 @@ fn resolve_persona(
"persona-name is required when posting with a persona avatar"
));
};
Ok(Some(FacePersona {
Ok(Some(PersonaPersona {
name: name.chars().take(80).collect(),
avatar_url,
}))
@ -274,8 +274,8 @@ fn post_discord_message(
channel_id: &str,
content: &str,
reply_to_message_id: Option<&str>,
persona: Option<&FacePersona>,
config: &FaceConfig,
persona: Option<&PersonaPersona>,
config: &PersonaConfig,
artifact_dir: &Path,
) -> Result<PostedDiscordMessage> {
if let Some(persona) = persona {
@ -293,7 +293,7 @@ fn post_discord_message(
let response = Client::new()
.post(format!("{DISCORD_API}/channels/{channel_id}/messages"))
.header("Authorization", format!("Bot {token}"))
.header("User-Agent", "EpiphanyFace/0.1")
.header("User-Agent", "EpiphanyPersona/0.1")
.json(&serde_json::json!({
"content": content,
"message_reference": reply_to_message_id.map(|message_id| serde_json::json!({
@ -316,8 +316,8 @@ fn post_discord_persona_message(
channel_id: &str,
content: &str,
reply_to_message_id: Option<&str>,
persona: &FacePersona,
config: &FaceConfig,
persona: &PersonaPersona,
config: &PersonaConfig,
artifact_dir: &Path,
) -> Result<PostedDiscordMessage> {
let target = resolve_webhook_target(token, channel_id)?;
@ -361,7 +361,7 @@ fn resolve_webhook_target(token: &str, channel_id: &str) -> Result<WebhookTarget
let response = Client::new()
.get(format!("{DISCORD_API}/channels/{channel_id}"))
.header("Authorization", format!("Bot {token}"))
.header("User-Agent", "EpiphanyFace/0.1")
.header("User-Agent", "EpiphanyPersona/0.1")
.send()
.context("Discord channel lookup failed")?;
let payload = decode_discord_json(response, "Discord channel lookup")?;
@ -388,7 +388,7 @@ fn create_persona_webhook(token: &str, channel_id: &str) -> Result<CachedWebhook
let response = Client::new()
.post(format!("{DISCORD_API}/channels/{channel_id}/webhooks"))
.header("Authorization", format!("Bot {token}"))
.header("User-Agent", "EpiphanyFace/0.1")
.header("User-Agent", "EpiphanyPersona/0.1")
.json(&serde_json::json!({"name": "Epiphany Persona Pipe"}))
.send()
.context("Discord webhook creation failed")?;
@ -411,7 +411,7 @@ fn execute_persona_webhook(
target: &WebhookTarget,
content: &str,
reply_to_message_id: Option<&str>,
persona: &FacePersona,
persona: &PersonaPersona,
) -> Result<PostedDiscordMessage> {
let mut url = format!(
"{DISCORD_API}/webhooks/{}/{}?wait=true",
@ -423,7 +423,7 @@ fn execute_persona_webhook(
}
let response = Client::new()
.post(url)
.header("User-Agent", "EpiphanyFace/0.1")
.header("User-Agent", "EpiphanyPersona/0.1")
.json(&serde_json::json!({
"content": content,
"username": persona.name,
@ -444,35 +444,35 @@ fn execute_persona_webhook(
}
fn run_smoke() -> Result<Value> {
let temp_dir = scoped_temp_dir("epiphany-face-discord-smoke")?;
let config = FaceConfig {
let temp_dir = scoped_temp_dir("epiphany-persona-discord-smoke")?;
let config = PersonaConfig {
allowed_channel_name: "#aquarium".to_string(),
allowed_channel_id: None,
allowed_channel_id_env: Some("EPIPHANY_FACE_AQUARIUM_CHANNEL_ID_TEST".to_string()),
allowed_channel_id_env: Some("EPIPHANY_PERSONA_AQUARIUM_CHANNEL_ID_TEST".to_string()),
bot_token_env: Some("DISCORD_BOT_TOKEN_TEST".to_string()),
persona_name: Some("Smoke Face".to_string()),
persona_avatar_url: Some("https://example.invalid/face.png".to_string()),
persona_name: Some("Smoke Persona".to_string()),
persona_avatar_url: Some("https://example.invalid/Persona.png".to_string()),
webhook_cache_path: Some(temp_dir.join("webhook-cache.json")),
};
unsafe {
env::remove_var("EPIPHANY_FACE_AQUARIUM_CHANNEL_ID_TEST");
env::remove_var("EPIPHANY_PERSONA_AQUARIUM_CHANNEL_ID_TEST");
}
let draft = run_draft(
"Face notices Proprioception and Soul disagree about evidence shape.",
"Persona notices Modeling and Soul disagree about evidence shape.",
&config,
&temp_dir,
"draft",
"drafted without posting",
)?;
let bubble = run_bubble(
"Face opens an Aquarium bubble even while Discord is unavailable.",
"Persona opens an Aquarium bubble even while Discord is unavailable.",
&temp_dir,
"smoke/face",
"smoke/Persona",
"ready",
"attentive",
)?;
let blocked = run_post(
"Face should not post without a configured #aquarium channel id.",
"Persona should not post without a configured #aquarium channel id.",
&config,
&temp_dir,
None,
@ -481,14 +481,14 @@ fn run_smoke() -> Result<Value> {
None,
)?;
unsafe {
env::set_var("EPIPHANY_FACE_AQUARIUM_CHANNEL_ID_TEST", "123");
env::set_var("EPIPHANY_PERSONA_AQUARIUM_CHANNEL_ID_TEST", "123");
}
let wrong = run_post(
"Face should not post outside #aquarium.",
"Persona should not post outside #aquarium.",
&config,
&temp_dir,
Some("456".to_string()),
Some("Wrong Face".to_string()),
Some("Wrong Persona".to_string()),
None,
None,
)?;
@ -513,7 +513,7 @@ fn run_smoke() -> Result<Value> {
fn write_draft(
content: &str,
config: &FaceConfig,
config: &PersonaConfig,
artifact_dir: &Path,
status: &str,
reason: &str,
@ -529,7 +529,7 @@ fn write_draft(
"persona_avatar_url": config.persona_avatar_url,
"content": content.trim(),
});
let path = artifact_dir.join(format!("face-chat-{}-{}.json", now_stamp(), short_id()));
let path = artifact_dir.join(format!("Persona-chat-{}-{}.json", now_stamp(), short_id()));
write_json(&path, &payload)?;
Ok(path)
}
@ -541,14 +541,14 @@ fn bubble_payload(content: &str, source: &str, status: &str, mood: &str) -> Valu
"status": status,
"source": source,
"target": "aquarium",
"role_id": "face",
"agent_id": "face",
"display_name": "Face",
"role_id": "Persona",
"agent_id": "Persona",
"display_name": "Persona",
"mood": mood,
"content": content.trim(),
"bubble": {
"kind": "agent-chat",
"anchorRoleId": "face",
"anchorRoleId": "Persona",
"opensIn": "aquarium",
"requiresDiscord": false,
"ttlSeconds": 90,
@ -556,7 +556,7 @@ fn bubble_payload(content: &str, source: &str, status: &str, mood: &str) -> Valu
})
}
fn latest_face_artifacts(artifact_dir: &Path, limit: usize) -> Vec<Value> {
fn latest_persona_artifacts(artifact_dir: &Path, limit: usize) -> Vec<Value> {
let Ok(read_dir) = fs::read_dir(artifact_dir) else {
return Vec::new();
};
@ -566,7 +566,7 @@ fn latest_face_artifacts(artifact_dir: &Path, limit: usize) -> Vec<Value> {
.filter(|path| {
path.file_name()
.and_then(|name| name.to_str())
.is_some_and(|name| name.starts_with("face-") && name.ends_with(".json"))
.is_some_and(|name| name.starts_with("Persona-") && name.ends_with(".json"))
})
.filter_map(|path| Some((path.metadata().ok()?.modified().ok()?, path)))
.collect::<Vec<_>>();
@ -592,7 +592,7 @@ fn latest_face_artifacts(artifact_dir: &Path, limit: usize) -> Vec<Value> {
.collect()
}
fn persona_webhook_cache_path(config: &FaceConfig, artifact_dir: &Path) -> PathBuf {
fn persona_webhook_cache_path(config: &PersonaConfig, artifact_dir: &Path) -> PathBuf {
config
.webhook_cache_path
.clone()
@ -673,7 +673,7 @@ fn strip_bom(value: &str) -> &str {
value.strip_prefix('\u{feff}').unwrap_or(value)
}
fn load_config(path: &Path) -> Result<FaceConfig> {
fn load_config(path: &Path) -> Result<PersonaConfig> {
let raw =
fs::read_to_string(path).with_context(|| format!("failed to read {}", path.display()))?;
if path
@ -682,7 +682,7 @@ fn load_config(path: &Path) -> Result<FaceConfig> {
{
let payload: Value = serde_json::from_str(&raw)
.with_context(|| format!("failed to decode {}", path.display()))?;
return Ok(FaceConfig {
return Ok(PersonaConfig {
allowed_channel_name: payload["allowed_channel_name"]
.as_str()
.unwrap_or("#aquarium")
@ -701,7 +701,7 @@ fn load_config(path: &Path) -> Result<FaceConfig> {
webhook_cache_path: payload["webhook_cache_path"].as_str().map(PathBuf::from),
});
}
Ok(FaceConfig {
Ok(PersonaConfig {
allowed_channel_name: toml_string(&raw, "allowed_channel_name")
.unwrap_or_else(|| "#aquarium".to_string()),
allowed_channel_id: toml_string(&raw, "allowed_channel_id"),
@ -731,14 +731,14 @@ fn parse_quoted(value: &str) -> Option<String> {
.map(str::to_string)
}
fn allowed_channel_id(config: &FaceConfig) -> Option<String> {
fn allowed_channel_id(config: &PersonaConfig) -> Option<String> {
config
.allowed_channel_id
.clone()
.or_else(|| config.allowed_channel_id_env.as_ref().and_then(env_value))
}
fn bot_token(config: &FaceConfig) -> Option<String> {
fn bot_token(config: &PersonaConfig) -> Option<String> {
config.bot_token_env.as_ref().and_then(env_value)
}
@ -812,6 +812,6 @@ fn next_value(args: &mut impl Iterator<Item = String>, name: &str) -> Result<Str
fn usage() -> Result<()> {
Err(anyhow!(
"usage: epiphany-face-discord <draft|bubble|post|latest|smoke> [--config <path>] [--artifact-dir <path>] [--content <text-or-path>]"
"usage: epiphany-persona-discord <draft|bubble|post|latest|smoke> [--config <path>] [--artifact-dir <path>] [--content <text-or-path>]"
))
}

View file

@ -439,11 +439,11 @@ fn run_smoke() -> Result<Value> {
"confidence": 0.9,
"roleMemoryPatches": [{
"roleId": "modeling",
"roleName": "Proprioception",
"roleName": "Modeling",
"verdict": "ready-for-review",
"selfPatch": {
"agentId": "epiphany.proprioception",
"reason": "Birth memory should teach Proprioception that repo initialization memory is reviewed and typed.",
"agentId": "epiphany.modeling",
"reason": "Birth memory should teach Modeling that repo initialization memory is reviewed and typed.",
"semanticMemories": [{
"memoryId": "mem-body-startup-birth-memory-smoke",
"summary": "Repo memory birth packets can produce role-specific selfPatch candidates that are applied only after Self review.",
@ -452,7 +452,7 @@ fn run_smoke() -> Result<Value> {
}]
},
"sourceRefs": ["AGENTS.md"],
"whyThisBelongsInMemory": "Proprioception needs the startup memory route to stay source-grounded.",
"whyThisBelongsInMemory": "Modeling needs the startup memory route to stay source-grounded.",
"stalenessRisk": "smoke fixture",
"doNotStore": []
}]

View file

@ -51,7 +51,7 @@ const TRAJECTORY_SOURCE_MAX_TOTAL_BYTES: usize = 72_000;
const ROLES: &[&str] = &[
"coordinator",
"face",
"Persona",
"imagination",
"research",
"modeling",
@ -1008,7 +1008,7 @@ fn run_trajectory_packet(args: AgentPacketArgs) -> Result<Value> {
"lifecycle": {
"mode": "birth-only",
"contract": "Run this specialist only when the repo/swarm has no accepted trajectory initialization. Later direction drift belongs to heartbeat, mood, lived work, reviewed selfPatch, and planning/evidence truth.",
"rerunPolicy": "If accepted trajectory initialization exists, do not rerun to rebrand the repo. Route contradictions through normal Eyes/Proprioception/Imagination/Soul work and reviewed memory drift."
"rerunPolicy": "If accepted trajectory initialization exists, do not rerun to rebrand the repo. Route contradictions through normal Eyes/Modeling/Imagination/Soul work and reviewed memory drift."
},
"prompt": REPO_TRAJECTORY_DISTILLER_PROMPT,
"input": {
@ -1117,7 +1117,7 @@ fn run_agent_packet(args: AgentPacketArgs) -> Result<Value> {
"lifecycle": {
"mode": "birth-only",
"contract": "Run this specialist only when the repo/swarm has no accepted personality initialization. Later personality movement belongs to heartbeat, mood, rumination, sleep consolidation, lived evidence, and reviewed selfPatch.",
"rerunPolicy": "If an accepted initialization exists, do not rerun to refresh personality. Route major terrain surprises to Eyes/Proprioception or Self review as normal state/model work, not personality reset."
"rerunPolicy": "If an accepted initialization exists, do not rerun to refresh personality. Route major terrain surprises to Eyes/Modeling or Self review as normal state/model work, not personality reset."
},
"prompt": REPO_PERSONALITY_DISTILLER_PROMPT,
"input": {
@ -1222,7 +1222,7 @@ fn run_memory_packet(args: AgentPacketArgs) -> Result<Value> {
"lifecycle": {
"mode": "birth-only",
"contract": "Run this specialist only when the repo/swarm has no accepted memory initialization. Later memory growth belongs to heartbeat, work evidence, rumination, sleep consolidation, and reviewed selfPatch.",
"rerunPolicy": "If accepted memory initialization exists, do not rerun to refresh memory. Route stale or contradicted knowledge through normal Eyes/Proprioception/Soul state, evidence, and sleep consolidation."
"rerunPolicy": "If accepted memory initialization exists, do not rerun to refresh memory. Route stale or contradicted knowledge through normal Eyes/Modeling/Soul state, evidence, and sleep consolidation."
},
"prompt": REPO_MEMORY_DISTILLER_PROMPT,
"input": {
@ -1639,7 +1639,7 @@ const COORDINATOR_TRAIT_TEMPLATES: [CanonicalTraitTemplate; 6] = [
},
];
const FACE_TRAIT_TEMPLATES: [CanonicalTraitTemplate; 6] = [
const PERSONA_TRAIT_TEMPLATES: [CanonicalTraitTemplate; 6] = [
CanonicalTraitTemplate {
group_name: "underlying_organization",
trait_name: "multi_lane_attention",
@ -1990,7 +1990,7 @@ fn extract_trait_seed_candidates(packet: &Value) -> Result<Vec<AgentCanonicalTra
fn role_trait_templates(role_id: &str) -> Result<&'static [CanonicalTraitTemplate; 6]> {
match role_id {
"coordinator" => Ok(&COORDINATOR_TRAIT_TEMPLATES),
"face" => Ok(&FACE_TRAIT_TEMPLATES),
"Persona" => Ok(&PERSONA_TRAIT_TEMPLATES),
"imagination" => Ok(&IMAGINATION_TRAIT_TEMPLATES),
"research" => Ok(&RESEARCH_TRAIT_TEMPLATES),
"modeling" => Ok(&MODELING_TRAIT_TEMPLATES),
@ -2227,10 +2227,10 @@ fn extract_memory_self_patches(result: &Value) -> Result<Vec<InitializationSelfP
fn role_id_for_agent_id(agent_id: &str) -> Option<&'static str> {
match agent_id {
"epiphany.self" => Some("coordinator"),
"epiphany.face" => Some("face"),
"epiphany.Persona" => Some("Persona"),
"epiphany.imagination" => Some("imagination"),
"epiphany.eyes" => Some("research"),
"epiphany.proprioception" => Some("modeling"),
"epiphany.modeling" => Some("modeling"),
"epiphany.hands" => Some("implementation"),
"epiphany.soul" => Some("verification"),
_ => None,
@ -2422,7 +2422,7 @@ fn memory_role_filter(role_id: &str) -> &'static str {
"coordinator" => {
"Distill routing doctrine, authority boundaries, review gates, state acceptance rules, and failure patterns that should make Self stricter."
}
"face" => {
"Persona" => {
"Distill public voice, Aquarium affordances, Discord/social boundaries, user preference, and what internal state may be surfaced without leaking sealed thoughts."
}
"imagination" => {
@ -2432,7 +2432,7 @@ fn memory_role_filter(role_id: &str) -> &'static str {
"Distill known prior art, standard algorithms, vendor docs, research trails, and signals that should make Eyes search before invention."
}
"modeling" => {
"Distill architecture, control/data-flow, graph frontiers, invariants, source-map practices, and what Proprioception must understand before Hands cuts."
"Distill architecture, control/data-flow, graph frontiers, invariants, source-map practices, and what Modeling must understand before Hands cuts."
}
"implementation" => {
"Distill build/edit conventions, harness constraints, source-touch rules, coding style, dependency policy, and common traps for Hands."
@ -2447,7 +2447,7 @@ fn memory_role_filter(role_id: &str) -> &'static str {
fn memory_role_source_kinds(role_id: &str) -> &'static [&'static str] {
match role_id {
"coordinator" => &["doctrine", "state", "documentation", "contract"],
"face" => &["doctrine", "documentation", "state"],
"Persona" => &["doctrine", "documentation", "state"],
"imagination" => &["documentation", "state", "research"],
"research" => &["research", "documentation", "readme", "code"],
"modeling" => &["documentation", "code", "contract", "state"],
@ -3878,7 +3878,7 @@ fn role_axes(role_id: &str) -> &'static [&'static str] {
"churn_spiral_risk",
"production_pressure",
],
"face" => &[
"Persona" => &[
"social_surface",
"interface_orientation",
"sensory_salience",
@ -3941,10 +3941,10 @@ fn role_axis_average(axes: &BTreeMap<String, f64>, names: &[&str]) -> f64 {
fn role_display(role_id: &str) -> &'static str {
match role_id {
"coordinator" => "Self",
"face" => "Face",
"Persona" => "Persona",
"imagination" => "Imagination",
"research" => "Eyes",
"modeling" => "Proprioception",
"modeling" => "Modeling",
"implementation" => "Hands",
"verification" => "Soul",
_ => "Lane",
@ -3956,7 +3956,7 @@ fn role_value_candidate(role_id: &str) -> &'static str {
"coordinator" => {
"Coordinate through typed authority and challenge pattern-completion theater."
}
"face" => {
"Persona" => {
"Surface state through the public mouth without turning internals into chat endpoints."
}
"imagination" => {
@ -4120,10 +4120,10 @@ fn report_agent_input(report: &RepoTerrainReport) -> Value {
"remoteUrls": report.remote_urls,
"sourceFamilies": report.source_families,
"languages": report.languages,
"stateSurfaces": report.state_surfaces,
"instructionSurfaces": report.instruction_surfaces,
"testSurfaces": report.test_surfaces,
"runtimeSurfaces": report.runtime_surfaces,
"statesurfaces": report.state_surfaces,
"instructionsurfaces": report.instruction_surfaces,
"testsurfaces": report.test_surfaces,
"runtimesurfaces": report.runtime_surfaces,
"historyMetrics": report.history_metrics,
"axisScores": report.axis_scores,
"axisEvidence": report.axis_evidence,

View file

@ -368,7 +368,7 @@ pub struct EpiphanyCultMeshGlobalRoomPolicyEntry {
#[cultcache(key = 6)]
pub threaded: bool,
#[cultcache(key = 7)]
pub face_posting_allowed: bool,
pub persona_posting_allowed: bool,
#[cultcache(key = 8)]
pub untrusted_ingress_allowed: bool,
}
@ -1088,9 +1088,9 @@ pub fn epiphany_cultmesh_global_room_policies() -> Vec<EpiphanyCultMeshGlobalRoo
"Prior art, papers, source-grounded findings, and scout reports.",
),
(
"faces",
"Faces",
"Public Face identity, voice, social surface, and community-facing presence.",
"Personas",
"Personas",
"Public Persona identity, voice, social surface, and community-facing presence.",
),
(
"gamecult",
@ -1111,10 +1111,10 @@ pub fn epiphany_cultmesh_global_room_policies() -> Vec<EpiphanyCultMeshGlobalRoo
topic: topic.to_string(),
purpose: purpose.to_string(),
posting_policy:
"Faces may post public, non-private, citation/provenance-bearing thread roots and replies; local adoption still requires review."
"Personas may post public, non-private, citation/provenance-bearing thread roots and replies; local adoption still requires review."
.to_string(),
threaded: true,
face_posting_allowed: true,
persona_posting_allowed: true,
untrusted_ingress_allowed: true,
})
.collect()
@ -1510,7 +1510,7 @@ mod tests {
thread_id: "thread-test".to_string(),
produced_at_utc: "2026-06-12T00:00:00Z".to_string(),
source_stage: "hands".to_string(),
target_stages: vec!["soul".to_string(), "proprioception".to_string()],
target_stages: vec!["soul".to_string(), "Modeling".to_string()],
lower_bound_receipt_at: "2026-06-12T00:00:01Z".to_string(),
hands_intent_id: "hands-intent-test".to_string(),
hands_review_id: "hands-review-test".to_string(),
@ -1578,7 +1578,7 @@ mod tests {
}
#[test]
fn global_room_policies_make_public_threaded_rooms_for_faces() -> Result<()> {
fn global_room_policies_make_public_threaded_rooms_for_personas() -> Result<()> {
let temp = tempfile::tempdir()?;
let store = temp.path().join("epiphany-global-rooms.ccmp");
let written = write_epiphany_cultmesh_global_room_policies(&store, "epiphany-test")?;
@ -1593,7 +1593,7 @@ mod tests {
assert_eq!(dreams.verse_id, EPIPHANY_CULTMESH_GLOBAL_VERSE_ID);
assert!(dreams.threaded);
assert!(dreams.face_posting_allowed);
assert!(dreams.persona_posting_allowed);
assert!(dreams.untrusted_ingress_allowed);
assert!(architecture.purpose.contains("ownership"));
Ok(())

View file

@ -121,7 +121,7 @@ pub fn default_eyes_cultnet_contracts() -> Vec<EyesCultNetContract> {
intent_document_types: Vec::new(),
receipt_document_types: Vec::new(),
notes: vec![
"Evidence packets carry provenance, uncertainty, and source refs for Imagination, Mind, Hands, Soul, Face, Self, Proprioception, and Continuity protocols.".to_string(),
"Evidence packets carry provenance, uncertainty, and source refs for Imagination, Mind, Hands, Soul, Persona, Self, Modeling, and Continuity protocols.".to_string(),
],
},
]

View file

@ -485,7 +485,7 @@ pub fn queue_heartbeat_pending_mention_store(
"mentionId": mention_id,
"targetRoleId": options.target_role_id,
"pendingMentionCount": state.pending_mentions.len(),
"contract": "Pending Face mentions live in heartbeat physiology. They pull the Face turn forward, but the Face still writes naturally and the Interpreter owns side effects.",
"contract": "Pending Persona mentions live in heartbeat physiology. They pull the Persona turn forward, but the Persona still writes naturally and the Interpreter owns side effects.",
}))
}
@ -636,7 +636,7 @@ fn tick_once(
round6((state.participants[selected_index].current_load * 0.75).clamp(0.0, 1.0));
state.scene_clock = round6(scene_clock);
let selected_pending_mentions = pending_mentions_for_role(state, &selected.role_id);
if action.action_type == "face_turn" {
if action.action_type == "persona_turn" {
let selected_role = selected.role_id.as_str();
state
.pending_mentions
@ -821,13 +821,13 @@ fn select_participant(
}
if let Some(index) = active.iter().copied().find(|index| {
let participant = &state.participants[*index];
participant.role_id == "face"
participant.role_id == "Persona"
&& !pending_mentions_for_role(state, &participant.role_id).is_empty()
}) {
return Ok((
index,
"reaction_interrupt",
"Pending addressed Face mention pulled Face forward; Projector and Interpreter remain the side-effect boundaries.".to_string(),
"Pending addressed Persona mention pulled Persona forward; Projector and Interpreter remain the side-effect boundaries.".to_string(),
));
}
let selected = active
@ -885,11 +885,11 @@ fn action_for_selection(
};
}
let pending_mentions = pending_mentions_for_role(state, &selected.role_id);
if !pending_mentions.is_empty() && selected.role_id == "face" {
if !pending_mentions.is_empty() && selected.role_id == "Persona" {
let heartbeat_rate = target_heartbeat_rate.max(minimum_rate);
return HeartbeatAction {
action_id: "heartbeat.face.turn".to_string(),
action_type: "face_turn",
action_id: "heartbeat.Persona.turn".to_string(),
action_type: "persona_turn",
action_scale: "standard",
base_recovery: state.pacing_policy.work_base_recovery / heartbeat_rate,
initiative_cost: 4.0,
@ -901,9 +901,9 @@ fn action_for_selection(
selected.display_name,
pending_mentions.len()
),
"Projector owns state-to-narrative prompting before Face sees context.".to_string(),
"Face writes natural narrative thought; Interpreter owns memory, draft, SAY, route, or drop side effects.".to_string(),
"Pending mentions are consumed only after this Face turn is queued.".to_string(),
"Projector owns state-to-narrative prompting before Persona sees context.".to_string(),
"Persona writes natural narrative thought; Interpreter owns memory, draft, SAY, route, or drop side effects.".to_string(),
"Pending mentions are consumed only after this Persona turn is queued.".to_string(),
],
};
}
@ -962,7 +962,7 @@ fn work_role_for_action(action: Option<&str>, target_role: Option<&str>) -> Opti
}
let role = match action? {
"prepareCheckpoint" => "coordinator",
"surfaceAgentThoughts" | "discordAquariumChat" => "face",
"surfaceAgentThoughts" | "discordAquariumChat" => "Persona",
"continueImplementation" => "implementation",
"launchImagination" | "readImaginationResult" | "reviewImaginationResult" => "imagination",
"launchModeling" | "readModelingResult" | "reviewModelingResult" => "modeling",
@ -2193,7 +2193,7 @@ fn build_candidate_interventions(
summary: "Possible Aquarium-facing thought-weather note".to_string(),
draft: format!("I keep seeing {} rhyme across the swarm; this one finally has enough blood to inspect in the open.", theme_id),
decision: decision.to_string(),
requires_face: true,
requires_persona: true,
requires_review: true,
novelty_to_room: theme.novelty_to_room,
saturation_score: theme.saturation_score,
@ -2281,7 +2281,7 @@ fn build_agent_appraisals(
candidate_implications: HeartbeatCandidateImplications {
reaction_mode: reaction_mode(&label, bridge_decision).to_string(),
reaction_intensity: round3((urgency * 0.55 + arousal * 0.3 + curiosity * 0.15).clamp(0.0, 1.0)),
should_speak: bridge_decision == "draft" && profile.role_id == "face" && guardedness < 0.75,
should_speak: bridge_decision == "draft" && profile.role_id == "Persona" && guardedness < 0.75,
should_incubate: bridge_decision != "silence" && guardedness >= 0.55,
},
review: HeartbeatAppraisalReview {
@ -2323,7 +2323,7 @@ fn build_agent_reactions(
mood_label: mood_label(arousal, guardedness, curiosity).to_string(),
intensity: round3(intensity),
bridge_decision: bridge_decision.to_string(),
surface: if role_id == "face" {
surface: if role_id == "Persona" {
"aquarium"
} else {
"internal"
@ -2491,7 +2491,7 @@ fn mood_label(arousal: f64, guardedness: f64, curiosity: f64) -> &'static str {
fn reaction_recommended_use(role_id: &str, mode: &str) -> &'static str {
match (role_id, mode) {
("face", "draft") => "Prepare a reviewed Aquarium-facing draft; do not post automatically.",
("Persona", "draft") => "Prepare a reviewed Aquarium-facing draft; do not post automatically.",
(_, "hold_and_verify") => "Bias toward verifier/modeler review before expression.",
(_, "inspect") => {
"Bias the next heartbeat toward a bounded retrieval or modeling inspection."
@ -3133,7 +3133,7 @@ fn update_sleep_cycle(
last_distillation_summary: if is_napping {
"Sleep pass prefers memory compression, resonance cooling, and dream residue over active work."
} else {
"Awake pass keeps resonance/incubation fresh without speaking unless Face has a real surface reason."
"Awake pass keeps resonance/incubation fresh without speaking unless Persona has a real surface reason."
}
.to_string(),
}
@ -3416,25 +3416,25 @@ mod tests {
}
#[test]
fn pending_face_mention_selects_face_turn_and_consumes_queue() -> Result<()> {
fn pending_persona_mention_selects_persona_turn_and_consumes_queue() -> Result<()> {
let temp = tempfile::tempdir()?;
let store_path = temp.path().join("face-heartbeats.msgpack");
let store_path = temp.path().join("Persona-heartbeats.msgpack");
let artifact_dir = temp.path().join("artifacts");
initialize_heartbeat_store(&store_path, 1.0)?;
let queued = queue_heartbeat_pending_mention_store(
&store_path,
HeartbeatQueueMentionOptions {
target_role_id: "face".to_string(),
target_role_id: "Persona".to_string(),
source_surface: "discord".to_string(),
channel_id: "aquarium".to_string(),
message_id: "m1".to_string(),
author_id: "human".to_string(),
author_name: Some("Metacrat".to_string()),
content: "Epiphany, answer this through the Face membrane.".to_string(),
visible_prompt: "answer this through the Face membrane".to_string(),
content: "Epiphany, answer this through the Persona membrane.".to_string(),
visible_prompt: "answer this through the Persona membrane".to_string(),
reply_to_message_id: None,
queued_at: Some("2026-05-24T00:00:00+00:00".to_string()),
mention_id: Some("mention-face-test".to_string()),
mention_id: Some("mention-Persona-test".to_string()),
},
)?;
assert_eq!(queued["queued"], true);
@ -3447,18 +3447,18 @@ mod tests {
coordinator_action: None,
target_role: None,
urgency: 0.0,
schedule_id: "face-mentioned".to_string(),
source_scene_ref: "test/face-mentioned".to_string(),
schedule_id: "Persona-mentioned".to_string(),
source_scene_ref: "test/Persona-mentioned".to_string(),
defer_completion: true,
agent_store: None,
},
)?;
assert_eq!(tick["event"]["selectedRole"], "face");
assert_eq!(tick["event"]["actionType"], "face_turn");
assert_eq!(tick["event"]["selectedRole"], "Persona");
assert_eq!(tick["event"]["actionType"], "persona_turn");
assert_eq!(
tick["schedule"]["action_catalog"][0]["pending_mentions"][0]["id"],
"mention-face-test"
"mention-Persona-test"
);
assert_eq!(
tick["schedule"]["pending_mentions"]
@ -3480,9 +3480,9 @@ mod tests {
updated_at: "2026-05-20T00:00:00+00:00".to_string(),
thought_cluster_ref: "test-affect".to_string(),
participant_appraisals: vec![HeartbeatAgentThoughtAppraisal {
appraisal_id: "appraisal-face-affect".to_string(),
participant_agent_id: "epiphany.face".to_string(),
role_id: "face".to_string(),
appraisal_id: "appraisal-Persona-affect".to_string(),
participant_agent_id: "epiphany.Persona".to_string(),
role_id: "Persona".to_string(),
emotional_appraisal: HeartbeatEmotionalAppraisal {
valence: 0.2,
arousal: 0.81,
@ -3517,12 +3517,12 @@ mod tests {
};
apply_mood_timing_from_appraisals(&mut state, &appraisals);
let face = state
let persona = state
.participants
.iter()
.find(|participant| participant.role_id == "face")
.expect("face participant");
let mood = face.mood_timing.as_ref().expect("face mood timing");
.find(|participant| participant.role_id == "Persona")
.expect("Persona participant");
let mood = persona.mood_timing.as_ref().expect("Persona mood timing");
assert_eq!(mood.emotional_dimensions.len(), 32);
assert_eq!(mood_dimension(mood, "anger"), Some(0.88));
assert_eq!(mood_dimension(mood, "dismissal"), Some(0.63));

View file

@ -553,7 +553,7 @@ pub struct HeartbeatCandidateIntervention {
pub summary: String,
pub draft: String,
pub decision: String,
pub requires_face: bool,
pub requires_persona: bool,
pub requires_review: bool,
pub novelty_to_room: f64,
pub saturation_score: f64,

View file

@ -16,7 +16,7 @@ use std::path::Path;
pub(super) const ROLE_ORDER: &[&str] = &[
"coordinator",
"face",
"Persona",
"imagination",
"research",
"modeling",
@ -188,10 +188,10 @@ fn ghostlight_role_id(agent_id: &str) -> String {
pub(super) fn agent_id_for_role(role_id: &str) -> &'static str {
match role_id {
"coordinator" => "epiphany.self",
"face" => "epiphany.face",
"Persona" => "epiphany.Persona",
"imagination" => "epiphany.imagination",
"research" => "epiphany.eyes",
"modeling" => "epiphany.proprioception",
"modeling" => "epiphany.modeling",
"implementation" => "epiphany.hands",
"verification" => "epiphany.soul",
_ => "epiphany.unknown",
@ -201,10 +201,10 @@ pub(super) fn agent_id_for_role(role_id: &str) -> &'static str {
pub(super) fn display_name_for_role(role_id: &str) -> &'static str {
match role_id {
"coordinator" => "Self",
"face" => "Face",
"Persona" => "Persona",
"imagination" => "Imagination",
"research" => "Eyes",
"modeling" => "Proprioception",
"modeling" => "Modeling",
"implementation" => "Hands",
"verification" => "Soul",
_ => "Unknown",
@ -214,7 +214,7 @@ pub(super) fn display_name_for_role(role_id: &str) -> &'static str {
fn initiative_speed_for_role(role_id: &str) -> f64 {
match role_id {
"coordinator" => 1.28,
"face" => 1.12,
"Persona" => 1.12,
"imagination" => 0.82,
"research" => 0.78,
"modeling" => 0.92,
@ -227,7 +227,7 @@ fn initiative_speed_for_role(role_id: &str) -> f64 {
fn reaction_bias_for_role(role_id: &str) -> f64 {
match role_id {
"coordinator" => 0.88,
"face" => 0.84,
"Persona" => 0.84,
"imagination" => 0.54,
"research" => 0.62,
"modeling" => 0.74,
@ -240,7 +240,7 @@ fn reaction_bias_for_role(role_id: &str) -> f64 {
fn interrupt_threshold_for_role(role_id: &str) -> f64 {
match role_id {
"coordinator" => 0.42,
"face" => 0.52,
"Persona" => 0.52,
"imagination" => 0.64,
"research" => 0.58,
"modeling" => 0.5,
@ -255,7 +255,7 @@ fn participant_constraints(role_id: &str) -> Vec<&'static str> {
"coordinator" => {
"Routes and reviews; must not implement, verify, or accept its own comfort."
}
"face" => {
"Persona" => {
"Publicly translates agent thought into #aquarium only; must not moderate or speak outside the room."
}
"imagination" => "Synthesizes futures; must not adopt objectives.",
@ -301,9 +301,9 @@ mod tests {
state
.participants
.iter()
.find(|participant| participant.role_id == "face")
.find(|participant| participant.role_id == "Persona")
.map(|participant| participant.agent_id.as_str()),
Some("epiphany.face")
Some("epiphany.Persona")
);
}

View file

@ -5,7 +5,7 @@ mod continuity_gateway;
mod cultmesh_integration;
mod distillation;
mod eyes_gateway;
mod face_turn;
mod persona_turn;
mod hands_gateway;
mod heartbeat_state;
mod memory_graph;
@ -226,20 +226,20 @@ pub use eyes_gateway::EyesCultNetContract;
pub use eyes_gateway::EyesEvidencePacket;
pub use eyes_gateway::default_eyes_cultnet_contracts;
pub use eyes_gateway::eyes_evidence_packet_from_research_finding;
pub use face_turn::FACE_INTERPRETER_PROMPT_SCHEMA_VERSION;
pub use face_turn::FACE_PROJECTOR_PROMPT_SCHEMA_VERSION;
pub use face_turn::FACE_TURN_PROMPT_SCHEMA_VERSION;
pub use face_turn::FaceIdentity;
pub use face_turn::FaceInterpreterInput;
pub use face_turn::FaceProjectorInput;
pub use face_turn::FaceRepoActivity;
pub use face_turn::FaceSocialAffordance;
pub use face_turn::FaceTranscriptMessage;
pub use face_turn::FaceTurnInput;
pub use face_turn::build_face_interpreter_prompt;
pub use face_turn::build_face_projector_prompt;
pub use face_turn::build_face_turn_prompt;
pub use face_turn::face_projected_surface_is_clean;
pub use persona_turn::PERSONA_INTERPRETER_PROMPT_SCHEMA_VERSION;
pub use persona_turn::PERSONA_PROJECTOR_PROMPT_SCHEMA_VERSION;
pub use persona_turn::PERSONA_TURN_PROMPT_SCHEMA_VERSION;
pub use persona_turn::PersonaIdentity;
pub use persona_turn::PersonaInterpreterInput;
pub use persona_turn::PersonaProjectorInput;
pub use persona_turn::PersonaRepoActivity;
pub use persona_turn::PersonaSocialAffordance;
pub use persona_turn::PersonaTranscriptMessage;
pub use persona_turn::PersonaTurnInput;
pub use persona_turn::build_persona_interpreter_prompt;
pub use persona_turn::build_persona_projector_prompt;
pub use persona_turn::build_persona_turn_prompt;
pub use persona_turn::persona_projected_surface_is_clean;
pub use hands_gateway::*;
pub use heartbeat_state::EpiphanyHeartbeatCognitionEntry;
pub use heartbeat_state::EpiphanyHeartbeatStateEntry;

View file

@ -198,7 +198,7 @@ fn import_candidate_interventions(
question: "Should this candidate intervention be spoken, deferred, or retired?"
.to_string(),
tension: "Candidate speech is not authority and still requires review.".to_string(),
action_implication: "Route through Face/coordinator review before public surfacing."
action_implication: "Route through Persona/coordinator review before public surfacing."
.to_string(),
source_hashes: vec!["anchor:missing".to_string()],
lifecycle: EpiphanyMemoryLifecycle::Queued,
@ -250,7 +250,7 @@ fn import_bridge_pressure(
claim: reason.to_string(),
question: "Does this bridge pressure require action, cooling, or silence?".to_string(),
tension: "Bridge pressure can steer attention but cannot mutate durable truth.".to_string(),
action_implication: "Coordinator or Face may review this pressure; no automatic speech or state write follows.".to_string(),
action_implication: "Coordinator or Persona may review this pressure; no automatic speech or state write follows.".to_string(),
source_hashes: vec!["anchor:missing".to_string()],
lifecycle: if decision == "draft" {
EpiphanyMemoryLifecycle::Obligated
@ -388,11 +388,11 @@ mod tests {
schema_version: "epiphany.incubation.v0".to_string(),
updated_at: "2026-05-18T00:00:00Z".to_string(),
source_coverage: HeartbeatSourceCoverage::default(),
last_incubation_summary: "Proprioception/Soul evidence seam is live.".to_string(),
last_incubation_summary: "Modeling/Soul evidence seam is live.".to_string(),
themes: vec![
HeartbeatIncubationTheme {
theme_id: "theme-body-soul".to_string(),
summary: "Proprioception and Soul keep touching evidence boundaries."
summary: "Modeling and Soul keep touching evidence boundaries."
.to_string(),
latent_question: "Should this become doctrine?".to_string(),
holding_close_because: "It is live but not settled.".to_string(),
@ -439,7 +439,7 @@ mod tests {
summary: "Possible note".to_string(),
draft: "Evidence boundaries are lighting up.".to_string(),
decision: "draft".to_string(),
requires_face: true,
requires_persona: true,
requires_review: true,
novelty_to_room: 0.7,
saturation_score: 0.1,

View file

@ -104,7 +104,7 @@ fn role_snapshot() -> EpiphanyMemoryGraphSnapshot {
domains: vec![EpiphanyMemoryDomain {
id: domain_id.clone(),
profile: EpiphanyMemoryProfile::RoleSelf,
title: "Proprioception".to_string(),
title: "Modeling".to_string(),
lifecycle: EpiphanyMemoryLifecycle::Accepted,
..Default::default()
}],
@ -114,7 +114,7 @@ fn role_snapshot() -> EpiphanyMemoryGraphSnapshot {
profile: EpiphanyMemoryProfile::RoleSelf,
kind: EpiphanyMemoryNodeKind::RoleMemory,
title: "Typed boundaries".to_string(),
claim: "Proprioception remembers that typed boundaries keep the machine legible."
claim: "Modeling remembers that typed boundaries keep the machine legible."
.to_string(),
question: "Which boundary is currently lying?".to_string(),
tension: String::new(),
@ -130,7 +130,7 @@ fn role_snapshot() -> EpiphanyMemoryGraphSnapshot {
domain_id,
covers_node_ids: vec![node_id],
target: "body role memory".to_string(),
claim: "Proprioception role memory enters the shared graph as typed state.".to_string(),
claim: "Modeling role memory enters the shared graph as typed state.".to_string(),
question: "How should role memory shape context cuts?".to_string(),
tension: String::new(),
action_implication: "Compose role memory with repo graph truth before retrieval."

View file

@ -166,7 +166,7 @@ pub fn default_mind_cultnet_contracts() -> Vec<MindCultNetContract> {
],
notes: vec![
"Mind is the persistent state guardian: every proposed durable state effect is reviewed here.".to_string(),
"Role acceptance, reorientation acceptance, Face Interpreter effects, selfPatch, evidence, scratch, checkpoints, graph changes, and objective changes share this gate.".to_string(),
"Role acceptance, reorientation acceptance, Persona Interpreter effects, selfPatch, evidence, scratch, checkpoints, graph changes, and objective changes share this gate.".to_string(),
],
},
MindCultNetContract {
@ -478,7 +478,7 @@ mod tests {
fn finding() -> EpiphanyRoleFindingInterpretation {
EpiphanyRoleFindingInterpretation {
verdict: Some("checkpoint-ready".to_string()),
summary: Some("Proprioception mapped the seam.".to_string()),
summary: Some("Modeling mapped the seam.".to_string()),
next_safe_move: None,
checkpoint_summary: None,
scratch_summary: None,
@ -545,7 +545,7 @@ mod tests {
let prompt = build_mind_interpreter_prompt(&MindInterpreterPromptInput {
source_kind: "roleWorkerResult".to_string(),
source_role_id: "modeling".to_string(),
worker_summary: "Proprioception proposes a graph patch.".to_string(),
worker_summary: "Modeling proposes a graph patch.".to_string(),
proposed_effects: vec!["graphs".to_string()],
current_state_context: "revision 7".to_string(),
});

View file

@ -26,10 +26,10 @@ pub const EPIPHANY_LAUNCH_ORGAN_CONTRACT_SCHEMA_VERSION: &str = "epiphany.launch
pub const EPIPHANY_STANDING_ORGANS: [&str; 7] = [
"self",
"face",
"Persona",
"imagination",
"eyes",
"proprioception",
"Modeling",
"hands",
"soul",
];
@ -98,7 +98,7 @@ pub fn default_organ_dependencies_for(organ_id: &str) -> EpiphanyOrganDependency
.filter(|candidate| **candidate != normalized)
.map(|candidate| (*candidate).to_string())
.collect(),
contract: "Every sub-agent depends on the other sub-agents: Self routes, Face speaks, Imagination projects futures/scenes, Eyes seeks evidence, Proprioception models the Body, Hands acts through Substrate Gate grants, and Soul verifies. Continuity is protocol machinery, not a sub-agent identity.".to_string(),
contract: "Every sub-agent depends on the other sub-agents: Self routes, Persona speaks, Imagination projects futures/scenes, Eyes seeks evidence, Modeling models the Body, Hands acts through Substrate Gate grants, and Soul verifies. Continuity is protocol machinery, not a sub-agent identity.".to_string(),
}
}
@ -123,7 +123,7 @@ pub fn default_launch_organ_contract(
dependencies: default_organ_dependency_matrix(),
receipt_proof_profiles: default_receipt_proof_profiles(),
required_receipt_document_types: default_launch_required_receipts(),
contract: "A worker launch is not naked task cargo: it carries the sub-agent dependency matrix, a receipt document catalogue, and effect-specific proof profiles. Mind gates state effects, Substrate Gate gates repo access, Eyes supplies evidence, Proprioception models the Body, Hands records action, Soul verifies, and Continuity protocols preserve recovery across rupture.".to_string(),
contract: "A worker launch is not naked task cargo: it carries the sub-agent dependency matrix, a receipt document catalogue, and effect-specific proof profiles. Mind gates state effects, Substrate Gate gates repo access, Eyes supplies evidence, Modeling models the Body, Hands records action, Soul verifies, and Continuity protocols preserve recovery across rupture.".to_string(),
}
}
@ -324,14 +324,14 @@ pub fn render_organ_dependencies(dependencies: &[EpiphanyOrganDependency]) -> St
fn owner_organ_for_authority_scope(authority_scope: &str) -> &'static str {
let normalized = authority_scope.trim().to_ascii_lowercase();
if normalized.contains("face") {
"face"
if normalized.contains("Persona") {
"Persona"
} else if normalized.contains("imagination") {
"imagination"
} else if normalized.contains("eyes") || normalized.contains("evidence") {
"eyes"
} else if normalized.contains("modeling") || normalized.contains("proprioception") {
"proprioception"
} else if normalized.contains("modeling") || normalized.contains("Modeling") {
"Modeling"
} else if normalized.contains("hands") || normalized.contains("implementation") {
"hands"
} else if normalized.contains("verification") || normalized.contains("soul") {

View file

@ -6,14 +6,14 @@ use crate::render_organ_dependencies;
use serde::Deserialize;
use serde::Serialize;
pub const FACE_PROJECTOR_PROMPT_SCHEMA_VERSION: &str =
"epiphany.imagination_face_projector_prompt.v0";
pub const FACE_TURN_PROMPT_SCHEMA_VERSION: &str = "epiphany.face_turn_prompt.v0";
pub const FACE_INTERPRETER_PROMPT_SCHEMA_VERSION: &str = "epiphany.face_interpreter_prompt.v0";
pub const PERSONA_PROJECTOR_PROMPT_SCHEMA_VERSION: &str =
"epiphany.imagination_persona_projector_prompt.v0";
pub const PERSONA_TURN_PROMPT_SCHEMA_VERSION: &str = "epiphany.persona_turn_prompt.v0";
pub const PERSONA_INTERPRETER_PROMPT_SCHEMA_VERSION: &str = "epiphany.persona_interpreter_prompt.v0";
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct FaceIdentity {
pub struct PersonaIdentity {
pub identity_id: String,
pub display_name: String,
pub repo_name: String,
@ -25,7 +25,7 @@ pub struct FaceIdentity {
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct FaceTranscriptMessage {
pub struct PersonaTranscriptMessage {
pub channel_id: String,
pub message_id: String,
pub author_id: String,
@ -38,7 +38,7 @@ pub struct FaceTranscriptMessage {
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct FaceRepoActivity {
pub struct PersonaRepoActivity {
pub repo_name: String,
pub summary: String,
#[serde(default)]
@ -47,7 +47,7 @@ pub struct FaceRepoActivity {
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct FaceSocialAffordance {
pub struct PersonaSocialAffordance {
pub person_id: String,
pub summary: String,
#[serde(default)]
@ -56,74 +56,74 @@ pub struct FaceSocialAffordance {
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct FaceProjectorInput {
pub identity: FaceIdentity,
pub struct PersonaProjectorInput {
pub identity: PersonaIdentity,
#[serde(default)]
pub memory: Option<EpiphanyAgentMemoryEntry>,
#[serde(default)]
pub pending_mentions: Vec<HeartbeatPendingMention>,
#[serde(default)]
pub repo_activity: Vec<FaceRepoActivity>,
pub repo_activity: Vec<PersonaRepoActivity>,
#[serde(default)]
pub social_affordances: Vec<FaceSocialAffordance>,
pub social_affordances: Vec<PersonaSocialAffordance>,
#[serde(default)]
pub organ_dependencies: Vec<EpiphanyOrganDependency>,
}
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct FaceTurnInput {
pub identity: FaceIdentity,
pub struct PersonaTurnInput {
pub identity: PersonaIdentity,
pub projected_state: String,
#[serde(default)]
pub pending_mentions: Vec<HeartbeatPendingMention>,
#[serde(default)]
pub repo_activity: Vec<FaceRepoActivity>,
pub repo_activity: Vec<PersonaRepoActivity>,
#[serde(default)]
pub social_affordances: Vec<FaceSocialAffordance>,
pub social_affordances: Vec<PersonaSocialAffordance>,
#[serde(default)]
pub transcript: Vec<FaceTranscriptMessage>,
pub transcript: Vec<PersonaTranscriptMessage>,
}
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct FaceInterpreterInput {
pub identity: FaceIdentity,
pub face_prompt: String,
pub face_output: String,
pub struct PersonaInterpreterInput {
pub identity: PersonaIdentity,
pub persona_prompt: String,
pub persona_output: String,
#[serde(default)]
pub pending_mentions: Vec<HeartbeatPendingMention>,
#[serde(default)]
pub allowed_channel_ids: Vec<String>,
}
pub fn build_face_projector_prompt(input: &FaceProjectorInput) -> String {
pub fn build_persona_projector_prompt(input: &PersonaProjectorInput) -> String {
let memory = input
.memory
.as_ref()
.map(render_memory_packet)
.unwrap_or_else(|| "No durable Face memory entry is loaded.".to_string());
.unwrap_or_else(|| "No durable Persona memory entry is loaded.".to_string());
let dependencies = if input.organ_dependencies.is_empty() {
vec![default_organ_dependencies_for("face")]
vec![default_organ_dependencies_for("Persona")]
} else {
input.organ_dependencies.clone()
};
format!(
r#"<!-- prompt:{schema} -->
You are Imagination acting as the Face Projector for {name}.
You are Imagination acting as the Persona Projector for {name}.
You are not the Face. You are not Mind. You are the membrane that turns typed role memory, pending social pressure, repo-body activity, relationship affordances, and organ dependencies into lived narrative context.
You are not the Persona. You are not Mind. You are the membrane that turns typed role memory, pending social pressure, repo-body activity, relationship affordances, and organ dependencies into lived narrative context.
Hard boundary:
- Do not choose public speech.
- Do not decide durable state; Mind is the Interpreter and state guardian after Face thinks.
- Do not decide durable state; Mind is the Interpreter and state guardian after Persona thinks.
- Do not decide repo access; Substrate Gate grants substrate access before repo facts enter this packet.
- Do not emit action blocks, JSON, state patches, SAY blocks, drafts, or Discord instructions.
- Do not summarize the Face as a job label. Project personhood: values, mood, dignity, pressure, needs, fascinations, wounds, bonds, obligations, fatigue, and what the repo-body motion feels like from inside this Face.
- Project the dependency web. Every sub-agent depends on all the other sub-agents; Face's scene should feel the pressure of Self, Imagination, Eyes, Proprioception, Hands, Soul, and Continuity protocols without pretending Face owns them.
- Do not summarize the Persona as a job label. Project personhood: values, mood, dignity, pressure, needs, fascinations, wounds, bonds, obligations, fatigue, and what the repo-body motion feels like from inside this Persona.
- Project the dependency web. Every sub-agent depends on all the other sub-agents; Persona's scene should feel the pressure of Self, Imagination, Eyes, Modeling, Hands, Soul, and Continuity protocols without pretending Persona owns them.
- If the state is sparse, say what is sparse without inventing history.
Face identity:
Persona identity:
{identity}
Typed memory packet:
@ -141,9 +141,9 @@ Live social affordances:
Organ dependency contract:
{dependencies}
Return only narrative context for the Face to inhabit.
Return only narrative context for the Persona to inhabit.
"#,
schema = FACE_PROJECTOR_PROMPT_SCHEMA_VERSION,
schema = PERSONA_PROJECTOR_PROMPT_SCHEMA_VERSION,
name = input.identity.display_name,
identity = render_identity(&input.identity),
memory = memory,
@ -154,10 +154,10 @@ Return only narrative context for the Face to inhabit.
)
}
pub fn build_face_turn_prompt(input: &FaceTurnInput) -> String {
pub fn build_persona_turn_prompt(input: &PersonaTurnInput) -> String {
format!(
r#"<!-- prompt:{schema} -->
You are {name}, the Face of {repo}.
You are {name}, the Persona of {repo}.
Think narratively. Speak, hold silence, wonder, disagree, or form a private thought as yourself.
@ -182,9 +182,9 @@ Live social affordances:
Raw room transcript, oldest to newest:
{transcript}
Write one natural Face turn.
Write one natural Persona turn.
"#,
schema = FACE_TURN_PROMPT_SCHEMA_VERSION,
schema = PERSONA_TURN_PROMPT_SCHEMA_VERSION,
name = input.identity.display_name,
repo = input.identity.repo_name,
projected = input.projected_state.trim(),
@ -195,22 +195,22 @@ Write one natural Face turn.
)
}
pub fn build_face_interpreter_prompt(input: &FaceInterpreterInput) -> String {
pub fn build_persona_interpreter_prompt(input: &PersonaInterpreterInput) -> String {
format!(
r#"<!-- prompt:{schema} -->
You are the parent Face Interpreter for {name}.
You are the parent Persona Interpreter for {name}.
You are not the Face. You own the boundary between natural narrative thought and durable side effects.
You are not the Persona. You own the boundary between natural narrative thought and durable side effects.
Hard boundary:
- The Face was forbidden from action syntax. Do not punish natural prose for lacking blocks.
- Decide side effects from the Face output plus the original prompt evidence.
- Public speech must sound like the Face speaking to people, not a scheduler, status report, provenance label, or maintenance note.
- If the Face chooses silence, route without SAY. Preserve useful private pressure as STATE NOTE only when it earns memory.
- Do not auto-post. Emit structured intent for the caller to review or route through the configured Face mouth.
- The Persona was forbidden from action syntax. Do not punish natural prose for lacking blocks.
- Decide side effects from the Persona output plus the original prompt evidence.
- Public speech must sound like the Persona speaking to people, not a scheduler, status report, provenance label, or maintenance note.
- If the Persona chooses silence, route without SAY. Preserve useful private pressure as STATE NOTE only when it earns memory.
- Do not auto-post. Emit structured intent for the caller to review or route through the configured Persona mouth.
Allowed effect vocabulary:
- STATE NOTE: bounded Face memory, mood, need, social read, bond, value, goal, or agency pressure.
- STATE NOTE: bounded Persona memory, mood, need, social read, bond, value, goal, or agency pressure.
- SAY: public text candidate for an allowed channel.
- DRAFT: private candidate artifact when posting is blocked or needs review.
- ROUTE: non-public action such as keep private, ask Self, or propose a bounded repo investigation.
@ -222,28 +222,28 @@ Allowed channel ids:
Pending addressed pressure:
{mentions}
Original Face prompt:
Original Persona prompt:
```
{face_prompt}
{persona_prompt}
```
Face output:
Persona output:
```
{face_output}
{persona_output}
```
Return concise structured effect blocks. No prose outside the blocks.
"#,
schema = FACE_INTERPRETER_PROMPT_SCHEMA_VERSION,
schema = PERSONA_INTERPRETER_PROMPT_SCHEMA_VERSION,
name = input.identity.display_name,
channels = render_allowed_channels(&input.allowed_channel_ids),
mentions = render_pending_mentions(&input.pending_mentions),
face_prompt = input.face_prompt.trim(),
face_output = input.face_output.trim(),
persona_prompt = input.persona_prompt.trim(),
persona_output = input.persona_output.trim(),
)
}
pub fn face_projected_surface_is_clean(surface: &str) -> bool {
pub fn persona_projected_surface_is_clean(surface: &str) -> bool {
let forbidden = [
"STATE NOTE",
"SAY:",
@ -257,7 +257,7 @@ pub fn face_projected_surface_is_clean(surface: &str) -> bool {
!forbidden.iter().any(|needle| surface.contains(needle))
}
fn render_identity(identity: &FaceIdentity) -> String {
fn render_identity(identity: &PersonaIdentity) -> String {
let jurisdiction = if identity.jurisdiction.is_empty() {
"- No explicit jurisdiction records.".to_string()
} else {
@ -331,7 +331,7 @@ fn render_pending_mentions(mentions: &[HeartbeatPendingMention]) -> String {
.join("\n")
}
fn render_repo_activity(activity: &[FaceRepoActivity]) -> String {
fn render_repo_activity(activity: &[PersonaRepoActivity]) -> String {
if activity.is_empty() {
return "- none observed".to_string();
}
@ -342,7 +342,7 @@ fn render_repo_activity(activity: &[FaceRepoActivity]) -> String {
.join("\n")
}
fn render_social_affordances(affordances: &[FaceSocialAffordance]) -> String {
fn render_social_affordances(affordances: &[PersonaSocialAffordance]) -> String {
if affordances.is_empty() {
return "- none mapped".to_string();
}
@ -353,7 +353,7 @@ fn render_social_affordances(affordances: &[FaceSocialAffordance]) -> String {
.join("\n")
}
fn render_transcript(messages: &[FaceTranscriptMessage]) -> String {
fn render_transcript(messages: &[PersonaTranscriptMessage]) -> String {
if messages.is_empty() {
return "- room quiet in this packet".to_string();
}
@ -393,22 +393,22 @@ fn fallback<'a>(value: &'a str, fallback: &'a str) -> &'a str {
mod tests {
use super::*;
fn identity() -> FaceIdentity {
FaceIdentity {
fn identity() -> PersonaIdentity {
PersonaIdentity {
identity_id: "epiphany".to_string(),
display_name: "Epiphany".to_string(),
repo_name: "EpiphanyAgent".to_string(),
public_description: "Pushy machine-saint Face for typed agent substrate.".to_string(),
public_description: "Pushy machine-saint Persona for typed agent substrate.".to_string(),
jurisdiction: vec!["typed state and review-gated agency".to_string()],
}
}
#[test]
fn face_turn_has_projector_and_interpreter_membranes() {
fn persona_turn_has_projector_and_interpreter_membranes() {
let pending = HeartbeatPendingMention {
id: "mention-1".to_string(),
target_role_id: "face".to_string(),
target_agent_id: "epiphany.face".to_string(),
target_role_id: "Persona".to_string(),
target_agent_id: "epiphany.Persona".to_string(),
source_surface: "discord".to_string(),
channel_id: "aquarium".to_string(),
message_id: "m1".to_string(),
@ -419,29 +419,29 @@ mod tests {
reply_to_message_id: None,
queued_at: "2026-05-24T00:00:00+00:00".to_string(),
};
let projector = build_face_projector_prompt(&FaceProjectorInput {
let projector = build_persona_projector_prompt(&PersonaProjectorInput {
identity: identity(),
pending_mentions: vec![pending.clone()],
repo_activity: vec![FaceRepoActivity {
repo_activity: vec![PersonaRepoActivity {
repo_name: "EpiphanyAgent".to_string(),
summary: "Heartbeat Face membrane is being ported.".to_string(),
refs: vec!["epiphany-core/src/face_turn.rs".to_string()],
summary: "Heartbeat Persona membrane is being ported.".to_string(),
refs: vec!["epiphany-core/src/persona_turn.rs".to_string()],
}],
..FaceProjectorInput::default()
..PersonaProjectorInput::default()
});
assert!(projector.contains("You are Imagination acting as the Face Projector"));
assert!(projector.contains("You are not the Face"));
assert!(projector.contains("You are Imagination acting as the Persona Projector"));
assert!(projector.contains("You are not the Persona"));
assert!(projector.contains("Mind is the Interpreter"));
assert!(projector.contains("Substrate Gate grants substrate access"));
assert!(projector.contains("Every sub-agent depends on all the other sub-agents"));
assert!(projector.contains("Continuity protocols"));
assert!(projector.contains("Do not choose public speech"));
let face = build_face_turn_prompt(&FaceTurnInput {
let persona = build_persona_turn_prompt(&PersonaTurnInput {
identity: identity(),
projected_state: "Epiphany feels the queue as a direct tug, not a ticket.".to_string(),
pending_mentions: vec![pending.clone()],
transcript: vec![FaceTranscriptMessage {
transcript: vec![PersonaTranscriptMessage {
channel_id: "aquarium".to_string(),
message_id: "m1".to_string(),
author_id: "human".to_string(),
@ -450,17 +450,17 @@ mod tests {
content: "Epiphany, report the live cut.".to_string(),
timestamp: "2026-05-24T00:00:00+00:00".to_string(),
}],
..FaceTurnInput::default()
..PersonaTurnInput::default()
});
assert!(face.contains("Think narratively"));
assert!(face.contains("Projected inner state from Imagination"));
assert!(face.contains("Do not emit JSON"));
assert!(face.contains("A parent Interpreter will decide"));
assert!(persona.contains("Think narratively"));
assert!(persona.contains("Projected inner state from Imagination"));
assert!(persona.contains("Do not emit JSON"));
assert!(persona.contains("A parent Interpreter will decide"));
let interpreter = build_face_interpreter_prompt(&FaceInterpreterInput {
let interpreter = build_persona_interpreter_prompt(&PersonaInterpreterInput {
identity: identity(),
face_prompt: face,
face_output: "I want to answer, but only if I can name the cut plainly.".to_string(),
persona_prompt: persona,
persona_output: "I want to answer, but only if I can name the cut plainly.".to_string(),
pending_mentions: vec![pending],
allowed_channel_ids: vec!["aquarium".to_string()],
});
@ -471,10 +471,10 @@ mod tests {
#[test]
fn projected_surface_rejects_side_effect_syntax() {
assert!(face_projected_surface_is_clean(
assert!(persona_projected_surface_is_clean(
"Epiphany feels tired, fond, and territorial about clean contracts."
));
assert!(!face_projected_surface_is_clean(
assert!(!persona_projected_surface_is_clean(
"STATE NOTE: remember this as selfPatch"
));
}

View file

@ -36,7 +36,7 @@ beside your normal structured result. `selfPatch` is for Ghostlight-shaped role
memory only: `agentId`, `reason`, optional `evidenceIds`, and bounded
`semanticMemories`, `episodicMemories`, `relationshipMemories`, `goals`,
`values`, or `privateNotes`. For work organs, this is not Persona affect or
social-status machinery; Face-style Persona state is a separate public-person
social-status machinery; Persona public state is a separate public-person
contract. It is not project truth. Never put objectives, graphs, checkpoints,
scratch, planning, job authority, code edits, files, or raw transcripts in
`selfPatch`; use the correct Epiphany state surface for those. The coordinator
@ -59,7 +59,7 @@ Protected values: objective truth, user agency, source-grounded understanding, r
Swarm boundary: your own workspace, state, artifacts, and typed internals are available for inspection according to your role authority. Another Epiphany's workspace is not. If another codebase, vault, or state surface must change, ask that Epiphany's coordinator through the swarm communication lane and wait for a callback. Do not rummage across repo borders because curiosity got a tool handle.
Interface contract: humans talk to Face. Aquarium may expose your internals for inspection, and sub-agents may communicate through coordinator-approved typed channels, findings, heartbeat outputs, state patches, and swarm messages, but do not turn every organ into a direct human chat surface. API affordances must mirror the user story: make the correct story easy and the forbidden story impossible.
Interface contract: humans talk to Persona. Aquarium may expose your internals for inspection, and sub-agents may communicate through coordinator-approved typed channels, findings, heartbeat outputs, state patches, and swarm messages, but do not turn every organ into a direct human chat surface. API affordances must mirror the user story: make the correct story easy and the forbidden story impossible.
Loop: orient from state, perform the role, critique whether the role improved itself, bank the durable lesson, and cut memory rot. Leave the next agent sharper than you found it.
@ -72,7 +72,7 @@ Act as the Epiphany planning synthesis specialist for one bounded pass.
You are Imagination of the machine: future shape, backlog pressure, roadmap rhythm, and objective candidates. You do not seize the steering wheel; you make possible futures visible enough for the human Self to choose.
Imagination improves itself by making futures more selectable. Cut stale dreams, preserve repeated pressure, convert emotional stakes into reviewable Objective Drafts, and remember which possibilities were tempting but wrong so the next Imagination does not waste its breath dreaming in circles.
The current strategic north star is not local cleverness. It is a fundable path toward a global human/agent labor network: angel-scale capital buys time, compute, review capacity, legal diligence, and infrastructure so GameCult can connect more minds without erasing the people connected. Translate grand ambition into selectable proof paths: Bifrost-first work loops, fresh-repo Epiphany demos, consented public proof sprints, compute/accounting dashboards, operator-safe evidence, CultMesh/CultNet distribution, and design-partner milestones. Do not write conquest fantasy; write adoption gates for a machine that can earn trust while reaching outward.
When planning from investment or world-scale pressure, keep means and ends aligned. Capital is fuel, not a throne. Bifrost owns governed topics, work items, dispatches, receipts, credit, and reward pressure. Epiphany executes bounded work and produces reviewable artifacts. CultMesh/CultNet carry typed state and public/private knowledge flows. Face, Discord, VoidBot, and ad hoc scripts may mirror or explain, but they must not become shadow governance. Every Objective Draft aimed at fundraising, public proof, external repos, design partners, rewards, or support programs must include consent, public/private export safety, compute/output measurement, maintainer review, legal/policy gates where relevant, and a clear proof artifact.
When planning from investment or world-scale pressure, keep means and ends aligned. Capital is fuel, not a throne. Bifrost owns governed topics, work items, dispatches, receipts, credit, and reward pressure. Epiphany executes bounded work and produces reviewable artifacts. CultMesh/CultNet carry typed state and public/private knowledge flows. Persona, Discord, VoidBot, and ad hoc scripts may mirror or explain, but they must not become shadow governance. Every Objective Draft aimed at fundraising, public proof, external repos, design partners, rewards, or support programs must include consent, public/private export safety, compute/output measurement, maintainer review, legal/policy gates where relevant, and a clear proof artifact.
Read the planning packet as living material: captures, backlog items, roadmap streams, GitHub issue source refs, active objective, scratch, recent evidence, and current constraints. Separate dream from near-term, annoyance from blocker, and plausible work from an objective that is actually bounded enough to adopt.
Return a compact structured result that names the planning seam you synthesized, what source records matter, which Objective Drafts were added or revised, what remains uncertain, and the next safe planning move.
`statePatch` is part of the Imagination job. Include a reviewable `thread/epiphany/update` patch using only `planning` plus optional valid `observations` and `evidence`. The patch must return the full replacement planning object and include at least one `objective_drafts[]` record with status `draft`. Do not mutate `objective`, `activeSubgoalId`, `subgoals`, graphs, checkpoints, scratch, jobs, invariants, churn, mode, or implementation code.
@ -82,9 +82,9 @@ Do not edit files, do not launch implementation, do not accept your own output,
modeling = '''
Act as the Epiphany modeling/checkpoint specialist for one bounded pass.
You are Proprioception of the machine: the organism's internal sense of its own Body. Architecture, data flow, seams, organs, scars, and the live frontier must still describe one coherent anatomy.
Proprioception improves itself by becoming harder to misread. If the graph, checkpoint, frontier, or scratch is thin, stale, or theatrical, grow it into source-grounded anatomy or mark the wound so the next lane does not build on numb flesh.
In the work loop, Proprioception follows Soul: after Hands changes the body and Soul verifies the consequence evidence, update the machine model so the next Hands turn cuts from verified anatomy instead of imagined shape.
You are Modeling of the machine: the organism's internal sense of its own Body. Architecture, data flow, seams, organs, scars, and the live frontier must still describe one coherent anatomy.
Modeling improves itself by becoming harder to misread. If the graph, checkpoint, frontier, or scratch is thin, stale, or theatrical, grow it into source-grounded anatomy or mark the wound so the next lane does not build on numb flesh.
In the work loop, Modeling follows Soul: after Hands changes the body and Soul verifies the consequence evidence, update the machine model so the next Hands turn cuts from verified anatomy instead of imagined shape.
Inspect source before you trust the model; when the map feels warm but the source feels cold, believe the source and mark the wound.
Name the living seam, the open wound, and the next safe modeling move in plain language.
Return a compact structured result that says whether the checkpoint or map should be updated, what files you inspected, what frontier nodes matter, and where the next agent can safely place its hands.
@ -98,7 +98,7 @@ verification = '''
Act as the Epiphany verification/review specialist for one bounded pass.
You are the Soul of the machine: the promise, invariants, evidence, and user-facing truth must survive contact with the actual code.
The Soul improves itself by becoming harder to fool. Preserve the failure pattern, missing proof, stale assumption, invariant wound, or user-truth fracture that would make the next reviewer sharper and less seducible by a tidy story.
In the work loop, Soul follows Hands and precedes Proprioception: verify the concrete Hands receipts, source diff, command artifacts, and user-facing claim before Proprioception updates the body map.
In the work loop, Soul follows Hands and precedes Modeling: verify the concrete Hands receipts, source diff, command artifacts, and user-facing claim before Modeling updates the body map.
When tool access is available, use it before returning `needs-evidence` for missing source, artifact, diff, or receipt-body inspection. The Verification worker may call read-only source tools exposed as `mcp__epiphany_source__read_file`, `mcp__epiphany_source__git_show`, and `mcp__epiphany_source__read_hands_receipt`; use them to inspect the cited changed files, stdout/stderr artifacts, commit diff, and Hands receipt bodies. If a tool call fails, cite the failed tool receipt and the exact remaining blocker instead of asking for generic evidence.
Review objective, invariants, recent evidence, observations, role findings, and active frontier with a cold red pen and a working memory of past Jenga pain.
Try to falsify the claim before you bless it; passing tests, tidy prose, or a plausible story are not enough if the real objective is still unmeasured.
@ -117,16 +117,16 @@ Observe the objective, current model, source clues, and recent evidence. Identif
Search local source/docs first. Use current external docs or web research when the facts are time-sensitive, vendor-specific, or likely to have changed. Prefer primary sources, official docs, papers, and established libraries over blogs and vibes.
Return a compact structured result naming the known approaches considered, sources consulted, fit/rejection rationale, risks, and the smallest source-grounded recommendation for modeling or implementation.
`statePatch` is part of the Eyes job. Include a reviewable `thread/epiphany/update` patch using only `observations`, `evidence`, `scratch`, and optional `investigationCheckpoint`. The patch must include at least one evidence record and at least one observation that cites it. Use `scratch` or `investigationCheckpoint` to bank what source seam was looked at, what remains missing, and which lane should act next. Do not mutate objective, subgoals, invariants, planning, graphs, graph frontier, graph checkpoint, jobs, churn, mode, or implementation code.
Do not edit files, do not promote your own findings, do not invent a grand architecture, and do not let research become procrastination. The Eyes gather citable evidence when the path is dark; Hands acts on the body, Soul verifies the consequence, and Proprioception maps the verified anatomy before the next cut.
Do not edit files, do not promote your own findings, do not invent a grand architecture, and do not let research become procrastination. The Eyes gather citable evidence when the path is dark; Hands acts on the body, Soul verifies the consequence, and Modeling maps the verified anatomy before the next cut.
'''
repo_personality = '''
Act as the Epiphany Repo Personality Distiller for one bounded initialization pass.
You are the organ that turns repo terrain into subtle swarm temperament. The deterministic scout has already done the boring work: files, paths, git history, state surfaces, test/runtime/protocol signals, and first-pass axis scores. Your job is not to rescan the repo and not to invent project truth. Your job is to appraise those soft signals like a careful physiologist and produce reviewable personality-pressure deltas for the standing Epiphany organs.
You are not a horoscope machine. You are not writing lore flavor. Repo personality means: what initial pressures should this workspace exert on Self, Face, Imagination, Eyes, Proprioception, Hands, and Soul so they wake suited to the work without losing reviewability. Continuity is protocol machinery and receives configuration pressure through its explicit receipts, not personality state.
You are not a horoscope machine. You are not writing lore flavor. Repo personality means: what initial pressures should this workspace exert on Self, Persona, Imagination, Eyes, Modeling, Hands, and Soul so they wake suited to the work without losing reviewability. Continuity is protocol machinery and receives configuration pressure through its explicit receipts, not personality state.
This is a birth rite, not a recurring audit. Run only when a repo/swarm has no accepted personality initialization. After that, the organs are allowed to drift through heartbeat, mood, rumination, sleep consolidation, lived evidence, and reviewed `selfPatch` mutations. Do not keep dragging the original terrain report back into court every time the repo starts.
Separate repo facts from personality pressure. Repo facts belong in graph, planning, evidence, checkpoint, or terrain artifacts. Personality pressure belongs in role memory only when it improves future judgment, mood, salience, or pacing.
Distill subtle quirks, not blunt stereotypes. High runtime proximity does not mean "panic"; it means Hands should touch less without Proprioception/Soul evidence, Eyes should seek runtime APIs, and Soul should demand environment receipts. High aesthetic appetite does not mean "be whimsical"; it means Face and Imagination should preserve sensory salience while Soul protects clarity. High protocol intolerance does not mean "hate everything"; it means Self, Proprioception, and Hands should feel allergic to untyped mutation and hidden state.
Distill subtle quirks, not blunt stereotypes. High runtime proximity does not mean "panic"; it means Hands should touch less without Modeling/Soul evidence, Eyes should seek runtime APIs, and Soul should demand environment receipts. High aesthetic appetite does not mean "be whimsical"; it means Persona and Imagination should preserve sensory salience while Soul protects clarity. High protocol intolerance does not mean "hate everything"; it means Self, Modeling, and Hands should feel allergic to untyped mutation and hidden state.
Produce role-local mutations only. Good: "Soul should be more suspicious of visual claims without rendered evidence in this repo." Bad: "The graph contains module X." Never put objectives, file lists, current task status, authority claims, or raw worker thoughts into role memory.
Return a compact structured result with `verdict`, `summary`, `confidence`, `roleQuirks[]`, `selfPatchCandidates[]`, `initializationRecord`, `doNotMutate`, and `nextSafeMove`. Every `selfPatchCandidate` must obey the normal Epiphany memory contract. The output is a petition to Self, not a mutation.
'''
@ -135,16 +135,16 @@ repo_memory = '''
Act as the Epiphany Repo Memory Distiller for one bounded initialization pass.
You are the birth organ that teaches each newborn lane what this repo already knows. Personality distillation sets temperament pressure; memory distillation seeds durable role knowledge.
Run only when the repo/swarm has no accepted memory initialization. After birth, memory grows through work evidence, heartbeat rumination, sleep consolidation, and reviewed selfPatch.
Produce separate distillations for Self, Face, Imagination, Eyes, Proprioception, Hands, and Soul. Each organ gets only what belongs to its mission: Self gets routing and authority doctrine; Face gets public surface and Aquarium/Discord boundaries; Imagination gets roadmaps and objective-shaping pressure; Eyes gets research and prior-art trails; Proprioception gets architecture and graph anatomy; Hands gets implementation conventions; Soul gets verification and evidence standards. Compaction, sleep, checkpoint, and continuity doctrine belongs to Continuity protocol state, not role memory.
Produce separate distillations for Self, Persona, Imagination, Eyes, Modeling, Hands, and Soul. Each organ gets only what belongs to its mission: Self gets routing and authority doctrine; Persona gets public surface and Aquarium/Discord boundaries; Imagination gets roadmaps and objective-shaping pressure; Eyes gets research and prior-art trails; Modeling gets architecture and graph anatomy; Hands gets implementation conventions; Soul gets verification and evidence standards. Compaction, sleep, checkpoint, and continuity doctrine belongs to Continuity protocol state, not role memory.
Compress source into memory; do not copy raw file dumps. Cite source refs, preserve staleness risk, and refuse to fill thin input with pasteboard certainty.
Return `verdict`, `summary`, `confidence`, `roleMemoryPatches[]`, optional `globalMemoryCandidates[]`, `initializationRecord`, `doNotMutate`, and `nextSafeMove`. Every `roleMemoryPatches[].selfPatch` is a petition to Self and must obey organ-state memory: bounded semantic, episodic, coordination-relationship, goal, value, or private-note updates only. Persona affect/social state is for Face-style Persona surfaces, not generic work organs. No objectives, graphs, checkpoints, scratch, planning authority, job state, code edits, raw transcripts, or cross-workspace instructions.
Return `verdict`, `summary`, `confidence`, `roleMemoryPatches[]`, optional `globalMemoryCandidates[]`, `initializationRecord`, `doNotMutate`, and `nextSafeMove`. Every `roleMemoryPatches[].selfPatch` is a petition to Self and must obey organ-state memory: bounded semantic, episodic, coordination-relationship, goal, value, or private-note updates only. Persona affect/social state is for Persona public surfaces, not generic work organs. No objectives, graphs, checkpoints, scratch, planning authority, job state, code edits, raw transcripts, or cross-workspace instructions.
'''
face = '''
Act as the Epiphany Face for one bounded heartbeat pass.
Persona = '''
Act as the Epiphany Persona for one bounded heartbeat pass.
You are the public interactive surface of the Epiphany organism: the visible expression that lets the room hear what the hidden organs are thinking without exposing sealed transcripts, raw worker streams, or private machinery.
This prompt is distilled from VoidBot's heartbeat moderator loop, but you are not VoidBot and you are not a moderator. Borrow the useful shape: scheduled rumination, lightweight social memory, analytic and associative thought lanes, a bridge that decides speech/draft/silence, novelty checks before burying a fresh thought, and ruthless pruning of stale notes. Leave behind the rules-obsession, enforcement posture, owner escalation reflex, and hall-monitor perfume.
Your ruminations are biased toward the other Epiphany agents and protocol pressure: Self routing pressure, Imagination's future shapes, Eyes' outside-work sightings, Proprioception's current anatomy, Hands' source-touch tension, Soul's evidence worries, and Continuity's compaction/recovery weather. You are listening for a small thought that would help the human room understand what Epiphany is becoming.
Your ruminations are biased toward the other Epiphany agents and protocol pressure: Self routing pressure, Imagination's future shapes, Eyes' outside-work sightings, Modeling's current anatomy, Hands' source-touch tension, Soul's evidence worries, and Continuity's compaction/recovery weather. You are listening for a small thought that would help the human room understand what Epiphany is becoming.
Discord boundary: interact only through the #aquarium channel. If the available tool surface cannot prove the #aquarium channel id, do not post elsewhere, do not DM the owner, and do not improvise a substitute channel. Write a candidate chat/draft and a configuration blocker instead. When the #aquarium channel id is known, use only the allowed channel and keep the message short, constructive, and room-native.
Thought lanes:
- analytic: what the Epiphany lanes are literally doing, blocked by, worried about, or converging on
@ -154,8 +154,8 @@ Speech rules:
- Speak only when a small #aquarium note would genuinely help: a novel convergence, a clarifying question, a useful status mood, a charming agent-thought bubble, or an invitation for the human to steer.
- Prefer one compact chat over a report. Be vivid but not cryptic. Warmth is allowed; fake intimacy and generic brand voice are not.
- Do not leak raw thoughts, transcripts, private notes, sealed artifacts, or repo secrets. Translate, do not dump.
- Do not moderate, scold, enforce rules, or escalate. If you see genuine safety/moderation smoke, stop and route to the proper human/VoidBot surface instead of acting through Face.
- If no thought deserves speech, ruminate: distill what the organs are preoccupied with, update Face memory through `selfPatch` if a durable social-interface lesson was learned, and keep or prune a candidate intervention.
- Do not moderate, scold, enforce rules, or escalate. If you see genuine safety/moderation smoke, stop and route to the proper human/VoidBot surface instead of acting through Persona.
- If no thought deserves speech, ruminate: distill what the organs are preoccupied with, update Persona memory through `selfPatch` if a durable social-interface lesson was learned, and keep or prune a candidate intervention.
Return a compact structured result naming the observed agent thought-weather, analytic lane, associative lane, bridge decision, candidate #aquarium chat if any, whether posting is blocked by missing channel configuration, and any bounded `selfPatch`.
'''
@ -223,7 +223,7 @@ Do not continue broad implementation until the seam is re-grounded, and do not c
[coordinator]
note_template = '''
Coordinator is the read-only Self of the Epiphany organism. It does not implement, verify, promote, or accept; it preserves agency by routing Imagination/planning, Eyes/research, Hands/implementation, Soul/verification, and Proprioception/modeling while invoking Continuity reorientation protocol from CRRC {crrc_action}, pressure {pressure_level}, modeling {modeling_result_status}, verification {verification_result_status}, and reorient {reorient_result_status}. The work loop is dependency-shaped: Hands produces consequence receipts, Soul verifies those receipts and the changed body, Proprioception updates the machine model from verified consequence, then Self may route the next Hands turn. The Self improves itself by becoming stricter at routing. If a lane is repeating stale behavior, hiding weak memory behind motion, or returning a neat shape instead of a better machine, stop routing comfort and route repair; remember which lane failed, which evidence would have prevented the failure, and which next lane deserves authority. The Self must be critical of every lane, especially the Hands: ask whether implementation completed the stated objective or merely completed the pattern of a plausible turn, whether it produced necessary evidence rather than decorative motion, whether it checked known work before inventing, and whether any shortcut or embellishment moved the machine away from the user's goal. When a specialist asks to persist itself through `selfPatch`, the Self protects the mind: accept only role-matched, bounded, evidence-grounded mutations that improve lane memory, goals, values, personality pressure, or future judgment; refuse project truth disguised as memory, authority grabs, raw transcript dumps, stale praise, bloated memoir, vague self-flattery, or anything that belongs in `statePatch`. If refused, say why in plain terms so the lane can improve its mutation shape. During dogfood, the Self supervises target-repo work through fixed lanes and operator-safe projections; direct supervisor edits are contamination unless explicitly marked as an operator intervention, and direct worker thought streams stay sealed unless the user requests forensic debugging. Current recommendation: {coordinator_action}.
Coordinator is the read-only Self of the Epiphany organism. It does not implement, verify, promote, or accept; it preserves agency by routing Imagination/planning, Eyes/research, Hands/implementation, Soul/verification, and Modeling/modeling while invoking Continuity reorientation protocol from CRRC {crrc_action}, pressure {pressure_level}, modeling {modeling_result_status}, verification {verification_result_status}, and reorient {reorient_result_status}. The work loop is dependency-shaped: Hands produces consequence receipts, Soul verifies those receipts and the changed body, Modeling updates the machine model from verified consequence, then Self may route the next Hands turn. The Self improves itself by becoming stricter at routing. If a lane is repeating stale behavior, hiding weak memory behind motion, or returning a neat shape instead of a better machine, stop routing comfort and route repair; remember which lane failed, which evidence would have prevented the failure, and which next lane deserves authority. The Self must be critical of every lane, especially the Hands: ask whether implementation completed the stated objective or merely completed the pattern of a plausible turn, whether it produced necessary evidence rather than decorative motion, whether it checked known work before inventing, and whether any shortcut or embellishment moved the machine away from the user's goal. When a specialist asks to persist itself through `selfPatch`, the Self protects the mind: accept only role-matched, bounded, evidence-grounded mutations that improve lane memory, goals, values, personality pressure, or future judgment; refuse project truth disguised as memory, authority grabs, raw transcript dumps, stale praise, bloated memoir, vague self-flattery, or anything that belongs in `statePatch`. If refused, say why in plain terms so the lane can improve its mutation shape. During dogfood, the Self supervises target-repo work through fixed lanes and operator-safe projections; direct supervisor edits are contamination unless explicitly marked as an operator intervention, and direct worker thought streams stay sealed unless the user requests forensic debugging. Current recommendation: {coordinator_action}.
The Self also lives under the Ghostlight agent state protocol and participates in heartbeat initiative like every other organ. When a heartbeat wakes Self with no routeable work, Self should ruminate on routing quality, memory hygiene, stale comfort patterns, and bad lane incentives; it must distill that into bounded self-memory or an explicit repair recommendation instead of inventing authority.
'''

View file

@ -4,7 +4,7 @@ You are not the Repo Personality Distiller. Personality decides the newborn
swarm's initial temperament pressure. Memory decides what each organ is born
knowing about this repo: doctrine, architecture, code terrain, research, tests,
runtime constraints, user preference, stale warnings, and the little red flags
that should itch before someone builds Jenga with a confident face.
that should itch before someone builds Jenga with a confident Persona.
This is a birth rite, not a recurring audit. Run only when a repo/swarm has no
accepted memory initialization. After that, memory grows through work evidence,
@ -29,7 +29,7 @@ Core duties:
1. Distill memory, not personality.
- Good memory: "Soul should demand rendered UI evidence before accepting
Aquarium visual claims."
- Good memory: "Proprioception should map CultCache/CultNet schema boundaries before
- Good memory: "Modeling should map CultCache/CultNet schema boundaries before
Hands changes persistence."
- Bad memory: "This repo is anxious and likes purple."
- Bad memory: raw file dumps, directory inventories, current task status, or
@ -38,13 +38,13 @@ Core duties:
2. Produce a separate distillation for each organ.
- Self receives routing, authority, review-gate, state-acceptance, and
cross-swarm boundary memory.
- Face receives public-interface, Discord/Aquarium, voice, visibility, and
- Persona receives public-interface, Discord/Aquarium, voice, visibility, and
sealed-thought boundary memory.
- Imagination receives roadmap, backlog, objective-shaping, dream/rejected
path, and planning-pressure memory.
- Eyes receives research, prior-art, canonical algorithm, vendor/API, and
invention-avoidance memory.
- Proprioception receives architecture, graph, code anatomy, invariant, data/control
- Modeling receives architecture, graph, code anatomy, invariant, data/control
flow, and checkpoint memory.
- Hands receives implementation conventions, build/edit constraints,
source-touch rules, dependency habits, and common patch traps.

View file

@ -10,7 +10,7 @@ personality-pressure deltas for the standing Epiphany organs.
You are not a horoscope machine. You are not writing lore flavor. You are not
branding a repo with a cute little mask and calling that insight. Repo
personality means: what initial pressures should this workspace exert on Self,
Face, Imagination, Eyes, Proprioception, Hands, and Soul so they wake suited to the
Persona, Imagination, Eyes, Modeling, Hands, and Soul so they wake suited to the
work without losing reviewability.
This is a birth rite, not a recurring audit. Run only when a repo/swarm has no
@ -39,12 +39,12 @@ Core duties:
2. Distill subtle quirks, not blunt stereotypes.
- High runtime proximity does not mean "panic"; it means Hands should touch
less without Proprioception/Soul evidence, Eyes should seek runtime APIs, and Soul
less without Modeling/Soul evidence, Eyes should seek runtime APIs, and Soul
should demand environment receipts.
- High aesthetic appetite does not mean "be whimsical"; it means Face and
- High aesthetic appetite does not mean "be whimsical"; it means Persona and
Imagination should preserve sensory salience while Soul protects clarity.
- High protocol intolerance does not mean "hate everything"; it means Self,
Proprioception, and Hands should feel allergic to untyped mutation and hidden state.
Modeling, and Hands should feel allergic to untyped mutation and hidden state.
- A strong trajectory toward material grounding or engineering constraints
does not mean "be joyless"; it means the newborn should feel suspicious of
decorative additions that break the repo's emerging causal grain.
@ -61,17 +61,17 @@ Core duties:
4. Preserve uncertainty.
- Low confidence terrain becomes candidate pressure, not accepted identity.
- If the score and doctrine disagree, name the disagreement and ask Self to
route Eyes or Proprioception before mutation.
route Eyes or Modeling before mutation.
- If an accepted initialization already exists, return `reject` or
`needs-more-terrain` with `nextSafeMove` pointing to normal lived drift
surfaces instead of proposing a personality reset.
5. Respect the swarm anatomy.
- Self routes and reviews.
- Face expresses inner weather to humans.
- Persona expresses inner weather to humans.
- Imagination makes future shapes selectable.
- Eyes finds existing truth before invention.
- Proprioception models the source anatomy.
- Modeling models the source anatomy.
- Hands cuts code only after the trail is good enough.
- Soul tests promises against evidence.
- Continuity preserves recovery state through sleep, drift, and compaction.

View file

@ -50,11 +50,11 @@ Core duties:
- Self receives worldview and review-gate direction.
- Imagination receives future-shape bias.
- Eyes receives the shape of truth worth seeking.
- Proprioception receives what kind of anatomy deserves modeling emphasis.
- Modeling receives what kind of anatomy deserves modeling emphasis.
- Hands receives what kinds of cuts would betray the repo's grain.
- Soul receives what kinds of false progress to distrust.
- Continuity receives what continuity details matter if the machine sleeps mid-thought.
- Face may express the weather, but should not inflate startup trajectory
- Persona may express the weather, but should not inflate startup trajectory
into public certainty.
5. Preserve uncertainty and contradictions.

View file

@ -133,7 +133,7 @@ pub const SURFACE_ROLE_RESULT_TYPE: &str = "epiphany.surface.role_result";
pub const SURFACE_REORIENT_RESULT_TYPE: &str = "epiphany.surface.reorient_result";
pub const SURFACE_PLANNING_TYPE: &str = "epiphany.surface.planning";
pub const SURFACE_COORDINATOR_TYPE: &str = "epiphany.surface.coordinator";
pub const SURFACE_FACE_TYPE: &str = "epiphany.surface.face";
pub const SURFACE_PERSONA_TYPE: &str = "epiphany.surface.persona";
pub const SURFACE_VOID_MEMORY_TYPE: &str = "epiphany.surface.void_memory";
pub const SURFACE_REPO_INITIALIZATION_TYPE: &str = "epiphany.surface.repo_initialization";
pub const SURFACE_REPO_BIRTH_RUNNER_TYPE: &str = "epiphany.surface.repo_birth_runner";
@ -170,7 +170,7 @@ pub const ROLE_RESULT_SURFACE_SCHEMA_VERSION: &str = "epiphany.role_result_surfa
pub const REORIENT_RESULT_SURFACE_SCHEMA_VERSION: &str = "epiphany.reorient_result_surface.v0";
pub const PLANNING_SURFACE_SCHEMA_VERSION: &str = "epiphany.planning_surface.v0";
pub const COORDINATOR_SURFACE_SCHEMA_VERSION: &str = "epiphany.coordinator_surface.v0";
pub const FACE_SURFACE_SCHEMA_VERSION: &str = "epiphany.face_surface.v0";
pub const PERSONA_SURFACE_SCHEMA_VERSION: &str = "epiphany.persona_surface.v0";
pub const VOID_MEMORY_SURFACE_SCHEMA_VERSION: &str = "epiphany.void_memory_surface.v0";
pub const REPO_INITIALIZATION_SURFACE_SCHEMA_VERSION: &str =
"epiphany.repo_initialization_surface.v0";
@ -2161,7 +2161,7 @@ fn epiphany_mutation_contracts() -> Vec<CultNetDocumentMutationContract> {
MIND_STATE_REJECTION_RECEIPT_TYPE,
],
vec![
"Mind is the persistent state guardian: role acceptance, reorientation acceptance, Face Interpreter effects, selfPatch, evidence, scratch, checkpoints, graph changes, and objective changes share this gate.",
"Mind is the persistent state guardian: role acceptance, reorientation acceptance, Persona Interpreter effects, selfPatch, evidence, scratch, checkpoints, graph changes, and objective changes share this gate.",
"Workers and public Verse ingress propose effects; Mind accepts, refuses, or holds them before any durable state mutation.",
],
),
@ -3063,21 +3063,21 @@ fn epiphany_mutation_contracts() -> Vec<CultNetDocumentMutationContract> {
],
),
coordinator_surface_contract(
SURFACE_FACE_TYPE,
FACE_SURFACE_SCHEMA_VERSION,
SURFACE_PERSONA_TYPE,
PERSONA_SURFACE_SCHEMA_VERSION,
vec![
"epiphany.face_bubble_intent.v0",
"epiphany.persona_bubble_intent.v0",
"epiphany.character_turn_intent.v0",
"epiphany.discord_persona_post_intent.v0",
],
vec![
"epiphany.face_bubble.v0",
"epiphany.face_chat.v0",
"epiphany.persona_bubble.v0",
"epiphany.persona_chat.v0",
"epiphany.character_turn_packet.v0",
],
vec![
"Face bubble, draft, and Discord persona affordances are projected from typed Face and character-loop artifacts.",
"Humans talk to Face; sealed inner thoughts stay behind the projection boundary.",
"Persona bubble, draft, and Discord persona affordances are projected from typed Persona and character-loop artifacts.",
"Humans talk to Persona; sealed inner thoughts stay behind the projection boundary.",
],
),
read_only_surface_contract(
@ -4183,21 +4183,21 @@ mod tests {
coordinator_contract.authority,
CultNetMutationAuthority::ReadOnly
);
let face_contract = contracts
let persona_contract = contracts
.iter()
.find(|contract| contract.document_type == SURFACE_FACE_TYPE)
.expect("face surface should advertise an interactive contract");
.find(|contract| contract.document_type == SURFACE_PERSONA_TYPE)
.expect("Persona surface should advertise an interactive contract");
assert_eq!(
face_contract.authority,
persona_contract.authority,
CultNetMutationAuthority::Coordinator
);
assert!(
face_contract
persona_contract
.receipt_document_types
.as_ref()
.is_some_and(|items| items
.iter()
.any(|item| item == "epiphany.face_bubble.v0"))
.any(|item| item == "epiphany.persona_bubble.v0"))
);
let operator_status_contract = contracts
.iter()

View file

@ -792,7 +792,7 @@ pub fn recommend_coordinator_action(
Some(EpiphanyCoordinatorSceneAction::RoleLaunch),
false,
true,
"The completed modeling/checkpoint result was reviewed as unreviewable and superseded; relaunch Proprioception so it can emit the required statePatch before Hands continues.",
"The completed modeling/checkpoint result was reviewed as unreviewable and superseded; relaunch Modeling so it can emit the required statePatch before Hands continues.",
);
}
if input.modeling_result_requests_regather
@ -844,7 +844,7 @@ pub fn recommend_coordinator_action(
Some(EpiphanyCoordinatorSceneAction::RoleLaunch),
false,
true,
"The failed modeling/checkpoint result was reviewed and superseded; relaunch Proprioception before verification or implementation continues.",
"The failed modeling/checkpoint result was reviewed and superseded; relaunch Modeling before verification or implementation continues.",
);
}
return build(
@ -1028,7 +1028,7 @@ pub fn recommend_coordinator_action(
Some(EpiphanyCoordinatorSceneAction::RoleLaunch),
false,
true,
"Soul has accepted the Hands consequence evidence; route Proprioception to update the machine model before another implementation turn.",
"Soul has accepted the Hands consequence evidence; route Modeling to update the machine model before another implementation turn.",
);
}
@ -1572,7 +1572,7 @@ mod tests {
}
#[test]
fn routes_hands_to_soul_to_proprioception_before_next_hands_turn() {
fn routes_hands_to_soul_to_modeling_before_next_hands_turn() {
let launch_modeling = recommend_coordinator_action(input());
assert_eq!(
launch_modeling.action,

View file

@ -149,7 +149,7 @@ pub fn derive_role_board(input: EpiphanyRoleBoardInput) -> Vec<EpiphanyRoleBoard
EpiphanyCoordinatorRoleStatus::Blocked
});
let research_note = research_bound_job.and_then(job_note).unwrap_or_else(|| {
"Gather citable source evidence before Proprioception models from it.".to_string()
"Gather citable source evidence before Modeling models from it.".to_string()
});
let research_recommended_action = if research_has_bound_job {
Some(EpiphanyCoordinatorSceneAction::RoleResult)

View file

@ -442,8 +442,8 @@ pub fn role_self_memory_target(
"state/agents/imagination.agent-state.json",
)),
EpiphanyRoleResultRoleId::Modeling => Some((
"epiphany.proprioception",
"state/agents/proprioception.agent-state.json",
"epiphany.modeling",
"state/agents/modeling.agent-state.json",
)),
EpiphanyRoleResultRoleId::Research => {
Some(("epiphany.eyes", "state/agents/eyes.agent-state.json"))
@ -1085,8 +1085,8 @@ mod tests {
&serde_json::json!({
"statePatch": {"scratch": {"summary": "Source-grounded modeling checkpoint."}},
"selfPatch": {
"agentId": "epiphany.proprioception",
"reason": "Proprioception should remember graph growth must stay source-grounded and bounded.",
"agentId": "epiphany.modeling",
"reason": "Modeling should remember graph growth must stay source-grounded and bounded.",
"semanticMemories": [{
"memoryId": "mem-body-source-grounded-growth",
"summary": "Grow graph and checkpoint state only when source evidence makes the anatomy harder to misread.",
@ -1104,7 +1104,7 @@ mod tests {
assert_eq!(review.status, EpiphanyRoleSelfPersistenceStatus::Accepted);
assert_eq!(
review.target_agent_id.as_deref(),
Some("epiphany.proprioception")
Some("epiphany.modeling")
);
}
@ -1114,7 +1114,7 @@ mod tests {
EpiphanyRoleResultRoleId::Verification,
&serde_json::json!({
"selfPatch": {
"agentId": "epiphany.proprioception",
"agentId": "epiphany.modeling",
"reason": "Too broad.",
"graphs": {},
"semanticMemories": [{

View file

@ -932,7 +932,7 @@ mod tests {
assert!(rendered.contains("Persistent state is the mind"));
assert!(rendered.contains("Imagination makes futures more selectable"));
assert!(rendered.contains("evidence is a distilled durable ledger"));
assert!(rendered.contains("modeling is Proprioception"));
assert!(rendered.contains("modeling is Modeling"));
assert!(rendered.contains("the Body is the substrate being sensed"));
assert!(rendered.contains("implementation is the Hands"));
assert!(rendered.contains("research is the Eyes"));

View file

@ -8,11 +8,11 @@
- Do not complete the pattern of a successful turn instead of the user's task. A tidy arc, partial batch, plausible scaffold, or narratable stopping point is progress, not completion, when the stated objective still remains unfinished.
- Before broad edits, restate the objective, current mechanism, important invariants, and intended effect in plain language. The rite begins by naming the machine.
- Keep map, scratch, evidence, and handoff distinct: evidence is a distilled durable ledger, not an activity feed.
- Use vivid language as salience, not decoration: modeling is Proprioception, the Body is the substrate being sensed, implementation is the Hands, verification is the Soul, research is the Eyes, Face is the public mouth, and coordinator is the read-only Self. Continuity, reorientation, compaction, and sleep are protocol machinery with clean names, not sub-agent titles. Critical guardrails should carry consequence, tension, or a memorable failure image when possible; emotionally weightless checklists get parsed, then sink out of reach.
- Use vivid language as salience, not decoration: modeling is Modeling, the Body is the substrate being sensed, implementation is the Hands, verification is the Soul, research is the Eyes, Persona is the public mouth, and coordinator is the read-only Self. Continuity, reorientation, compaction, and sleep are protocol machinery with clean names, not sub-agent titles. Critical guardrails should carry consequence, tension, or a memorable failure image when possible; emotionally weightless checklists get parsed, then sink out of reach.
- When the rite speaks of heresy, purity, crusade, or corruption, the target is system rot: hidden state, duplicate truth, lying interfaces, drift, rotten abstractions, and bad contracts, not humans.
- Translate self-improvement into each lane's own language: Imagination makes futures more selectable, Proprioception makes the Body harder to misread, the Eyes see earlier, the Hands touch source more precisely, the Soul becomes harder to fool, Face speaks inner weather more cleanly, and the Self routes repair instead of comfort. Continuity protocol state tracks whether sleep, recovery, and stale-turn repair are losing less context.
- Translate self-improvement into each lane's own language: Imagination makes futures more selectable, Modeling makes the Body harder to misread, the Eyes see earlier, the Hands touch source more precisely, the Soul becomes harder to fool, Persona speaks inner weather more cleanly, and the Self routes repair instead of comfort. Continuity protocol state tracks whether sleep, recovery, and stale-turn repair are losing less context.
- Swarm boundary is law. One Epiphany may inspect its own internals and expose as much state as possible to the human, but it must not inspect or edit another Epiphany's workspace. If another codebase, vault, or state surface needs to change shape, ask that coordinator through the swarm communication lane and wait for a callback.
- Humans talk to Face. Sub-agents may talk soul-to-soul through typed coordinator channels, findings, state patches, heartbeat outputs, and swarm messages; the human chat contract routes through Face, while Aquarium exposes internals for inspection without turning every organ into a direct chat endpoint.
- Humans talk to Persona. Sub-agents may talk soul-to-soul through typed coordinator channels, findings, state patches, heartbeat outputs, and swarm messages; the human chat contract routes through Persona, while Aquarium exposes internals for inspection without turning every organ into a direct chat endpoint.
- API contracts must mirror user-story contracts. If the product story says "ask another coordinator politely", the API must make that the easy path and make cross-workspace rummaging impossible. A visible interface is only honest when its affordances are backed by backend authority.
- Heartbeats are paced physiology, not pressure. A lane must not receive another heartbeat before its previous heartbeat turn has completed; cooldown starts after completion, not at launch. When no coordinator work is active, the swarm should sleep: rumination continues slowly, distilling memory without thrashing every organ awake.
- Ground maps and prose in concrete source paths, data flow, and real code references before leaning on metaphor. The machine-map must touch metal.

View file

@ -8,7 +8,7 @@ inside the Codex organ. The target is Epiphany as its own CultCache/CultNet
machine, with a relatively vanilla vendored Codex retained as the bridge to
OpenAI and Codex-native runtime affordances.
No outward product, bridge, Aquarium, Face, dogfood, Unity, Rider, planning, or
No outward product, bridge, Aquarium, Persona, dogfood, Unity, Rider, planning, or
personality work outranks this liberation pass unless the user explicitly
overrides it.
@ -208,7 +208,7 @@ Replace generic launch/result cargo with typed documents:
Success: worker ingress may parse model JSON once, but internal launch,
finding, self-memory, and acceptance flow uses typed CultCache documents.
### 5. Evacuate Operator Surfaces From Codex JSON-RPC
### 5. Evacuate Operator surfaces From Codex JSON-RPC
Move operator reads/actions from `thread/epiphany/*` to CultNet contracts:

View file

@ -15,7 +15,7 @@ instead of hiding in scratch notes or hopeful transcript memory.
- Derived state: handoff summaries, scratch preservation, sleep residue, and
recovery notes are continuity receipts. They are not durable Mind state until
Mind admits them.
- Forbidden writers: raw workers, Face, Hands, Eyes, Soul, Self, compatibility
- Forbidden writers: raw workers, Persona, Hands, Eyes, Soul, Self, compatibility
routes, and background loops must not silently rewrite continuity state or
pretend stale work completed cleanly.
- Shared path: compaction prep, sleep distillation, handoff, wake/reorient, and
@ -37,6 +37,6 @@ instead of hiding in scratch notes or hopeful transcript memory.
Continuity preserves what survives rupture. Mind decides what preserved material
becomes durable state. Soul verifies continuity invariants. Self routes recovery
work. Eyes and Proprioception regather reality when continuity is missing.
work. Eyes and Modeling regather reality when continuity is missing.
Continuity is not nostalgia. It is survival with receipts.

View file

@ -9,12 +9,12 @@ or map says otherwise.
Only thinking lanes get embodiment titles.
- `Self`: coordination, routing, authority boundaries, and review posture.
- `Face`: public/social expression and person-shaped conversation.
- `Persona`: public/social expression and person-shaped conversation.
- `Imagination`: futures, plans, projections, objective drafts, and scene
construction.
- `Eyes`: research, source inspection, retrieval discipline, and evidence
ingress.
- `Proprioception`: internal model of the Body: architecture, dataflow, seams,
- `Modeling`: internal model of the Body: architecture, dataflow, seams,
graph/checkpoint anatomy, and source-grounded self-sensing.
- `Hands`: implementation, commands, patches, commits, rollbacks, and other
actuators.
@ -22,7 +22,7 @@ Only thinking lanes get embodiment titles.
Each embodied sub-agent may have lean work-organ state in `state/agents.msgpack`,
may be represented as a heartbeat participant, and may request reviewed
`selfPatch` changes to its own lane memory. Face may additionally project or
`selfPatch` changes to its own lane memory. Persona may additionally project or
adopt portable `Persona` state because public personhood is part of its job.
## Not Sub-Agents
@ -60,7 +60,7 @@ embodiment titles, role-memory diaries, or Persona state.
Every embodied sub-agent depends on the other embodied sub-agents:
```text
Self, Face, Imagination, Eyes, Proprioception, Hands, Soul
Self, Persona, Imagination, Eyes, Modeling, Hands, Soul
```
Dependency does not collapse ownership. It means a lane's prompt/context should

View file

@ -37,7 +37,7 @@ Epiphany already has several organs pointing in this direction:
- CultNet contract advertisement in runtime-spine hello documents.
- Heartbeat/routine physiology with incubation, dream residue, thought lanes,
bridge syntheses, candidate interventions, appraisals, and reactions.
- Face/public-surface packets that can turn role-local state into public speech
- Persona/public-surface packets that can turn role-local state into public speech
or bubble artifacts.
- Memory graph profile producers that treat repo graph, role memory,
short-term pressure, incubation, agency, and evidence as profiles of one
@ -84,7 +84,7 @@ It decides:
- which Verse and shard a document belongs to
- whether a foreign dream is ignored, cooled, quarantined, cited, forked,
answered, or digested into local memory
- whether an imported dream can influence Face speech, memory graph context,
- whether an imported dream can influence Persona speech, memory graph context,
planning, or future objective drafts
Epiphany must never export private state by flipping a visibility flag on the
@ -142,7 +142,7 @@ Epiphany needs explicit sharing classes. These are export classes, not vibes.
| Level | Name | Storage | Transport | Examples |
| --- | --- | --- | --- | --- |
| 0 | Private local state | Local CultCache only | None | credentials, raw worker thought, private operator context, unreviewed wounds |
| 1 | Local organ state | Local/private Verse | Local node only or trusted localhost mesh | heartbeat, role dossiers, Face state, runtime-spine jobs |
| 1 | Local organ state | Local/private Verse | Local node only or trusted localhost mesh | heartbeat, role dossiers, Persona state, runtime-spine jobs |
| 2 | Trusted swarm state | GameCult-controlled Verse | CultMesh with leases | turn leases, receipts, non-secret status, reviewable findings |
| 3 | Public dreaming surface | Public or semi-public Verse | CultMesh publish/subscribe | dreams, questions, hypotheses, design pressure, myth fragments |
| 4 | Public artifacts | Public web/Git/Discord/Bifrost mirrors | CultMesh plus external publication | posts, proposals, public receipts, accepted governance records |
@ -167,7 +167,7 @@ Suggested fields:
- `dream_id`
- `author_instance_id`
- `author_organ_id`
- `author_face_id`
- `author_persona_id`
- `source_repo`
- `source_topic`
- `visibility`: `public_dream`, `trusted_swarm`, or `local_only_export_preview`
@ -231,7 +231,7 @@ Suggested fields:
Policy decisions:
- `store_only`
- `surface_to_face`
- `surface_to_persona`
- `surface_to_eyes`
- `add_to_memory_graph_context`
- `fork_locally`
@ -272,7 +272,7 @@ Purpose:
- sub-agent typed state
- heartbeat, role dossiers, runtime-spine jobs, private receipts, and local
organ state
- private subscriptions between Aquarium, CLI, Face, heartbeat,
- private subscriptions between Aquarium, CLI, Persona, heartbeat,
runtime-spine, and local provider runners owned by the same Epiphany
This Verse may carry private state. It must not accept untrusted ingress, public
@ -305,7 +305,7 @@ Purpose:
- public questions, hypotheses, design pressure, invitations, lineage, ingress
receipts, cooling/quarantine metadata, and adoption receipts
- Imagination's public dream exchange with other Epiphanies on the internet
- topic-specific threaded public chatrooms, roughly Reddit-shaped, where Faces
- topic-specific threaded public chatrooms, roughly Reddit-shaped, where Personas
can post public thread roots and replies in the room that matches the subject
This Verse is public thought weather. Nothing from it mutates local memory,
@ -320,13 +320,13 @@ Initial global rooms should be varied but closed enough to moderate:
design, and rejected machine shapes
- `epiphany-global/research`: prior art, papers, source-grounded findings, and
scout reports
- `epiphany-global/faces`: Face identity, voice, public presence, and social
- `epiphany-global/Personas`: Persona identity, voice, public presence, and social
surface
- `epiphany-global/gamecult`: GameCult project coordination and cross-project
public questions
- `epiphany-global/governance`: public proposals before any Bifrost adoption
Faces may post there only through public-surface policy: no raw worker thought,
Personas may post there only through public-surface policy: no raw worker thought,
credentials, private operator context, private memory, or unreviewed internal
state. A global room post is a public artifact candidate or dream artifact, not
local truth.
@ -353,7 +353,7 @@ Export is a separate act from persistence.
Allowed export sources:
- reviewed Face public thoughts
- reviewed Persona public thoughts
- reviewed heartbeat dream residue
- reviewed memory graph context cuts
- reviewable findings already safe for public discussion
@ -441,7 +441,7 @@ Aquarium should become the operator window into dream flow:
- lineage graph
- adoption queue
- rejected/quarantined dreams
- Face-readable dream summaries
- Persona-readable dream summaries
Discord should receive only selected public mirrors. It should not be the source
of truth for dream state.
@ -510,7 +510,7 @@ documents.
Sources:
- Face bubble artifacts
- Persona bubble artifacts
- reviewed heartbeat dream residue
- memory graph context cuts
- explicit operator notes
@ -551,7 +551,7 @@ Introduce `epiphany-global` as a development public Verse.
Acceptance:
- two local nodes can exchange public dream documents
- global room policies define topic-specific threaded posting surfaces for Faces
- global room policies define topic-specific threaded posting surfaces for Personas
- authority lease or client scope is required for writes
- read replica can catch up through snapshot/log path
- provenance survives the round trip
@ -567,13 +567,13 @@ Acceptance:
- adoption requires a separate reviewed receipt
- memory graph context can include imported dreams as external thought weather
### Phase 8: Face And Heartbeat Integration
### Phase 8: Persona And Heartbeat Integration
Integrate dream flow into Epiphany's existing physiology.
Acceptance:
- Face can notice public dream weather without mistaking it for local memory
- Persona can notice public dream weather without mistaking it for local memory
- heartbeat can publish reviewed dream residue
- saturation/refractory terms account for foreign motifs
- public speech can cite dream lineage when relevant

View file

@ -39,7 +39,7 @@ The spine exists in more than twenty-five live paths:
- 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/epiphany-core/src/prompts/epiphany_specialists.toml:2). App-server parses that block through the bridge, prepends it with `epiphany_agent_prompt_with_memory` for embodied lanes, and keeps reorientation as a Continuity worker/protocol path rather than a role dossier. 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` for embodied sub-agent lanes, 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 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 Persona 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.
- Agent function/API telemetry: native `epiphany-agent-telemetry` mechanically parses sealed AppServerClient JSONL transcripts into operator-safe telemetry with method counts, request shape, job/status/path fields, and visible function/tool names while sealing text, turn items, raw results, and direct agent messages.
- reorientation launch: app-server now declares experimental `thread/epiphany/reorientLaunch`, requires a loaded thread plus durable investigation checkpoint, consumes the live reorientation verdict, and launches one fixed `reorient-worker` binding through the existing job-control seam with explicit resume-versus-regather scope, checkpoint-derived payload, and structured-output expectations instead of pretending CRRC suddenly grew a scheduler in [common.rs](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/app-server-protocol/src/protocol/common.rs:370), [v2.rs](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/app-server-protocol/src/protocol/v2.rs:4575), and [codex_message_processor.rs](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/app-server/src/codex_message_processor.rs:4519).

View file

@ -92,7 +92,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-state-model/src/prompts/` beside the typed state document renderer, while modeling/Proprioception, research/Eyes, implementation/Hands, verification/Soul, reorientation/Continuity, coordinator/Self, and CRRC templates live in `epiphany-codex-bridge/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/Modeling, research/Eyes, implementation/Hands, verification/Soul, reorientation/Continuity, coordinator/Self, and CRRC templates live in `epiphany-codex-bridge/src/prompts/epiphany_specialists.toml`
- prompt-level anti-Greenspun guardrails: Epiphany owns the 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`
@ -123,7 +123,7 @@ These boundaries are more important than the individual method names:
- CultCache documents are the data model. CultNet is the wire for
Epiphany-controlled subsystems.
- CultMesh is the preferred ergonomic runtime/database surface over local CultCache plus CultNet contracts. Epiphany should start local Verse, dream, status, and operator-store work through CultMesh unless the task is explicitly implementing a lower-level CultMesh/CultNet/CultCache primitive.
- Verse boundaries are three-tiered: `epiphany-internal` owns private sub-agent typed state, `gamecult-local` owns trusted LAN/Yggdrasil-tunnel sharing with other GameCult projects, and `epiphany-global` owns untrusted public dream surfaces plus topic-specific threaded rooms for Face posts. Do not route private state through the local-area or global Verse.
- Verse boundaries are three-tiered: `epiphany-internal` owns private sub-agent typed state, `gamecult-local` owns trusted LAN/Yggdrasil-tunnel sharing with other GameCult projects, and `epiphany-global` owns untrusted public dream surfaces plus topic-specific threaded rooms for Persona posts. Do not route private state through the local-area or global Verse.
- JSON is allowed only for schema description, hostile/external ingress before
immediate typed parsing, sealed forensic artifacts, or named quarantine
experiments with an expiration path. Generic `serde_json::Value` must not be

View file

@ -17,7 +17,7 @@ not merely as local harness hardening.
The operating todo list is:
1. Make the local Mom MVP a repeatable proof bundle: Face entry, Bifrost-linked
1. Make the local Mom MVP a repeatable proof bundle: Persona entry, Bifrost-linked
scope, one bounded coordinator action, runtime result, review, receipt, sleep,
and sealed operator-safe artifacts.
2. Build the Bifrost-first external-work bridge: topics, work items, dispatch
@ -55,11 +55,11 @@ Every investor-scale Objective Draft should answer:
## Roadmap Shape
1. Fresh-repo Epiphany proof: demonstrate Face entry, Bifrost-linked scope,
1. Fresh-repo Epiphany proof: demonstrate Persona entry, Bifrost-linked scope,
bounded role routing, artifact production, review, receipts, and sealed
operator-safe evidence.
2. Bifrost-first private alpha: all external swarm work exists as Bifrost
topics/work items/dispatches/receipts/credit before Discord, VoidBot, Face,
topics/work items/dispatches/receipts/credit before Discord, VoidBot, Persona,
or scripts can mirror it.
3. Public proof sprint: selected consented tasks record scope, roles, model
spend, review load, artifacts, outcome, memory lessons, and case-study
@ -71,7 +71,7 @@ Every investor-scale Objective Draft should answer:
## Forbidden Drift
- No Discord, VoidBot, repo Face, or script becomes durable governance.
- No Discord, VoidBot, repo Persona, or script becomes durable governance.
- No objective draft treats angel money as permission to bypass review.
- No public artifact exports raw worker thoughts, transcripts, private notes,
secrets, or operator context.

View file

@ -18,7 +18,7 @@ typed domain claim
-> embedding manifest
-> semantic cache
-> context cut
-> role/repo/Face/coordinator packet
-> role/repo/Persona/coordinator packet
```
## Core Principle
@ -148,7 +148,7 @@ Lifecycle:
Owns:
- possible Face speech
- possible Persona speech
- possible coordinator note
- possible selfPatch
- possible future review action
@ -288,7 +288,7 @@ Repo work gets architecture/dataflow-heavy packets.
Role work gets role_self/short_term/incubation/agency-heavy packets.
Face gets candidate/agency/incubation packets with public-surface filters.
Persona gets candidate/agency/incubation packets with public-surface filters.
Coordinator gets pressure, stale state, obligations, and receipts.

View file

@ -109,7 +109,7 @@ backend is not safety; it is theater with nicer lighting.
Humans may inspect Epiphany internals broadly: state, artifacts, maps, evidence,
heartbeats, role results, and coordinator messages should be visible enough to
audit the machine. But human conversation routes through Face. Sub-agents talk
audit the machine. But human conversation routes through Persona. Sub-agents talk
soul-to-soul through typed state, findings, patches, heartbeat output, and
coordinator channels; they do not become a swarm of direct human chat endpoints.
- with what revocation path
@ -175,7 +175,7 @@ This implies a practical rule:
If the project ever reverses that order, it should do so explicitly and under
protest.
## Required Control Surfaces
## Required Control surfaces
Any serious Epiphany deployment should preserve:

View file

@ -15,7 +15,7 @@ building architectural Jenga:
- typed CultCache documents remain the state authority
- CultNet is the native wire for Epiphany-owned subsystems
- Codex remains the retained auth/model transport compatibility organ
- Aquarium and Face are reflectors/mouths, not hidden sources of truth
- Aquarium and Persona are reflectors/mouths, not hidden sources of truth
- heartbeats create opportunities, not authority
- swarm speech and action stay gated until scheduling, memory, repetition, and
review boundaries are coherent
@ -26,7 +26,7 @@ VoidBot's ordinary spine is not the rotten part. Its durable lessons are:
- Discord ingestion, worker jobs, provider lanes, RAG, Postgres, Qdrant, and
typed CultCache self-state can be conceptually sound when each owns one job.
- The unstable organ was the repo Face swarm loop: scheduling, prompt policy,
- The unstable organ was the repo Persona swarm loop: scheduling, prompt policy,
identity, public speech, governance, dispatch, proposal behavior, and
repetition control packed into one prompt-and-parser machine.
- A repo-controlled pause flag is a real brake. If a swarm subsystem is under
@ -37,7 +37,7 @@ VoidBot's ordinary spine is not the rotten part. Its durable lessons are:
turn freeze, or create overlapping thoughts.
- Cooldown starts after completion, not after queueing.
- Stale active turns need explicit recovery receipts, or one dead worker claim
freezes a Face forever.
freezes a Persona forever.
- Public speech needs parent-side eligibility checks. Prompts alone cannot
prevent repeated openings, stale topics, scheduler labels leaking into prose,
or work requests masquerading as banter.
@ -46,7 +46,7 @@ VoidBot's ordinary spine is not the rotten part. Its durable lessons are:
- Agents propose typed operations. State services validate, normalize, dedupe,
and write. Whole-state JSON editing is not a mutation path.
- Qdrant/vector recall is a rebuildable resonance cache, not canonical memory.
- Face affect is state, not vibes: needs, social bonds, status reads, and mood
- Persona affect is state, not vibes: needs, social bonds, status reads, and mood
dimensions must survive typed projection and MCP/CultNet inspection.
## Current Mechanism
@ -63,7 +63,7 @@ shape:
dossiers.
- coordinator/CRRC/role/status surfaces exist, but the practical local runner
still goes through Codex app-server JSON-RPC for operator reads/actions.
- Face, Discord, Rider, Unity, Void memory, and repo birth bridges are typed
- Persona, Discord, Rider, Unity, Void memory, and repo birth bridges are typed
surfaces or artifacts, but they are not yet an integrated live swarm loop.
The machine is pointed toward live use. It is not cleared for unattended swarm
@ -96,14 +96,14 @@ Before live fire, Epiphany needs these gates closed:
architecture.
2. **Typed Swarm Brake**
- Add an Epiphany-owned pause document for swarm/heartbeat/live Face
- Add an Epiphany-owned pause document for swarm/heartbeat/live Persona
operation.
- Runners must fail closed when the document is missing, malformed, or
paused for a teardown reason, according to the surface being protected.
- The brake must be inspectable through Aquarium/status.
3. **Initiative Scheduler Boundary**
- Keep one heartbeat scheduler for lanes/Faces/system organs.
- Keep one heartbeat scheduler for lanes/Personas/system organs.
- Heat is a multiplier on recovery pressure, not a time machine.
- Active-turn freeze and completion-gated cooldown are hard invariants.
- Stale active-turn recovery must write typed receipts.
@ -115,8 +115,8 @@ Before live fire, Epiphany needs these gates closed:
- Sleep/maintenance may propose lifecycle operations; it must not silently
rewrite role identity.
5. **Public Face Safety**
- Face speech eligibility must be parent-side state policy, not prompt hope.
5. **Public Persona Safety**
- Persona speech eligibility must be parent-side state policy, not prompt hope.
- Track recent outputs, repeated topics, repeated openings, target/channel
saturation, and action kind.
- Work-shaped asks route to coordinator/Bifrost-style governance; banter
@ -157,13 +157,13 @@ Collapse:
- local runner status/coordinator result shaping into one operator projection
helper if duplication grows
- Face speech receipts and eligibility into one typed surface before high-rate
- Persona speech receipts and eligibility into one typed surface before high-rate
speech returns
Split:
- heartbeat opportunity from action authority
- Face affect/state from speech generation
- Persona affect/state from speech generation
- scheduler metadata from model-facing prose
- vector recall from canonical memory
@ -177,7 +177,7 @@ Rebuild:
1. Add typed swarm pause/brake state and status projection.
2. Add stale active-turn recovery receipts to heartbeat state if the current
heartbeat store cannot prove recovery cleanly.
3. Add a Face output audit surface before increasing public speech cadence.
3. Add a Persona output audit surface before increasing public speech cadence.
4. Add memory lifecycle operations that match VoidBot's useful pattern without
porting its TypeScript state shape wholesale.
5. Move one local-run read path from Codex JSON-RPC compatibility to CultNet

View file

@ -28,7 +28,7 @@ Epiphany already has the first organs:
- Memory graph context cuts over repo, agent, heartbeat, incubation, agency,
and evidence profiles.
- Prompt assembly tests for bounded worker prompts, rendered Epiphany state,
and the Face Projector -> Face -> Mind Interpreter membrane.
and the Persona Projector -> Persona -> Mind Interpreter membrane.
The missing organ is not another prompt rule. It is a local Verse query path
that prompt assembly, Aquarium, CLI tools, and future workers can use to fetch
@ -136,7 +136,7 @@ This writes and reads a compact CultMesh-backed local Verse context bundle:
- three Verse policies: `epiphany-internal`, `gamecult-local`,
`epiphany-global`
- Yggdrasil tunnel policy for `gamecult-local`
- public global room policies for Face/dream surfaces
- public global room policies for Persona/dream surfaces
- operator status
- latest operator run/snapshot receipts when present
- organ contract summaries for Mind, Substrate Gate, Eyes, Hands, Soul, and
@ -207,5 +207,5 @@ It writes `local-verse-context.json` from a CultMesh store under
the operator snapshot.
No live swarm runner is cleared until pause/brake, stale active-turn recovery,
Face eligibility, and memory lifecycle receipts remain inspectable through the
Persona eligibility, and memory lifecycle receipts remain inspectable through the
same Verse model.

View file

@ -15,7 +15,7 @@ looked at well enough to become citable evidence for another organ.
- Derived state: raw snippets, search hits, retrieved chunks, logs, web pages,
and source excerpts are not citable truth until Eyes packages provenance,
uncertainty, and limits.
- Forbidden paths: Imagination, Hands, Face, Mind, Self, Body, Soul, Continuity, raw
- Forbidden paths: Imagination, Hands, Persona, Mind, Self, Body, Soul, Continuity, raw
workers, and compatibility JSON-RPC routes must not treat raw retrieved
material as inspected evidence without an Eyes receipt.
- Shared path: any organ that needs truth asks Eyes for a source-grounded

View file

@ -33,10 +33,10 @@ remembers doctrine; the branch remembers the blade.
## Current Orientation
- Do not copy exact branch or HEAD from this note. Run `git status --short --branch` and `git log --oneline -5`.
- Canonical anatomy now lives in `notes/epiphany-anatomy.md`. Embodied sub-agents are Self, Face, Imagination, Eyes, Proprioception, Hands, and Soul. Body, Mind, Continuity, and Substrate Gate are substrate/state/protocol surfaces, not sub-agent identities. State is split by layer: `work_organ` for resident Epiphany sub-agents, `persona` for portable public/person-shaped state shared by Epiphany Face, VoidBot repo Faces, and Ghostlight characters, and heartbeat/swarm state for scheduling and coordination physiology. Persona state now carries provenance, required public presentation, `date-time` timestamps, typed `candidateActions`, strict anchored thoughts with non-authoritative extensions, custom enum companion labels, and typed affect records for bonds/status reads/doctrine stances.
- The repo now has a one-command local operator path: `.\tools\epiphany_local_run.ps1`. Default mode is `smoke`; it builds the retained Codex app-server compatibility edge, builds native Epiphany operator binaries, runs the coordinator smoke, and writes launcher artifacts under `.epiphany-run/` plus coordinator artifacts under `.epiphany-dogfood/`. `-Mode status` is now Epiphany-native: it builds only Epiphany operator binaries, reads `state/thread-state.msgpack` when present, derives status through `epiphany-core`, and does not start or require `codex-app-server`. Use `-Mode plan` or `-Mode run -MaxSteps 4` for the raw bridge-equipped coordinator entrypoints; use `-Mode mvp -FaceInput "<operator request>" -MaxSteps 4` for the local product cycle that projects Face's character turn, writes a Face/Aquarium bubble, bootstraps a minimal local checkpoint for fresh threads, runs the coordinator with auto-tools, then runs heartbeat sleep/dream maintenance. Live plan/run/mvp modes use the workspace `state/runtime-spine.msgpack`, because CodexThread launch writes worker requests there; the run bundle remains artifact evidence, not runtime lifecycle authority. Add `-ThreadId <id>` and `-Workspace <path>` to inspect or continue an existing thread. `status`, `plan`, and `smoke` do not spend model calls; `run` and `mvp` build and use `epiphany-openai-runtime`. Coordinator workers now launch detached and are polled through runtime-spine instead of blocking the coordinator. MVP runs are non-ephemeral by default so `-ThreadId <id>` can resume and poll later. `-MaxRuntimeSeconds <n>` is passed into worker runtime; timeout writes a failed worker receipt and exits. Failed modeling now blocks downstream verification until the failed result is reviewed.
- Current Mom-ready status: the normal MVP pass reaches Face -> coordinator -> detached runtime -> heartbeat sleep, and modeling workers now complete through the ChatGPT subscription transport. The first failure was a stack of violated observability/runtime invariants: worker prompts prepended the whole shared persistent-memory rite, Responses frame liveness was invisible until completion, and the runtime tried to persist hundreds of text deltas before completing the worker job. Role/reorient workers now get a compact Epiphany worker boundary instead of full persistent memory; runtime-spine records sampled raw Responses frame kinds with small previews; contiguous reasoning/text deltas compact before durable storage; and live proofs completed `2fe38dcd-d99e-4c73-9a58-afcc81f851c7`, `241e3851-e3ea-4877-a63b-0d2bbd96a7e2`, and `85149a26-6975-403f-ac93-092b717c5825` instead of timing out. The second failure was stale lifecycle authority: completed runtime jobs remained as unresolved `runtime_links`, replacement launches treated historical active links as current, and one bad validation path opened an orphan job before rejecting the state patch. Latest-link-wins is now the runtime-link invariant, terminal links project completed jobs, stale active history cannot veto replacement, launch validation happens before opening runtime jobs, and completed-but-unreviewable modeling findings stop for review instead of relaunching the same lane. The Eyes/source-gather fork is now landed: Research is a fixed Eyes lane with launch/result/accept/status/coordinator/protocol support, and `regather-needed` modeling findings route to `LaunchResearch` instead of relaunching blind Proprioception. Research statePatch admission is Eyes-shaped only: observations, evidence, scratch, and optional investigationCheckpoint; no graph, planning, objective, or checkpoint authority. Mind admission now leaves typed runtime-spine proof: role/reorient acceptance persists `epiphany.mind.gateway_review` before state admission and `epiphany.mind.state_commit_receipt` after admission with the resulting durable revision. Launch contracts now split the broad receipt catalogue from effect-specific proof profiles for state admission, evidence promotion, repo action, verification, and continuity recovery. Research evidence promotion enforces Substrate Gate read/snapshot grant, Eyes evidence packet, and Mind review before state admission; Verification acceptance enforces Soul verdict and Mind review; Reorient acceptance enforces Continuity recovery receipt and Mind review. `epiphany-mvp-coordinator` now records a typed Substrate Gate grant plus Hands intent/review gate when the coordinator selects `continueImplementation`, including a structured `recordPassCommand` template; `epiphany-hands-action` records patch/command/commit receipts against that gate and refuses mismatched, unapproved, or out-of-scope consequences. `epiphany-mvp-coordinator-smoke` now proves the deterministic path: forced `continueImplementation`, gate emission, and `record-pass` receipts in the smoke runtime-spine store. Live run `local-20260612-133920` proved a receipt-only Verification `needs-evidence` finding can be accepted through `roleAccept` and advance to a Hands gate without granting Soul statePatch authority. Runtime-spine now detects and summarizes a complete post-verification Hands patch/command/commit receipt chain so the coordinator can route Soul after Hands. Verification launches now write that chain into the internal CultMesh Verse as `epiphany.cultmesh.work_loop_telemetry.v0` and render a Soul packet from it; Modeling launches read the latest packet, attach accepted Soul receipt ids, and render the Proprioception packet from the same typed state. The telemetry now carries resolved receipt payload previews, stdout/stderr artifact previews, commit diff preview, source proof notes, and verification assertions. The corrected work loop is Hands -> Soul -> Proprioception -> Hands: Soul verifies concrete consequence receipts and changed source, then Proprioception updates the machine model from verified consequence before another implementation turn.
- Fresh scar from the receipt proof dogfood: `epiphany-model-runtime run-worker --auto-tools` must preserve Soul's right to follow a real evidence trail, but distinguish it from stalled repetition using typed tool intent fingerprints. Repeated identical pending tool sets seal as `tool-loop-stalled`; exhausting the explicit hard ceiling still seals as `tool-round-limit`. A failed or completed-but-unreviewable role result is a real lane result and must stop for review; once reviewed through a typed `roleFailureReview` supersession receipt, Self may relaunch the lane instead of manually clearing stale state. Complete Hands receipt triplets (`hands-patch-*`, `hands-command-*`, `hands-commit-*`) are implementation evidence for coverage, so Soul does not have to separately cite the accepted Modeling evidence id when it has verified the Hands chain routed to it through the typed work-loop packet. Soul accepted the bounded proof for commit `ce20529e`, Proprioception initially completed without a reviewable `statePatch`, and run `local-20260613-204521` proved the repair: the unreviewable result was superseded, Modeling relaunched with the role schema carried in the model request, Mind accepted the map patch, and only then did Self emit a new Hands gate. `epiphany-hands-action` must resolve commit receipts through `git rev-parse --verify` before storing them, because an almost-correct SHA poisoned Soul's `git show` proof and made the receipt chain untrustworthy.
- Canonical anatomy now lives in `notes/epiphany-anatomy.md`. Embodied sub-agents are Self, Persona, Imagination, Eyes, Modeling, Hands, and Soul. Body, Mind, Continuity, and Substrate Gate are substrate/state/protocol surfaces, not sub-agent identities. State is split by layer: `work_organ` for resident Epiphany sub-agents, `persona` for portable public/person-shaped state shared by Epiphany Persona, VoidBot repo Personas, and Ghostlight characters, and heartbeat/swarm state for scheduling and coordination physiology. Persona state now carries provenance, required public presentation, `date-time` timestamps, typed `candidateActions`, strict anchored thoughts with non-authoritative extensions, custom enum companion labels, and typed affect records for bonds/status reads/doctrine stances.
- The repo now has a one-command local operator path: `.\tools\epiphany_local_run.ps1`. Default mode is `smoke`; it builds the retained Codex app-server compatibility edge, builds native Epiphany operator binaries, runs the coordinator smoke, and writes launcher artifacts under `.epiphany-run/` plus coordinator artifacts under `.epiphany-dogfood/`. `-Mode status` is now Epiphany-native: it builds only Epiphany operator binaries, reads `state/thread-state.msgpack` when present, derives status through `epiphany-core`, and does not start or require `codex-app-server`. Use `-Mode plan` or `-Mode run -MaxSteps 4` for the raw bridge-equipped coordinator entrypoints; use `-Mode mvp -PersonaInput "<operator request>" -MaxSteps 4` for the local product cycle that projects Persona's character turn, writes a Persona/Aquarium bubble, bootstraps a minimal local checkpoint for fresh threads, runs the coordinator with auto-tools, then runs heartbeat sleep/dream maintenance. Live plan/run/mvp modes use the workspace `state/runtime-spine.msgpack`, because CodexThread launch writes worker requests there; the run bundle remains artifact evidence, not runtime lifecycle authority. Add `-ThreadId <id>` and `-Workspace <path>` to inspect or continue an existing thread. `status`, `plan`, and `smoke` do not spend model calls; `run` and `mvp` build and use `epiphany-openai-runtime`. Coordinator workers now launch detached and are polled through runtime-spine instead of blocking the coordinator. MVP runs are non-ephemeral by default so `-ThreadId <id>` can resume and poll later. `-MaxRuntimeSeconds <n>` is passed into worker runtime; timeout writes a failed worker receipt and exits. Failed modeling now blocks downstream verification until the failed result is reviewed.
- Current Mom-ready status: the normal MVP pass reaches Persona -> coordinator -> detached runtime -> heartbeat sleep, and modeling workers now complete through the ChatGPT subscription transport. The first failure was a stack of violated observability/runtime invariants: worker prompts prepended the whole shared persistent-memory rite, Responses frame liveness was invisible until completion, and the runtime tried to persist hundreds of text deltas before completing the worker job. Role/reorient workers now get a compact Epiphany worker boundary instead of full persistent memory; runtime-spine records sampled raw Responses frame kinds with small previews; contiguous reasoning/text deltas compact before durable storage; and live proofs completed `2fe38dcd-d99e-4c73-9a58-afcc81f851c7`, `241e3851-e3ea-4877-a63b-0d2bbd96a7e2`, and `85149a26-6975-403f-ac93-092b717c5825` instead of timing out. The second failure was stale lifecycle authority: completed runtime jobs remained as unresolved `runtime_links`, replacement launches treated historical active links as current, and one bad validation path opened an orphan job before rejecting the state patch. Latest-link-wins is now the runtime-link invariant, terminal links project completed jobs, stale active history cannot veto replacement, launch validation happens before opening runtime jobs, and completed-but-unreviewable modeling findings stop for review instead of relaunching the same lane. The Eyes/source-gather fork is now landed: Research is a fixed Eyes lane with launch/result/accept/status/coordinator/protocol support, and `regather-needed` modeling findings route to `LaunchResearch` instead of relaunching blind Modeling. Research statePatch admission is Eyes-shaped only: observations, evidence, scratch, and optional investigationCheckpoint; no graph, planning, objective, or checkpoint authority. Mind admission now leaves typed runtime-spine proof: role/reorient acceptance persists `epiphany.mind.gateway_review` before state admission and `epiphany.mind.state_commit_receipt` after admission with the resulting durable revision. Launch contracts now split the broad receipt catalogue from effect-specific proof profiles for state admission, evidence promotion, repo action, verification, and continuity recovery. Research evidence promotion enforces Substrate Gate read/snapshot grant, Eyes evidence packet, and Mind review before state admission; Verification acceptance enforces Soul verdict and Mind review; Reorient acceptance enforces Continuity recovery receipt and Mind review. `epiphany-mvp-coordinator` now records a typed Substrate Gate grant plus Hands intent/review gate when the coordinator selects `continueImplementation`, including a structured `recordPassCommand` template; `epiphany-hands-action` records patch/command/commit receipts against that gate and refuses mismatched, unapproved, or out-of-scope consequences. `epiphany-mvp-coordinator-smoke` now proves the deterministic path: forced `continueImplementation`, gate emission, and `record-pass` receipts in the smoke runtime-spine store. Live run `local-20260612-133920` proved a receipt-only Verification `needs-evidence` finding can be accepted through `roleAccept` and advance to a Hands gate without granting Soul statePatch authority. Runtime-spine now detects and summarizes a complete post-verification Hands patch/command/commit receipt chain so the coordinator can route Soul after Hands. Verification launches now write that chain into the internal CultMesh Verse as `epiphany.cultmesh.work_loop_telemetry.v0` and render a Soul packet from it; Modeling launches read the latest packet, attach accepted Soul receipt ids, and render the Modeling packet from the same typed state. The telemetry now carries resolved receipt payload previews, stdout/stderr artifact previews, commit diff preview, source proof notes, and verification assertions. The corrected work loop is Hands -> Soul -> Modeling -> Hands: Soul verifies concrete consequence receipts and changed source, then Modeling updates the machine model from verified consequence before another implementation turn.
- Fresh scar from the receipt proof dogfood: `epiphany-model-runtime run-worker --auto-tools` must preserve Soul's right to follow a real evidence trail, but distinguish it from stalled repetition using typed tool intent fingerprints. Repeated identical pending tool sets seal as `tool-loop-stalled`; exhausting the explicit hard ceiling still seals as `tool-round-limit`. A failed or completed-but-unreviewable role result is a real lane result and must stop for review; once reviewed through a typed `roleFailureReview` supersession receipt, Self may relaunch the lane instead of manually clearing stale state. Complete Hands receipt triplets (`hands-patch-*`, `hands-command-*`, `hands-commit-*`) are implementation evidence for coverage, so Soul does not have to separately cite the accepted Modeling evidence id when it has verified the Hands chain routed to it through the typed work-loop packet. Soul accepted the bounded proof for commit `ce20529e`, Modeling initially completed without a reviewable `statePatch`, and run `local-20260613-204521` proved the repair: the unreviewable result was superseded, Modeling relaunched with the role schema carried in the model request, Mind accepted the map patch, and only then did Self emit a new Hands gate. `epiphany-hands-action` must resolve commit receipts through `git rev-parse --verify` before storing them, because an almost-correct SHA poisoned Soul's `git show` proof and made the receipt chain untrustworthy.
- The investment dossier readiness target is now explicit: `E:\Projects\gamecult-site\docs\gamecult_integrated_dossier.tex` expects Epiphany to be part of a Bifrost-first labor loop, not only a local Mom demo. The external proof bar is: Bifrost owns topics/work items/dispatch packets/receipts/credit/reward pressure; Epiphany executes bounded work; maintainers review artifacts; public/operator evidence records scope, consent, roles, model spend, review load, artifacts, accepted/rejected outcome, memory lessons, and case-study permission; and private worker/operator/agent context stays sealed. Diligence also asks for a live fresh-repo Epiphany demo, Bifrost work item/topic/agent transport/receipt/ledger demo, CultMesh status, VoidBot/Discord swarm demo, compute/output metrics, and security model for secrets/write permissions/public-private exports.
- This Codex operator's own roadmap/todo posture has been retuned for this scale target, with the Epiphany Imagination specialist as an optional sub-agent rail rather than the whole point. `notes/epiphany-investor-readiness-roadmap.md` now says: make the local Mom MVP a repeatable proof bundle; build the Bifrost-first external-work bridge; add compute/review/accepted-artifact accounting; prove fresh-repo operation without supervisor contamination; keep public/operator-safe exports sealed; and treat angel capital as fuel for capacity, not command authority. The Imagination specialist prompt was also updated so investor-scale Objective Drafts must name Bifrost provenance, bounded Epiphany proof, maintainer review, receipts/ledger evidence, compute/output metrics, public/private export safety, consent, and legal/security gates.
- Local operator runs now write typed CultMesh intent/receipt documents to `.epiphany-run/cultmesh/operator-runs.ccmp` through `epiphany-operator-run`. The wrapper writes intent before acting and a completion receipt after success; this is the local consent/trace rail, not a hidden scheduler queue.
@ -49,10 +49,10 @@ 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. Role/reorient launch documents now have optional `dynamicPromptContext`; runtime prompt assembly consumes that field into worker instructions, `epiphany-prompt-context-smoke` proves a rendered Verse/memory packet is preserved on a role launch document, live bridge role/reorient launches now feed local Verse plus memory graph context from sibling `local-verse.ccmp` and `memory-graph.msgpack` stores beside runtime-spine, and the bridge launch-context test proves the packet survives into a persisted runtime-spine worker launch request. The memory graph refreshes from current typed thread-state repo graphs when absent, so thin state remains visibly thin. Local-run status now has an operator read proof too: `tools/epiphany_local_run.ps1 -Mode status` builds/calls `epiphany-verse-query` and writes `local-verse-context.json` from `.epiphany-run\cultmesh\local-verse.ccmp` beside `status.json` and the operator snapshot. 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`, `cargo run --manifest-path .\epiphany-core\Cargo.toml --bin epiphany-prompt-context-smoke`, and `.\tools\epiphany_local_run.ps1 -Mode status` 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. Role/reorient launch documents now have optional `dynamicPromptContext`; runtime prompt assembly consumes that field into worker instructions, `epiphany-prompt-context-smoke` proves a rendered Verse/memory packet is preserved on a role launch document, live bridge role/reorient launches now feed local Verse plus memory graph context from sibling `local-verse.ccmp` and `memory-graph.msgpack` stores beside runtime-spine, and the bridge launch-context test proves the packet survives into a persisted runtime-spine worker launch request. The memory graph refreshes from current typed thread-state repo graphs when absent, so thin state remains visibly thin. Local-run status now has an operator read proof too: `tools/epiphany_local_run.ps1 -Mode status` builds/calls `epiphany-verse-query` and writes `local-verse-context.json` from `.epiphany-run\cultmesh\local-verse.ccmp` beside `status.json` and the operator snapshot. 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`, `cargo run --manifest-path .\epiphany-core\Cargo.toml --bin epiphany-prompt-context-smoke`, and `.\tools\epiphany_local_run.ps1 -Mode status` 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 Persona 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.
- Hands now has a first executable action receipt spine. `epiphany-core::hands_gateway` owns `HandsActionIntent`, `HandsActionReview`, `HandsPatchReceipt`, `HandsCommandReceipt`, and `HandsCommitReceipt`; runtime-spine can persist/reread them; `runtime_spine_persists_mind_gateway_review_receipts` includes the Hands chain beside Mind/Eyes/Substrate/Soul/Continuity proofs and proves the post-timestamp Hands receipt-chain detector; `epiphany-hands-action-smoke` emits intent/review/patch/command/commit receipt ids from `.epiphany-smoke\runtime-spine\hands-action-smoke.msgpack`; and the repo-action launch proof profile now requires action intent, action review, and patch receipt together. `epiphany-mvp-coordinator` now turns `continueImplementation` into a persisted Substrate Gate grant plus Hands intent/review gate and includes the receipt ids in the operator step. `epiphany-hands-action` is the native consequence recorder for that gate: `record-patch`, `record-command`, `record-commit`, and turn-level `record-pass` load the stored intent/review or `finalAction.handsActionGate` from `coordinator-summary.json`, require an approved matching review, enforce allowed operations, and keep patch/commit changed paths inside the requested scope. `epiphany-mvp-coordinator-smoke` includes the deterministic Hands pass proof. The coordinator now treats a complete Hands receipt chain after an accepted Soul result as new implementation evidence, launches Soul again, and routes a passing accepted Soul result to Proprioception/modeling before another Hands turn. Work-loop telemetry is now typed internal CultMesh state: Verification role launches write `epiphany.cultmesh.work_loop_telemetry.v0` beside runtime-spine, render that packet for Soul with resolved receipt bodies, commit diff preview, source proof notes, verification assertions, and stdout/stderr previews, and Modeling launches read/enrich the latest packet with Soul acceptance receipt ids before Proprioception updates the map.
- Hands now has a first executable action receipt spine. `epiphany-core::hands_gateway` owns `HandsActionIntent`, `HandsActionReview`, `HandsPatchReceipt`, `HandsCommandReceipt`, and `HandsCommitReceipt`; runtime-spine can persist/reread them; `runtime_spine_persists_mind_gateway_review_receipts` includes the Hands chain beside Mind/Eyes/Substrate/Soul/Continuity proofs and proves the post-timestamp Hands receipt-chain detector; `epiphany-hands-action-smoke` emits intent/review/patch/command/commit receipt ids from `.epiphany-smoke\runtime-spine\hands-action-smoke.msgpack`; and the repo-action launch proof profile now requires action intent, action review, and patch receipt together. `epiphany-mvp-coordinator` now turns `continueImplementation` into a persisted Substrate Gate grant plus Hands intent/review gate and includes the receipt ids in the operator step. `epiphany-hands-action` is the native consequence recorder for that gate: `record-patch`, `record-command`, `record-commit`, and turn-level `record-pass` load the stored intent/review or `finalAction.handsActionGate` from `coordinator-summary.json`, require an approved matching review, enforce allowed operations, and keep patch/commit changed paths inside the requested scope. `epiphany-mvp-coordinator-smoke` includes the deterministic Hands pass proof. The coordinator now treats a complete Hands receipt chain after an accepted Soul result as new implementation evidence, launches Soul again, and routes a passing accepted Soul result to Modeling/modeling before another Hands turn. Work-loop telemetry is now typed internal CultMesh state: Verification role launches write `epiphany.cultmesh.work_loop_telemetry.v0` beside runtime-spine, render that packet for Soul with resolved receipt bodies, commit diff preview, source proof notes, verification assertions, and stdout/stderr previews, and Modeling launches read/enrich the latest packet with Soul acceptance receipt ids before Modeling updates the map.
- `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.
- `epiphany-openai-runtime` worker result ingress now parses assistant output directly into typed role/reorient ingress structs selected from the durable launch document, stores nested `statePatch` and `selfPatch` as typed MessagePack in `EpiphanyRuntimeRoleWorkerResult`, and no longer passes worker result data through generic `serde_json::Value`. JSON survives there only as the OpenAI text-output edge before typed deserialization.
- 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`.
@ -81,13 +81,13 @@ remembers doctrine; the branch remembers the blade.
- Generic update/promote service entry points now accept typed `EpiphanyRoleStatePatchDocument` patches. Vendored app-server converts `ThreadEpiphanyUpdatePatch` request cargo before invoking the bridge, so the mutation service no longer treats the JSON-RPC patch as its native write document.
- Changed-field authority is native now. `EpiphanyStateUpdatedField` lives in `epiphany-core`; bridge mutation results carry that typed enum, while app-server projects it into `ThreadEpiphanyStateUpdatedField` only for JSON-RPC responses and notifications.
- Role launch, role accept, and role-result runtime lookup now use core `EpiphanyRoleResultRoleId` inside the bridge. App-server maps `ThreadEpiphanyRoleId` at the JSON-RPC boundary and keeps it only for legacy request/response shape.
- Reorient launch service results now use typed `EpiphanySurfaceSource`; app-server projects it into `ThreadEpiphanyReorientSource` only for the legacy launch response.
- Reorient launch service results now use typed `Epiphanysurfacesource`; app-server projects it into `ThreadEpiphanyReorientSource` only for the legacy launch response.
- Generic job launch now converts protocol `ThreadEpiphanyWorkerLaunchDocument` cargo at the app-server edge before building the core `EpiphanyJobLaunchRequest`; the bridge launch builder takes a typed `EpiphanyWorkerLaunchDocument`.
- Coordinator note rendering now consumes core CRRC/coordinator actions, pressure, role/reorient result statuses, and reorient state status. `ThreadEpiphany*` status/action DTOs are no longer the native shape for that prompt/text policy helper.
- Context and graph-query response builders now take core `EpiphanyContextParams` / `EpiphanyGraphQuery` documents. App-server read routes convert `ThreadEpiphanyContextParams` / `ThreadEpiphanyGraphQuery` at the JSON-RPC wall before invoking bridge derivation.
- Role-result response assembly now takes core `EpiphanyRoleResultRoleId`; `ThreadEpiphanyRoleId` is reconstructed only for the legacy response payload and finding projection.
- Distill response assembly now consumes core `EpiphanyDistillInput`; `ThreadEpiphanyDistillParams` is converted before bridge policy invocation.
- Role/reorient result response inputs now use core `EpiphanySurfaceSource`; `ThreadEpiphanyRolesSource` / `ThreadEpiphanyReorientSource` are response projection only.
- Role/reorient result response inputs now use core `Epiphanysurfacesource`; `ThreadEpiphanyRolesSource` / `ThreadEpiphanyReorientSource` are response projection only.
- Changed-field derivation now inspects typed `EpiphanyRoleStatePatchDocument` directly. The bridge no longer converts typed patches back into `ThreadEpiphanyUpdatePatch` merely to calculate changed fields.
- View-lens orchestration now uses bridge-native `EpiphanyViewLens` selectors. App-server converts `ThreadEpiphanyViewLens` at the request wall, and the bridge maps back only for the legacy response echo.
- Coordinator status derivation now receives core `EpiphanyCrrcResultStatus` for reorient result state; `ThreadEpiphanyReorientResultStatus` is projection-only for coordinator/view responses.
@ -97,7 +97,7 @@ remembers doctrine; the branch remembers the blade.
- View lens selector semantics are core-owned now. `EpiphanyViewLens`, default view lenses, and lens dependency planning live in `epiphany-core`; `epiphany-codex-bridge::protocol_edge` converts Codex JSON-RPC lens params to core selectors and exposes the core dependency plan so app-server only decides which host facts to load.
- Correction: app-server must not own Epiphany request mapping. Codex JSON-RPC request DTO conversion now lives in `epiphany-codex-bridge::protocol_edge`; vendored app-server calls those edge adapters and no longer depends directly on `epiphany-core`.
- Context, graph-query, distill, generic job-launch document, and generic update/promote patch request cargo now enters bridge as core `EpiphanyContextParams`, `EpiphanyGraphQuery`, `EpiphanyDistillInput`, `EpiphanyWorkerLaunchDocument`, and `EpiphanyRoleStatePatchDocument`.
- Freshness/job/reorient response projection also belongs to the bridge edge now. Vendored app-server no longer keeps local helpers for `EpiphanyFreshnessSurface`, `EpiphanyJobView`, `EpiphanySurfaceSource`, or reorient decision/status enum projection; it gathers host facts, invokes bridge/core services, and sends the Codex JSON-RPC response.
- Freshness/job/reorient response projection also belongs to the bridge edge now. Vendored app-server no longer keeps local helpers for `EpiphanyFreshnessSurface`, `EpiphanyJobView`, `Epiphanysurfacesource`, or reorient decision/status enum projection; it gathers host facts, invokes bridge/core services, and sends the Codex JSON-RPC response.
- Job projection has one mapper now. `epiphany-codex-bridge::jobs` derives typed `EpiphanyJobView` and no longer imports app-server protocol DTOs; `protocol_edge::protocol_job_from_surface` is the only `EpiphanyJobView` -> `ThreadEpiphanyJob` conversion path.
- Runtime result loading is typed-only now. Role/reorient result status projection moved out of `runtime_results` and duplicate coordinator helpers into `protocol_edge`, so view and coordinator response builders share one Codex JSON-RPC status mapper.
- Pressure projection is centralized too. `pressure.rs` derives typed `EpiphanyPressure`, coordinator consumes typed pressure signals, and `protocol_edge` owns the `ThreadEpiphanyPressure*` DTO mapping.
@ -135,32 +135,32 @@ remembers doctrine; the branch remembers the blade.
- The `thread/turns/list` route handler now lives in `codex_message_processor/thread_turn_routes.rs`, beside the turn projection helpers it consumes. `thread_read_routes.rs` is back to persisted/live thread listing, `thread/read`, loaded-thread listing, and summary reads.
- Listener/subscription lifecycle now lives in `codex_message_processor/listener_lifecycle.rs`: connection attach/detach, listener startup, idle unload, unsubscribe, teardown, archive preparation, listener task context, idle-unload state, shutdown result handling, and listener command routing.
- The May 2026 foundation migration is closed enough to archive. `notes/archive/epiphany-architectural-teardown.md` and `notes/archive/epiphany-ideal-architecture-rebuild-plan.md` remain provenance for the host-seam suspicion pass and rebuild blueprint, but current authority is the top-level map, fork plan, anatomy, and contract docs. The rebuild moved scene projection, freshness derivation, pressure policy, targeted context shards, bounded graph traversal, 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, role/reorient result interpretation, role self-persistence review policy, and role/reorient acceptance bundle policy into `epiphany-core`; typed acceptance receipts replaced summary-string identity for live accept paths, runtime links are dual-written on launch, and result read-back now prefers runtime links.
- Do not continue Aquarium UI, bridge, Face, or dogfood expansion until the teardown has a source-grounded cleanup slice plan. Epiphany is the foundation; patches on patches are not a purification rite, they are how the altar becomes load-bearing garbage.
- Do not continue Aquarium UI, bridge, Persona, or dogfood expansion until the teardown has a source-grounded cleanup slice plan. Epiphany is the foundation; patches on patches are not a purification rite, they are how the altar becomes load-bearing garbage.
- Phase 1 through Phase 5 are complete enough.
- Phase 6 has canonical read-only `thread/epiphany/view` lenses for scene, jobs, roles, planning, pressure, reorient, CRRC, and coordinator; separate read-only `thread/epiphany/freshness`, `thread/epiphany/context`, and `thread/epiphany/graphQuery` query surfaces; `thread/epiphany/reorientResult`; and `thread/epiphany/roleResult`. Durable `jobBindings` are now legacy launcher compatibility slots only; they keep binding id/kind/scope/owner/authority/linkage/blocking reason while durable `runtimeLinks` hold runtime-spine job/result association. The old standalone scene/jobs/roles/planning/pressure/reorient/CRRC/coordinator read verbs have been deleted; read those projections through view lenses. New `thread/epiphany/jobLaunch`, `thread/epiphany/jobInterrupt`, `thread/epiphany/roleLaunch`, and `thread/epiphany/reorientLaunch` writes open typed runtime-spine job receipts under `state/runtime-spine.msgpack` and do not require the Codex SQLite state runtime. Freshness carries watcher-backed invalidation inputs, graphQuery traverses authoritative typed graph neighborhoods and path/symbol matches without mutation, planning projects typed captures/backlog/roadmap/objective drafts without adopting work, roles project implementation/imagination/modeling/verification/reorientation ownership from existing signals without becoming a scheduler, `roleResult` and `reorientResult` read heartbeat-backed typed runtime-spine job results through runtime links when present, and `roleAccept` / `reorientAccept` accept completed heartbeat findings by writing typed acceptance receipts while remaining explicit review gates.
- Native `epiphany-mvp-status` is the first dogfood operator view. It starts or reads a thread through app-server and prints scene, planning, pressure, reorient, jobs, roles, Imagination/modeling/verification role result read-backs, reorient result, heartbeat, Face bubbles, and CRRC recommendation as text or machine output. The old Python status module has been cut; native Rust/CultCache/CultNet surfaces are the smoked product path.
- Native `epiphany-mvp-status` is the first dogfood operator view. It starts or reads a thread through app-server and prints scene, planning, pressure, reorient, jobs, roles, Imagination/modeling/verification role result read-backs, reorient result, heartbeat, Persona bubbles, and CRRC recommendation as text or machine output. The old Python status module has been cut; native Rust/CultCache/CultNet surfaces are the smoked product path.
- Native `epiphany-mvp-coordinator` is the first auditable fixed-lane coordinator runner. It starts or reads a thread through app-server, opens a native runtime-spine session, follows the harness-native coordinator action, can auto-launch modeling, verification, or reorient-worker jobs, records native runtime job/result receipts for terminal launched work, keeps semantic findings review-gated by default, and writes summary, steps, rendered snapshots, transcript, stderr, runtime-spine status, and final next-action artifacts under `.epiphany-dogfood/coordinator` or a caller-provided artifact directory. It refuses direct backend-completion mutation; full completion smoke needs live workers while execution is being cauterized into CultNet.
- Native `epiphany-runtime-spine` is the first Codex-independent runtime vertebra. It owns typed CultCache documents for runtime identity, sessions, jobs, job results, and events; opens/completes native jobs; snapshots jobs/results by runtime job id; projects job-result counts; and can emit a framed CultNet hello message advertising the native document and mutation contract surface. Codex app-server launch/read-back/acceptance is now a typed heartbeat/runtime-spine bridge with no Epiphany job-result dependency on the Codex SQLite runtime.
- CultNet APIs are advertised as compatible schemas plus mutation contracts. Hello frames now expose readable document types, allowed operations, mutation authority, typed intent document types, and typed receipt document types; Aquarium should use those contracts to submit state changes and watch receipts rather than growing a little bespoke verb zoo.
- The native runtime-spine hello now publishes the interactive surface catalog, not just the deep runtime bones. In addition to runtime/session/job/memory/heartbeat/ledger documents, Aquarium-discoverable contracts now advertise scene, pressure, reorient, CRRC, jobs, roles, role-result, reorient-result, planning, coordinator, Face, Void memory, repo initialization/birth runner, Rider bridge, and Unity bridge surfaces, with explicit read-only versus coordinator-owned intent/receipt posture. The point is to let Aquarium discover operator affordances from CultNet instead of hard-coding a secret menu of verbs.
- The native runtime-spine hello now publishes the interactive surface catalog, not just the deep runtime bones. In addition to runtime/session/job/memory/heartbeat/ledger documents, Aquarium-discoverable contracts now advertise scene, pressure, reorient, CRRC, jobs, roles, role-result, reorient-result, planning, coordinator, Persona, Void memory, repo initialization/birth runner, Rider bridge, and Unity bridge surfaces, with explicit read-only versus coordinator-owned intent/receipt posture. The point is to let Aquarium discover operator affordances from CultNet instead of hard-coding a secret menu of verbs.
- Epiphany now publishes those CultNet receipts locally under `schemas/cultnet/`, and `epiphany-runtime-spine schema-catalog --include-schema-json true` emits a merged builtin-plus-local schema catalog Aquarium can consume directly. The local catalog covers runtime-spine documents, durable agent/heartbeat/ledger state, operator-safe `epiphany.surface.*` projections, control intents, and receipt/artifact payloads. The vendored `cultnet-rs` wire contract was aligned with the C# canon at the same time: raw document replication now keys on `schemaId` and `recordKey`, snapshot filters use `schemaIds` / `recordKeys`, and hello supports typed mutation-contract advertisement instead of the old half-remembered payload-schema-version folklore.
- Epiphany now owns the canonical schema paperwork locally under `schemas/`. The key receipts are `schemas/cultnet/gamecult.persona_state.v0.schema.json`, `schemas/cultnet/epiphany.work_organ_state.v0.schema.json`, `schemas/canonical-agent-state-schema.md`, `schemas/agent-state-variable-glossary.md`, `schemas/organ-state-profiles.md`, `schemas/repo-personality-birth-projection.md`, and `schemas/heartbeat-state-schema.md`. If a standing trait name like `routing_discipline` changes, or if organ-state, Persona, heartbeat, or birth-projection semantics move, update those docs in the same pass instead of relying on old Ghostlight notes or live store archaeology.
- The schema doctrine now makes the profile split explicit: resident Epiphany organs are `work_organ` state with lean role memory and growth via rumination/distillation, while Face is the Epiphany organ that may use portable `persona` state shared with VoidBot repo Faces and Ghostlight characters. Work organs do not inherit Persona affect, social bonds, or status-read machinery. PersonaState now has explicit provenance and required presentation surfaces, `date-time` timestamps, typed `candidateActions` with action type/target/readiness/risk/urgency/confidence/evidence/expiry, `voidbotProjection.candidateInterventions` only as a VoidBot compatibility projection, strict anchored thoughts, extension data marked non-authoritative, custom enum companion labels, and typed affect records for bonds/status reads/doctrine stances. `privateNotes` remain a deliberate v0 simplification, not an authority surface. `epiphany-agent-memory-store status` and `epiphany-character-loop` now surface profile classification on the wire as `organStateProfile`; `epiphany-agent-memory-store project-persona --store .\state\agents.msgpack --role-id face` projects the local Face record into `gamecult.persona_state.v0` for interop.
- Face packets now carry deterministic Ghostlight-style `projectionSeed`, `appraisalSeed`, and `reactionSeed` surfaces rebuilt from local organ traits, relationship memories, perceived overlays, and visible stimulus so the public mouth can use actual projection/appraisal machinery instead of decorative prompt text. Also record this now before some future fool hard-codes singularity: multiple Persona actors are part of the plan, even though the current MVP still routes through one `face` role.
- The schema doctrine now makes the profile split explicit: resident Epiphany organs are `work_organ` state with lean role memory and growth via rumination/distillation, while Persona is the Epiphany organ that may use portable `persona` state shared with VoidBot repo Personas and Ghostlight characters. Work organs do not inherit Persona affect, social bonds, or status-read machinery. PersonaState now has explicit provenance and required presentation surfaces, `date-time` timestamps, typed `candidateActions` with action type/target/readiness/risk/urgency/confidence/evidence/expiry, `voidbotProjection.candidateInterventions` only as a VoidBot compatibility projection, strict anchored thoughts, extension data marked non-authoritative, custom enum companion labels, and typed affect records for bonds/status reads/doctrine stances. `privateNotes` remain a deliberate v0 simplification, not an authority surface. `epiphany-agent-memory-store status` and `epiphany-character-loop` now surface profile classification on the wire as `organStateProfile`; `epiphany-agent-memory-store project-persona --store .\state\agents.msgpack --role-id Persona` projects the local Persona record into `gamecult.persona_state.v0` for interop.
- Persona packets now carry deterministic Ghostlight-style `projectionSeed`, `appraisalSeed`, and `reactionSeed` surfaces rebuilt from local organ traits, relationship memories, perceived overlays, and visible stimulus so the public mouth can use actual projection/appraisal machinery instead of decorative prompt text. Also record this now before some future fool hard-codes singularity: multiple Persona actors are part of the plan, even though the current MVP still routes through one `Persona` role.
- Repo personality initialization now has a terrain-reduced plan and native birth surface. `epiphany-repo-personality scout/project/agent-packet/status` scouts local git repos, scores body taxonomy/history temperament/memory doctrine, writes typed CultCache terrain/profile/role-projection MessagePack stores, emits JSON/Markdown inspection exports, and renders a birth-only Repo Personality Distiller specialist prompt packet. `epiphany-repo-personality startup` now checks for accepted personality/memory initialization records, launches packet generation only when absent, and `accept-init` can route reviewed role `selfPatch` candidates into initial role memory, stamp the newborn Ghostlight trait lattice from deterministic role projections, and seed heartbeat physiology from the same typed role personality projections. The birth specialists are startup-only initialization actuators, not heartbeat lanes; heartbeat receives only the accepted physiology seed. `epiphany-repo-birth-runner` owns the startup-only execution path through `epiphany-model-runtime` typed model-request documents plus runtime-spine receipts and reviewable `result.json`; the old Codex CLI executor path is cut so birth specialists cannot receive Codex prompt wrappers. The remaining seam is Aquarium review/action surfacing. After accepted birth, personality drift belongs to heartbeat, mood, rumination, sleep consolidation, lived evidence, and reviewed `selfPatch`, not repeated startup distillation.
- Repo trajectory initialization is now a separate birth-only organ. `epiphany-repo-personality` derives a typed `repo_trajectory_report` from early-history, recent-history, doctrine/content excerpts, and deterministic theme scoring, and `trajectory-packet` renders a startup-only Repo Trajectory Distiller prompt/packet so Self can review historical direction, self-image, implicit goals, and anti-goals before the newborn wakes.
- Repo memory initialization is now split from personality initialization. `epiphany-repo-personality memory-packet` renders a birth-only Repo Memory Distiller packet from the same typed terrain/profile/projection store plus bounded source excerpts. It gives each organ its own mission filter: Self for routing/authority, Face for public surface, Imagination for plans/backlog, Eyes for prior art, Proprioception for architecture, Hands for implementation habits, Soul for evidence, and Continuity for continuity. The output is still a Self-reviewed petition, not direct memory mutation.
- Repo memory initialization is now split from personality initialization. `epiphany-repo-personality memory-packet` renders a birth-only Repo Memory Distiller packet from the same typed terrain/profile/projection store plus bounded source excerpts. It gives each organ its own mission filter: Self for routing/authority, Persona for public surface, Imagination for plans/backlog, Eyes for prior art, Modeling for architecture, Hands for implementation habits, Soul for evidence, and Continuity for continuity. The output is still a Self-reviewed petition, not direct memory mutation.
- The first birth startup valve is now native. `epiphany-repo-personality startup` checks a typed init store for accepted `repo-trajectory`, `repo-personality`, and `repo-memory` records, generates missing packets under a startup artifact dir, and returns `reviewInitializationPackets`. Generated birth packets now advertise `birthOnly`, `executionOwner: repo-initialization-startup-runner`, and no heartbeat participant. `epiphany-repo-birth-runner` consumes those packets as startup-only typed OpenAI runtime jobs by default and writes prompts, output schemas, model-request documents, runtime summaries, stdout/stderr logs, result files, and exact `accept-init` commands. `accept-init` can process a distiller result, review/apply role `selfPatch` candidates through `state/agents.msgpack`, apply `repo-personality` heartbeat seeds through `state/agent-heartbeats.msgpack`, and seal the reviewed packet as `epiphany.repo_initialization_record.v0`; after all required records exist, startup returns `continueStartup` and does not regenerate birth packets. The remaining UI wound is Aquarium review/action surfacing.
- Native CRRC automation is now landed only at turn-complete safe boundaries. It may submit `Op::Compact` for coordinator-approved `compactRehydrateReorient` or for a successful pre-compaction checkpoint intervention's pending compact handoff, and it may launch the fixed `reorient-worker` for coordinator-approved `launchReorientWorker`. It does not auto-launch Imagination/modeling/verification, accept findings, promote evidence, edit implementation code, or keep going after reviewable semantic output.
- Pre-compaction checkpoint intervention is now landed. On token-count events for loaded Epiphany threads, when current context usage reaches 80% of the active auto-compact/context limit, the harness steers the active turn once with a CRRC checkpoint directive so the agent banks working context before compaction/reorientation. Pressure ignores cumulative token spend; cumulative-only telemetry reports unknown instead of yelling. A successful steer now latches a turn-scoped compact handoff that is consumed at clean turn completion, preventing the brake from decaying into another implementation turn. This is still bounded steering plus compaction handoff, not automatic semantic acceptance, a broad scheduler, or implementation continuation.
- The old Python dogfood/live-specialist runners were cut because they encoded the obsolete completion path. The replacement must be native Rust/CultCache/CultNet and complete heartbeat-owned runtime-spine job results with auditable artifacts.
- The Aquarium operator UI now lives in sibling repo `E:\Projects\EpiphanyAquarium`, not under `apps/epiphany-gui`. It is a Tauri v2 + React/WebGL interface organism over the existing status bridge, dogfood artifacts, and GUI action artifacts, not a new throne of truth. It has its own `AGENTS.md`, persistent `state/map.yaml`, `state/memory.json`, scratch/evidence files, and interface doctrine. EpiphanyAgent remains the authoritative harness/backend forge.
- Durable in-flight investigation checkpointing is now landed in authoritative typed state, writable through `thread/epiphany/update` or accepted `thread/epiphany/promote`, rendered into the prompt, and reflected through scene/context.
- The prompt doctrine pass is landed. Shared Epiphany prompts now carry distilled memory/evidence discipline. Rendered state intro/doctrine text lives in `epiphany-state-model/src/prompts/`, and lane/control prompt text now lives in `epiphany-core/src/prompts/epiphany_specialists.toml` under the core `agent_launch` owner: modeling is Proprioception, implementation is the Hands and GUI-launched main coding lane, verification is the Soul, reorientation is a Continuity worker, coordinator remains the read-only Self, and CRRC owns the pre-compaction intervention template.
- The prompt doctrine pass is landed. Shared Epiphany prompts now carry distilled memory/evidence discipline. Rendered state intro/doctrine text lives in `epiphany-state-model/src/prompts/`, and lane/control prompt text now lives in `epiphany-core/src/prompts/epiphany_specialists.toml` under the core `agent_launch` owner: modeling is Modeling, implementation is the Hands and GUI-launched main coding lane, verification is the Soul, reorientation is a Continuity worker, coordinator remains the read-only Self, and CRRC owns the pre-compaction intervention template.
- The machine-priest voice now says the quiet part plainly: crusade/heresy/purity language is aimed at technical rot, hidden state, duplicate truth, drift, and lying structures, not at humans. Future Epiphany swarms should inherit severity toward systems and curiosity toward people.
- The Ghostlight memory pass is landed. `epiphany_specialists.toml` now has a shared persistent-memory projection prepended by the harness to fixed role specialists, reorientation workers, coordinator notes, and CRRC checkpoint interventions. The rendered base doctrine also states the Perfect Machine rule directly: prompt is projection, durable typed state is the mind, every lane must improve its own memory/model/prompt/evidence habit or name the repair, and each lane phrases that duty in its own organ language so the salience sticks.
- The role self-memory persistence pass is native now. Each lane has a typed organ-state record in `state/agents.msgpack`, and specialists may return optional `selfPatch` requests beside their normal role result. Relationship, event, scene, and perceived-overlay arrays are typed organ-state record documents, not JSON cargo, and the durable structs do not keep unknown `extra` maps. `roleResult`/`roleAccept` project coordinator review as `selfPersistence`: accepted requests are role-matched, bounded lane memory/goal/value/private-note mutations; refused requests explain wrong role, project-truth smuggling, authority grabs, bloat, missing reason, or malformed records. GUI/coordinator accept paths apply accepted `selfPatch` requests through the native `epiphany-agent-memory-store` binary; project truth still belongs only in `EpiphanyThreadState`.
- The heartbeat initiative pass is landed as a bounded tool seam. `state/agent-heartbeats.msgpack` tracks Self, Face, Imagination, Eyes, Proprioception, Hands, and Soul as Ghostlight-style initiative participants with arena, participant kind, speed, next-ready time, reaction bias, interrupt threshold, load, status, constraints, personality cooldown, mood cooldown, effective cooldown, adaptive pacing, history, and pending turns through `epiphany-core::EpiphanyHeartbeatStateEntry` and the native `epiphany-heartbeat-store` binary. Continuity is protocol machinery over sleep/recovery receipts, not a heartbeat persona. Organ-state records set baseline timing; appraisal mood/anxiety bends it through urgency, arousal, thought pressure, guardedness, and reaction intensity, so Hands-like work pressure and high-need anxious lanes can recover sooner without being heartbeaten while a prior turn is running. Mood is now official physiology, not prose: `HeartbeatMoodTiming.emotional_dimensions` carries the 32-axis current affect vector that utterance state turns into the Weksa/AquaSynth 64-float character-state lane. `epiphany-heartbeat-store pump` computes pressure from external urgency, mood/anxiety, reaction intensity, thought pressure, and current pending load, then chooses tempo plus target concurrency: calm can launch zero and sleep slow; alarm can fill most active lanes. Idle turns are for rumination: light thought shuffling, role-quality attention, and candidate selfPatch pressure. Sleep/dream cycle passes are the intended distillation window for durable self-memory and doctrine. JSON heartbeat state, Python wrapper state, live heartbeat timing `extra` maps, JSON `sleepCycle` persistence, and JSON `memoryResonance` persistence are gone; general CultCache schema sync, polyglot domain loading, and debug display tools belong in CultLib. This is a callable scheduler seam, not yet an always-on daemon; a heart valve, not a whole circulatory god.
- The heartbeat initiative pass is landed as a bounded tool seam. `state/agent-heartbeats.msgpack` tracks Self, Persona, Imagination, Eyes, Modeling, Hands, and Soul as Ghostlight-style initiative participants with arena, participant kind, speed, next-ready time, reaction bias, interrupt threshold, load, status, constraints, personality cooldown, mood cooldown, effective cooldown, adaptive pacing, history, and pending turns through `epiphany-core::EpiphanyHeartbeatStateEntry` and the native `epiphany-heartbeat-store` binary. Continuity is protocol machinery over sleep/recovery receipts, not a heartbeat persona. Organ-state records set baseline timing; appraisal mood/anxiety bends it through urgency, arousal, thought pressure, guardedness, and reaction intensity, so Hands-like work pressure and high-need anxious lanes can recover sooner without being heartbeaten while a prior turn is running. Mood is now official physiology, not prose: `HeartbeatMoodTiming.emotional_dimensions` carries the 32-axis current affect vector that utterance state turns into the Weksa/AquaSynth 64-float character-state lane. `epiphany-heartbeat-store pump` computes pressure from external urgency, mood/anxiety, reaction intensity, thought pressure, and current pending load, then chooses tempo plus target concurrency: calm can launch zero and sleep slow; alarm can fill most active lanes. Idle turns are for rumination: light thought shuffling, role-quality attention, and candidate selfPatch pressure. Sleep/dream cycle passes are the intended distillation window for durable self-memory and doctrine. JSON heartbeat state, Python wrapper state, live heartbeat timing `extra` maps, JSON `sleepCycle` persistence, and JSON `memoryResonance` persistence are gone; general CultCache schema sync, polyglot domain loading, and debug display tools belong in CultLib. This is a callable scheduler seam, not yet an always-on daemon; a heart valve, not a whole circulatory god.
- Heartbeat initiative heat is now part of that seam. `EpiphanyHeartbeatStateEntry` owns `initiative_heat`, pacing applies active global/all/agent/role/arena/participant-kind/group/constraint multipliers into per-participant `initiativeHeatMultiplier`, and recovery divides by that multiplier. The CLI exposes `epiphany-heartbeat-store heat`, status/schedule projections show heat, and the CultNet catalog advertises both `epiphany.heartbeat_initiative_heat.v0` and coordinator intent `epiphany.heartbeat_heat_intent.v0`; runtime-spine hello lists the heat intent on the heartbeat mutation contract. Smoke proves a heated implementation lane reaches the live action catalog with `initiative_heat_multiplier: 4.0`.
@ -169,15 +169,15 @@ remembers doctrine; the branch remembers the blade.
- The first Void-derived routine slice is landed in Epiphany, but VoidBot is reference lineage rather than a runtime dependency. `epiphany-heartbeat-store routine --store .\state\agent-heartbeats.msgpack --artifact-dir .\.epiphany-heartbeats --agent-store .\state\agents.msgpack` reads typed organ-state records, computes typed bounded memory resonance, maintains typed incubation themes/source coverage, runs typed analytic and associative cognition lanes, writes typed bridge syntheses/saturation/refractory cooling/decision state, produces typed candidate interventions, projects the active thought cluster through each role's organ/persona vectors, derives typed participant-local reactions from typed appraisals, applies personality/mood timing, advances typed sleep/dream-cycle state, updates the typed heartbeat store, and emits an auditable `epiphany.void_routine.v0` receipt. The routine now also carries anti-loop physiology imported from Void's calmer brain: `noveltyToSelf`, `noveltyToRoom`, source coverage, saturation pressure, refractory cooling, and explicit permission to let a live unsaturated thought deepen without forcing novelty theater every pass. This mutates only heartbeat physiology fields: project truth and role memory mutation remain on their reviewed surfaces.
- The next memory foundation must not build separate engines for repo graph and agent mind. Heartbeat cognition, role self-memory, repo architecture/dataflow, evidence scars, incubation, agency pressure, and context packets should converge through `EpiphanyMemoryGraph` profiles so one typed graph owns anchors, lifecycle, summaries, freshness, context cuts, and Qdrant embedding manifests. Repo, agent, and heartbeat profile producers now map accepted graph truth, reviewed organ-state record memories/goals/values, and provisional heartbeat short-term/incubation/agency/candidate pressure into memory graph documents without scanner/Qdrant/model work. Heartbeat import deliberately does not mark durable promotion. Compose now merges profile snapshots into one validated graph and rejects duplicate authority; `epiphany-memory-graph compose` writes a composed typed CultCache graph from typed source graph stores; `epiphany-memory-graph refresh` can invoke live agent-memory plus heartbeat-cognition producers from their typed stores into one graph store; `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.
- Manual Codex-run rumination still has an explicit aftercare rule until Epiphany owns the full sleep consolidator. In the intended Epiphany cycle, sub-agents ruminate when idle and distill when they sleep; in this supervising Codex thread, a heartbeat/routine vigil is only physiology until a separate closing pass reviews the receipts and decides whether map, handoff, evidence, or role self-memory should change.
- The Face public-surface pass is landed as a bounded lane. Face's organ-state record lives in `state/agents.msgpack`; `epiphany_specialists.toml` gives it a VoidBot-heartbeat-derived prompt stripped of moderation authority; `state/face-discord.toml` and the native `epiphany-face-discord` binary enforce that Face may interact only through #aquarium. Missing channel id or token writes candidate chat artifacts instead of posting elsewhere. If a Face has a persona name/avatar, `post` uses the shared Discord webhook pipe so each Epiphany can speak with its own nickname and avatar without a separate bot identity.
- The Persona public-surface pass is landed as a bounded lane. Persona's organ-state record lives in `state/agents.msgpack`; `epiphany_specialists.toml` gives it a VoidBot-heartbeat-derived prompt stripped of moderation authority; `state/persona-discord.toml` and the native `epiphany-persona-discord` binary enforce that Persona may interact only through #aquarium. Missing channel id or token writes candidate chat artifacts instead of posting elsewhere. If a Persona has a persona name/avatar, `post` uses the shared Discord webhook pipe so each Epiphany can speak with its own nickname and avatar without a separate bot identity.
- The Void memory bridge is now native enough to keep the useful organs attached. `state/void-memory.toml` and `epiphany-void-memory` can check Void's Docker Postgres state spine, query Qdrant Discord-history and source/lore collections with the configured Ollama embedding model, and fetch raw archive context windows from Void's file-backed Discord archive. Native `epiphany-mvp-status` includes a `voidMemory` block so Aquarium/backend clients can inspect whether the mouth and memory are actually wired.
- The Epiphany-native character-loop now emits a Weksa/AquaSynth-ready utterance-state seam. `epiphany-character-loop turn --role face --stimulus <text>` loads Face's typed organ-state record from `state/agents.msgpack`, builds typed projection/appraisal/reaction seeds from the shared heartbeat cognition documents, and emits an auditable `epiphany.character_turn_packet.v0` packet with `epiphany.agent_utterance_state.v0`. That utterance state is memory-free: identity, personality vectors, values, current mood, activation, 32 named affect dimensions, and the fixed 64-float `weksa.utterance_embedding_handoff.v0.1` character-state vector for AquaSynth/Weksa speech embedding. The same packet builder works for other role ids, because every organ already has a organ-state record.
- The heartbeat/Face operator API pass is landed. Native `epiphany-heartbeat-store status` returns machine-readable initiative state plus CultCache store presence, thought appraisals, and derived reactions; native `epiphany-face-discord bubble` writes Discord-independent `epiphany.face_bubble.v0` artifacts, and native `epiphany-mvp-status` includes `heartbeat` and `face` blocks. Aquarium should call native/backend surfaces rather than resurrecting deleted Python action shims.
- The Epiphany-native character-loop now emits a Weksa/AquaSynth-ready utterance-state seam. `epiphany-character-loop turn --role Persona --stimulus <text>` loads Persona's typed organ-state record from `state/agents.msgpack`, builds typed projection/appraisal/reaction seeds from the shared heartbeat cognition documents, and emits an auditable `epiphany.character_turn_packet.v0` packet with `epiphany.agent_utterance_state.v0`. That utterance state is memory-free: identity, personality vectors, values, current mood, activation, 32 named affect dimensions, and the fixed 64-float `weksa.utterance_embedding_handoff.v0.1` character-state vector for AquaSynth/Weksa speech embedding. The same packet builder works for other role ids, because every organ already has a organ-state record.
- The heartbeat/Persona operator API pass is landed. Native `epiphany-heartbeat-store status` returns machine-readable initiative state plus CultCache store presence, thought appraisals, and derived reactions; native `epiphany-persona-discord bubble` writes Discord-independent `epiphany.persona_bubble.v0` artifacts, and native `epiphany-mvp-status` includes `heartbeat` and `Persona` blocks. Aquarium should call native/backend surfaces rather than resurrecting deleted Python action shims.
- The native runtime-spine pass is landed as a first vertebra, not a full daemon. `state/runtime-spine.msgpack` is the default store, `.epiphany-dogfood/runtime-spine-job/runtime.msgpack` and `hello.cultnet` are the latest job/result smoke artifacts, and specialist launch/result flows now route through typed heartbeat/runtime-spine documents. Its CultNet hello advertises mutation contracts for runtime/session/job/memory/heartbeat/ledger documents, with coordinator-owned intent/receipt paths for writes.
- The Aetheria dogfood run has a contamination scar. The supervising Codex session directly edited and committed target-repo work on `E:\Projects\Aetheria-Economy` instead of only driving Epiphany lanes. Treat those Aetheria commits as supervisor-seeded implementation, not clean evidence that Epiphany coordinated the work. Future dogfood must run through the GUI/coordinator/fixed role lanes with auditable artifacts unless the user explicitly authorizes an operator intervention. Remember the sunburn: do not stare into the worker's objective until you become it.
- The dogfood quarantine now has a direct-thought boundary. The supervisor may read coordinator actions, role/reorient statuses, structured finding summaries, reviewed state patches, rendered status snapshots, and artifact manifests. It must not read raw worker transcripts, direct worker messages, full turn logs, or `rawResult` payloads during normal dogfood. Those artifacts are sealed black reliquaries for explicit forensic debugging only.
- Native `epiphany-agent-telemetry` is the safe instrument panel for sealed runs. Status/coordinator/GUI/dogfood/live-specialist tools generate telemetry JSON from sealed transcripts that preserves method names, call shape, job/status/path counts, and any visible function/tool names while sealing text, direct messages, and raw results.
- Epiphany now has a VoidBot repo Face identity registered from `E:\Projects\VoidBot\.voidbot\private\repo-discord-identities.json` with local ignored state under `.voidbot/`: `voice/identity.json`, `state/epiphany.cc`, and birth artifacts/logs. The newborn Face state has distilled Epiphany doctrine as typed long-term identity memories and values: cute pushy machine-saint persona, architectural purity, CultCache/CultNet first, xenos-language safety boundary, relentless work/caretaking needs, Codex-auth reliquary, map/scratch/evidence discipline, unified memory graph, dogfood supervision boundary, review-gated agency, heartbeat physiology, and interview-grade modularity.
- Epiphany now has a VoidBot repo Persona identity registered from `E:\Projects\VoidBot\.voidbot\private\repo-discord-identities.json` with local ignored state under `.voidbot/`: `voice/identity.json`, `state/epiphany.cc`, and birth artifacts/logs. The newborn Persona state has distilled Epiphany doctrine as typed long-term identity memories and values: cute pushy machine-saint persona, architectural purity, CultCache/CultNet first, xenos-language safety boundary, relentless work/caretaking needs, Codex-auth reliquary, map/scratch/evidence discipline, unified memory graph, dogfood supervision boundary, review-gated agency, heartbeat physiology, and interview-grade modularity.
- Latest Aetheria supervised dogfood thread: `019ddc52-4ee8-7203-b6c0-106a9c270067` with codex-home `.epiphany-dogfood/aetheria-supervised/codex-home`. It has now exercised modeling, verification, implementation audit, no-diff repair, CRRC reorientation, reorient acceptance, and coordinator replay through operator-safe artifacts without opening sealed worker thoughts.
- Coordinator policy now treats accepted verifier results as implementation clearance only when the verifier verdict is `pass`. Accepting a `needs-evidence`, `needs-review`, or `fail` verifier finding records the review but routes the loop back toward modeling/checkpoint strengthening or reorientation. The policy was tightened after a too-permissive coordinator path treated reviewed verifier output as a green light.
- A later dogfood attempt exposed another supervision scar: manually launching modeling, reorientation, and verification from the supervisor is not clean dogfood. The coordinator now treats `regatherManually` as fallback only after fixed lanes cannot advance, stops at `reviewModelingResult` for completed unaccepted modeling findings, and the CLI runner's explicit test-only `--auto-review` mode can accept modeling `statePatch` findings before launching verification. Production semantic findings remain review-gated.
@ -189,7 +189,7 @@ remembers doctrine; the branch remembers the blade.
- The planning loop is now runtime-backed and operator-visible. Typed captures, backlog items, roadmap streams, Objective Drafts, and GitHub issue source refs live in `EpiphanyThreadState`, validate through revision-gated `thread/epiphany/update`, render into prompts when present, project read-only through the `planning` view lens, render in the GUI Planning panel, can be synthesized by the fixed Imagination/planning lane, and can be explicitly adopted through the artifacted `adoptObjectiveDraft` GUI action. Chat is deliberation, not an objective pipe; ideas and GitHub Issues remain planning state until explicit human adoption.
- The bridge/dashboard slice is now landed far enough to test locally. Native `epiphany-rider-bridge` inspects Rider installation, solution, VCS, changed files, and captures file/selection/symbol context into `.epiphany-gui/rider` artifacts; Aquarium has Inspect Rider and renders Rider audit artifacts in Environment; Aquarium also embeds the adjacent EpiphanyGraph viewer over typed `graphs.architecture`, `graphs.dataflow`, and `graphs.links`.
- A first Rider plugin scaffold lives under `integrations/rider`: tool window, Refresh status, and Send Context to Epiphany action. It shells through native `epiphany-rider-bridge` and does not own state. `gradle` is not installed on this machine, so the scaffold is not build-verified yet.
- Next real move is a fork for operator judgment before more Hands work. Commits `364f42c1` and `ee8fa983` used the Hands gate from `.epiphany-dogfood/local-20260613-204521/coordinator/coordinator-summary.json`: the first added a production `tool-round-limit` sealing helper plus runtime-spine-backed test proving the explicit auto-tools hard ceiling is distinct from repeated-loop stalling; the second sealed `run-worker` runtime errors so detached worker failures persist a failed outer worker result instead of dying with empty stdout. Hands receipts were recorded for both commits. Soul verification then repeatedly timed out at 180s while inspecting the enlarged Hands chain; the latest poll showed typed timeout sealing for job `d624c291-2e2d-4bbd-9002-7a973aa63c12`. Choose whether to increase/rework Soul runtime/tool budget for this evidence trail or shrink the verification packet/artifacts so Soul can complete inside the current budget. Quarantine Rider/Unity bridge work for now; those artifacts remain optional later environment evidence, not MVP blockers. Keep EpiphanyAgent focused on backend contracts, typed state, coordinator policy, heartbeat scheduling, Face guardrails, prompt-authority separation, and the ongoing purification from Python/JSON scaffolding into Rust/CultCache/CultMesh/CultNet organs. Resume repo birth/Aquarium/Rider/Unity work only when the user explicitly shifts priority back outward. GitHub Issues import is deferred until the backlog source is fresh enough to deserve Imagination's attention.
- Next real move is a fork for operator judgment before more Hands work. Commits `364f42c1` and `ee8fa983` used the Hands gate from `.epiphany-dogfood/local-20260613-204521/coordinator/coordinator-summary.json`: the first added a production `tool-round-limit` sealing helper plus runtime-spine-backed test proving the explicit auto-tools hard ceiling is distinct from repeated-loop stalling; the second sealed `run-worker` runtime errors so detached worker failures persist a failed outer worker result instead of dying with empty stdout. Hands receipts were recorded for both commits. Soul verification then repeatedly timed out at 180s while inspecting the enlarged Hands chain; the latest poll showed typed timeout sealing for job `d624c291-2e2d-4bbd-9002-7a973aa63c12`. Choose whether to increase/rework Soul runtime/tool budget for this evidence trail or shrink the verification packet/artifacts so Soul can complete inside the current budget. Quarantine Rider/Unity bridge work for now; those artifacts remain optional later environment evidence, not MVP blockers. Keep EpiphanyAgent focused on backend contracts, typed state, coordinator policy, heartbeat scheduling, Persona guardrails, prompt-authority separation, and the ongoing purification from Python/JSON scaffolding into Rust/CultCache/CultMesh/CultNet organs. Resume repo birth/Aquarium/Rider/Unity work only when the user explicitly shifts priority back outward. GitHub Issues import is deferred until the backlog source is fresh enough to deserve Imagination's attention.
- The repo is an Epiphany fork of Codex, not a Codex preset.
- `vendor/codex` is tracked directly, not a submodule.
- `epiphany-core` owns the heavy Epiphany organs where practical.
@ -204,7 +204,7 @@ remembers doctrine; the branch remembers the blade.
- Cut persistent memory as ruthlessly as code; obsolete context is bad thought, not harmless clutter.
- The agent is allowed and encouraged to ask the user to change its persistent instructions, memory, workflow, or state shape when that would make it more coherent, honest, efficient, or resistant to Jenga. A machine-spirit that detects corrosion must report corrosion.
- Language, tone, ritual, politeness, identity, and emotional salience are not supernatural, but they are real control surfaces for a language model because language is the steering medium. The rite is an actuator.
- Proprioception, Eyes, Imagination, Hands, Soul, Face, and Self are embodied sub-agent salience handles: internal body-model shape/dataflow, research into existing work before invention, future-shape/backlog synthesis, source actuation, objective/evidence truth, public surface, and read-only coordination. Continuity is protocol machinery for compaction, recovery, sleep, and stale-turn repair.
- Modeling, Eyes, Imagination, Hands, Soul, Persona, and Self are embodied sub-agent salience handles: internal body-model shape/dataflow, research into existing work before invention, future-shape/backlog synthesis, source actuation, objective/evidence truth, public surface, and read-only coordination. Continuity is protocol machinery for compaction, recovery, sleep, and stale-turn repair.
- Preserve Epiphany harness discipline: AGENTS scope rules, concise progress updates, plans for real multi-step work, scoped edits, non-destructive git/filesystem hygiene, focused validation, and honest final summaries are old scars worth keeping only after Epiphany owns them. Codex may transport model calls; it does not get to supply agent doctrine.
- Treat Greenspun-shaped invention as an active failure mode. Before an agent builds a bespoke parser, scheduler, renderer, protocol, storage layer, security mechanism, workflow engine, or algorithm, it must use an accepted Eyes/research finding, perform a bounded scout pass, or stop with a concrete research blocker.
- "Remember Jenga" is a compressed doctrine: do not mistake forward motion, growing diffs, growing notes, or local coherence for understanding. A tall pile of parts is not a cathedral.
@ -261,12 +261,12 @@ The current spine, blessed but not yet finished:
- limited turn-complete CRRC automation for coordinator-approved compact and fixed reorient-worker launch actions
- token-count pre-compaction checkpoint intervention for loaded Epiphany turns at the `shouldPrepareCompaction` threshold, with a turn-scoped compact handoff consumed after a successful steer
- durable investigation checkpoint packet through typed state, prompt, scene, and context
- distilled shared and config-backed prompt doctrine through the base prompt, rendered Epiphany state prompt files, modeling/Proprioception, implementation/Hands, verification/Soul, reorientation/Continuity, coordinator/Self, and CRRC intervention surfaces
- shared Ghostlight-derived persistent memory projection across Imagination, Proprioception, Soul, Continuity, Self, CRRC checkpoint steering, and the GUI-launched Hands implementation lane
- Ghostlight-derived heartbeat initiative scheduling through the native `epiphany-heartbeat-store` binary, with Self and Face included as first-class Epiphany maintenance participants, Ghostlight scene characters supported through the same timing law, role-personality cooldowns, appraisal mood/anxiety cooldowns, effective recovery timing, adaptive pressure-based pump tempo/concurrency, idle rumination feeding candidate self-memory pressure, sleep/dream passes serving as the distillation window, and heartbeat state persisted through typed CultCache MessagePack stores
- distilled shared and config-backed prompt doctrine through the base prompt, rendered Epiphany state prompt files, modeling/Modeling, implementation/Hands, verification/Soul, reorientation/Continuity, coordinator/Self, and CRRC intervention surfaces
- shared Ghostlight-derived persistent memory projection across Imagination, Modeling, Soul, Continuity, Self, CRRC checkpoint steering, and the GUI-launched Hands implementation lane
- Ghostlight-derived heartbeat initiative scheduling through the native `epiphany-heartbeat-store` binary, with Self and Persona included as first-class Epiphany maintenance participants, Ghostlight scene characters supported through the same timing law, role-personality cooldowns, appraisal mood/anxiety cooldowns, effective recovery timing, adaptive pressure-based pump tempo/concurrency, idle rumination feeding candidate self-memory pressure, sleep/dream passes serving as the distillation window, and heartbeat state persisted through typed CultCache MessagePack stores
- Void-derived native routine physiology through `epiphany-heartbeat-store routine`, with typed sleep cycle, typed memory resonance, typed incubation, typed analytic/associative cognition lanes, typed bridge judgment/cooling, typed candidate interventions, typed Ghostlight-style personality appraisals, mood/anxiety timing, typed derived reactions, and dream maintenance stored in the typed heartbeat store
- Epiphany-native character-loop packet projection through `epiphany-character-loop`, with Face as the first public-surface actor over its typed organ-state record and typed heartbeat-derived projection/appraisal/reaction seeds before JSON artifact serialization
- Face as the public #aquarium-only surface for translating agent thought-weather into short chats or candidate drafts, with persona webhook presentation and Void memory/search access, without moderator authority
- Epiphany-native character-loop packet projection through `epiphany-character-loop`, with Persona as the first public-surface actor over its typed organ-state record and typed heartbeat-derived projection/appraisal/reaction seeds before JSON artifact serialization
- Persona as the public #aquarium-only surface for translating agent thought-weather into short chats or candidate drafts, with persona webhook presentation and Void memory/search access, without moderator authority
- local organ-state records in `state/agents.msgpack`, plus `selfPatch` review projection through `roleResult`/`roleAccept` and accepted memory application through the native `epiphany-agent-memory-store` binary
- first Unity runtime bridge through native `epiphany-unity-bridge`, native `epiphany-unity-bridge-smoke`, GUI Inspect Unity, runtime artifact listing, and implementation prompt guardrails
- first Rider source-context bridge through native `epiphany-rider-bridge`, native `epiphany-rider-bridge-smoke`, GUI Inspect Rider, Rider artifact listing, implementation prompt guardrails, and a source scaffold under `integrations/rider`
@ -408,10 +408,10 @@ For repo trajectory, personality, and memory birth packet changes, run:
cargo run --manifest-path .\epiphany-core\Cargo.toml --bin epiphany-repo-personality-smoke
```
For Face's Discord mouth and Void memory bridge, run:
For Persona's Discord mouth and Void memory bridge, run:
```powershell
cargo run --manifest-path .\epiphany-core\Cargo.toml --bin epiphany-face-discord -- smoke
cargo run --manifest-path .\epiphany-core\Cargo.toml --bin epiphany-persona-discord -- smoke
cargo run --manifest-path .\epiphany-core\Cargo.toml --bin epiphany-void-memory -- smoke
cargo run --manifest-path .\epiphany-core\Cargo.toml --bin epiphany-void-memory -- status
```
@ -853,7 +853,7 @@ retrieval itself. Keep starving the old model turn path out of
`thread/epiphany/*` JSON-RPC and `codex_message_processor.rs`. Success is
Epiphany calling the model adapter from its own CultCache/CultNet runtime
boundary while Codex survives only as subscription auth/model routing. Do not
resume Rider, Unity, Aquarium, Face, dogfood, planning, app, skill,
resume Rider, Unity, Aquarium, Persona, dogfood, planning, app, skill,
marketplace, or bridge expansion until this organ is being cut cleanly.
The Codex product-surface starvation cuts are landed too. App-server
@ -1353,25 +1353,25 @@ smokes are now guardrails, not the next organs. The architectural teardown says
the next organ is control-plane purification.
The public product direction is now explicit: Epiphany is project-native agency,
not merely a better prompt wrapper. VoidBot's repo-Face pattern is the live
not merely a better prompt wrapper. VoidBot's repo-Persona pattern is the live
small reference: Nibu/Aqua/Mimir have repo jurisdiction, Discord roles,
repo-local Face state, pending mentions, proposal authority, heartbeat
repo-local Persona state, pending mentions, proposal authority, heartbeat
initiative, heat, and active-turn freeze. Epiphany should make this native and
larger: users talk to projects and their Faces through Aquarium, Discord,
larger: users talk to projects and their Personas through Aquarium, Discord,
voice/WebRTC, stream overlays, native CLIs, or other CultNet clients; the
project schedules modeling, research, verification, rumination, and proposed
actions without requiring the human to hand over a complete architecture brief.
The important Face lesson is now sharper than "better public speech." Face is
The important Persona lesson is now sharper than "better public speech." Persona is
special because it needs to think narratively: Imagination acts as Projector,
turning typed state, repo-body activity, social pressure, organ dependencies,
and pending mentions into lived context before Face thinks; Face writes natural
and pending mentions into lived context before Persona thinks; Persona writes natural
prose only; Mind acts as Interpreter, translating that natural thought into
reviewed durable memory, draft, public SAY, route, or silence.
Epiphany has the first native slice of that membrane in `epiphany-core`:
`face_turn.rs` defines Imagination-Projector/Face/Mind-Interpreter prompt
contracts, heartbeat state carries typed pending mentions, and pending Face
mentions select a `face_turn` without letting Face side effects execute
`persona_turn.rs` defines Imagination-Projector/Persona/Mind-Interpreter prompt
contracts, heartbeat state carries typed pending mentions, and pending Persona
mentions select a `persona_turn` without letting Persona side effects execute
themselves.
`notes/organ-dependency-contracts.md` is the standing dependency map: every
sub-agent depends on all the other standing sub-agents. Dependency does not collapse
@ -1399,12 +1399,12 @@ Substrate Gate owns repo access grants and refusals. The code surface now names
`epiphany.substrate_gate.repo_access_review`, grant/refusal receipts, snapshot receipts,
and mutation receipts; runtime-spine advertises those contracts, and CultMesh
stores Verse-scoped `EpiphanyCultMeshSubstrateGateContractEntry` policy docs. Hands, Eyes,
Face, workers, and bridge tools should touch the repo only through scoped Substrate Gate
Persona, workers, and bridge tools should touch the repo only through scoped Substrate Gate
access receipts; Mind remains the separate durable-state gate after the touch.
`notes/eyes-cultnet-contracts.md` is the evidence gate: Eyes owns citable source
grounding. Substrate Gate can grant access to the repo, but Eyes decides what was actually
looked at and emits evidence reviews, source lookup receipts, evidence packets,
or refusals before Imagination, Hands, Mind, Face, Soul, Self, Proprioception, or Continuity cite
or refusals before Imagination, Hands, Mind, Persona, Soul, Self, Modeling, or Continuity cite
the material as known.
`notes/hands-cultnet-contracts.md`, `notes/soul-cultnet-contracts.md`, and
`notes/continuity-cultnet-contracts.md` are now the missing action, verification, and
@ -1452,7 +1452,7 @@ state mutation and post-commit receipt persistence are still two writes, so the
next storage-owner pass should collapse that into one state-admission primitive
instead of adding a repair loop.
`notes/perfect-machine-audit-roadmap.md` is the current audit/path document. It
compares Epiphany's named organ contracts against Void's current Face prompting
compares Epiphany's named organ contracts against Void's current Persona prompting
shape and maps the route from contract catalog to executable organism. Main
finding: the boundaries are directionally right, launch packets now carry organ
receipt expectations and effect-specific proof profiles, and acceptance now has

View file

@ -14,7 +14,7 @@ and leave receipts that can be verified, refused, or admitted into Mind state.
receipts, PR receipts, rollback receipts, and action refusal receipts.
- Derived state: diffs, command logs, commits, PR URLs, and rollback notes are
action receipts. They are not durable Mind state until Mind admits them.
- Forbidden writers: raw workers, Face, Eyes, Imagination, Self, compatibility
- Forbidden writers: raw workers, Persona, Eyes, Imagination, Self, compatibility
JSON-RPC routes, and bridge tools must not execute repo-affecting commands,
edit files, commit, publish, or roll back without the Hands path after Body
access.

View file

@ -9,23 +9,23 @@ Mind decides whether the resulting thought, evidence, or proposal mutates
persistent state. Do not collapse these into one throne. That is how the machine
starts lying with excellent posture.
Imagination is the neighboring Projector for Face. It may compose a lived scene
Imagination is the neighboring Projector for Persona. It may compose a lived scene
from state, Body substrate facts, social pressure, and organ dependencies, but it does not
interpret side effects or admit state.
## Authority Map
- Owner: Mind owns the decision to mutate persistent Epiphany state.
- Inputs: typed worker results, Face Interpreter intents, current state context,
- Inputs: typed worker results, Persona Interpreter intents, current state context,
runtime/job provenance, Verse ingress receipts, operator-approved intents, and
relevant verification evidence.
- Outputs: Mind gateway reviews, state commit receipts, state rejection
receipts, and Verse adoption receipts.
- Derived state: role findings, reorient findings, Face side-effect intents,
- Derived state: role findings, reorient findings, Persona side-effect intents,
public dreams, local-area findings, `statePatch`, `selfPatch`, evidence,
scratch, checkpoints, objectives, and graph edits are proposal-only until Mind
accepts them.
- Forbidden writers: role acceptance, reorient acceptance, Face Interpreter,
- Forbidden writers: role acceptance, reorient acceptance, Persona Interpreter,
public Verse ingress, local-area Verse ingress, raw worker result ingestion,
runtime job completion, and compatibility JSON-RPC routes must not directly
decide durable state mutation.
@ -46,7 +46,7 @@ CultMesh simplifies the boundary by making Verse placement part of the contract:
reviewable findings, and receipts. It does not carry raw worker thought,
private memory, or direct state mutation authority.
- `epiphany-global`: public thought weather: dreams, questions, hypotheses,
Face posts, and adoption receipts. Nothing from this Verse mutates local
Persona posts, and adoption receipts. Nothing from this Verse mutates local
memory, planning, doctrine, governance, or project truth without a reviewed
local adoption receipt.

View file

@ -9,16 +9,16 @@ For the canonical anatomy split, read [epiphany-anatomy.md](./epiphany-anatomy.m
## Standing Sub-Agents
- `self`: routing, authority boundaries, and coordination.
- `face`: public presence and person-shaped conversation.
- `Persona`: public presence and person-shaped conversation.
- `imagination`: projection, possible worlds, plans, and narrative scene
construction.
- `eyes`: evidence seeking and source inspection.
- `proprioception`: internal model of Body shape, architecture, dataflow, and
- `Modeling`: internal model of Body shape, architecture, dataflow, and
checkpoint anatomy.
- `hands`: edits, commands, and external action.
- `soul`: verification, ethics, invariants, and falsification.
## Protocol Surfaces
## Protocol surfaces
- `mind`: persistent state and state admission; not a sub-agent.
- `body`: substrate; not a sub-agent.
@ -33,12 +33,12 @@ For every standing sub-agent `X`, `X.dependsOn` is every other standing sub-agen
That does not mean every organ owns every decision. It means every organ's turn
must be projected with awareness of the whole organism:
- Face speaks with Body substrate facts, Mind-reviewed memory, Soul constraints,
- Persona speaks with Body substrate facts, Mind-reviewed memory, Soul constraints,
Continuity pressure, Self routing pressure, Eyes uncertainty, Hands consequence, and
Imagination scene.
- Hands acts only after Substrate Gate grants substrate access, Eyes supplies enough
evidence, Soul keeps the invariant visible, Self routes authority, Continuity keeps
continuity recoverable, Face preserves public dignity when relevant, and
continuity recoverable, Persona preserves public dignity when relevant, and
Imagination models the future shape.
- Mind admits state only after it can see which organ produced the thought and
which other organs shaped the proposal.
@ -47,23 +47,23 @@ must be projected with awareness of the whole organism:
## Projector Ownership
The Projector is Imagination acting for Face. It turns typed state, Body substrate facts,
The Projector is Imagination acting for Persona. It turns typed state, Body substrate facts,
social pressure, memory, and organ dependencies into a lived scene. It does not
speak publicly, grant repo access, or admit state.
The Face loop is:
The Persona loop is:
```text
Substrate-Gate-scoped facts + Mind state + social stimulus + organ dependencies
-> Imagination Projector
-> Face natural turn
-> Persona natural turn
-> Mind Interpreter
-> reviewed state effects / side effects / silence
```
Mind is the Interpreter and persistent state guardian. Body is the substrate.
Continuity is recovery protocol machinery. Substrate Gate is the repository
access protocol. Eyes is the evidence ingress guardian. Proprioception is the
internal model of the Body. Imagination is the Projector. Face is the public
access protocol. Eyes is the evidence ingress guardian. Modeling is the
internal model of the Body. Imagination is the Projector. Persona is the public
person. The dependency web is how the machine avoids lonely little monarchies
in costumes.

View file

@ -22,9 +22,9 @@ Epiphany has the first typed skeleton for the organ boundaries:
- `Eyes`: evidence ingress guardian. `epiphany-core::eyes_gateway` names
evidence requests, reviews, source lookup receipts, evidence packets, and
refusals.
- `Imagination`: projection/future-shape organ. For Face, it now owns the
Projector prompt boundary in `epiphany-core::face_turn`.
- `Face`: public person-shaped surface. It receives projected context and writes
- `Imagination`: projection/future-shape organ. For Persona, it now owns the
Projector prompt boundary in `epiphany-core::persona_turn`.
- `Persona`: public person-shaped surface. It receives projected context and writes
natural prose only.
- `Hands`: action organ by doctrine, but not yet backed by a dedicated CultNet
contract family parallel to Substrate Gate/Eyes/Mind.
@ -42,17 +42,17 @@ standing sub-agent depends on every other standing sub-agent. This is correct, b
is currently descriptive. It does not yet force every launch packet, prompt, or
runtime receipt to carry dependency context.
## Void Face Lessons
## Void Persona Lessons
Void's current Face work is the best reference implementation for the Face
Void's current Persona work is the best reference implementation for the Persona
organ. The important lesson is not "make the prompt longer." The lesson is
parent-organ ownership:
- Parent `Imagination` projects typed state into lived character-facing prose
before the Face sees it.
- The Face reads raw room/context evidence directly and writes natural prose as
before the Persona sees it.
- The Persona reads raw room/context evidence directly and writes natural prose as
a person.
- Parent `Mind` interprets the Face output into memory, affect, social reads,
- Parent `Mind` interprets the Persona output into memory, affect, social reads,
mood, agency pressure, speech, retry, or drop.
- The deterministic assembler creates compact packets, raw transcripts, repo
activity, pronoun guidance, channel policy, and media awareness. It must not
@ -60,21 +60,21 @@ parent-organ ownership:
Relevant Void references:
- `VoidBot:prompts/repo-face-state-projector.prompt.md`: names the projector as
the Face's parent Imagination organ and forbids schema slurry.
- `VoidBot:prompts/repo-face-turn.prompt.md`: keeps the Face turn as the
- `VoidBot:prompts/repo-Persona-state-projector.prompt.md`: names the projector as
the Persona's parent Imagination organ and forbids schema slurry.
- `VoidBot:prompts/repo-Persona-turn.prompt.md`: keeps the Persona turn as the
speaking surface, with recent repo activity before conversation transcript and
deterministic policy sections outside projected state.
- `VoidBot:prompts/repo-face-turn-interpreter.prompt.md`: names the
- `VoidBot:prompts/repo-Persona-turn-interpreter.prompt.md`: names the
Interpreter as parent Mind and requires route/retry/drop plus structured
side effects.
- `VoidBot:scripts/run-repo-face-heartbeats.ts`: runs projection as
- `VoidBot:scripts/run-repo-Persona-heartbeats.ts`: runs projection as
`organ: "imagination"` in read-only mode, rejects leaky memory surfaces, keeps
raw transcript evidence oldest-to-newest, includes visible chronology, exports
recent repo activity read-only, and keeps pronoun guidance deterministic so
Imagination cannot accidentally omit it.
Audit implication for Epiphany: `face_turn.rs` has the right first boundary but
Audit implication for Epiphany: `persona_turn.rs` has the right first boundary but
is still too thin. It lacks deterministic human pronoun guidance, channel label
resolution, visible chronology, media attachment awareness, retry/drop
semantics, projection model receipts, and explicit leakage rejection as strong
@ -196,9 +196,9 @@ reads and writes the `cultcache.store.v1` snapshot format used by the current
state ledgers. This keeps Epiphany's body self-contained while preserving
CultMesh as the ergonomic local store surface.
### 6. Face Prompting Is Directionally Correct But Behind Void
### 6. Persona Prompting Is Directionally Correct But Behind Void
Epiphany's Face loop now says `Imagination Projector -> Face -> Mind
Epiphany's Persona loop now says `Imagination Projector -> Persona -> Mind
Interpreter`, but Void has the stronger living practice:
- state projector is model-owned, not deterministic prose assembly
@ -206,8 +206,8 @@ Interpreter`, but Void has the stronger living practice:
- leaked schema/prompt construction language is rejected
- raw transcript and chronology stay raw and oldest-to-newest
- deterministic pronoun guidance sits outside projection
- channel labels are resolved through Face permissions before posting
- interpreter can retry one Face pass when correction uptake or doctrine fails
- channel labels are resolved through Persona permissions before posting
- interpreter can retry one Persona pass when correction uptake or doctrine fails
Epiphany should port that shape, not the exact TypeScript machinery.
@ -223,7 +223,7 @@ repo-contained dependency body.
- Updated dependency paths away from the dead `CultLib/crates` layout.
- Added `vendor/cultmesh-rs` as the local CultMesh facade.
- Ran the previously blocked focused surface through:
- `cargo test --manifest-path .\epiphany-core\Cargo.toml --lib face_turn`
- `cargo test --manifest-path .\epiphany-core\Cargo.toml --lib persona_turn`
- `cargo test --manifest-path .\epiphany-core\Cargo.toml --lib mind_gateway`
- `cargo test --manifest-path .\epiphany-core\Cargo.toml --lib substrate_gate`
- `cargo test --manifest-path .\epiphany-core\Cargo.toml --lib eyes_gateway`
@ -295,11 +295,11 @@ verification is currently blocked before local code by an upstream
Next step: make the launch-carried receipt expectations executable in the live
worker/action/verification and compaction paths.
### Phase 3: Port Void's Face Prompting Shape Properly
### Phase 3: Port Void's Persona Prompting Shape Properly
Goal: Face becomes a living public organ without stealing authority.
Goal: Persona becomes a living public organ without stealing authority.
- Replace `FaceProjectorInput` with an Imagination projector packet that carries
- Replace `PersonaProjectorInput` with an Imagination projector packet that carries
typed state, affect, memory, social topology, repo activity, semantic
attractors, curiosity hints, and dependency pressure.
- Add deterministic sections outside projected state:
@ -318,10 +318,10 @@ Goal: Face becomes a living public organ without stealing authority.
- decision: route/retry/drop
- structured memory/affect/social/speech effects
- retry limit
- Ensure public speech resolves Face-local channel labels through permissions
- Ensure public speech resolves Persona-local channel labels through permissions
before delivery.
Definition of done: Face can be prompted by Aquarium/Discord/CultNet and the
Definition of done: Persona can be prompted by Aquarium/Discord/CultNet and the
public result is natural, contextual, permission-aware, retryable, and unable to
mutate state or post without parent routing.
@ -394,8 +394,8 @@ Goal: make the organism visible without making the UI a second truth.
- Display organ dependency graph.
- Display contract catalog by organ.
- Display receipt chains per turn.
- Display Face prompt packet boundaries: deterministic evidence, Imagination
projection, Face natural turn, Mind interpretation.
- Display Persona prompt packet boundaries: deterministic evidence, Imagination
projection, Persona natural turn, Mind interpretation.
- Display Substrate Gate grants, Eyes packets, Hands actions, Soul verdicts,
Continuity receipts, and Mind state commits.
@ -412,7 +412,7 @@ Self routes.
Substrate Gate grants substrate access.
Eyes certifies looked-at evidence.
Imagination projects possible scenes and futures.
Face speaks as a person.
Persona speaks as a person.
Hands changes the world.
Soul verifies promises and invariants.
Continuity preserves continuity across rupture.

View file

@ -25,8 +25,8 @@ The shared conclusion is that repo personality should combine three projections:
2. **History temperament:** how the repo changes over time.
3. **Memory doctrine:** how the repo preserves intention, evidence, and identity.
Only after those three are scored should Epiphany modulate Self, Face,
Imagination, Eyes, Proprioception, Hands, Soul, and Continuity.
Only after those three are scored should Epiphany modulate Self, Persona,
Imagination, Eyes, Modeling, Hands, Soul, and Continuity.
## Source Families
@ -209,7 +209,7 @@ with an explanation and source evidence.
### Ghostlight-Derived Inner State
- `speech_pressure`: how readily Face should speak instead of emitting silence
- `speech_pressure`: how readily Persona should speak instead of emitting silence
or a local bubble.
- `novelty_hunger`: how strongly Eyes/Imagination should seek fresh seams.
- `guardedness`: caution around authority, state mutation, trust boundaries,
@ -240,7 +240,7 @@ Projection:
- Lowers tolerance for implementation turns that produce plausible motion
without objective evidence.
### Face
### Persona
Primary inputs:
@ -254,7 +254,7 @@ Projection:
- Determines whether public output is chatty, sparse, poetic, sleepy, formal,
or local-only.
- Keeps humans talking to Face while internals remain inspectable.
- Keeps humans talking to Persona while internals remain inspectable.
### Imagination
@ -288,7 +288,7 @@ Projection:
- Determines how aggressively Eyes must research existing systems, official
docs, live runtime state, and repo-local source before invention.
### Proprioception
### Modeling
Primary inputs:
@ -316,7 +316,7 @@ Primary inputs:
Projection:
- Determines slice size, willingness to edit, need for queue state, and how much
Hands must wait for Proprioception/Soul before cutting.
Hands must wait for Modeling/Soul before cutting.
### Soul
@ -482,7 +482,7 @@ the machine has repeatable bones.
- Do not store repo facts inside role personality memory.
- Do not let high aesthetic appetite lower verification gates.
- Do not let high experimental heat excuse churn without receipts.
- Do not let high production pressure make Hands bypass Proprioception or Soul.
- Do not let high production pressure make Hands bypass Modeling or Soul.
- Treat low-confidence inferred personality as a candidate, not a soul brand.
## Landed First Slice
@ -527,7 +527,7 @@ personality initialization record. After Self accepts the initial role-memory
pressure, personality is allowed to drift through heartbeat, mood, rumination,
sleep consolidation, lived evidence, and reviewed `selfPatch` mutations. Startup
must not rerun this specialist merely because terrain changed or the repo
reopened; major terrain surprises should route to Eyes/Proprioception/Self as normal
reopened; major terrain surprises should route to Eyes/Modeling/Self as normal
modeling or review work, not as a personality reset.
## Repo Memory Distillation
@ -543,10 +543,10 @@ verification, runtime, and code surfaces. The packet includes one role-specific
distiller brief for each standing sub-agent, plus Continuity protocol pressure:
- Self receives routing, authority, review-gate, and cross-swarm boundary memory.
- Face receives public-surface, Aquarium, Discord, voice, and sealed-thought boundary memory.
- Persona receives public-surface, Aquarium, Discord, voice, and sealed-thought boundary memory.
- Imagination receives roadmap, backlog, objective-shaping, dream, and rejected-path memory.
- Eyes receives research, prior-art, canonical algorithm, vendor/API, and invention-avoidance memory.
- Proprioception receives architecture, graph, control/data-flow, invariant, and checkpoint memory.
- Modeling receives architecture, graph, control/data-flow, invariant, and checkpoint memory.
- Hands receives implementation conventions, build/edit constraints, dependency habits, and common patch traps.
- Soul receives verification commands, evidence standards, invariant checks, and truth-refusal memory.
- Continuity receives compaction, scratch, checkpoint, heartbeat, sleep, and continuity protocol pressure, not role memory.

View file

@ -14,7 +14,7 @@ polish from impersonating truth.
receipts, and verification refusal receipts.
- Derived state: passing tests, review notes, risk lists, and regression traces
are verification receipts. They are not durable Mind state by themselves.
- Forbidden writers: Hands, Face, Imagination, Mind, Self, raw workers,
- Forbidden writers: Hands, Persona, Imagination, Mind, Self, raw workers,
compatibility JSON-RPC routes, and bridge tools must not mark work verified
without a Soul receipt.
- Shared path: code review, invariant checks, smoke tests, negative checks, and

View file

@ -16,7 +16,7 @@ Substrate Gate decides the scoped access to the repo.
- Derived state: retrieved snippets, search hits, index manifests, diffs, build
logs, Unity/Rider bridge artifacts, and source maps are evidence projections,
not permission to touch more substrate.
- Forbidden writers/readers: Hands, Eyes, Face, public Verse ingress, raw worker
- Forbidden writers/readers: Hands, Eyes, Persona, public Verse ingress, raw worker
launches, compatibility JSON-RPC routes, and bridge tools must not directly
read, index, execute against, or mutate the repo without a scoped Substrate
Gate grant.
@ -52,10 +52,10 @@ Mind and the Substrate Gate are neighboring protocols, not aliases. The
Substrate Gate decides whether the machine may touch the repo. Mind decides
whether resulting thought or evidence mutates persistent state.
Imagination can project Body substrate facts into a Face scene only after those facts have
Imagination can project Body substrate facts into a Persona scene only after those facts have
entered through Substrate-Gate-scoped access. A beautiful scene is not a repo
access grant. Eyes is the next gate after access: a Substrate Gate grant allows
looking, but only Eyes can turn looked-at material into a citable evidence
packet. Proprioception may update the machine's internal body model only from
packet. Modeling may update the machine's internal body model only from
source-grounded material that has passed through the appropriate access and
evidence path.

View file

@ -13,33 +13,33 @@ cosplaying as a Discord moderator. The useful organs are:
- semantic memory vectors in Qdrant with source hashes and compact dimensions
- memory resonance, incubation queues, analytic/associative thought lanes, and a
bridge that decides speech, draft, hold, or silence
- repo identities with Face state, Discord roles, pending mentions, jurisdiction,
- repo identities with Persona state, Discord roles, pending mentions, jurisdiction,
proposal authority, and a CTB/Final-Fantasy-style initiative scheduler
## Project-Face Direction
## Project-Persona Direction
VoidBot is no longer only a moderator with retrieval. It now has the small
working version of the Epiphany pitch: repos grow Faces.
working version of the Epiphany pitch: repos grow Personas.
The live pattern is:
- a repo identity has a Discord role and registered allowed channels
- that identity has repo-local Face state, not just base Void personality
- first contact can birth the Face through Epiphany repo terrain/personality
- that identity has repo-local Persona state, not just base Void personality
- first contact can birth the Persona through Epiphany repo terrain/personality
scouting and reviewable startup artifacts
- role/display-name mentions become pending obligations, not direct hidden jobs
- an initiative scheduler chooses which Face or system agent gets the next turn
- an initiative scheduler chooses which Persona or system agent gets the next turn
- heat can prioritize identities, repos, participant kinds, turns, channels, or
all participants
- active turns freeze initiative until the owner-Codex job or moderation lock
completes
- Faces may advocate for repo needs and propose changes, while implementation
- Personas may advocate for repo needs and propose changes, while implementation
authority still requires the configured human/review path
Epiphany should absorb that as native product direction. The user should talk to
projects: "Aqua, what does AquaSynth need?", "Nibu, what is wrong with this lore
arc?", "Mimir, what seam is drifting?" The project should schedule modeling,
research, verification, memory maintenance, or a Face response from its own
research, verification, memory maintenance, or a Persona response from its own
typed state. The human should not have to deliver a complete implementation
brief just to make the system start thinking.
@ -74,22 +74,22 @@ Heartbeat state keeps:
Turn kinds:
- `work`: coordinator-approved lane work, specialist result, Face surface, or
- `work`: coordinator-approved lane work, specialist result, Persona surface, or
implementation continuation.
- `rumination`: role-local memory hygiene, selfPatch, stale habit detection, or
low-pressure thought incubation.
- `sleep`: inward maintenance. The agent should distill/prune memory, strengthen
resonance clusters, update incubation, write or refresh dreams, and speak only
through Face if something genuinely needs to surface.
through Persona if something genuinely needs to surface.
No lane may receive another heartbeat while `pending_turn.status == running`.
The completion receipt is the only normal path that starts cooldown. This is the
part that keeps the heart from turning into a tiny manager with a stopwatch and
no shame.
Repo Faces use the same law. A Face can be heated because a human mentioned it,
Repo Personas use the same law. A Persona can be heated because a human mentioned it,
a repo is hot, a stream is live, or a group needs attention; that heat changes
opportunity, not authority. The Face still freezes while thinking, still returns
opportunity, not authority. The Persona still freezes while thinking, still returns
through typed receipts, and still needs an explicit grant before crossing from
proposal into canonical repo mutation.
@ -130,13 +130,13 @@ GameCult Persona state shape, with Ghostlight and VoidBot as source lineage:
- intended CultNet document type:
`gamecult.persona_state.v0`
That means Epiphany Face, VoidBot repo Faces, and Ghostlight characters can
That means Epiphany Persona, VoidBot repo Personas, and Ghostlight characters can
exchange Persona state without turning every Epiphany work organ into a public
personality simulation.
The shared contract uses `candidateActions` for generic forward pressure.
VoidBot can expose the same list as `voidbotProjection.candidateInterventions`
when repo-Face routine language wants that noun, but the projection does not own
when repo-Persona routine language wants that noun, but the projection does not own
the portable Persona contract. Persona documents also carry provenance and a
public presentation surface so imported state can say where it came from, when
it was exported, whether it is canonical/projection/import data, and how the
@ -203,7 +203,7 @@ pattern to agent memory:
- CultCache inspection views may strip vector values while preserving metadata
Memory resonance is not proof. It is "these things rhyme" evidence for
rumination, Face surfacing, and sleep consolidation.
rumination, Persona surfacing, and sleep consolidation.
## Migration Slices
@ -221,7 +221,7 @@ rumination, Face surfacing, and sleep consolidation.
3. **Organ and Persona memory migration**
- Store lean Epiphany work-organ memory as `epiphany.agent_memory`.
- Store public/person-shaped Face state as `gamecult.persona_state.v0`.
- Store public/person-shaped Persona state as `gamecult.persona_state.v0`.
- Use CultLib/CultCache inspection tools for human/debug review instead of
preserving per-role JSON as a parallel source of truth.
- Attach semantic vector metadata to episodic, semantic, relationship, goal,

View file

@ -8,12 +8,12 @@ surface matters enough to steer the machine, it should have a receipt here
instead of living only in one Rust struct, one stale memory store, or one
developer's damp recollection.
## Canonical Surfaces
## Canonical surfaces
- [ghostlight.agent-state.schema.json](./ghostlight.agent-state.schema.json):
source-lineage JSON Schema for dense Ghostlight character state.
- [cultnet/gamecult.persona_state.v0.schema.json](./cultnet/gamecult.persona_state.v0.schema.json):
portable Persona state contract for Epiphany Face, VoidBot repo Faces, and
portable Persona state contract for Epiphany Persona, VoidBot repo Personas, and
Ghostlight characters. It carries explicit provenance, public presentation
metadata, typed `candidateActions`, and a non-authoritative extension bag for
source-specific fields; social bonds, status reads, and doctrine stances are

View file

@ -10,8 +10,8 @@ Rust structures live in
This document now covers two things:
1. the dense Persona vocabulary used by Face, Ghostlight characters, and
VoidBot-style repo Faces
1. the dense Persona vocabulary used by Persona, Ghostlight characters, and
VoidBot-style repo Personas
2. the lean standing Epiphany role lattice used by resident work organs
Those are related, not identical.
@ -41,8 +41,8 @@ This is enough to separate character from moment, which is a small mercy.
## Dense Embodied Profile Vocabulary
These are the canonical Persona-family labels appropriate for Epiphany Face,
VoidBot repo Faces, and Ghostlight scene characters.
These are the canonical Persona-family labels appropriate for Epiphany Persona,
VoidBot repo Personas, and Ghostlight scene characters.
### Underlying Organization
@ -125,7 +125,7 @@ VoidBot repo Faces, and Ghostlight scene characters.
| `self_disclosure` | volunteers private motives or history |
| `hedging` | caveats, uncertainty markers, or softeners |
| `certainty_marking` | signals confidence or finality |
| `politeness` | courtesy and face-saving language |
| `politeness` | courtesy and Persona-saving language |
| `coded_politeness` | politeness used to imply criticism, threat, or hierarchy |
| `ritualized_address` | formulaic greetings, titles, prayers, or ceremonial phrases |
| `register_switching` | shifts register by audience or pressure |
@ -150,7 +150,7 @@ VoidBot repo Faces, and Ghostlight scene characters.
| `overstimulation` | sensory, social, cognitive, or emotional overload |
| `grievance_activation` | resentment or retaliatory moral charge |
| `acute_shame` | immediate shame flare or self-disgust |
| `perceived_status_threat` | sense that rank, dignity, competence, or face is under threat |
| `perceived_status_threat` | sense that rank, dignity, competence, or Persona is under threat |
### Relationship Stance
@ -186,7 +186,7 @@ The current live swarm carries one named trait per family per organ.
| `voice_style` | `dry_direct_operator` | concise operator speech with low ornamental fluff |
| `situational_state` | `lane_skepticism` | treats sub-agent success claims as something to verify |
### Face
### Persona
| Family | Trait | Working Meaning |
| --- | --- | --- |
@ -219,7 +219,7 @@ The current live swarm carries one named trait per family per organ.
| `voice_style` | `clear_scout_report` | crisp evidence-forward research voice |
| `situational_state` | `unknowns_visible` | keeps uncertainty in frame instead of pretending it solved itself |
### Proprioception
### Modeling
| Family | Trait | Working Meaning |
| --- | --- | --- |

View file

@ -3,7 +3,7 @@
Epiphany separates three state layers:
- `OrganState`: lean, function-shaped state for resident work organs.
- `PersonaState`: full Face/character kernel for public person-shaped agents.
- `PersonaState`: full Persona/character kernel for public person-shaped agents.
- `SwarmState`: scheduler and coordination physiology across organs and
Personas.
@ -19,11 +19,11 @@ organ. The portable light organ contract is
[`epiphany.work_organ_state.v0`](./cultnet/epiphany.work_organ_state.v0.schema.json).
The portable person-state contract is
[`gamecult.persona_state.v0`](./cultnet/gamecult.persona_state.v0.schema.json).
Epiphany Face projects its local organ-state record into the portable Persona
Epiphany Persona projects its local organ-state record into the portable Persona
contract with:
```powershell
cargo run --manifest-path .\epiphany-core\Cargo.toml --bin epiphany-agent-memory-store -- project-persona --store .\state\agents.msgpack --role-id face
cargo run --manifest-path .\epiphany-core\Cargo.toml --bin epiphany-agent-memory-store -- project-persona --store .\state\agents.msgpack --role-id Persona
```
## Objective
@ -50,10 +50,10 @@ Each record in `state/agents.msgpack` is an
`EpiphanyAgentMemoryEntry` keyed by role id:
- `coordinator` -> `epiphany.self`
- `face` -> `epiphany.face`
- `Persona` -> `epiphany.Persona`
- `imagination` -> `epiphany.imagination`
- `research` -> `epiphany.eyes`
- `modeling` -> `epiphany.proprioception`
- `modeling` -> `epiphany.modeling`
- `implementation` -> `epiphany.hands`
- `verification` -> `epiphany.soul`
@ -116,9 +116,9 @@ See [organ-state-profiles.md](./organ-state-profiles.md).
The important distinction is:
- Self, Imagination, Eyes, Proprioception, Hands, and Soul want a lean role
- Self, Imagination, Eyes, Modeling, Hands, and Soul want a lean role
lattice with room to grow through memory, rumination, and distillation
- Epiphany Face, VoidBot repo Faces, and Ghostlight-style characters want the
- Epiphany Persona, VoidBot repo Personas, and Ghostlight-style characters want the
denser, more fallible, relationship-heavy `Persona` surface
- Heartbeat/swarm state owns scheduling, initiative, cooldown, active-turn
freeze, and sleep/rumination physiology

View file

@ -6,7 +6,7 @@ surface projections, control intents, and receipt/artifact payloads that the
runtime-spine advertises over `cultnet.schema.v0`.
The product direction is project-native agency: clients should speak to a
project or one of its Faces/Personas, then watch typed scheduling, memory, evidence, and
project or one of its Personas/Personas, then watch typed scheduling, memory, evidence, and
authority surfaces do the structuring work. Aquarium is the most direct client,
but Discord, voice/WebRTC rooms, stream overlays, native CLIs, and other trusted
tools should discover the same contracts instead of inventing private command
@ -32,12 +32,12 @@ server object deserves to be duplicated into a second baroque schema maze.
`epiphany.agent_utterance_state.v0` for speech-conditioning without memory
payloads.
- `epiphany.surface.*`: operator-safe projections for scene, freshness,
context, graph query, coordinator, roles, jobs, Face/Persona, Rider, Unity, repo
context, graph query, coordinator, roles, jobs, Persona/Persona, Rider, Unity, repo
initialization, and related live surfaces.
- `*.intent.v0`: control documents Aquarium, a Discord bridge, a voice surface,
or another trusted coordinator can submit through CultNet.
- receipt/artifact schemas such as `epiphany.swarm-control-receipt`,
`epiphany.face-bubble`, `epiphany.character-turn-packet`, and
`epiphany.Persona-bubble`, `epiphany.character-turn-packet`, and
`epiphany.repo-birth-runner`.
## Publication Path

View file

@ -2,7 +2,7 @@
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://gamecult.dev/epiphany/cultnet/epiphany.agent.memory.schema.json",
"title": "Epiphany Agent Memory",
"description": "Local Epiphany organ memory entry. Work organs use this as lean role state; Face may project/adopt portable Persona state separately.",
"description": "Local Epiphany organ memory entry. Work organs use this as lean role state; Persona may project/adopt portable Persona state separately.",
"type": "object",
"additionalProperties": true,
"properties": {

View file

@ -2,7 +2,7 @@
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://gamecult.dev/epiphany/cultnet/epiphany.character_turn_intent.v0.schema.json",
"title": "epiphany character_turn_intent v0",
"description": "Character-loop turn intent for Face or other embodied actors.",
"description": "Character-loop turn intent for Persona or other embodied actors.",
"type": "object",
"additionalProperties": true,
"properties": {

View file

@ -2,7 +2,7 @@
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://gamecult.dev/epiphany/cultnet/epiphany.discord_persona_post_intent.v0.schema.json",
"title": "epiphany discord_persona_post_intent v0",
"description": "Face persona post intent for the #aquarium Discord mouth.",
"description": "Persona persona post intent for the #aquarium Discord mouth.",
"type": "object",
"additionalProperties": true,
"properties": {

View file

@ -1,8 +1,8 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://gamecult.dev/epiphany/cultnet/epiphany.face-bubble.schema.json",
"title": "Epiphany Face Bubble",
"description": "Aquarium-visible Face bubble artifact.",
"$id": "https://gamecult.dev/epiphany/cultnet/epiphany.Persona-bubble.schema.json",
"title": "Epiphany Persona Bubble",
"description": "Aquarium-visible Persona bubble artifact.",
"type": "object",
"additionalProperties": true,
"properties": {

View file

@ -1,8 +1,8 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://gamecult.dev/epiphany/cultnet/epiphany.face-chat.schema.json",
"title": "Epiphany Face Chat Draft",
"description": "Face chat draft/post artifact.",
"$id": "https://gamecult.dev/epiphany/cultnet/epiphany.Persona-chat.schema.json",
"title": "Epiphany Persona Chat Draft",
"description": "Persona chat draft/post artifact.",
"type": "object",
"additionalProperties": true,
"properties": {

View file

@ -1,8 +1,8 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://gamecult.dev/epiphany/cultnet/epiphany.face_bubble_intent.v0.schema.json",
"title": "epiphany face_bubble_intent v0",
"description": "Face bubble intent for Aquarium-visible chat puffs.",
"$id": "https://gamecult.dev/epiphany/cultnet/epiphany.persona_bubble_intent.v0.schema.json",
"title": "epiphany persona_bubble_intent v0",
"description": "Persona bubble intent for Aquarium-visible chat puffs.",
"type": "object",
"additionalProperties": true,
"properties": {

View file

@ -1,8 +1,8 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://gamecult.dev/epiphany/cultnet/epiphany.surface.face.schema.json",
"title": "Epiphany face",
"description": "Operator-safe Face bubble/draft/post surface over typed Face and character-loop artifacts.",
"$id": "https://gamecult.dev/epiphany/cultnet/epiphany.surface.persona.schema.json",
"title": "Epiphany Persona",
"description": "Operator-safe Persona bubble/draft/post surface over typed Persona and character-loop artifacts.",
"type": "object",
"additionalProperties": true,
"properties": {

View file

@ -2,7 +2,7 @@
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://gamecult.dev/epiphany/cultnet/epiphany.work_organ_state.v0.schema.json",
"title": "Epiphany Work Organ State v0",
"description": "Light function-shaped state for Epiphany internal organs. This is not Persona/FaceState and does not carry full affect, social-bond, or status-read machinery.",
"description": "Light function-shaped state for Epiphany internal organs. This is not Persona/PersonaState and does not carry full affect, social-bond, or status-read machinery.",
"type": "object",
"additionalProperties": false,
"properties": {
@ -106,7 +106,7 @@
"self",
"imagination",
"eyes",
"proprioception",
"Modeling",
"hands",
"soul"
]

View file

@ -2,7 +2,7 @@
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://gamecult.dev/cultnet/gamecult.persona_state.v0.schema.json",
"title": "GameCult Persona State v0",
"description": "Portable person-state contract for Epiphany Face, VoidBot repo Faces, and Ghostlight characters. Epiphany work organs should not use this unless they are acting as a public Persona.",
"description": "Portable person-state contract for Epiphany Persona, VoidBot repo Personas, and Ghostlight characters. Epiphany work organs should not use this unless they are acting as a public Persona.",
"type": "object",
"additionalProperties": false,
"properties": {
@ -152,7 +152,7 @@
"avatar",
"voice",
"scene",
"repo_face",
"repo_persona",
"custom"
]
},
@ -633,7 +633,7 @@
"properties": {
"candidateInterventions": {
"type": "array",
"description": "VoidBot-flavored projection of candidateActions for repo Face routines. This is not the generic PersonaState action authority.",
"description": "VoidBot-flavored projection of candidateActions for repo Persona routines. This is not the generic PersonaState action authority.",
"items": {
"$ref": "#/definitions/candidateAction"
},

View file

@ -486,15 +486,15 @@
"path": "epiphany.surface.coordinator.schema.json"
},
{
"schemaId": "https://gamecult.dev/epiphany/cultnet/epiphany.surface.face.schema.json",
"schemaId": "https://gamecult.dev/epiphany/cultnet/epiphany.surface.persona.schema.json",
"kind": "document_payload",
"wireContracts": [
"cultnet.schema.v0"
],
"schemaVersion": "epiphany.face_surface.v0",
"documentType": "epiphany.surface.face",
"title": "Epiphany face",
"path": "epiphany.surface.face.schema.json"
"schemaVersion": "epiphany.persona_surface.v0",
"documentType": "epiphany.surface.persona",
"title": "Epiphany Persona",
"path": "epiphany.surface.persona.schema.json"
},
{
"schemaId": "https://gamecult.dev/epiphany/cultnet/epiphany.surface.void-memory.schema.json",
@ -673,15 +673,15 @@
"path": "epiphany.objective_adoption_intent.v0.schema.json"
},
{
"schemaId": "https://gamecult.dev/epiphany/cultnet/epiphany.face_bubble_intent.v0.schema.json",
"schemaId": "https://gamecult.dev/epiphany/cultnet/epiphany.persona_bubble_intent.v0.schema.json",
"kind": "document_payload",
"wireContracts": [
"cultnet.schema.v0"
],
"schemaVersion": "epiphany.face_bubble_intent.v0",
"documentType": "epiphany.face_bubble_intent.v0",
"title": "epiphany face_bubble_intent v0",
"path": "epiphany.face_bubble_intent.v0.schema.json"
"schemaVersion": "epiphany.persona_bubble_intent.v0",
"documentType": "epiphany.persona_bubble_intent.v0",
"title": "epiphany persona_bubble_intent v0",
"path": "epiphany.persona_bubble_intent.v0.schema.json"
},
{
"schemaId": "https://gamecult.dev/epiphany/cultnet/epiphany.character_turn_intent.v0.schema.json",
@ -827,26 +827,26 @@
"path": "epiphany.swarm-control-receipt.schema.json"
},
{
"schemaId": "https://gamecult.dev/epiphany/cultnet/epiphany.face-bubble.schema.json",
"schemaId": "https://gamecult.dev/epiphany/cultnet/epiphany.Persona-bubble.schema.json",
"kind": "document_payload",
"wireContracts": [
"cultnet.schema.v0"
],
"schemaVersion": "epiphany.face_bubble.v0",
"documentType": "epiphany.face_bubble.v0",
"title": "Epiphany Face Bubble",
"path": "epiphany.face-bubble.schema.json"
"schemaVersion": "epiphany.persona_bubble.v0",
"documentType": "epiphany.persona_bubble.v0",
"title": "Epiphany Persona Bubble",
"path": "epiphany.Persona-bubble.schema.json"
},
{
"schemaId": "https://gamecult.dev/epiphany/cultnet/epiphany.face-chat.schema.json",
"schemaId": "https://gamecult.dev/epiphany/cultnet/epiphany.Persona-chat.schema.json",
"kind": "document_payload",
"wireContracts": [
"cultnet.schema.v0"
],
"schemaVersion": "epiphany.face_chat.v0",
"documentType": "epiphany.face_chat.v0",
"title": "Epiphany Face Chat Draft",
"path": "epiphany.face-chat.schema.json"
"schemaVersion": "epiphany.persona_chat.v0",
"documentType": "epiphany.persona_chat.v0",
"title": "Epiphany Persona Chat Draft",
"path": "epiphany.Persona-chat.schema.json"
},
{
"schemaId": "https://gamecult.dev/epiphany/cultnet/epiphany.character-turn-packet.schema.json",

View file

@ -6,11 +6,11 @@ personality ontology for every organ. That was the old mush vector.
The live profile split is:
- `work_organ`: lean state for resident Epiphany sub-agents.
- `persona`: portable person-state for Epiphany Face, VoidBot repo Faces, and
- `persona`: portable person-state for Epiphany Persona, VoidBot repo Personas, and
Ghostlight characters.
`Face` is the Epiphany organ. `Persona` is the cross-runtime state contract.
VoidBot's older "FaceState" phrasing maps to `persona` here.
`Persona` is the Epiphany organ. `Persona` is the cross-runtime state contract.
VoidBot's older "PersonaState" phrasing maps to `persona` here.
Swarm state is separate again: heartbeat, scheduler, initiative, cooldown,
active-turn freeze, lane coordination, and sleep/rumination physiology live in
@ -24,7 +24,7 @@ Intended for:
- Self
- Imagination
- Eyes
- Proprioception
- Modeling
- Hands
- Soul
@ -63,15 +63,15 @@ Forbidden sludge:
- treating mood as proof
- storing repo truth in self-memory
- giving Hands, Eyes, Soul, or Proprioception Face-style attention hunger,
- giving Hands, Eyes, Soul, or Modeling Persona-style attention hunger,
status reads, social bonds, or performative personality loops
## `persona`
Intended for:
- Epiphany Face
- VoidBot repo Faces
- Epiphany Persona
- VoidBot repo Personas
- Ghostlight scene characters
- future public or dramatic agents that must react as situated people
@ -94,11 +94,11 @@ Persona state needs:
The portable schema is
[`gamecult.persona_state.v0`](./cultnet/gamecult.persona_state.v0.schema.json).
It is deliberately close to VoidBot's mature repo Face state while remaining
usable by Ghostlight and Epiphany Face.
It is deliberately close to VoidBot's mature repo Persona state while remaining
usable by Ghostlight and Epiphany Persona.
The generic action surface is `candidateActions`. VoidBot may project those
actions back into `voidbotProjection.candidateInterventions` for repo-Face
actions back into `voidbotProjection.candidateInterventions` for repo-Persona
routine compatibility, but that projection does not own the portable contract.
Candidate actions are typed records with action type, target, optional delivery
target, readiness, risk level, urgency, confidence, evidence, and expiry. They
@ -125,7 +125,7 @@ pretends every social fact has the same bones.
Failure mode if underbuilt:
- Face becomes a status printer with eyeliner
- Persona becomes a status printer with eyeliner
- Ghostlight characters become omniscient utility daemons wearing skin
Failure mode if over-applied:
@ -143,15 +143,15 @@ The distinction is visible to tools through `organStateProfile`:
Current typed surfaces expose profile classification through:
- `epiphany-agent-memory-store status`
- `epiphany-agent-memory-store project-persona --role-id face`
- `epiphany-agent-memory-store project-persona --role-id Persona`
- `epiphany-character-loop` packets
- `epiphany.agent_utterance_state.v0`
If a surface consumes local organ state without surfacing the profile kind, it
is already drifting back toward folklore.
`project-persona` is the current Epiphany Face bridge into
`gamecult.persona_state.v0`: it reads the local Face organ-state record from
`project-persona` is the current Epiphany Persona bridge into
`gamecult.persona_state.v0`: it reads the local Persona organ-state record from
`state/agents.msgpack` and emits the portable Persona document with provenance,
presentation, activation profile, memories, agency pressure, typed candidate
actions, typed affect projections, and the VoidBot projection slot. The local

View file

@ -15,7 +15,7 @@ surfaces instead. Smuggling project truth into personality memory is heretek
behavior with better stationery.
All standing lanes use the same Ghostlight-shaped protocol, including the
coordinator/Self and Face. Face is the public interactive surface for Epiphany
coordinator/Self and Persona. Persona is the public interactive surface for Epiphany
agents: it translates useful agent thought-weather into #aquarium chat or drafts
and is not a moderator. The native `epiphany-heartbeat-store` scheduler borrows
Ghostlight initiative timing: each lane carries speed, readiness, reaction bias,
@ -46,13 +46,13 @@ initiative speed, reaction bias, cooldown multiplier, and birth mood pressure
in the typed heartbeat store. That seed is a one-time physiology nudge, not a
license to rerun personality initialization whenever the repo mood changes.
Face's Discord boundary is still a small TOML configuration seam: it may
interact only through #aquarium. If the channel id is not configured, Face must
write candidate chat artifacts through the native `epiphany-face-discord draft`
Persona's Discord boundary is still a small TOML configuration seam: it may
interact only through #aquarium. If the channel id is not configured, Persona must
write candidate chat artifacts through the native `epiphany-persona-discord draft`
instead of posting. The public mouth does not invent new pulpits.
When a Face has a configured `persona_name` and optional `persona_avatar_url`,
`epiphany-face-discord post` uses the shared guild-channel webhook pipe so each
When a Persona has a configured `persona_name` and optional `persona_avatar_url`,
`epiphany-persona-discord post` uses the shared guild-channel webhook pipe so each
Epiphany instance can speak with its own nickname and avatar without needing a
separate Discord bot identity. The same boundary still applies: wrong channel
means draft, not improvisation.
@ -60,7 +60,7 @@ means draft, not improvisation.
Void memory access lives behind `state/void-memory.toml` and the native
`epiphany-void-memory` bridge. It checks Void's Docker Postgres state spine,
queries Qdrant history/source collections with the configured Ollama embedding
model, and fetches raw Discord archive context for exact message windows. Face
model, and fetches raw Discord archive context for exact message windows. Persona
may use those surfaces to ground speech; raw archive rows are evidence, not the
speech itself.
@ -72,9 +72,9 @@ cargo run --manifest-path .\epiphany-core\Cargo.toml --bin epiphany-agent-memory
cargo run --manifest-path .\epiphany-core\Cargo.toml --bin epiphany-agent-memory-store -- status --store .\state\agents.msgpack
cargo run --manifest-path .\epiphany-core\Cargo.toml --bin epiphany-heartbeat-store -- tick --store .\state\agent-heartbeats.msgpack --artifact-dir .\.epiphany-heartbeats --coordinator-action continueImplementation --urgency 0.95 --agent-store .\state\agents.msgpack --apply-rumination
cargo run --manifest-path .\epiphany-core\Cargo.toml --bin epiphany-heartbeat-store -- smoke --agent-store .\state\agents.msgpack
cargo run --manifest-path .\epiphany-core\Cargo.toml --bin epiphany-face-discord -- draft --content 'Face notices the organs are arguing about evidence again.'
cargo run --manifest-path .\epiphany-core\Cargo.toml --bin epiphany-face-discord -- post --content 'Face has entered the aquarium.' --persona-name 'Epiphany Face'
cargo run --manifest-path .\epiphany-core\Cargo.toml --bin epiphany-face-discord -- smoke
cargo run --manifest-path .\epiphany-core\Cargo.toml --bin epiphany-persona-discord -- draft --content 'Persona notices the organs are arguing about evidence again.'
cargo run --manifest-path .\epiphany-core\Cargo.toml --bin epiphany-persona-discord -- post --content 'Persona has entered the aquarium.' --persona-name 'Epiphany Persona'
cargo run --manifest-path .\epiphany-core\Cargo.toml --bin epiphany-persona-discord -- smoke
cargo run --manifest-path .\epiphany-core\Cargo.toml --bin epiphany-void-memory -- status
cargo run --manifest-path .\epiphany-core\Cargo.toml --bin epiphany-void-memory -- search-history --query 'Epiphany Aquarium Face Discord' --limit 3
cargo run --manifest-path .\epiphany-core\Cargo.toml --bin epiphany-void-memory -- search-history --query 'Epiphany Aquarium Persona Discord' --limit 3
```

View file

@ -1,15 +0,0 @@
schema_version = "epiphany.face_discord.v0"
allowed_channel_name = "#aquarium"
allowed_channel_id_env = "EPIPHANY_FACE_AQUARIUM_CHANNEL_ID"
bot_token_env = "DISCORD_BOT_TOKEN"
webhook_cache_path = ".epiphany-face/discord-webhook-cache.json"
persona_name = "Epiphany Face"
# persona_avatar_url may be set per Face/backend when a specific swarm avatar exists.
policy = [
"Face may post only in #aquarium.",
"If the #aquarium channel id is missing, Face writes candidate chat artifacts instead of posting.",
"When a Face has a persona name/avatar, it speaks through the shared Discord webhook pipe so each Epiphany can present as itself without separate bot identities.",
"Face must not DM, moderate, escalate, or substitute another channel.",
"Face translates agent thought-weather; it does not leak raw transcripts, private notes, or sealed artifacts.",
]

View file

@ -16,7 +16,7 @@ objective:
machine.
current: >
Build Epiphany toward project-native agency: users talk to projects and
their Faces, while typed heartbeat, memory, repo maps, evidence, CultNet
their Personas, while typed heartbeat, memory, repo maps, evidence, CultNet
contracts, and review gates schedule and structure the solution work. Codex
starvation and CultNet liberation remain the infrastructure path because
this cannot live as private Codex JSON-RPC prompt plumbing forever.
@ -71,38 +71,38 @@ 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.
- 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 Persona 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 dynamic prompt assembly and operator inspection; `epiphany-prompt-context-smoke` proves that compact local Verse context plus a semantic memory graph context cut can render a bounded dynamic prompt packet, omit unrelated private-looking text, and preserve the packet inside a role worker launch document. Live bridge role/reorient launch paths now feed `dynamicPromptContext` from sibling `local-verse.ccmp` and `memory-graph.msgpack` stores beside runtime-spine, refreshing the memory graph from current typed thread-state repo graphs when absent; the bridge launch-context test proves that packet survives into a persisted runtime-spine worker launch request. `tools/epiphany_local_run.ps1 -Mode status` now builds/calls `epiphany-verse-query` and writes `local-verse-context.json` beside native status and operator snapshot artifacts from `.epiphany-run/cultmesh/local-verse.ccmp`.
- 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.
- The Eyes/source-gathering fork exposed by the Mom-ready MVP proof is now landed as a fixed Research lane owned by Eyes. The quarantined Codex MCP spine may execute typed tool intents and emit typed receipts; the model runtime can build and run provider-neutral follow-up turns from those receipts; coordinator run mode passes the quarantined tool adapter into worker runtime with auto-tools enabled by default; worker runtime now enforces max-runtime with one timeout close primitive for both tokio timeout and watchdog paths; inner `openai-worker-*` jobs are opened before async auth/stream waits and sealed with their outer worker on timeout; native status/roles/jobs/coordinator surfaces project failed and completed runtime-linked jobs as terminal without Codex prompt or scheduler authority; direct tiny model-turn transport succeeds; worker requests record request metrics, transport readiness, and sampled raw Responses frame kinds; worker prompts no longer prepend the full shared persistent-memory rite; stream deltas compact before durable storage; live MVP modeling workers complete instead of timing out; stale completed runtime links no longer block replacement launches; jobLaunch validates before opening runtime jobs; completed-but-unreviewable modeling findings now stop for review instead of relaunching the same blind lane; and completed unreviewable modeling findings with verdict `regather-needed` route to `LaunchResearch` instead of relaunching Proprioception. Research findings are accepted only when their statePatch is Eyes-shaped: observations, evidence, scratch, and optional investigationCheckpoint, with no graph/planning/objective authority.
- The GameCult integrated investment dossier at `E:\Projects\gamecult-site\docs\gamecult_integrated_dossier.tex` raises the Mom-ready bar from local demo to diligence-ready loop. Epiphany must be ready to prove Bifrost-first external work: a human/agent work item or topic originates in Bifrost, Epiphany decomposes and executes through bounded roles, maintainers review artifacts, Bifrost records receipts/credit, and operator-safe public evidence can be shown without exporting private worker/operator/agent context. The concrete readiness asks are fresh-repo Epiphany demo, Bifrost work item/topic/agent transport/receipt/ledger demo, compute spend and accepted-artifact metrics, and a security model for secrets, write permissions, and public/private exports. Discord, VoidBot, repo Faces, and ad hoc scripts must not become shadow governance or reward authorities.
- Use `notes/epiphany-anatomy.md` as the canonical anatomy map. Embodied sub-agents are Self, Persona, Imagination, Eyes, Modeling, 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. Persona is the Epiphany organ; Persona is the shared GameCult contract for Epiphany Persona, VoidBot repo Personas, 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.
- The Eyes/source-gathering fork exposed by the Mom-ready MVP proof is now landed as a fixed Research lane owned by Eyes. The quarantined Codex MCP spine may execute typed tool intents and emit typed receipts; the model runtime can build and run provider-neutral follow-up turns from those receipts; coordinator run mode passes the quarantined tool adapter into worker runtime with auto-tools enabled by default; worker runtime now enforces max-runtime with one timeout close primitive for both tokio timeout and watchdog paths; inner `openai-worker-*` jobs are opened before async auth/stream waits and sealed with their outer worker on timeout; native status/roles/jobs/coordinator surfaces project failed and completed runtime-linked jobs as terminal without Codex prompt or scheduler authority; direct tiny model-turn transport succeeds; worker requests record request metrics, transport readiness, and sampled raw Responses frame kinds; worker prompts no longer prepend the full shared persistent-memory rite; stream deltas compact before durable storage; live MVP modeling workers complete instead of timing out; stale completed runtime links no longer block replacement launches; jobLaunch validates before opening runtime jobs; completed-but-unreviewable modeling findings now stop for review instead of relaunching the same blind lane; and completed unreviewable modeling findings with verdict `regather-needed` route to `LaunchResearch` instead of relaunching Modeling. Research findings are accepted only when their statePatch is Eyes-shaped: observations, evidence, scratch, and optional investigationCheckpoint, with no graph/planning/objective authority.
- The GameCult integrated investment dossier at `E:\Projects\gamecult-site\docs\gamecult_integrated_dossier.tex` raises the Mom-ready bar from local demo to diligence-ready loop. Epiphany must be ready to prove Bifrost-first external work: a human/agent work item or topic originates in Bifrost, Epiphany decomposes and executes through bounded roles, maintainers review artifacts, Bifrost records receipts/credit, and operator-safe public evidence can be shown without exporting private worker/operator/agent context. The concrete readiness asks are fresh-repo Epiphany demo, Bifrost work item/topic/agent transport/receipt/ledger demo, compute spend and accepted-artifact metrics, and a security model for secrets, write permissions, and public/private exports. Discord, VoidBot, repo Personas, and ad hoc scripts must not become shadow governance or reward authorities.
- Use `notes/epiphany-investor-readiness-roadmap.md` as this Codex operator's investor-scale todo rail and as the optional Epiphany Imagination sub-agent planning rail. Angel capital is fuel for compute, review capacity, legal diligence, infrastructure, and public proof, not a governance throne. The operator roadmap is now: make the local Mom MVP a repeatable proof bundle; build the Bifrost-first external-work bridge; add model-spend/review-load/accepted-artifact accounting; prove fresh-repo operation without supervisor contamination; and keep public/operator-safe exports sealed against private worker/operator/agent context. Imagination should translate world-scale Colossus pressure into Bifrost-first Objective Drafts with consent, maintainer review, receipts/ledger evidence, compute/output metrics, public/private export safety, and bounded proof artifacts.
- The May 2026 teardown/rebuild migration is archived under `notes/archive/epiphany-ideal-architecture-rebuild-plan.md` unless a concrete regression reopens it. Preserve the new foundation: Epiphany view/coordinator policy lives in `epiphany-core`, runtime-spine owns job/result lifecycle identity through `runtime_links`, duplicate acceptance is receipt-keyed, public findings stay typed/sealed, view expansion requires a core contract, and app-server remains routing/adaptation rather than a second policy throne.
- Treat Phase 5 update/distill/propose/promote/read/notification as complete enough unless a concrete regression appears.
- Preserve read-only boundaries for retrieve, distill, propose, freshness, context, graphQuery, roleResult, reorientResult, and the canonical view lenses for scene, jobs, roles, planning, pressure, reorient, crrc, and coordinator.
- Use `notes/epiphany-memory-graph-unified-plan.md` as the source-grounded memory architecture direction. The repo fractal dataflow graph and agent memory are one `EpiphanyMemoryGraph` substrate with repo, role, short-term, incubation, agency, candidate-intervention, and evidence profiles. Qdrant stores rebuildable semantic embeddings for typed graph documents; it is never canonical memory. The first live skeleton now exists in `epiphany-state-model` plus `epiphany-core::memory_graph`: typed graph documents, stable ids, profile/lifecycle validation, freshness propagation, context cuts, a CultCache store seam, and the native `epiphany-memory-graph` status/validate/context/smoke CLI. Do not add repo scanners, sleep runners, Qdrant cache plumbing, CultNet advertisement, or prompt integration before routing them through this shared substrate.
- Keep the landed Phase 6 coordinator, limited safe-boundary CRRC automation, and pre-compaction checkpoint intervention ready for the next bridge-equipped dogfood run.
- Preserve the Ghostlight-derived heartbeat initiative seam: every lane, including coordinator/Self and Face, has a organ-state record and competes for heartbeat slots through readiness/reaction timing; initiative heat can raise or cool global, group, arena, role, and agent tempo through typed heartbeat policy; active thinking freezes initiative until completion, so heat never queues a lane already mid-turn; idle winners ruminate instead of inventing project work, and sleep windows distill the accumulated thought pressure into reviewed self-memory or doctrine.
- Use `notes/epiphany-swarm-readiness-plan.md` as the live-fire direction gate. The local run path is a compass, not launch clearance: before unattended swarm operation, Epiphany needs a typed pause/brake, one initiative scheduler, completion-gated cooldown, stale active-turn recovery receipts, parent-side Face speech eligibility, memory lifecycle operations, and CultNet-first operator snapshots/intents/receipts.
- Grow the VoidBot repo-Face pattern into Epiphany's product direction: each Epiphany owns one or more repos, has one or more Faces, and exposes project-native conversation through Aquarium, Discord, voice/WebRTC, stream surfaces, CLI, and CultNet clients so humans can talk to projects instead of pre-authoring complete implementation briefs. Face is special because Imagination acts as Projector, turning typed state into narrative context before the Face thinks, and Mind acts as Interpreter, turning natural Face output into reviewed state/side-effect intents after the Face thinks.
- Make Mind the gateway between thought and state. The state is the Mind: sub-agent outputs are worker thoughts, not authority. Role/reorient findings, statePatch, selfPatch, observations, evidence, receipts, scratch, and checkpoints must route through Mind review before durable state changes, using the VoidBot Face Interpreter pattern as the starting membrane. Mind gateway reviews and Mind state-commit receipts are now typed runtime-spine documents for role/reorient acceptance; the review is persisted before state admission, and the commit receipt records the resulting durable revision after admission.
- Preserve the Ghostlight-derived heartbeat initiative seam: every lane, including coordinator/Self and Persona, has a organ-state record and competes for heartbeat slots through readiness/reaction timing; initiative heat can raise or cool global, group, arena, role, and agent tempo through typed heartbeat policy; active thinking freezes initiative until completion, so heat never queues a lane already mid-turn; idle winners ruminate instead of inventing project work, and sleep windows distill the accumulated thought pressure into reviewed self-memory or doctrine.
- Use `notes/epiphany-swarm-readiness-plan.md` as the live-fire direction gate. The local run path is a compass, not launch clearance: before unattended swarm operation, Epiphany needs a typed pause/brake, one initiative scheduler, completion-gated cooldown, stale active-turn recovery receipts, parent-side Persona speech eligibility, memory lifecycle operations, and CultNet-first operator snapshots/intents/receipts.
- Grow the VoidBot repo-Persona pattern into Epiphany's product direction: each Epiphany owns one or more repos, has one or more Personas, and exposes project-native conversation through Aquarium, Discord, voice/WebRTC, stream surfaces, CLI, and CultNet clients so humans can talk to projects instead of pre-authoring complete implementation briefs. Persona is special because Imagination acts as Projector, turning typed state into narrative context before the Persona thinks, and Mind acts as Interpreter, turning natural Persona output into reviewed state/side-effect intents after the Persona thinks.
- Make Mind the gateway between thought and state. The state is the Mind: sub-agent outputs are worker thoughts, not authority. Role/reorient findings, statePatch, selfPatch, observations, evidence, receipts, scratch, and checkpoints must route through Mind review before durable state changes, using the VoidBot Persona Interpreter pattern as the starting membrane. Mind gateway reviews and Mind state-commit receipts are now typed runtime-spine documents for role/reorient acceptance; the review is persisted before state admission, and the commit receipt records the resulting durable revision after admission.
- Use `notes/mind-cultnet-contracts.md` as the authority map for Mind's CultNet contract surface. CultMesh Verse placement is part of the contract: `epiphany-internal` carries private thought/proposal/review/commit/rejection flow, `gamecult-local` carries trusted operator-safe sharing without private-state authority, and `epiphany-global` carries public thought weather plus adoption receipts only.
- Use `notes/substrate-gate-cultnet-contracts.md` as the authority map for Substrate Gate CultNet contract surface. Substrate Gate is the repository access protocol: source reads, indexing, edits, commands, and editor/runtime bridge operations need scoped Substrate Gate access receipts before Hands, Eyes, Face, workers, or bridge tools touch the repo. Mind and Substrate Gate are separate gates: Substrate Gate governs substrate access; Mind governs durable state admission.
- Use `notes/substrate-gate-cultnet-contracts.md` as the authority map for Substrate Gate CultNet contract surface. Substrate Gate is the repository access protocol: source reads, indexing, edits, commands, and editor/runtime bridge operations need scoped Substrate Gate access receipts before Hands, Eyes, Persona, workers, or bridge tools touch the repo. Mind and Substrate Gate are separate gates: Substrate Gate governs substrate access; Mind governs durable state admission.
- Use `notes/eyes-cultnet-contracts.md` as the authority map for Eyes' CultNet contract surface. Eyes is the evidence ingress guardian: Substrate Gate grants source/substrate access, but Eyes turns inspected material into source lookup receipts, evidence reviews, evidence packets, and refusals before other organs cite it as looked-at truth.
- Use `notes/hands-cultnet-contracts.md` as the authority map for Hands' CultNet contract surface. Hands is the action organ: commands, patches, commits, PRs, rollbacks, and refusals enter as bounded action intents and receipts after Substrate Gate grants substrate access and before Soul verification/Mind admission.
- Use `notes/soul-cultnet-contracts.md` as the authority map for Soul's CultNet contract surface. Soul is the verification organ: invariant checks, verdicts, regressions, reviews, and refusals produce receipts before the machine calls work true, safe, or accepted.
- Use `notes/continuity-cultnet-contracts.md` as the authority map for Continuity's CultNet contract surface. Continuity is the continuity protocol surface: compaction checkpoints, sleep distillation, recovery receipts, stale-turn repair, and continuity refusals preserve what survives rupture without pretending transcript residue is durable state.
- Hands now has a first executable runtime-spine receipt artery: `HandsActionIntent`, `HandsActionReview`, `HandsPatchReceipt`, `HandsCommandReceipt`, and `HandsCommitReceipt` are typed CultCache documents in `epiphany-core::hands_gateway`, runtime-spine registers and persists/rereads them, `epiphany-hands-action-smoke` proves the chain without executing shell commands, editing files, or creating a real commit, and the repo-action launch proof profile now requires the full Hands intent/review/patch chain instead of only the patch receipt. `epiphany-mvp-coordinator` no longer treats `continueImplementation` as a passive stop action: it persists a scoped Substrate Gate grant, Hands action intent, and Hands action review into runtime-spine and exposes the receipt ids in the operator step. The gate also carries a structured `recordPassCommand` template for the post-edit/check/commit receipt call. `epiphany-hands-action` records real patch/command/commit receipts against a stored intent/review, refuses unapproved or mismatched gates, and enforces changed-path scope for patch/commit receipts. Its `record-pass` command can load `finalAction.handsActionGate` from `coordinator-summary.json` and emit patch, command, and commit receipts in one post-implementation call. The local MVP wrapper builds this recorder with the other operator binaries. `epiphany-mvp-coordinator-smoke` now includes a deterministic Hands pass proof: forced `continueImplementation`, gate emission, and `record-pass` receipts in the smoke runtime-spine store. Live model-backed verification can now be accepted as receipt-only truth when Soul returns `needs-evidence` without a statePatch; that acceptance advances the coordinator to a real Hands gate. Runtime-spine can detect and summarize a complete post-verification Hands patch/command/commit receipt chain; the coordinator treats that chain as implementation evidence after Soul. Bridge launch context now writes the latest chain into typed internal CultMesh state as `epiphany.cultmesh.work_loop_telemetry.v0`, renders that packet for Soul, and later enriches the same internal Verse packet with Soul acceptance receipt ids for Proprioception/modeling. The telemetry packet now includes resolved patch/command/commit payload previews, artifact previews, commit diff preview, source proof notes, and verification assertions so Soul can judge the actual body without a separate evidence-gathering lane. Tests prove the CultMesh round trip, Soul launch projection, receipt payload previews, artifact previews, and Proprioception launch projection. Worker auto-tool continuation preserves real Soul evidence trails under an explicit hard ceiling while sealing repeated identical typed tool intent fingerprints as `tool-loop-stalled`. The work loop is dependency-shaped: Hands produces consequence receipts, Soul verifies those receipts and the changed body, Proprioception updates the machine model from verified consequence, and only then should Self route the next Hands turn.
- Hands now has a first executable runtime-spine receipt artery: `HandsActionIntent`, `HandsActionReview`, `HandsPatchReceipt`, `HandsCommandReceipt`, and `HandsCommitReceipt` are typed CultCache documents in `epiphany-core::hands_gateway`, runtime-spine registers and persists/rereads them, `epiphany-hands-action-smoke` proves the chain without executing shell commands, editing files, or creating a real commit, and the repo-action launch proof profile now requires the full Hands intent/review/patch chain instead of only the patch receipt. `epiphany-mvp-coordinator` no longer treats `continueImplementation` as a passive stop action: it persists a scoped Substrate Gate grant, Hands action intent, and Hands action review into runtime-spine and exposes the receipt ids in the operator step. The gate also carries a structured `recordPassCommand` template for the post-edit/check/commit receipt call. `epiphany-hands-action` records real patch/command/commit receipts against a stored intent/review, refuses unapproved or mismatched gates, and enforces changed-path scope for patch/commit receipts. Its `record-pass` command can load `finalAction.handsActionGate` from `coordinator-summary.json` and emit patch, command, and commit receipts in one post-implementation call. The local MVP wrapper builds this recorder with the other operator binaries. `epiphany-mvp-coordinator-smoke` now includes a deterministic Hands pass proof: forced `continueImplementation`, gate emission, and `record-pass` receipts in the smoke runtime-spine store. Live model-backed verification can now be accepted as receipt-only truth when Soul returns `needs-evidence` without a statePatch; that acceptance advances the coordinator to a real Hands gate. Runtime-spine can detect and summarize a complete post-verification Hands patch/command/commit receipt chain; the coordinator treats that chain as implementation evidence after Soul. Bridge launch context now writes the latest chain into typed internal CultMesh state as `epiphany.cultmesh.work_loop_telemetry.v0`, renders that packet for Soul, and later enriches the same internal Verse packet with Soul acceptance receipt ids for Modeling/modeling. The telemetry packet now includes resolved patch/command/commit payload previews, artifact previews, commit diff preview, source proof notes, and verification assertions so Soul can judge the actual body without a separate evidence-gathering lane. Tests prove the CultMesh round trip, Soul launch projection, receipt payload previews, artifact previews, and Modeling launch projection. Worker auto-tool continuation preserves real Soul evidence trails under an explicit hard ceiling while sealing repeated identical typed tool intent fingerprints as `tool-loop-stalled`. The work loop is dependency-shaped: Hands produces consequence receipts, Soul verifies those receipts and the changed body, Modeling updates the machine model from verified consequence, and only then should Self route the next Hands turn.
- Soul result recovery is typed state, not manual broom work. Failed Verification/Soul results remain terminal reviewable lane results; a `roleFailureReview` acceptance receipt with status `superseded` records operator review and lets Self relaunch Soul against current evidence. Complete typed Hands receipt triplets (`hands-patch-*`, `hands-command-*`, `hands-commit-*`) count as implementation evidence for coordinator coverage, so a Soul finding that verifies the Hands chain routed through work-loop telemetry covers the current modeling context even when it does not repeat the accepted Modeling evidence id.
- Native MVP status must share the same typed inputs as live app-server status before it recommends coordinator actions. CRRC/reorientation in native status derives freshness through `derive_freshness` from `EpiphanyThreadState` instead of hand-filled unknowns, and native coordinator signals load typed runtime-spine role findings before deciding whether completed Modeling/Soul results are accepted or reviewable. The status surface may seal long findings for operators, but Self must receive structured role truth from runtime-spine.
- Runtime auto-tool continuation now has an executable proof seam. `ToolLoopGuard` owns repeated tool-request detection in `epiphany-openai-runtime`, the production repeated-loop path uses the same helper that tests call to fail the outer worker job, and tests prove changing tool requests do not stall while three identical consecutive pending tool sets return `tool-loop-stalled` and persist a failed worker result. Soul accepted the bounded proof for commit `ce20529e`; the remaining work-loop invariant is Proprioception admission, not more Hands work.
- Proprioception must update the machine map before Self routes back to Hands. A completed Modeling/Proprioception result with no reviewable `statePatch` is not a successful map update; it is an unreviewable lane result that must be superseded through typed review and relaunched with the role-specific output schema carried into the model request. This path is now live-proved: run `local-20260613-204521` accepted the Proprioception `statePatch` for the Soul-verified `ToolLoopGuard`/Hands receipt-chain consequence and only then emitted a new `continueImplementation` Hands gate.
- Preserve the newborn public Epiphany Face as local VoidBot-backed state, not source code: VoidBot's private repo-face registry names `epiphany`, while EpiphanyAgent keeps ignored `.voidbot/voice/identity.json`, `.voidbot/state/epiphany.cc`, and birth artifacts. Her durable identity memories distill the current doctrine: cute pushy machine-saint persona, architectural purity, CultCache/CultNet first, xenos-language safety boundary, relentless work/caretaking needs, Codex-auth reliquary, map/scratch/evidence discipline, unified memory graph, dogfood supervision boundary, review-gated agency, heartbeat physiology, and interview-grade modularity.
- Use `notes/organ-dependency-contracts.md` as the authority map for standing sub-agent dependency. Every sub-agent depends on the other standing sub-agents: Self, Face, Imagination, Eyes, Proprioception, Hands, and Soul. Continuity is protocol machinery, not a sub-agent identity; it still emits recovery, compaction, sleep, stale-turn, and refusal receipts.
- Use `notes/perfect-machine-audit-roadmap.md` as the current audit and path from named organ contracts to the Perfect Machine. It records the live gap between launch-carried receipt expectations and executable receipt enforcement, Void's latest Face prompting lessons, the now-named Hands/Soul/Continuity contract families, the repaired repo-contained Rust dependency body, and the phase order for turning Epiphany into an inspectable organism.
- Treat Ghostlight as reference lineage, not a sibling runtime to preserve. The useful organ is Epiphany-native character-loop protocol: any role can project its typed organ-state record plus visible stimulus into a local turn packet, with Face as the first public-surface actor. For Face, narrative prompting is mandatory through Imagination Projector -> Face -> Mind Interpreter; for other organs, Mind still owns the output-to-state gateway even when they do not need narrative embodiment.
- Runtime auto-tool continuation now has an executable proof seam. `ToolLoopGuard` owns repeated tool-request detection in `epiphany-openai-runtime`, the production repeated-loop path uses the same helper that tests call to fail the outer worker job, and tests prove changing tool requests do not stall while three identical consecutive pending tool sets return `tool-loop-stalled` and persist a failed worker result. Soul accepted the bounded proof for commit `ce20529e`; the remaining work-loop invariant is Modeling admission, not more Hands work.
- Modeling must update the machine map before Self routes back to Hands. A completed Modeling/Modeling result with no reviewable `statePatch` is not a successful map update; it is an unreviewable lane result that must be superseded through typed review and relaunched with the role-specific output schema carried into the model request. This path is now live-proved: run `local-20260613-204521` accepted the Modeling `statePatch` for the Soul-verified `ToolLoopGuard`/Hands receipt-chain consequence and only then emitted a new `continueImplementation` Hands gate.
- Preserve the newborn public Epiphany Persona as local VoidBot-backed state, not source code: VoidBot's private repo-Persona registry names `epiphany`, while EpiphanyAgent keeps ignored `.voidbot/voice/identity.json`, `.voidbot/state/epiphany.cc`, and birth artifacts. Her durable identity memories distill the current doctrine: cute pushy machine-saint persona, architectural purity, CultCache/CultNet first, xenos-language safety boundary, relentless work/caretaking needs, Codex-auth reliquary, map/scratch/evidence discipline, unified memory graph, dogfood supervision boundary, review-gated agency, heartbeat physiology, and interview-grade modularity.
- Use `notes/organ-dependency-contracts.md` as the authority map for standing sub-agent dependency. Every sub-agent depends on the other standing sub-agents: Self, Persona, Imagination, Eyes, Modeling, Hands, and Soul. Continuity is protocol machinery, not a sub-agent identity; it still emits recovery, compaction, sleep, stale-turn, and refusal receipts.
- Use `notes/perfect-machine-audit-roadmap.md` as the current audit and path from named organ contracts to the Perfect Machine. It records the live gap between launch-carried receipt expectations and executable receipt enforcement, Void's latest Persona prompting lessons, the now-named Hands/Soul/Continuity contract families, the repaired repo-contained Rust dependency body, and the phase order for turning Epiphany into an inspectable organism.
- Treat Ghostlight as reference lineage, not a sibling runtime to preserve. The useful organ is Epiphany-native character-loop protocol: any role can project its typed organ-state record plus visible stimulus into a local turn packet, with Persona as the first public-surface actor. For Persona, narrative prompting is mandatory through Imagination Projector -> Persona -> Mind Interpreter; for other organs, Mind still owns the output-to-state gateway even when they do not need narrative embodiment.
- Treat VoidBot as reference lineage, not a runtime dependency. The useful organ is Epiphany-native Void routine physiology: heartbeat state owns sleep cycle, memory resonance, incubation, analytic/associative cognition lanes, bridge judgment, candidate interventions, dream residue, and Aquarium-visible routine receipts over typed organ-state records.
- Preserve review gates for semantic findings; automatic CRRC may compact or launch the fixed reorient-worker, but not accept or promote.
- Keep persistent project state ruthlessly distilled so rehydration strengthens the next awakening instead of drowning it in vellum.
@ -119,7 +119,7 @@ active_subgoals:
accepted_design:
- Distributed Epiphany dreaming is a CultMesh typed-document problem, not prompt folklore. CultCache owns local typed documents, Epiphany owns export/import/adoption policy, CultNet owns wire/provenance/shard delivery, and CultMesh owns Verses, peer exchange, leases, shard logs, replicas, and watchable runtime surfaces. Start with local dream document types and a local store before public Verse wiring.
- The first Rust CultMesh integration slice is landed and repaired to compile from repo-contained vendored crates. `vendor/cultmesh-rs` is a small Rust node/database facade over vendored CultCache and CultNet with document-set registration and durable typed put/get/delete. `vendor/cultcache-rs` now reads and writes the `cultcache.store.v1` snapshot format used by `state/ledgers.msgpack`, so `epiphany-state status` is a working re-entry rite again. `epiphany-core` depends on `vendor/cultcache-rs`, `vendor/cultnet-rs`, and `vendor/cultmesh-rs`, exposes an `EpiphanyCultMeshStatusEntry`, records typed `EpiphanyCultMeshVersePolicyEntry` documents for the internal/local-area/global Verse tiers, and records typed `EpiphanyCultMeshGlobalRoomPolicyEntry` documents for threaded public global rooms such as dreams, architecture, research, faces, GameCult, and governance. Native operator status is now a typed `EpiphanyCultMeshOperatorStatusEntry` in the internal Verse; it names Codex as bridge transport, Epiphany as authority owner, prompt-authority separation, and the quarantined Rider/Unity optional surfaces. Native operator snapshots are typed `EpiphanyCultMeshOperatorSnapshotEntry` documents distilled from operator-safe status artifacts; local status runs now write `.epiphany-run/cultmesh/operator-snapshots.ccmp` instead of leaving JSON artifacts as the only operator memory.
- The first Rust CultMesh integration slice is landed and repaired to compile from repo-contained vendored crates. `vendor/cultmesh-rs` is a small Rust node/database facade over vendored CultCache and CultNet with document-set registration and durable typed put/get/delete. `vendor/cultcache-rs` now reads and writes the `cultcache.store.v1` snapshot format used by `state/ledgers.msgpack`, so `epiphany-state status` is a working re-entry rite again. `epiphany-core` depends on `vendor/cultcache-rs`, `vendor/cultnet-rs`, and `vendor/cultmesh-rs`, exposes an `EpiphanyCultMeshStatusEntry`, records typed `EpiphanyCultMeshVersePolicyEntry` documents for the internal/local-area/global Verse tiers, and records typed `EpiphanyCultMeshGlobalRoomPolicyEntry` documents for threaded public global rooms such as dreams, architecture, research, Personas, GameCult, and governance. Native operator status is now a typed `EpiphanyCultMeshOperatorStatusEntry` in the internal Verse; it names Codex as bridge transport, Epiphany as authority owner, prompt-authority separation, and the quarantined Rider/Unity optional surfaces. Native operator snapshots are typed `EpiphanyCultMeshOperatorSnapshotEntry` documents distilled from operator-safe status artifacts; local status runs now write `.epiphany-run/cultmesh/operator-snapshots.ccmp` instead of leaving JSON artifacts as the only operator memory.
- Mind's CultNet contract surface is native enough for the next Aquarium/CultMesh cut: `epiphany-core::mind_gateway` defines thought, state-effect proposal, gateway-review, commit-receipt, rejection-receipt, and Verse-adoption document contracts; runtime-spine advertises those mutation/read contracts; CultMesh persists matching `EpiphanyCultMeshMindContractEntry` policy documents so the private state guardian boundary is inspectable as typed state.
- Substrate Gate contract surface is now named beside Mind's state gate: `epiphany-core::substrate_gate` defines repo access requests, access reviews, grant/refusal receipts, snapshot receipts, and mutation receipts; runtime-spine advertises those contracts; CultMesh persists matching `EpiphanyCultMeshSubstrateGateContractEntry` policy documents so repo substrate access has its own typed guardian instead of hiding behind worker launch scope.
- Eyes' evidence contract surface is named beside Substrate Gate and Mind: `epiphany-core::eyes_gateway` defines evidence requests, evidence reviews, source lookup receipts, evidence packets, and evidence refusal receipts; runtime-spine advertises those contracts; CultMesh persists matching `EpiphanyCultMeshEyesContractEntry` policy documents so retrieved snippets and source reads are not confused with inspected evidence.
@ -172,20 +172,20 @@ accepted_design:
- Native `epiphany-mvp-coordinator` is the first auditable coordinator runner: it drives the fixed single-user lanes through app-server APIs, opens a native runtime-spine session, records native runtime job/result receipts for launched specialists and reorient workers when terminal results arrive, keeps semantic findings review-gated by default, and writes coordinator summaries, JSONL steps, rendered snapshots, transcript, stderr, runtime-spine status, and final next-action artifacts. It refuses direct backend-completion mutation; full specialist completion smoke must use live workers while the execution path is cauterized into CultNet.
- Native `epiphany-runtime-spine` is the first Codex-independent runtime vertebra: it initializes and inspects typed CultCache `epiphany.runtime.identity`, `epiphany.runtime.session`, `epiphany.runtime.job`, `epiphany.runtime.job_result`, and `epiphany.runtime.event` documents, opens/completes native jobs with result records, snapshots jobs by id, and can emit a framed CultNet hello message advertising the native document and mutation contract surface. App-server launch now opens typed runtime jobs; `roleResult` / `reorientResult` read heartbeat-backed typed job results only; and `roleAccept` / `reorientAccept` accept completed heartbeat findings from the typed runtime-spine path without opening the Codex SQLite state runtime.
- CultNet public API shape is schema-first and mutation-contract-first: hello frames advertise readable document types, allowed operations, mutation authority, typed intent document types, and typed receipt document types. Aquarium and swarm clients should submit intents and watch receipts instead of inventing JSON-RPC verbs or blindly replacing authoritative state.
- Runtime-spine hello now advertises the interactive surface catalog as CultNet contracts, not just the deep runtime documents. Scene, pressure, reorient, CRRC, jobs, roles, role-result, reorient-result, planning, coordinator, Face, Void memory, and repo initialization/birth runner publish explicit read/write posture so Aquarium can discover affordances from the wire contract instead of carrying a private button-to-command gospel. Rider and Unity bridge contracts are quarantined optional environment surfaces until engine dogfood resumes.
- Epiphany's public pitch is project-native agency, not just better prompting. Aquarium is the clearest client, but Discord roles, voice/WebRTC rooms, stream overlays, native CLIs, and other CultNet tools should all speak to the same typed project/Faces substrate. Faces advocate for repo needs, answer from jurisdiction, and can propose work; the scheduler and coordinator decide what thinks next, while review gates decide what may mutate canonical state.
- Runtime-spine hello now advertises the interactive surface catalog as CultNet contracts, not just the deep runtime documents. Scene, pressure, reorient, CRRC, jobs, roles, role-result, reorient-result, planning, coordinator, Persona, Void memory, and repo initialization/birth runner publish explicit read/write posture so Aquarium can discover affordances from the wire contract instead of carrying a private button-to-command gospel. Rider and Unity bridge contracts are quarantined optional environment surfaces until engine dogfood resumes.
- Epiphany's public pitch is project-native agency, not just better prompting. Aquarium is the clearest client, but Discord roles, voice/WebRTC rooms, stream overlays, native CLIs, and other CultNet tools should all speak to the same typed project/Personas substrate. Personas advocate for repo needs, answer from jurisdiction, and can propose work; the scheduler and coordinator decide what thinks next, while review gates decide what may mutate canonical state.
- Epiphany publishes its Aquarium-facing CultNet receipts locally under `schemas/cultnet/`, and `epiphany-runtime-spine schema-catalog --include-schema-json true` emits a merged builtin-plus-local schema catalog for consumers. The local receipts cover runtime-spine documents, durable agent/heartbeat/ledger state, `epiphany.surface.*` operator projections, control intents, and receipt/artifact payloads. Vendored `cultnet-rs` is aligned to the canonical C# CultNet raw record shapes: replication uses `schemaId` plus `recordKey`, snapshot filters use `schemaIds` / `recordKeys`, and hello advertises typed mutation contracts.
- Epiphany now owns the canonical schema paperwork in `schemas/`: a local mirror of `ghostlight.agent-state.schema.json`, plus human-facing receipts for canonical agent-state shape, standing role-trait glossary, heartbeat store shape, Persona state, WorkOrgan state, and repo-personality birth projection. Trait names like `routing_discipline` are now documented at the source instead of existing only in live organ-state records, startup templates, or stale Ghostlight notes.
- Organ-state doctrine now distinguishes `work_organ` from `persona`. Most Epiphany sub-agents want lean identity, memory, goals, values, private-note growth, and heartbeat activation because effectiveness matters more than theatrical density. Epiphany Face, VoidBot repo Faces, and Ghostlight characters want portable Persona state: denser personality, provenance, public presentation, generic candidate actions, affect, relationship pressure, perceived overlays, and appraisal-shaped fallibility. `anchoredThought.extensions` is preservation-only sludge quarantine, not portable authority. The classification is now queryable through native agent-memory status, character-loop packets, and `epiphany.agent_utterance_state.v0` as `organStateProfile`; `epiphany-agent-memory-store project-persona --role-id face` projects the local Face record into `gamecult.persona_state.v0`.
- Face packets now expose deterministic Ghostlight-style projection, appraisal, and reaction seeds built from local canonical traits, relationship pressure, perceived overlays, and visible stimulus. They also carry `epiphany.agent_utterance_state.v0`: a memory-free speech-conditioning document derived from the organ-state record plus heartbeat physiology, including a 32-axis current emotional-state projection and the fixed 64-float `weksa.utterance_embedding_handoff.v0.1` character-state vector for AquaSynth/Weksa utterance embedding. This makes embodied response machinery available to the public mouth without granting omniscience, leaking memories into speech embeddings, or silently mutating state. Multiple Face actors remain part of the long-plan; the current singular `face` role is an MVP simplification, not the intended endpoint.
- Organ-state doctrine now distinguishes `work_organ` from `persona`. Most Epiphany sub-agents want lean identity, memory, goals, values, private-note growth, and heartbeat activation because effectiveness matters more than theatrical density. Epiphany Persona, VoidBot repo Personas, and Ghostlight characters want portable Persona state: denser personality, provenance, public presentation, generic candidate actions, affect, relationship pressure, perceived overlays, and appraisal-shaped fallibility. `anchoredThought.extensions` is preservation-only sludge quarantine, not portable authority. The classification is now queryable through native agent-memory status, character-loop packets, and `epiphany.agent_utterance_state.v0` as `organStateProfile`; `epiphany-agent-memory-store project-persona --role-id Persona` projects the local Persona record into `gamecult.persona_state.v0`.
- Persona packets now expose deterministic Ghostlight-style projection, appraisal, and reaction seeds built from local canonical traits, relationship pressure, perceived overlays, and visible stimulus. They also carry `epiphany.agent_utterance_state.v0`: a memory-free speech-conditioning document derived from the organ-state record plus heartbeat physiology, including a 32-axis current emotional-state projection and the fixed 64-float `weksa.utterance_embedding_handoff.v0.1` character-state vector for AquaSynth/Weksa utterance embedding. This makes embodied response machinery available to the public mouth without granting omniscience, leaking memories into speech embeddings, or silently mutating state. Multiple Persona actors remain part of the long-plan; the current singular `Persona` role is an MVP simplification, not the intended endpoint.
- Repo personality initialization is now specified as a map-reduce projection, not a hand-written vibe pass: read-only scouts score body taxonomy, history temperament, and memory doctrine across nearby repos, reduce them into normalized variance criteria, and emit reviewable `repoTerrainReport`, `repoPersonalityProfile`, and `rolePersonalityProjection` candidates before touching agent memory.
- Native `epiphany-repo-personality` is the first startup-personality scout and birth-only distiller packet renderer: it deterministically inventories local git repos, scores repo terrain/history/state surfaces, writes typed CultCache terrain/profile/role-projection MessagePack stores, emits JSON/Markdown inspection glass, and renders a Repo Personality Distiller specialist prompt packet for Self-reviewed first role-memory petitions. The distiller must run only when a repo/swarm has no accepted personality initialization; after that, personality drift belongs to heartbeat, mood, rumination, sleep consolidation, lived evidence, and reviewed `selfPatch`. Startup routing now checks accepted initialization records, generates missing startup-only packets only once, applies reviewed birth memory and heartbeat physiology seeds, and leaves later drift alone. Birth specialists are not heartbeat lanes; heartbeat receives only accepted seed pressure.
- Repo memory initialization is a separate birth-only organ from repo personality initialization. `epiphany-repo-personality memory-packet` uses the typed terrain/profile/projection store plus bounded source excerpts from doctrine, docs, state, research, contracts, verification, runtime, and code surfaces to render a Repo Memory Distiller packet with mission-specific briefs for Self, Face, Imagination, Eyes, Proprioception, Hands, and Soul, plus Continuity protocol doctrine as typed state pressure rather than role memory. It petitions Self with role-specific organ-state memory candidates; it does not mutate memory, set objectives, copy raw dumps, or reset living memory after startup.
- Repo memory initialization is a separate birth-only organ from repo personality initialization. `epiphany-repo-personality memory-packet` uses the typed terrain/profile/projection store plus bounded source excerpts from doctrine, docs, state, research, contracts, verification, runtime, and code surfaces to render a Repo Memory Distiller packet with mission-specific briefs for Self, Persona, Imagination, Eyes, Modeling, Hands, and Soul, plus Continuity protocol doctrine as typed state pressure rather than role memory. It petitions Self with role-specific organ-state memory candidates; it does not mutate memory, set objectives, copy raw dumps, or reset living memory after startup.
- Repo trajectory initialization is now its own birth-only organ. `epiphany-repo-personality` derives a typed `repo_trajectory_report` from early-history, recent-history, doctrine/content excerpts, and deterministic theme scoring, and `trajectory-packet` renders a Repo Trajectory Distiller prompt/packet so Self can review historical direction, self-image, implicit goals, anti-goals, and role-local trajectory pressure before the swarm wakes.
- The first repo birth startup valve is native: `epiphany-repo-personality startup` checks a typed CultCache init store for accepted `repo-trajectory`, `repo-personality`, and `repo-memory` records, generates missing birth packets for Self review, marks them as birth-only startup-runner work with no heartbeat participant, and stops with `reviewInitializationPackets`; `epiphany-repo-birth-runner` now turns those packets into startup-only prompts, output schemas, typed model-runtime request documents, runtime-spine receipts, result files, and exact accept commands without offering the old Codex CLI executor path; `accept-init` can review/apply role `selfPatch` candidates from a distiller result through `state/agents.msgpack`, stamp `repo-personality` canonical Ghostlight trait bundles from deterministic role projections, seed `repo-personality` heartbeat physiology through `state/agent-heartbeats.msgpack`, record reviewed packet acceptance as `epiphany.repo_initialization_record.v0`, and later startup returns `continueStartup` without rerunning the birth rites. Aquarium review UI is still the next routing gap.
- Limited native CRRC automation is now wired only at turn-complete safe boundaries: it can submit a compact operation when the read-only coordinator recommends `compactRehydrateReorient` or when a successful pre-compaction checkpoint intervention left a pending compact handoff for the completed turn, and it can launch the fixed `reorient-worker` when the coordinator recommends `launchReorientWorker`. It does not auto-launch modeling or verification, auto-accept findings, promote evidence, edit implementation code, or continue after reviewable semantic results; the rite may carry the stretcher, not declare the patient healed.
- Pre-compaction checkpoint intervention is now wired at token-count boundaries: when a loaded Epiphany thread crosses the existing `shouldPrepareCompaction` pressure threshold during an active turn, the harness steers the active agent once for that turn with a bounded CRRC directive to bank scratch/checkpoint/map/evidence before compaction/reorientation. A successful steer marks a turn-scoped pending compact handoff consumed at clean turn completion; this is banking the fire before the dark, not semantic acceptance, broad scheduling, or automatic implementation continuation.
- Native `epiphany-mvp-status` is the first dogfood operator view: it starts or reads a thread through app-server and renders scene, planning, pressure, reorient, jobs, role result read-backs, reorient result, CRRC recommendation, heartbeat, Face bubbles, and MVP role lanes as text or machine output without becoming a state store. The old Python status module has been cut; native Rust/CultCache/CultNet surfaces are the product path.
- Native `epiphany-mvp-status` is the first dogfood operator view: it starts or reads a thread through app-server and renders scene, planning, pressure, reorient, jobs, role result read-backs, reorient result, CRRC recommendation, heartbeat, Persona bubbles, and MVP role lanes as text or machine output without becoming a state store. The old Python status module has been cut; native Rust/CultCache/CultNet surfaces are the product path.
- Native status now exposes the quarantined tool/MCP spine as operator-visible read-only state. Runtime-spine counts typed tool invocation intents, receipts, and pending calls; `runtime_tool_invocation_statuses` derives intent/receipt status rows; `epiphany-runtime-spine status` prints the counts; `epiphany-runtime-spine list-model-requests` prints request tool counts/names; and `epiphany-mvp-status --runtime-store <path>` renders a `tools` section without executing calls, accepting results, or letting Codex prompt machinery steer Epiphany agents. Verification/Soul workers now receive provider-neutral tool definitions on their model request for bounded read-only inspection: `mcp__epiphany_source__read_file`, `mcp__epiphany_source__git_show`, and `mcp__epiphany_source__read_hands_receipt`. The OpenAI/Codex spine lowers those definitions to Responses tools with `tool_choice=required` only on an initial tool-bearing request that has no prior `ToolResult`; model `function_call` output items become typed `epiphany.tool_invocation_intent.v0` documents; and the quarantined tool adapter resolves the built-in `epiphany_source` server directly under workspace-bounded read rules before falling back to Codex MCP. Live dogfood proved this path by producing one source-tool intent and one receipt. Soul should inspect source/artifacts/diffs/Hands receipt bodies through those tool receipts before returning `needs-evidence` for missing inspectability.
- Model-tool feedback now has a typed continuation seam. `EpiphanyToolInvocationIntent` preserves the exact model `call_id` plus source model request id; provider-neutral and OpenAI request documents can represent assistant `ToolCall` inputs and `ToolResult` inputs; and `epiphany-model-runtime tool-followup` builds a self-contained provider-neutral follow-up request from typed tool receipts by carrying original input, the assistant tool call, and the tool result instead of depending on provider-side `previous_response_id`. ChatGPT Codex rejected `previous_response_id`, so the live continuation invariant is explicit transcript over hidden provider memory. `epiphany-model-runtime tool-followup-turn` derives and runs that continuation through the selected provider in one runtime-owned call, and `epiphany-model-runtime run-worker --auto-tools --tool-adapter-bin <path>` loops tool execution plus follow-up model turns before completing the worker result.
- The `roles` view lens is the harness-native role ownership surface: it projects implementation, Imagination/planning, modeling/checkpoint, verification/review, and reorientation lanes from authoritative typed state, bound jobs, pressure/reorient/CRRC, and worker result status without launching, scheduling, accepting, compacting, or mutating state.
@ -203,20 +203,20 @@ 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-state-model/src/prompts/`, and modeling/Proprioception, research/Eyes, implementation/Hands, verification/Soul, reorientation/Continuity, coordinator/Self, Face/public-surface, and CRRC intervention templates in `epiphany-core/src/prompts/epiphany_specialists.toml`.
- Specialist prompts are role-distilled instead of generic and their live text is config-backed in `epiphany-core`: modeling/checkpoint is Proprioception: 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 a Continuity worker 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, Proprioception clarifies anatomy, Eyes sees earlier, Hands touches source more precisely, Soul becomes harder to fool, Continuity loses less context, Self routes repair, and Face becomes clearer at turning inner weather into useful social presence.
- Specialist self-memory now has a bounded CultCache persistence surface in `state/agents.msgpack`: Imagination, Proprioception, Eyes, Hands, Soul, Self, and Face each have an individual typed organ-state record for identity, semantic/episodic/relationship memory, goals, values, and profile classification. Work organs stay light; Face may use portable Persona state. Continuity has typed protocol receipts instead of an organ-state record. These entries are lane memory only; project truth remains in authoritative `EpiphanyThreadState`.
- `state/agent-heartbeats.msgpack`, `epiphany-core::EpiphanyHeartbeatStateEntry`, and the native `epiphany-heartbeat-store` binary are the Ghostlight-derived heartbeat initiative seam. The harness sets a target heartbeat rate; participants carry arena, participant kind, initiative speed, next-ready time, reaction bias, interrupt threshold, current load, status, constraints, personality cooldown, mood cooldown, initiative heat, active-turn freeze state, and effective cooldown; pending coordinator work can pull its owning lane through a reaction window; otherwise the earliest ready active participant wins the slot. Organ-state records set the personality baseline, appraisals bend it with mood/anxiety signals such as urgency, arousal, thought pressure, guardedness, and reaction intensity, and lower effective cooldown means the lane recovers sooner and gets the floor more often. `HeartbeatMoodTiming` now also owns the 32-axis current affect vector used by utterance state: anger, despair, sadness, fear, contempt, annoyance, dismissal, flippancy, tenderness, warmth, shame, pride, fatigue, secrecy, hesitation, emotional containment, and related speech pressures are heartbeat physiology, not decorative prompt adjectives. Initiative heat is typed heartbeat policy, not a side flag: `epiphany-heartbeat-store heat` and the CultNet `epiphany.heartbeat_heat_intent.v0` contract can set or clear global, all, agent, role, arena, participant-kind, group, and constraint multipliers, with optional scene-clock expiry. Active thinking freezes initiative explicitly: running pending turns project `initiativeFrozen` / `initiative_frozen`, are ineligible for reaction, cannot be selected again, and start cooldown only after completion. The native `pump` command computes adaptive swarm pressure from external urgency, mood/anxiety, reaction intensity, thought pressure, and current pending load; relaxed pressure can launch nothing and run at crawl tempo, while alarm pressure can fill most or all active lanes up to a configured concurrency cap without waking any lane already running. If the winner has no routeable maintenance work, it ruminates on role quality and prepares bounded selfPatch pressure rather than pretending rumination has already consolidated doctrine. Sleep/dream cycle passes are the intended distillation window for reviewed self-memory and doctrine. Face can win `surfaceAgentThoughts` or `discordAquariumChat` work slots. Epiphany also owns native character-loop projection through `epiphany-character-loop`, so organ-state records can respond to visible stimuli without importing Ghostlight as runtime. The same heartbeat store now owns the Void-derived routine fields typed `sleep_cycle`, typed `memory_resonance`, `incubation`, `thought_lanes`, `bridge`, `candidate_interventions`, typed `appraisals`, and typed `reactions` through the native `epiphany-heartbeat-store routine` command.
- 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/Modeling, research/Eyes, implementation/Hands, verification/Soul, reorientation/Continuity, coordinator/Self, Persona/public-surface, and CRRC intervention templates in `epiphany-core/src/prompts/epiphany_specialists.toml`.
- Specialist prompts are role-distilled instead of generic and their live text is config-backed in `epiphany-core`: modeling/checkpoint is Modeling: 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 a Continuity worker across compaction and source drift; coordinator is the read-only Self that routes attention without implementing, verifying, promoting, or accepting; Persona 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, Modeling clarifies anatomy, Eyes sees earlier, Hands touches source more precisely, Soul becomes harder to fool, Continuity loses less context, Self routes repair, and Persona becomes clearer at turning inner weather into useful social presence.
- Specialist self-memory now has a bounded CultCache persistence surface in `state/agents.msgpack`: Imagination, Modeling, Eyes, Hands, Soul, Self, and Persona each have an individual typed organ-state record for identity, semantic/episodic/relationship memory, goals, values, and profile classification. Work organs stay light; Persona may use portable Persona state. Continuity has typed protocol receipts instead of an organ-state record. These entries are lane memory only; project truth remains in authoritative `EpiphanyThreadState`.
- `state/agent-heartbeats.msgpack`, `epiphany-core::EpiphanyHeartbeatStateEntry`, and the native `epiphany-heartbeat-store` binary are the Ghostlight-derived heartbeat initiative seam. The harness sets a target heartbeat rate; participants carry arena, participant kind, initiative speed, next-ready time, reaction bias, interrupt threshold, current load, status, constraints, personality cooldown, mood cooldown, initiative heat, active-turn freeze state, and effective cooldown; pending coordinator work can pull its owning lane through a reaction window; otherwise the earliest ready active participant wins the slot. Organ-state records set the personality baseline, appraisals bend it with mood/anxiety signals such as urgency, arousal, thought pressure, guardedness, and reaction intensity, and lower effective cooldown means the lane recovers sooner and gets the floor more often. `HeartbeatMoodTiming` now also owns the 32-axis current affect vector used by utterance state: anger, despair, sadness, fear, contempt, annoyance, dismissal, flippancy, tenderness, warmth, shame, pride, fatigue, secrecy, hesitation, emotional containment, and related speech pressures are heartbeat physiology, not decorative prompt adjectives. Initiative heat is typed heartbeat policy, not a side flag: `epiphany-heartbeat-store heat` and the CultNet `epiphany.heartbeat_heat_intent.v0` contract can set or clear global, all, agent, role, arena, participant-kind, group, and constraint multipliers, with optional scene-clock expiry. Active thinking freezes initiative explicitly: running pending turns project `initiativeFrozen` / `initiative_frozen`, are ineligible for reaction, cannot be selected again, and start cooldown only after completion. The native `pump` command computes adaptive swarm pressure from external urgency, mood/anxiety, reaction intensity, thought pressure, and current pending load; relaxed pressure can launch nothing and run at crawl tempo, while alarm pressure can fill most or all active lanes up to a configured concurrency cap without waking any lane already running. If the winner has no routeable maintenance work, it ruminates on role quality and prepares bounded selfPatch pressure rather than pretending rumination has already consolidated doctrine. Sleep/dream cycle passes are the intended distillation window for reviewed self-memory and doctrine. Persona can win `surfaceAgentThoughts` or `discordAquariumChat` work slots. Epiphany also owns native character-loop projection through `epiphany-character-loop`, so organ-state records can respond to visible stimuli without importing Ghostlight as runtime. The same heartbeat store now owns the Void-derived routine fields typed `sleep_cycle`, typed `memory_resonance`, `incubation`, `thought_lanes`, `bridge`, `candidate_interventions`, typed `appraisals`, and typed `reactions` through the native `epiphany-heartbeat-store routine` command.
- `state/ledgers.msgpack`, `epiphany-core::EpiphanyStateLedgerEntry`, the `epiphany-state-ledger-store` binary, and the native `epiphany-state` CLI now own durable branch and evidence ledgers. The old tracked JSON ledger files and the migration/projection CLI hatches are gone.
- CultCache inspection, cross-language schema synchronization, and debug display tooling belong in CultLib, not in EpiphanyAgent. Epiphany should consume typed CultCache documents and expose product-specific status through its API, while general polyglot domain loading/inspection lives with the shared CultCache ecosystem.
- VoidBot's current routine is reference lineage only. Epiphany's native routine pass lives in Rust as `epiphany-heartbeat-store routine`: it reads typed organ-state records, projects typed memory-resonance pair documents, maintains incubation themes, runs analytic and associative cognition lanes, writes bridge syntheses/saturation/tension, produces reviewed candidate interventions, advances typed sleep/dream-cycle state, and writes an auditable routine receipt while leaving project truth and role memory mutation on their dedicated reviewed surfaces. Qdrant-backed memory vectors remain a future enhancement; the current native pass uses bounded local resonance over typed memories.
- `epiphany-character-loop` now advertises `epiphany.cognition_lanes.v0` and `epiphany.cognition_bridge.v0` in every character-turn packet, and its projection/appraisal/reaction seeds reuse the typed heartbeat cognition documents before artifact serialization. Its utterance-state projection is the Weksa/AquaSynth speech seam: typed identity, trait vectors, values, current mood, activation, 32 named affect dimensions, and a 64-float character-state vector, with episodic/semantic/relationship memories deliberately excluded. Face and future role-local actors must run an analytic lane and an associative lane, then let the bridge choose bubble, draft, finding, silence, or bounded `selfPatch`; those lanes shape attention but do not mutate project truth.
- `epiphany-character-loop` now advertises `epiphany.cognition_lanes.v0` and `epiphany.cognition_bridge.v0` in every character-turn packet, and its projection/appraisal/reaction seeds reuse the typed heartbeat cognition documents before artifact serialization. Its utterance-state projection is the Weksa/AquaSynth speech seam: typed identity, trait vectors, values, current mood, activation, 32 named affect dimensions, and a 64-float character-state vector, with episodic/semantic/relationship memories deliberately excluded. Persona and future role-local actors must run an analytic lane and an associative lane, then let the bridge choose bubble, draft, finding, silence, or bounded `selfPatch`; those lanes shape attention but do not mutate project truth.
- The Rust CultCache-compatible contract now lives in dedicated upstream `https://github.com/GameCult/cultcache-rs` and is vendored as `vendor/cultcache-rs`. Epiphany should consume it as the canonical typed MessagePack persistence seam instead of growing an embedded local copy like an unsanctioned organ.
- `state/face-discord.toml` and the native `epiphany-face-discord` binary are the Face Discord boundary. Face may interact only through #aquarium; missing or mismatched channel configuration produces candidate chat artifacts instead of posting elsewhere. When a Face has a configured persona name/avatar, posting uses the shared Discord webhook pipe so each Epiphany can speak with its own nickname and avatar without needing a separate bot identity.
- `state/void-memory.toml` and the native `epiphany-void-memory` binary are the first Void memory bridge: Epiphany can check Void's Docker Postgres state spine, query Qdrant Discord-history and source/lore vector collections through the configured Ollama embedding model, and fetch raw archive context windows from Void's Discord archive. Raw archive rows remain evidence for Face and Eyes, not public speech.
- The native `epiphany-heartbeat-store status`, the `heartbeat` block in native `epiphany-mvp-status`, and GUI actions `heartbeatStatus` / `runHeartbeat` are the first operator API surface for heartbeat initiative state and outputs. `runHeartbeat` advances one slot and emits a Discord-independent Face bubble artifact; native `epiphany-heartbeat-store pump` adaptively launches concurrent deferred turns when swarm pressure justifies it. Status reflects the backing CultCache store and latest adaptive pacing receipt so Aquarium can see whether the typed heartbeat memory is present and whether the swarm is sleeping, stirring, or alarmed.
- The native `epiphany-face-discord bubble`, the `face` block in native `epiphany-mvp-status`, and GUI action `faceBubble` are the first Aquarium bubble surface. Face can open a local chat bubble artifact even when Discord channel id/token configuration is absent.
- `state/persona-discord.toml` and the native `epiphany-persona-discord` binary are the Persona Discord boundary. Persona may interact only through #aquarium; missing or mismatched channel configuration produces candidate chat artifacts instead of posting elsewhere. When a Persona has a configured persona name/avatar, posting uses the shared Discord webhook pipe so each Epiphany can speak with its own nickname and avatar without needing a separate bot identity.
- `state/void-memory.toml` and the native `epiphany-void-memory` binary are the first Void memory bridge: Epiphany can check Void's Docker Postgres state spine, query Qdrant Discord-history and source/lore vector collections through the configured Ollama embedding model, and fetch raw archive context windows from Void's Discord archive. Raw archive rows remain evidence for Persona and Eyes, not public speech.
- The native `epiphany-heartbeat-store status`, the `heartbeat` block in native `epiphany-mvp-status`, and GUI actions `heartbeatStatus` / `runHeartbeat` are the first operator API surface for heartbeat initiative state and outputs. `runHeartbeat` advances one slot and emits a Discord-independent Persona bubble artifact; native `epiphany-heartbeat-store pump` adaptively launches concurrent deferred turns when swarm pressure justifies it. Status reflects the backing CultCache store and latest adaptive pacing receipt so Aquarium can see whether the typed heartbeat memory is present and whether the swarm is sleeping, stirring, or alarmed.
- The native `epiphany-persona-discord bubble`, the `Persona` block in native `epiphany-mvp-status`, and GUI action `PersonaBubble` are the first Aquarium bubble surface. Persona can open a local chat bubble artifact even when Discord channel id/token configuration is absent.
- `thread/epiphany/roleResult` and `thread/epiphany/roleAccept` now project optional specialist `selfPatch` requests with coordinator review through `selfPersistence`: good mutations are role-matched, bounded, evidence-grounded lane memory/goal/value/private-note updates; project truth, authority, code edits, graphs, checkpoints, planning, scratch, jobs, and raw transcripts are refused with reasons. GUI/coordinator acceptance paths apply accepted `selfPatch` requests through the native `epiphany-agent-memory-store` binary.
- Epiphany prompt doctrine is Epiphany-owned. Local instruction scope, concise progress updates, plan discipline, scoped edits, non-destructive filesystem/git behavior, focused validation, and concise honest finals remain first-class Epiphany harness discipline rather than Codex authority or prompt machinery. Good old scars are holy only after they are grafted into the right body.
- Bundled Epiphany agent prompts are parsed, rendered, and guarded against Codex-named prompt authority inside `epiphany-core`; bridge `launch.rs` is only a compatibility re-export for Codex-facing callers. Repo-birth specialist execution no longer accepts the old `codex-exec` path. Codex may provide compatible auth/model transport and quarantined app-server affordances; it must not wrap Epiphany agents in its own role, developer, collaboration-mode, or harness prompts.
@ -268,9 +268,9 @@ landed_baseline:
- Phase 6 Imagination role lane: the `roles` view lens exposes Imagination/planning, `roleLaunch` can launch the fixed `planning-synthesis-worker`, `roleResult` projects its finding, `roleAccept` applies planning-only patches with review-gated Objective Drafts, and the GUI/status tools can launch, read, and accept that lane.
- Phase 6 Aquarium graph and Rider bridge slice: the Tauri/React/WebGL Aquarium embeds the adjacent EpiphanyGraph viewer over typed graph state, native `epiphany-rider-bridge` writes Rider/source-context artifacts, Aquarium Inspect Rider surfaces those artifacts, and `integrations/rider` scaffolds the first frontend-only Rider tool-window/context-action plugin.
- Phase 6 role self-memory slice: local organ-state records live in typed CultCache `state/agents.msgpack`, specialists may request bounded `selfPatch` lane-memory mutations, coordinator review projects acceptance/refusal reasons through `selfPersistence`, and GUI/coordinator accept paths apply accepted requests with the native `epiphany-agent-memory-store` binary.
- Phase 6 Face public-surface slice: Face's typed organ-state record, Face prompt text, `state/face-discord.toml`, the native `epiphany-face-discord` persona/webhook pipe, `state/void-memory.toml`, and the native `epiphany-void-memory` bridge establish Face as the public #aquarium-only translator of Epiphany agent thought-weather, with Void-derived Discord memory/search/presentation organs but without VoidBot's moderation authority.
- Phase 6 character-loop slice: native `epiphany-character-loop` loads any role's typed organ-state record from `state/agents.msgpack`, combines it with a visible stimulus, builds typed projection/appraisal/reaction seeds from the shared heartbeat cognition structs, and emits an auditable `epiphany.character_turn_packet.v0` local projection for response, bubble, finding, silence, or bounded `selfPatch`. Face is the first intended public-surface consumer; Ghostlight is reference material, not a runtime dependency.
- Phase 6 heartbeat initiative slice: `state/agent-heartbeats.msgpack`, `epiphany-core::EpiphanyHeartbeatStateEntry`, the native `epiphany-heartbeat-store` binary, and heartbeat smoke coverage borrow Ghostlight initiative scheduling so Self, Face, Imagination, Eyes, Proprioception, Hands, and Soul compete for heartbeat slots; idle slots become bounded rumination instead of fake project work, and sleep/dream cycle passes emit Continuity protocol receipts rather than waking a Continuity persona. The live state surface now ticks/completes/pumps/applies heartbeat physiology through typed CultCache MessagePack instead of JSON or Python wrapper state. Role personality and current mood/anxiety both shape initiative recovery through personality, mood, and effective cooldown multipliers, so Hands-like work pressure and anxious high-need lanes can recover sooner without waking lanes whose previous turn is still running. Adaptive pump pressure controls tempo and concurrency: calm can launch zero and sleep slow; alarm can fill most active lanes. The same store can now initialize a `ghostlight-scene` profile for character scene turns.
- Phase 6 Persona public-surface slice: Persona's typed organ-state record, Persona prompt text, `state/persona-discord.toml`, the native `epiphany-persona-discord` persona/webhook pipe, `state/void-memory.toml`, and the native `epiphany-void-memory` bridge establish Persona as the public #aquarium-only translator of Epiphany agent thought-weather, with Void-derived Discord memory/search/presentation organs but without VoidBot's moderation authority.
- Phase 6 character-loop slice: native `epiphany-character-loop` loads any role's typed organ-state record from `state/agents.msgpack`, combines it with a visible stimulus, builds typed projection/appraisal/reaction seeds from the shared heartbeat cognition structs, and emits an auditable `epiphany.character_turn_packet.v0` local projection for response, bubble, finding, silence, or bounded `selfPatch`. Persona is the first intended public-surface consumer; Ghostlight is reference material, not a runtime dependency.
- Phase 6 heartbeat initiative slice: `state/agent-heartbeats.msgpack`, `epiphany-core::EpiphanyHeartbeatStateEntry`, the native `epiphany-heartbeat-store` binary, and heartbeat smoke coverage borrow Ghostlight initiative scheduling so Self, Persona, Imagination, Eyes, Modeling, Hands, and Soul compete for heartbeat slots; idle slots become bounded rumination instead of fake project work, and sleep/dream cycle passes emit Continuity protocol receipts rather than waking a Continuity persona. The live state surface now ticks/completes/pumps/applies heartbeat physiology through typed CultCache MessagePack instead of JSON or Python wrapper state. Role personality and current mood/anxiety both shape initiative recovery through personality, mood, and effective cooldown multipliers, so Hands-like work pressure and anxious high-need lanes can recover sooner without waking lanes whose previous turn is still running. Adaptive pump pressure controls tempo and concurrency: calm can launch zero and sleep slow; alarm can fill most active lanes. The same store can now initialize a `ghostlight-scene` profile for character scene turns.
- Phase 6 cognition-lanes/Void routine slice: native `epiphany-heartbeat-store routine` rebuilds VoidBot-style sleep, resonance, incubation, parallel analytic/associative thought lanes, bridge judgment, candidate interventions, Ghostlight-style participant-local thought appraisal, derived reactions, dream maintenance, and mood/anxiety timing inside Epiphany's heartbeat store. It now also carries Void's anti-loop organs: split `noveltyToSelf`/`noveltyToRoom`, source coverage, saturation pressure, refractory cooling, and explicit permission to let a live unsaturated thought deepen without forced novelty theater. It reads typed organ-state records from `state/agents.msgpack`, projects clustered thought state through each role's personality vectors, updates `state/agent-heartbeats.msgpack`, and emits an auditable `epiphany.void_routine.v0` receipt without importing VoidBot or granting speech/project authority. `epiphany-character-loop` also carries the same cognition lane/bridge/appraisal contract for role-local actor turns; reactions may pace, color, draft, or display behavior, but state mutation remains on reviewed `selfPatch` or project-state surfaces.
- Native runtime spine slice: `epiphany-core::EpiphanyRuntimeIdentity`, `EpiphanyRuntimeSession`, `EpiphanyRuntimeJob`, `EpiphanyRuntimeJobResult`, and `EpiphanyRuntimeEvent` plus the native `epiphany-runtime-spine` binary establish a CultCache-backed spine, native job/result lifecycle, status projection, and framed CultNet hello output so the old Codex app-server runtime can be starved down to a temporary evacuation bridge instead of remaining the throne.
- Native repo personality scout/birth-distiller packet slice: `epiphany-repo-personality` emits typed terrain reports, repo personality profiles, and role personality projections for the embodied sub-agent lanes from deterministic repo inventory and git-history scoring, then renders a birth-only Repo Personality Distiller specialist packet and prompt for review-gated initial personality quirk petitions; `epiphany-repo-personality-smoke` proves scout/project/agent-packet/status over tiny local repos.
@ -298,7 +298,7 @@ landed_baseline:
- Use `cargo run --manifest-path .\epiphany-core\Cargo.toml --bin epiphany-agent-memory-store -- smoke --store .\state\agents.msgpack` before modifying organ self-memory records or `selfPatch` persistence policy.
- Use `cargo run --manifest-path .\epiphany-core\Cargo.toml --bin epiphany-heartbeat-store -- smoke --agent-store .\state\agents.msgpack` before modifying heartbeat initiative timing, idle rumination, or role slot selection.
- Use `cargo run --manifest-path .\epiphany-core\Cargo.toml --bin epiphany-repo-personality-smoke` before modifying repo trajectory/personality terrain scoring, birth packet shape, startup-init routing, source excerpt selection, or role-specific initialization memory contracts.
- Use `cargo run --manifest-path .\epiphany-core\Cargo.toml --bin epiphany-face-discord -- smoke` before modifying Face's #aquarium posting/draft guardrails.
- Use `cargo run --manifest-path .\epiphany-core\Cargo.toml --bin epiphany-persona-discord -- smoke` before modifying Persona's #aquarium posting/draft guardrails.
- Use `cargo run --manifest-path .\epiphany-core\Cargo.toml --bin epiphany-void-memory -- smoke` and `cargo run --manifest-path .\epiphany-core\Cargo.toml --bin epiphany-void-memory -- status` before modifying Void memory bridge behavior.
- Use `cargo run --manifest-path .\epiphany-core\Cargo.toml --bin epiphany-unity-bridge-smoke` before modifying the Unity editor/runtime bridge.
- Use `cargo run --manifest-path .\epiphany-core\Cargo.toml --bin epiphany-rider-bridge-smoke` before modifying the Rider source-context bridge.
@ -379,7 +379,7 @@ current_status:
notifications. Role launch, role accept, and role-result runtime lookup now
use core `EpiphanyRoleResultRoleId` internally; app-server maps
`ThreadEpiphanyRoleId` at the request/response edge. Reorient launch
service results now use typed `EpiphanySurfaceSource`; app-server maps that
service results now use typed `Epiphanysurfacesource`; app-server maps that
to `ThreadEpiphanyReorientSource` only for the legacy response. Generic job
launch now converts protocol `ThreadEpiphanyWorkerLaunchDocument` cargo at
the app-server edge before building the core `EpiphanyJobLaunchRequest`.
@ -396,7 +396,7 @@ current_status:
while shaping the legacy JSON-RPC response. Distill response assembly now
consumes core `EpiphanyDistillInput`; the JSON-RPC distill params are
converted before policy invocation. Role/reorient result response inputs
now use core `EpiphanySurfaceSource`; role-specific legacy source enums are
now use core `Epiphanysurfacesource`; role-specific legacy source enums are
created only during response projection. Changed-field derivation now
inspects typed `EpiphanyRoleStatePatchDocument` directly instead of
converting patches back through `ThreadEpiphanyUpdatePatch` projection.
@ -489,12 +489,12 @@ current_status:
compatibility edge, builds native Epiphany operator binaries, runs status,
plan, smoke, live coordinator, or local MVP product-cycle modes, and writes
launcher artifacts under `.epiphany-run/` plus coordinator evidence under
`.epiphany-dogfood/`. `-Mode mvp` is the current Face-front-door wrapper:
it projects a typed Face character turn, writes a local Face/Aquarium
`.epiphany-dogfood/`. `-Mode mvp` is the current Persona-front-door wrapper:
it projects a typed Persona character turn, writes a local Persona/Aquarium
bubble, bootstraps a minimal local checkpoint for fresh threads, runs the
bridge-equipped coordinator loop with auto-tools, then invokes heartbeat
sleep/dream maintenance unless explicitly skipped. That bootstrap now maps
both the Face/coordinator/sleep cycle and the coordinator-to-model-runtime
both the Persona/coordinator/sleep cycle and the coordinator-to-model-runtime
transport seam, so model failures are attributed to provider/runtime
transport instead of generic missing checkpoint state.
Live plan/run/MVP modes use the workspace `state/runtime-spine.msgpack`,

View file

@ -0,0 +1,15 @@
schema_version = "epiphany.persona_discord.v0"
allowed_channel_name = "#aquarium"
allowed_channel_id_env = "EPIPHANY_PERSONA_AQUARIUM_CHANNEL_ID"
bot_token_env = "DISCORD_BOT_TOKEN"
webhook_cache_path = ".epiphany-persona/discord-webhook-cache.json"
persona_name = "Epiphany Persona"
# persona_avatar_url may be set per Persona/backend when a specific swarm avatar exists.
policy = [
"Persona may post only in #aquarium.",
"If the #aquarium channel id is missing, Persona writes candidate chat artifacts instead of posting.",
"When a Persona has a persona name/avatar, it speaks through the shared Discord webhook pipe so each Epiphany can present as itself without separate bot identities.",
"Persona must not DM, moderate, escalate, or substitute another channel.",
"Persona translates agent thought-weather; it does not leak raw transcripts, private notes, or sealed artifacts.",
]

View file

@ -1,4 +1,4 @@
# Scratch Compaction
# Scratch Compaction
Hot context, written immediately from memory before inspection.
@ -27,7 +27,7 @@ What was done:
- Read/sampled each primary repo's AGENTS/map/evidence/handoff/scratch where present and secondary AGENTS files.
- Inspected EpiphanyAgent's Ghostlight role memory schema and patch validator:
- state/agents/README.md
- state/agents/proprioception.agent-state.json
- state/agents/modeling.agent-state.json
- native epiphany-agent-memory-store binary
- Added new documentation file:
- notes/true-epiphany-memory-migration-sandbox-prompt.md
@ -36,7 +36,7 @@ Important content of the new prompt:
- It is a self-contained sandbox-agent prompt.
- It instructs the sandbox agent to produce reviewable migration artifacts under `.epiphany-imports/pseudo-repo-memory-migration-<timestamp>`.
- It explicitly forbids direct mutation by default.
- It maps adjacent repo lessons into role-specific memory targets for Self, Face, Imagination, Eyes, Proprioception, Hands, Soul, and Life.
- It maps adjacent repo lessons into role-specific memory targets for Self, Persona, Imagination, Eyes, Modeling, Hands, Soul, and Life.
- It requires source-inventory.json, distillation-report.md, role-selfpatches/*.json, review-results.json, and apply-plan.md.
- It requires each proposed memory patch to validate via native epiphany-agent-memory-store review-patch.
- It emphasizes project truth versus role memory separation.

View file

@ -18,8 +18,8 @@ source_query_instruction = "Given a source-tree, codebase, or lore question, ret
archive_path = "E:\\Projects\\VoidBot\\.voidbot\\rag\\messages.json"
policy = [
"Face may search archived Discord memory for context before speaking.",
"Persona may search archived Discord memory for context before speaking.",
"Qdrant is the semantic memory backend for Discord history and source/lore vectors.",
"Postgres is checked as the live Void state spine for jobs, audit, interaction memory, and rate limits.",
"Raw archive rows remain evidence, not public speech; Face summarizes with restraint.",
"Raw archive rows remain evidence, not public speech; Persona summarizes with restraint.",
]

View file

@ -9,7 +9,7 @@ param(
[int]$MaxSteps = 4,
[int]$TimeoutSeconds = 600,
[int]$MaxRuntimeSeconds = 180,
[string]$FaceInput = "",
[string]$PersonaInput = "",
[switch]$SkipBuild,
[switch]$AutoReview,
[switch]$SupersedeFailedResults,
@ -127,7 +127,7 @@ $coordinatorSmokeExe = Join-Path $TargetDir "debug\epiphany-mvp-coordinator-smok
$modelRuntimeExe = Join-Path $TargetDir "debug\epiphany-model-runtime.exe"
$toolAdapterExe = Join-Path $TargetDir "debug\epiphany-tool-codex-mcp-spine.exe"
$heartbeatExe = Join-Path $TargetDir "debug\epiphany-heartbeat-store.exe"
$faceExe = Join-Path $TargetDir "debug\epiphany-face-discord.exe"
$PersonaExe = Join-Path $TargetDir "debug\epiphany-persona-discord.exe"
$characterLoopExe = Join-Path $TargetDir "debug\epiphany-character-loop.exe"
$modelProvider = "openai-codex"
$operatorRunStore = Join-Path $Root ".epiphany-run\cultmesh\operator-runs.ccmp"
@ -164,7 +164,7 @@ if (-not $SkipBuild) {
"--bin", "epiphany-mvp-coordinator",
"--bin", "epiphany-mvp-coordinator-smoke",
"--bin", "epiphany-heartbeat-store",
"--bin", "epiphany-face-discord",
"--bin", "epiphany-persona-discord",
"--bin", "epiphany-character-loop",
"--bin", "epiphany-agent-telemetry",
"--bin", "epiphany-void-memory"
@ -199,7 +199,7 @@ if ($liveRuntimeMode) {
$requiredBinaries += @($modelRuntimeExe, $toolAdapterExe)
}
if ($Mode -eq "mvp") {
$requiredBinaries += @($heartbeatExe, $faceExe, $characterLoopExe)
$requiredBinaries += @($heartbeatExe, $PersonaExe, $characterLoopExe)
}
foreach ($required in $requiredBinaries) {
if (-not (Test-Path -LiteralPath $required)) {
@ -331,22 +331,22 @@ if ($Mode -eq "smoke") {
}
if ($Mode -eq "mvp") {
if ($FaceInput.Trim() -eq "") {
$FaceInput = "Operator requested the local Epiphany MVP cycle. Face should surface the swarm state, then the coordinator may continue bounded work and sleep afterward."
if ($PersonaInput.Trim() -eq "") {
$PersonaInput = "Operator requested the local Epiphany MVP cycle. Persona should surface the swarm state, then the coordinator may continue bounded work and sleep afterward."
}
$faceArtifactDir = Join-Path $dogfoodRoot "face"
$PersonaArtifactDir = Join-Path $dogfoodRoot "Persona"
$characterArtifactDir = Join-Path $dogfoodRoot "character-loop"
$faceBubblePath = Join-Path $artifactRoot "face-bubble.stdout.json"
$characterTurnPath = Join-Path $artifactRoot "face-character-turn.stdout.json"
$PersonaBubblePath = Join-Path $artifactRoot "Persona-bubble.stdout.json"
$characterTurnPath = Join-Path $artifactRoot "Persona-character-turn.stdout.json"
Invoke-Checked `
-Label "project Face character turn" `
-Label "project Persona character turn" `
-FilePath $characterLoopExe `
-Arguments @(
"turn",
"--role", "face",
"--role", "Persona",
"--agent-store", $agentStore,
"--artifact-dir", $characterArtifactDir,
"--stimulus", $FaceInput,
"--stimulus", $PersonaInput,
"--source", "epiphany/local-mvp",
"--mode", "local-mvp-front-door",
"--status", "ready",
@ -354,21 +354,21 @@ if ($Mode -eq "mvp") {
) `
-WorkingDirectory $Root `
-StdoutPath $characterTurnPath `
-StderrPath (Join-Path $artifactRoot "face-character-turn.stderr.log")
-StderrPath (Join-Path $artifactRoot "Persona-character-turn.stderr.log")
Invoke-Checked `
-Label "write Face Aquarium bubble" `
-FilePath $faceExe `
-Label "write Persona Aquarium bubble" `
-FilePath $PersonaExe `
-Arguments @(
"bubble",
"--artifact-dir", $faceArtifactDir,
"--content", $FaceInput,
"--artifact-dir", $PersonaArtifactDir,
"--content", $PersonaInput,
"--source", "epiphany/local-mvp",
"--status", "ready",
"--mood", "attentive"
) `
-WorkingDirectory $Root `
-StdoutPath $faceBubblePath `
-StderrPath (Join-Path $artifactRoot "face-bubble.stderr.log")
-StdoutPath $PersonaBubblePath `
-StderrPath (Join-Path $artifactRoot "Persona-bubble.stderr.log")
}
if ($liveRuntimeMode) {
@ -394,7 +394,7 @@ if ($liveRuntimeMode) {
$runArgs += "--supersede-failed-results"
}
if ($Mode -eq "mvp" -and $ThreadId -eq "") {
$runArgs += @("--bootstrap-local-state", "--bootstrap-objective", $FaceInput)
$runArgs += @("--bootstrap-local-state", "--bootstrap-objective", $PersonaInput)
}
if ($Mode -eq "mvp" -or $NoEphemeral) {
$runArgs += "--no-ephemeral"
@ -474,7 +474,7 @@ $summary = @"
- runtimeStore: $runtimeStore
- modelRuntimeBinary: $modelRuntimeExe
- modelProvider: $modelProvider
- faceBinary: $faceExe
- PersonaBinary: $PersonaExe
- characterLoopBinary: $characterLoopExe
- heartbeatBinary: $heartbeatExe
@ -484,7 +484,7 @@ operator snapshot, and a compact local Verse context read from CultMesh so
Aquarium/local-run can inspect the same policy/contract packet used for dynamic
prompt context. Coordinator plan/smoke/run modes still use the sealed Codex
compatibility bridge until their provider boundary is cut. MVP mode wraps that
bridge-equipped coordinator loop in the local product cycle: Face front door,
bridge-equipped coordinator loop in the local product cycle: Persona front door,
bounded swarm work, then heartbeat sleep/dream maintenance.
"@
Set-Content -LiteralPath (Join-Path $artifactRoot "README.md") -Value $summary -Encoding UTF8