Make frontier plan adoption canonical

This commit is contained in:
Meta Vens 2026-07-15 03:05:11 +01:00
commit f72228fe61
26 changed files with 2272 additions and 505 deletions

View file

@ -21,6 +21,8 @@ use epiphany_state_model::EpiphanyThreadState;
pub const EPIPHANY_IMAGINATION_ROLE_BINDING_ID: &str = "planning-synthesis-worker";
pub const EPIPHANY_IMAGINATION_OWNER_ROLE: &str = "epiphany-imagination";
pub const EPIPHANY_MIND_ROLE_BINDING_ID: &str = "mind-admission-reviewer";
pub const EPIPHANY_MIND_OWNER_ROLE: &str = "epiphany-mind-admission-review";
pub const EPIPHANY_RESEARCH_ROLE_BINDING_ID: &str = "research-source-gather-worker";
pub const EPIPHANY_RESEARCH_OWNER_ROLE: &str = "epiphany-eyes";
pub const EPIPHANY_MODELING_ROLE_BINDING_ID: &str = "modeling-checkpoint-worker";
@ -467,6 +469,32 @@ pub fn epiphany_frontier_planning_output_schema() -> serde_json::Value {
schema
}
pub fn epiphany_frontier_plan_mind_output_schema() -> serde_json::Value {
serde_json::json!({
"type": "object",
"properties": {
"roleId": {"type": "string", "const": "mindAdmissionReview"},
"verdict": {"type": "string", "minLength": 1},
"summary": {"type": "string", "minLength": 1},
"nextSafeMove": {"type": "string", "minLength": 1},
"filesInspected": {"type": "array", "items": {"type": "string"}},
"frontierPlanMindRequestId": {"type": "string", "minLength": 1},
"frontierPlanMindDecision": {
"type": "object",
"required": ["mindRequestId", "planningRequestId", "imaginationResultId", "candidateId", "candidateSha256", "decision", "rationale", "decidedAt"],
"properties": {
"mindRequestId": {"type": "string", "minLength": 1}, "planningRequestId": {"type": "string", "minLength": 1},
"imaginationResultId": {"type": "string", "minLength": 1}, "candidateId": {"type": "string", "minLength": 1},
"candidateSha256": {"type": "string", "minLength": 1}, "decision": {"type": "string", "enum": ["adopt", "refuse", "hold"]},
"rationale": {"type": "string", "minLength": 1}, "decidedAt": {"type": "string", "minLength": 1}
}, "additionalProperties": false
}
},
"required": ["roleId", "verdict", "summary", "nextSafeMove", "filesInspected", "frontierPlanMindRequestId", "frontierPlanMindDecision"],
"additionalProperties": false
})
}
pub fn epiphany_reorient_launch_output_schema() -> serde_json::Value {
serde_json::json!({
"type": "object",
@ -530,6 +558,7 @@ pub struct EpiphanySharedPromptConfig {
#[derive(Debug, serde::Deserialize)]
pub struct EpiphanyRolePromptConfig {
pub imagination: String,
pub mind: String,
pub modeling: String,
pub verification: String,
#[allow(dead_code)]
@ -613,6 +642,74 @@ pub fn build_epiphany_role_launch_request(
)
}
pub fn build_epiphany_frontier_plan_mind_launch_request(
thread_id: &str,
expected_revision: Option<u64>,
max_runtime_seconds: Option<u64>,
state: &EpiphanyThreadState,
mind_request_id: String,
) -> Result<EpiphanyJobLaunchRequest, String> {
let linked_subgoal_ids = epiphany_active_subgoal_ids(Some(state));
let linked_graph_node_ids = epiphany_active_graph_node_ids(Some(state));
let authority_scope = "epiphany.procedure.mind_admission_review";
let launch_document = EpiphanyWorkerLaunchDocument::Role(EpiphanyRoleWorkerLaunchDocument {
thread_id: thread_id.to_string(),
role_id: "mindAdmissionReview".to_string(),
state_revision: state.revision,
objective: state.objective.clone(),
dynamic_prompt_context: None,
proposal_modeling_context: None,
claim_repair_context: None,
frontier_planning_context: None,
frontier_plan_mind_context: None,
active_subgoal_id: state.active_subgoal_id.clone(),
active_subgoals: state
.subgoals
.iter()
.filter(|subgoal| Some(subgoal.id.as_str()) == state.active_subgoal_id.as_deref())
.cloned()
.collect(),
active_graph_node_ids: linked_graph_node_ids.clone(),
investigation_checkpoint: state.investigation_checkpoint.clone(),
scratch: state.scratch.clone(),
invariants: state.invariants.clone(),
graphs: Some(state.graphs.clone()),
recent_evidence: state.recent_evidence.iter().take(8).cloned().collect(),
recent_observations: state.observations.iter().take(8).cloned().collect(),
graph_frontier: state.graph_frontier.clone(),
graph_checkpoint: state.graph_checkpoint.clone(),
planning: Some(state.planning.clone()),
churn: state.churn.clone(),
});
let output_contract_id = launch_document.output_contract_id().to_string();
let organ_launch_contract = default_launch_organ_contract(
authority_scope,
launch_document.document_kind(),
&output_contract_id,
);
Ok(EpiphanyJobLaunchRequest {
expected_revision,
binding_id: EPIPHANY_MIND_ROLE_BINDING_ID.to_string(),
kind: CoreEpiphanyJobKind::Specialist,
scope: "role-scoped frontier plan judgment".to_string(),
owner_role: EPIPHANY_MIND_OWNER_ROLE.to_string(),
authority_scope: authority_scope.to_string(),
linked_subgoal_ids,
linked_graph_node_ids,
instruction: epiphany_worker_prompt(
epiphany_specialist_prompt_config().roles.mind.as_str(),
),
launch_document,
output_contract_id,
organ_launch_contract,
max_runtime_seconds,
proposal_modeling_request_id: None,
claim_repair_request_id: None,
frontier_planning_request_id: None,
frontier_plan_mind_request_id: Some(mind_request_id),
})
}
pub fn build_epiphany_role_launch_request_with_dynamic_context(
thread_id: &str,
role_id: EpiphanyRoleResultRoleId,
@ -659,6 +756,7 @@ pub fn build_epiphany_role_launch_request_with_dynamic_context(
proposal_modeling_context: None,
claim_repair_context: None,
frontier_planning_context: None,
frontier_plan_mind_context: None,
active_subgoal_id: state.active_subgoal_id.clone(),
active_subgoals: state
.subgoals
@ -702,6 +800,7 @@ pub fn build_epiphany_role_launch_request_with_dynamic_context(
proposal_modeling_request_id: None,
claim_repair_request_id: None,
frontier_planning_request_id: None,
frontier_plan_mind_request_id: None,
})
}
@ -807,6 +906,7 @@ pub fn build_epiphany_job_launch_request(
proposal_modeling_request_id: None,
claim_repair_request_id: None,
frontier_planning_request_id: None,
frontier_plan_mind_request_id: None,
}
}
@ -932,6 +1032,7 @@ mod tests {
prompts.shared.persistent_memory.as_str(),
),
("roles.imagination", prompts.roles.imagination.as_str()),
("roles.mind", prompts.roles.mind.as_str()),
("roles.modeling", prompts.roles.modeling.as_str()),
("roles.verification", prompts.roles.verification.as_str()),
("roles.research", prompts.roles.research.as_str()),
@ -981,6 +1082,42 @@ mod tests {
assert!(!prompt.contains("Heartbeat: every lane"));
}
#[test]
fn frontier_plan_mind_launch_is_a_real_prompted_role_with_strict_schema() {
let request = build_epiphany_frontier_plan_mind_launch_request(
"thread-mind",
Some(0),
Some(60),
&EpiphanyThreadState::default(),
"mind-request-1".into(),
)
.expect("Mind launch request");
assert_eq!(request.owner_role, EPIPHANY_MIND_OWNER_ROLE);
assert_eq!(request.binding_id, EPIPHANY_MIND_ROLE_BINDING_ID);
assert!(
request
.instruction
.contains("admission-review procedure serving Epiphany Mind")
);
assert_eq!(
request.frontier_plan_mind_request_id.as_deref(),
Some("mind-request-1")
);
let EpiphanyWorkerLaunchDocument::Role(document) = request.launch_document else {
panic!("Mind must use a role launch document")
};
assert_eq!(document.role_id, "mindAdmissionReview");
let schema = epiphany_frontier_plan_mind_output_schema();
assert_eq!(
schema["properties"]["roleId"]["const"],
"mindAdmissionReview"
);
assert_eq!(
schema["properties"]["frontierPlanMindDecision"]["properties"]["decision"]["enum"],
serde_json::json!(["adopt", "refuse", "hold"])
);
}
#[test]
fn modeling_schema_exposes_only_typed_authority_purposes() {
let schema = epiphany_role_launch_output_schema(EpiphanyRoleResultRoleId::Modeling);

View file

@ -47,6 +47,9 @@ fn main() -> Result<()> {
requested_at: "2026-06-02T00:00:10Z".to_string(),
contract: "Smoke intent proves Hands action starts as typed runtime-spine state."
.to_string(),
frontier_route_id: String::new(),
plan_candidate_sha256: String::new(),
plan_action: String::new(),
};
put_hands_action_intent(&store, &intent)?;

View file

@ -801,6 +801,9 @@ mod tests {
substrate_gate_grant_receipt_id: "substrate-grant-test".to_string(),
requested_at: "2026-06-02T00:00:01Z".to_string(),
contract: "Test Hands intent.".to_string(),
frontier_route_id: String::new(),
plan_candidate_sha256: String::new(),
plan_action: String::new(),
};
put_hands_action_intent(store, &intent)?;
let review = hands_action_review_for_intent(

View file

@ -853,6 +853,9 @@ fn record_hands_implementation_gate(
requested_at: requested_at.clone(),
contract: "Coordinator continuation becomes a typed Hands action intent before any file edit, command, or commit may count as implementation evidence."
.to_string(),
frontier_route_id: String::new(),
plan_candidate_sha256: String::new(),
plan_action: String::new(),
};
put_hands_action_intent(runtime_store, &intent)?;

View file

@ -1175,6 +1175,7 @@ mod tests {
frontier_modeling_request_id: String::new(),
proposal_modeling_request_id: String::new(),
claim_repair_request_id: String::new(),
frontier_plan_decision_id: String::new(),
},
)?;
let mut fresh = existing.clone();

View file

@ -138,6 +138,37 @@ fn commit_coordinator_job_launch_in_cache(
} else {
None
};
let frontier_plan_mind_launch =
if let Some(request_id) = request.frontier_plan_mind_request_id.as_deref() {
let (mind_request, planning, candidate, identity) =
validate_frontier_plan_mind_launch(cache, current_state, request, request_id)?;
let projection =
RepoFrontierPlanMindContextProjection::new(&mind_request, &planning, &candidate);
match &mut effective_launch_document {
EpiphanyWorkerLaunchDocument::Role(document) => {
if document.proposal_modeling_context.is_some()
|| document.claim_repair_context.is_some()
|| document.frontier_planning_context.is_some()
|| document.frontier_plan_mind_context.is_some()
{
return Err(anyhow!("Mind frontier decision context is exclusive"));
}
document.frontier_plan_mind_context = Some(projection);
}
EpiphanyWorkerLaunchDocument::Reorient(_) => {
return Err(anyhow!(
"reorient launch cannot carry Mind decision context"
));
}
}
let hash = format!(
"{:x}",
Sha256::digest(rmp_serde::to_vec_named(&effective_launch_document)?)
);
Some((mind_request, identity, hash))
} else {
None
};
let prepared = prepare_runtime_spine_heartbeat_job(
&cache,
RuntimeSpineHeartbeatJobOptions {
@ -163,6 +194,7 @@ fn commit_coordinator_job_launch_in_cache(
proposal_modeling_request_id: request.proposal_modeling_request_id.clone(),
claim_repair_request_id: request.claim_repair_request_id.clone(),
frontier_planning_request_id: request.frontier_planning_request_id.clone(),
frontier_plan_mind_request_id: request.frontier_plan_mind_request_id.clone(),
created_at: created_at.clone(),
},
)?;
@ -263,6 +295,31 @@ fn commit_coordinator_job_launch_in_cache(
.0,
);
}
if let Some((mind_request, identity, worker_launch_document_sha256)) = frontier_plan_mind_launch
{
let binding = RepoFrontierPlanMindLaunchBinding {
schema_version: REPO_FRONTIER_PLAN_MIND_LAUNCH_BINDING_SCHEMA_VERSION.into(),
binding_record_id: format!(
"repo-frontier-plan-mind-launch-{}",
mind_request.request_id
),
mind_request_id: mind_request.request_id,
job_id: plan.backend_job_id.clone(),
binding_id: request.binding_id.clone(),
runtime_id: identity.runtime_id,
thread_id: mind_request.thread_id,
launched_at: created_at.clone(),
worker_launch_document_sha256,
contract: REPO_FRONTIER_PLAN_MIND_LAUNCH_BINDING_CONTRACT.into(),
};
if cache
.get::<RepoFrontierPlanMindLaunchBinding>(&binding.binding_record_id)?
.is_some()
{
return Err(anyhow!("Mind request is already bound to a launch"));
}
batch.push(cache.prepare_entry(&binding.binding_record_id, &binding)?.0);
}
if request.binding_id == EPIPHANY_RESEARCH_ROLE_BINDING_ID {
let grant = substrate_gate_repo_access_grant_for_launch(
format!("substrate-grant-{}", plan.backend_job_id),
@ -295,15 +352,20 @@ pub fn plan_coordinator_job_launch(
launcher_job_id: String,
backend_job_id: String,
) -> Result<EpiphanyCoordinatorJobLaunchPlan> {
let (caller_proposal_projection, caller_repair_projection, caller_planning_projection) =
match &request.launch_document {
EpiphanyWorkerLaunchDocument::Role(document) => (
document.proposal_modeling_context.as_ref(),
document.claim_repair_context.as_ref(),
document.frontier_planning_context.as_ref(),
),
EpiphanyWorkerLaunchDocument::Reorient(_) => (None, None, None),
};
let (
caller_proposal_projection,
caller_repair_projection,
caller_planning_projection,
caller_mind_projection,
) = match &request.launch_document {
EpiphanyWorkerLaunchDocument::Role(document) => (
document.proposal_modeling_context.as_ref(),
document.claim_repair_context.as_ref(),
document.frontier_planning_context.as_ref(),
document.frontier_plan_mind_context.as_ref(),
),
EpiphanyWorkerLaunchDocument::Reorient(_) => (None, None, None, None),
};
if caller_proposal_projection.is_some() {
return Err(anyhow!(
"caller-prepopulated proposal Modeling context is forbidden; coordinator commit owns projection"
@ -319,10 +381,16 @@ pub fn plan_coordinator_job_launch(
"caller-prepopulated frontier planning context is forbidden; coordinator commit owns projection"
));
}
if caller_mind_projection.is_some() {
return Err(anyhow!(
"caller-prepopulated Mind decision context is forbidden; coordinator commit owns projection"
));
}
if [
request.proposal_modeling_request_id.is_some(),
request.claim_repair_request_id.is_some(),
request.frontier_planning_request_id.is_some(),
request.frontier_plan_mind_request_id.is_some(),
]
.into_iter()
.filter(|present| *present)
@ -330,7 +398,7 @@ pub fn plan_coordinator_job_launch(
> 1
{
return Err(anyhow!(
"proposal Modeling, claim repair, and frontier planning launches are mutually exclusive"
"specialized authority launches are mutually exclusive"
));
}
if let Some(expected) = request.expected_revision
@ -353,6 +421,10 @@ pub fn plan_coordinator_job_launch(
let mut cache = runtime_spine_cache(runtime_store)?;
cache.pull_all_backing_stores()?;
validate_frontier_planning_launch(&cache, state, request, request_id)?;
} else if let Some(request_id) = request.frontier_plan_mind_request_id.as_deref() {
let mut cache = runtime_spine_cache(runtime_store)?;
cache.pull_all_backing_stores()?;
validate_frontier_plan_mind_launch(&cache, state, request, request_id)?;
} else if request.owner_role == EPIPHANY_MODELING_OWNER_ROLE {
// Ordinary Modeling launches remain valid, but carry no proposal authority.
}
@ -410,6 +482,52 @@ pub fn plan_coordinator_job_launch(
})
}
fn validate_frontier_plan_mind_launch(
cache: &CultCache,
state: &EpiphanyThreadState,
launch: &EpiphanyJobLaunchRequest,
request_id: &str,
) -> Result<(
RepoFrontierPlanMindRequest,
RepoFrontierPlanningRequest,
RepoFrontierPlanCandidate,
EpiphanyRuntimeIdentity,
)> {
if launch.owner_role != EPIPHANY_MIND_OWNER_ROLE
|| launch.binding_id != EPIPHANY_MIND_ROLE_BINDING_ID
{
return Err(anyhow!(
"frontier plan decision may only be carried by the Mind role launch"
));
}
let request = cache
.get::<RepoFrontierPlanMindRequest>(request_id)?
.ok_or_else(|| anyhow!("Mind request does not exist"))?;
let (planning, candidate) =
crate::runtime_spine::validate_repo_frontier_plan_mind_request(cache, &request)?;
let identity = cache
.get::<EpiphanyRuntimeIdentity>(RUNTIME_IDENTITY_KEY)?
.ok_or_else(|| anyhow!("Mind launch requires runtime identity"))?;
let persisted = cache
.get::<crate::EpiphanyThreadStateEntry>(crate::THREAD_STATE_KEY)?
.ok_or_else(|| anyhow!("Mind launch requires thread state"))?;
if persisted.state()? != *state
|| request.runtime_id != identity.runtime_id
|| request.thread_id != persisted.thread_id
|| launch.launch_document.thread_id() != request.thread_id
{
return Err(anyhow!("Mind launch provenance mismatch"));
}
if cache
.get_all::<RepoFrontierPlanMindLaunchBinding>()?
.iter()
.any(|b| b.mind_request_id == request_id)
{
return Err(anyhow!("Mind request already bound"));
}
Ok((request, planning, candidate, identity))
}
fn validate_frontier_planning_launch(
cache: &CultCache,
state: &EpiphanyThreadState,
@ -891,9 +1009,97 @@ pub(crate) mod tests {
claim_repair_request_id: None,
frontier_planning_request_id: Some(planning.request_id.clone()),
frontier_plan_candidate_msgpack: Some(rmp_serde::to_vec_named(&candidate)?),
frontier_plan_mind_request_id: None,
frontier_plan_mind_decision_msgpack: None,
})
}
fn launch_frontier_mind_result(
store: &Path,
imagination_result: &EpiphanyRuntimeRoleWorkerResult,
decision: RepoFrontierPlanDecision,
suffix: &str,
) -> Result<EpiphanyRuntimeRoleWorkerResult> {
let mind_request = crate::commit_repo_frontier_plan_mind_request(
store,
&imagination_result.result_id,
"2026-07-15T09:00:05Z",
)?;
let mut cache = coordinator_acceptance_cache(store)?;
cache.pull_all_backing_stores()?;
let state = cache
.get_required::<EpiphanyThreadStateEntry>(THREAD_STATE_KEY)?
.state()?;
let launch = crate::build_epiphany_frontier_plan_mind_launch_request(
&mind_request.thread_id,
Some(state.revision),
Some(60),
&state,
mind_request.request_id.clone(),
)
.map_err(|error| anyhow!(error))?;
let job_id = format!("backend-mind-decision-{suffix}");
let plan = plan_coordinator_job_launch(
&state,
&launch,
store,
format!("launcher-mind-{suffix}"),
job_id.clone(),
)?;
commit_coordinator_job_launch(
store,
&mind_request.thread_id,
&state,
&launch,
&plan,
"2026-07-15T09:00:06Z".into(),
)?;
let payload = RepoFrontierPlanMindDecision {
mind_request_id: mind_request.request_id.clone(),
planning_request_id: mind_request.planning_request_id.clone(),
imagination_result_id: mind_request.imagination_result_id.clone(),
candidate_id: mind_request.candidate_id.clone(),
candidate_sha256: mind_request.candidate_sha256.clone(),
decision,
rationale: format!("Mind judged the exact typed candidate as {decision:?}."),
decided_at: "2026-07-15T09:00:07Z".into(),
};
let result = EpiphanyRuntimeRoleWorkerResult {
schema_version: RUNTIME_ROLE_WORKER_RESULT_SCHEMA_VERSION.into(),
result_id: format!("frontier-mind-result-{suffix}"),
job_id,
role_id: "mindAdmissionReview".into(),
verdict: format!("{decision:?}").to_lowercase(),
summary: "Judged one exact frontier plan candidate.".into(),
next_safe_move: "Coordinator may admit this immutable judgment.".into(),
checkpoint_summary: None,
scratch_summary: None,
files_inspected: Vec::new(),
frontier_node_ids: Vec::new(),
evidence_ids: vec![mind_request.request_id.clone()],
artifact_refs: Vec::new(),
open_questions: Vec::new(),
evidence_gaps: Vec::new(),
risks: Vec::new(),
state_patch_msgpack: None,
self_patch_msgpack: None,
item_error: None,
metadata: std::collections::BTreeMap::new(),
repo_model_patch_msgpack: None,
verification_request_id: None,
frontier_route_id: None,
repo_frontier_modeling_request_id: None,
proposal_modeling_request_id: None,
claim_repair_request_id: None,
frontier_planning_request_id: None,
frontier_plan_candidate_msgpack: None,
frontier_plan_mind_request_id: Some(mind_request.request_id),
frontier_plan_mind_decision_msgpack: Some(rmp_serde::to_vec_named(&payload)?),
};
put_runtime_role_worker_result(store, &result)?;
Ok(result)
}
fn research_launch(state: &EpiphanyThreadState) -> EpiphanyJobLaunchRequest {
build_epiphany_role_launch_request(
"thread-1",
@ -1428,7 +1634,7 @@ pub(crate) mod tests {
#[test]
fn frontier_planning_result_refuses_hostile_substitution_before_persistence() -> Result<()> {
let root = tempfile::tempdir()?;
for mutation in 0..9 {
for mutation in 0..10 {
let (store, state, launch, planning) =
frontier_planning_launch_fixture(root.path(), &format!("result-{mutation}"))?;
let job_id = format!("backend-result-{mutation}");
@ -1456,7 +1662,7 @@ pub(crate) mod tests {
4 => result.state_patch_msgpack = Some(vec![0]),
5 => result.self_patch_msgpack = Some(vec![0]),
6 => result.repo_model_patch_msgpack = Some(vec![0]),
_ => {
7 | 8 => {
let mut candidate = result.frontier_plan_candidate()?.unwrap();
if mutation == 7 {
candidate.frontier_item_hash = "adjacent-frontier".into();
@ -1466,6 +1672,7 @@ pub(crate) mod tests {
result.frontier_plan_candidate_msgpack =
Some(rmp_serde::to_vec_named(&candidate)?);
}
_ => result.item_error = Some("planner failed after emitting cargo".into()),
}
let before = std::fs::read(&store)?;
assert!(
@ -1478,6 +1685,573 @@ pub(crate) mod tests {
Ok(())
}
#[test]
fn mind_adopt_installs_plan_in_model_and_hands_route_copies_it() -> Result<()> {
let root = tempfile::tempdir()?;
let (store, state, launch, planning) =
frontier_planning_launch_fixture(root.path(), "mind-adopt")?;
let plan = plan_coordinator_job_launch(
&state,
&launch,
&store,
"launcher-mind-adopt".into(),
"backend-mind-adopt".into(),
)?;
commit_coordinator_job_launch(
&store,
&planning.thread_id,
&state,
&launch,
&plan,
"2026-07-15T09:00:03Z".into(),
)?;
let result =
frontier_planning_result(&planning, "backend-mind-adopt", "2026-07-15T09:00:04Z")?;
put_runtime_role_worker_result(&store, &result)?;
let mind_result =
launch_frontier_mind_result(&store, &result, RepoFrontierPlanDecision::Adopt, "adopt")?;
let before = runtime_current_repo_model(&store)?.expect("pre-Adopt model");
let mut illicit_item = before
.frontier
.iter()
.find(|item| item.id == planning.frontier_item_id)
.unwrap()
.clone();
illicit_item.recommended_next_organ = "Hands".into();
let illicit = RepoModelPatch {
patch_id: "generic-adopt-bypass".into(),
base_revision: before.model_revision,
base_hash: memory_graph_model_hash(&before)?,
applied_at: "2026-07-15T09:00:05Z".into(),
purpose: RepoModelPatchPurpose::Evolution,
operations: vec![RepoModelPatchOperation::ReviseFrontier { item: illicit_item }],
};
assert!(derive_repo_model_patch(&before, &illicit).is_err());
let decision = commit_repo_frontier_plan_decision(&store, &mind_result.result_id)?;
let retry = commit_repo_frontier_plan_decision(&store, &mind_result.result_id)?;
assert_eq!(retry, decision);
assert!(!decision.model_admission_receipt_id.is_empty());
let current = runtime_current_repo_model(&store)?.expect("admitted Adopt model");
assert_eq!(current.model_revision, before.model_revision + 1);
let item = current
.frontier
.iter()
.find(|item| item.id == planning.frontier_item_id)
.expect("adopted frontier");
assert_eq!(item.recommended_next_organ, "Hands");
let adopted = item.adopted_plan.as_ref().expect("model-owned plan");
assert_eq!(adopted.planning_request_id, planning.request_id);
assert_eq!(adopted.result_id, result.result_id);
assert_eq!(adopted.job_id, result.job_id);
assert_eq!(adopted.candidate_id, decision.candidate_id);
assert_eq!(adopted.candidate_sha256, decision.candidate_sha256);
let mut illicit_adopted_item = item.clone();
illicit_adopted_item.source_scope = vec!["different/execution-scope".into()];
let illicit_adopted_revision = RepoModelPatch {
patch_id: "generic-adopted-anatomy-mutation".into(),
base_revision: current.model_revision,
base_hash: memory_graph_model_hash(&current)?,
applied_at: "2026-07-15T09:00:06Z".into(),
purpose: RepoModelPatchPurpose::Evolution,
operations: vec![RepoModelPatchOperation::ReviseFrontier {
item: illicit_adopted_item,
}],
};
assert!(derive_repo_model_patch(&current, &illicit_adopted_revision).is_err());
let route = select_and_commit_repo_frontier_route(&store, "2026-07-15T09:00:06Z")?;
assert_eq!(route.adopted_plan.as_ref(), Some(adopted));
assert_eq!(route.source_scope, adopted.safe_paths);
let grant = crate::substrate_gate_coordinator_implementation_grant(
"adopt-hands-grant".into(),
"adopt-hands-job".into(),
adopted.safe_paths.clone(),
"2026-07-15T09:00:08Z".into(),
);
crate::put_substrate_gate_repo_access_grant_receipt(&store, &grant)?;
let intent = crate::HandsActionIntent {
schema_version: crate::HANDS_ACTION_INTENT_SCHEMA_VERSION.into(),
intent_id: "adopt-hands-intent".into(),
runtime_job_id: grant.runtime_job_id.clone(),
binding_id: grant.binding_id.clone(),
role: grant.role.clone(),
authority_scope: grant.authority_scope.clone(),
requested_action: "continueImplementation".into(),
requested_paths: adopted.safe_paths.clone(),
substrate_gate_grant_receipt_id: grant.receipt_id.clone(),
requested_at: "2026-07-15T09:00:09Z".into(),
contract: "Hands intent executes only the admitted plan.".into(),
frontier_route_id: route.route_id.clone(),
plan_candidate_sha256: adopted.candidate_sha256.clone(),
plan_action: adopted.action.clone(),
};
crate::put_hands_action_intent(&store, &intent)?;
let review = crate::hands_action_review_for_intent(
"adopt-hands-review".into(),
&intent,
"approved".into(),
vec!["patch".into(), "command".into(), "commit".into()],
vec!["Exact admitted plan binding is present.".into()],
"2026-07-15T09:00:10Z".into(),
);
crate::put_hands_action_review(&store, &review)?;
let authority = crate::RepoFrontierHandsAuthority {
schema_version: crate::REPO_FRONTIER_HANDS_AUTHORITY_SCHEMA_VERSION.into(),
authority_id: "adopt-hands-authority".into(),
route_id: route.route_id.clone(),
model_revision: route.model_revision,
model_hash: route.model_hash.clone(),
frontier_item_id: route.frontier_item_id.clone(),
frontier_item_hash: route.frontier_item_hash.clone(),
hands_intent_id: intent.intent_id.clone(),
hands_review_id: review.review_id.clone(),
substrate_grant_receipt_id: grant.receipt_id.clone(),
requested_paths: adopted.safe_paths.clone(),
granted_at: "2026-07-15T09:00:11Z".into(),
contract: crate::REPO_FRONTIER_HANDS_AUTHORITY_CONTRACT.into(),
};
crate::put_repo_frontier_hands_authority(&store, &authority)?;
let patch_receipt = crate::hands_patch_receipt_for_review(
"adopt-hands-patch".into(),
&intent,
&review,
adopted.safe_paths.clone(),
"bounded patch".into(),
"2026-07-15T09:00:12Z".into(),
);
crate::put_hands_patch_receipt(&store, &patch_receipt)?;
let wrong_command = crate::hands_command_receipt_for_review(
"adopt-hands-command-wrong".into(),
&intent,
&review,
"cargo test unrelated".into(),
"0".into(),
"stdout".into(),
"stderr".into(),
"wrong command".into(),
"2026-07-15T09:00:13Z".into(),
);
let commit_receipt = crate::hands_commit_receipt_for_review(
"adopt-hands-commit".into(),
&intent,
&review,
"abc123".into(),
"main".into(),
adopted.safe_paths.clone(),
adopted.commit_message.clone(),
"2026-07-15T09:00:14Z".into(),
);
crate::put_hands_commit_receipt(&store, &commit_receipt)?;
let hostile_request = crate::RepoFrontierVerificationRequest {
schema_version: crate::REPO_FRONTIER_VERIFICATION_REQUEST_SCHEMA_VERSION.into(),
request_id: "adopt-verification-hostile".into(),
route_id: route.route_id.clone(),
model_revision: route.model_revision,
model_hash: route.model_hash.clone(),
frontier_item_id: route.frontier_item_id.clone(),
frontier_item_hash: route.frontier_item_hash.clone(),
hands_intent_id: intent.intent_id.clone(),
hands_review_id: review.review_id.clone(),
hands_patch_receipt_id: patch_receipt.receipt_id.clone(),
hands_command_receipt_id: wrong_command.receipt_id.clone(),
hands_commit_receipt_id: commit_receipt.receipt_id.clone(),
requested_at: "2026-07-15T09:00:15Z".into(),
contract: crate::REPO_FRONTIER_VERIFICATION_REQUEST_CONTRACT.into(),
};
assert!(crate::put_repo_frontier_verification_request(&store, &hostile_request).is_err());
// Prove the whole admitted-plan nerve, not merely its neighboring joints. The
// rejected command above remains immutable evidence, while the exact planned
// command becomes the only chain Soul is allowed to verify.
let exact_command = crate::hands_command_receipt_for_review(
"adopt-hands-command-exact".into(),
&intent,
&review,
adopted.command.clone(),
"0".into(),
"stdout-exact".into(),
"stderr-exact".into(),
"exact admitted command passed".into(),
"2026-07-15T09:00:13Z".into(),
);
crate::put_hands_command_receipt(&store, &exact_command)?;
let chain =
crate::runtime_latest_hands_receipt_chain_after(&store, "2026-07-15T09:00:11Z")?
.expect("exact admitted Hands chain");
assert_eq!(chain.patch_receipt_id, patch_receipt.receipt_id);
assert_eq!(chain.command_receipt_id, exact_command.receipt_id);
assert_eq!(chain.commit_receipt_id, commit_receipt.receipt_id);
let verification_request = crate::commit_repo_frontier_verification_request_for_chain(
&store,
&chain,
"2026-07-15T09:00:17Z",
)?;
assert_eq!(verification_request.route_id, route.route_id);
let verification_result = crate::EpiphanyRuntimeRoleWorkerResult {
schema_version: crate::RUNTIME_ROLE_WORKER_RESULT_SCHEMA_VERSION.into(),
result_id: "adopt-verification-result".into(),
job_id: "adopt-verification-job".into(),
role_id: "verification".into(),
verdict: "pass".into(),
summary: "Exact adopted plan passed Soul verification.".into(),
next_safe_move: "Modeling incorporates the verdict.".into(),
checkpoint_summary: None,
scratch_summary: None,
files_inspected: adopted.safe_paths.clone(),
frontier_node_ids: vec![route.frontier_item_id.clone()],
evidence_ids: vec![verification_request.request_id.clone()],
artifact_refs: Vec::new(),
open_questions: Vec::new(),
evidence_gaps: Vec::new(),
risks: Vec::new(),
state_patch_msgpack: None,
self_patch_msgpack: None,
item_error: None,
metadata: Default::default(),
repo_model_patch_msgpack: None,
verification_request_id: Some(verification_request.request_id.clone()),
frontier_route_id: Some(route.route_id.clone()),
repo_frontier_modeling_request_id: None,
proposal_modeling_request_id: None,
claim_repair_request_id: None,
frontier_planning_request_id: None,
frontier_plan_candidate_msgpack: None,
frontier_plan_mind_request_id: None,
frontier_plan_mind_decision_msgpack: None,
};
crate::put_runtime_role_worker_result(&store, &verification_result)?;
let soul_verdict = crate::SoulVerdictReceipt {
schema_version: crate::SOUL_VERDICT_RECEIPT_SCHEMA_VERSION.into(),
receipt_id: "adopt-soul-verdict".into(),
source_result_id: verification_result.result_id.clone(),
source_job_id: verification_result.job_id.clone(),
verdict: "pass".into(),
summary: verification_result.summary.clone(),
evidence_ids: verification_result.evidence_ids.clone(),
risks: Vec::new(),
emitted_at: "2026-07-15T09:00:18Z".into(),
contract: "Soul judges the exact routed consequence chain.".into(),
verification_request_id: verification_request.request_id.clone(),
frontier_route_id: route.route_id.clone(),
};
crate::put_soul_verdict_receipt(&store, &soul_verdict)?;
let acceptance = epiphany_state_model::EpiphanyAcceptanceReceipt {
id: "adopt-verification-acceptance".into(),
result_id: verification_result.result_id.clone(),
job_id: verification_result.job_id.clone(),
binding_id: "verification-worker".into(),
surface: "roleAccept".into(),
role_id: "verification".into(),
status: "accepted".into(),
accepted_at: "2026-07-15T09:00:18Z".into(),
..Default::default()
};
let accepted_state = epiphany_state_model::EpiphanyThreadState {
revision: 1,
acceptance_receipts: vec![acceptance.clone()],
..Default::default()
};
let mut state_cache = crate::runtime_spine_cache(&store)?;
state_cache.put(
crate::THREAD_STATE_KEY,
&crate::EpiphanyThreadStateEntry::from_state("mind-adopt-thread", &accepted_state)?,
)?;
let modeling_request = crate::commit_repo_frontier_modeling_request(&store, &acceptance)?;
let pre_incorporation =
crate::runtime_current_repo_model(&store)?.expect("model before verdict incorporation");
let mut resolved_item = pre_incorporation
.frontier
.iter()
.find(|candidate| candidate.id == route.frontier_item_id)
.expect("routed adopted item before incorporation")
.clone();
let adopted_before = rmp_serde::to_vec_named(
resolved_item
.adopted_plan
.as_ref()
.expect("adopted plan before closure"),
)?;
resolved_item.status = crate::RepoFrontierStatus::Resolved;
resolved_item.updated_at = Some("2026-07-15T09:00:19Z".into());
resolved_item
.evidence_refs
.push(verification_request.request_id.clone());
resolved_item
.evidence_refs
.push(soul_verdict.receipt_id.clone());
resolved_item.evidence_refs.sort();
resolved_item.evidence_refs.dedup();
let incorporation_patch = crate::RepoModelPatch {
patch_id: "adopt-verdict-incorporation-patch".into(),
base_revision: pre_incorporation.model_revision,
base_hash: crate::memory_graph_model_hash(&pre_incorporation)?,
applied_at: "2026-07-15T09:00:19Z".into(),
purpose: crate::RepoModelPatchPurpose::IncorporateFrontierVerdict {
route_id: route.route_id.clone(),
soul_verdict_receipt_id: soul_verdict.receipt_id.clone(),
},
operations: vec![crate::RepoModelPatchOperation::ReviseFrontier {
item: resolved_item,
}],
};
let incorporation_bytes = rmp_serde::to_vec_named(&incorporation_patch)?;
let modeling_result = crate::EpiphanyRuntimeRoleWorkerResult {
schema_version: crate::RUNTIME_ROLE_WORKER_RESULT_SCHEMA_VERSION.into(),
result_id: "adopt-incorporation-result".into(),
job_id: "adopt-incorporation-job".into(),
role_id: "modeling".into(),
verdict: "checkpoint-ready".into(),
summary: "Close the verified adopted frontier.".into(),
next_safe_move: "Mind admits the exact Modeling transition.".into(),
checkpoint_summary: None,
scratch_summary: None,
files_inspected: Vec::new(),
frontier_node_ids: vec![route.frontier_item_id.clone()],
evidence_ids: vec![soul_verdict.receipt_id.clone()],
artifact_refs: Vec::new(),
open_questions: Vec::new(),
evidence_gaps: Vec::new(),
risks: Vec::new(),
state_patch_msgpack: None,
self_patch_msgpack: None,
item_error: None,
metadata: Default::default(),
repo_model_patch_msgpack: Some(incorporation_bytes.clone()),
verification_request_id: None,
frontier_route_id: None,
repo_frontier_modeling_request_id: Some(modeling_request.request_id.clone()),
proposal_modeling_request_id: None,
claim_repair_request_id: None,
frontier_planning_request_id: None,
frontier_plan_candidate_msgpack: None,
frontier_plan_mind_request_id: None,
frontier_plan_mind_decision_msgpack: None,
};
crate::put_runtime_role_worker_result(&store, &modeling_result)?;
let incorporation_review = crate::RepoModelAdmissionReview {
schema_version: crate::REPO_MODEL_ADMISSION_REVIEW_SCHEMA_VERSION.into(),
review_id: "adopt-incorporation-review".into(),
result_id: modeling_result.result_id.clone(),
job_id: modeling_result.job_id.clone(),
patch_id: incorporation_patch.patch_id.clone(),
patch_sha256: format!("{:x}", Sha256::digest(&incorporation_bytes)),
base_revision: incorporation_patch.base_revision,
base_hash: incorporation_patch.base_hash.clone(),
decision: crate::MindGatewayDecision::Accept,
evidence_ids: modeling_result.evidence_ids.clone(),
reviewed_at: "2026-07-15T09:00:20Z".into(),
contract: crate::REPO_MODEL_ADMISSION_CONTRACT.into(),
};
let incorporation = crate::commit_repo_model_admission(
&store,
&modeling_result.result_id,
&incorporation_review,
)?;
assert_eq!(incorporation.frontier_route_id, route.route_id);
assert_eq!(
incorporation.frontier_modeling_request_id,
modeling_request.request_id
);
let closed = crate::runtime_current_repo_model(&store)?.expect("closed model");
let closed_item = closed
.frontier
.iter()
.find(|candidate| candidate.id == route.frontier_item_id)
.expect("closed adopted frontier");
assert_eq!(closed_item.status, crate::RepoFrontierStatus::Resolved);
assert_eq!(
rmp_serde::to_vec_named(
closed_item
.adopted_plan
.as_ref()
.expect("plan survives closure")
)?,
adopted_before,
"verdict incorporation must preserve the adopted plan byte-for-byte"
);
let cache = coordinator_acceptance_cache(&store)?;
let admission = cache
.get::<RepoModelAdmissionReceipt>(&decision.model_admission_receipt_id)?
.expect("Adopt admission receipt");
assert_eq!(admission.frontier_plan_decision_id, decision.decision_id);
assert_eq!(admission.admitted_hash, memory_graph_model_hash(&current)?);
assert_eq!(
commit_repo_frontier_plan_decision(&store, &mind_result.result_id)?,
decision
);
Ok(())
}
#[test]
fn mind_refuse_and_hold_are_terminal_inert_receipts() -> Result<()> {
let root = tempfile::tempdir()?;
for (suffix, terminal) in [
("refuse", RepoFrontierPlanDecision::Refuse),
("hold", RepoFrontierPlanDecision::Hold),
] {
let (store, state, launch, planning) =
frontier_planning_launch_fixture(root.path(), suffix)?;
let job_id = format!("backend-{suffix}");
let plan = plan_coordinator_job_launch(
&state,
&launch,
&store,
format!("launcher-{suffix}"),
job_id.clone(),
)?;
commit_coordinator_job_launch(
&store,
&planning.thread_id,
&state,
&launch,
&plan,
"2026-07-15T09:00:03Z".into(),
)?;
let result = frontier_planning_result(&planning, &job_id, "2026-07-15T09:00:04Z")?;
put_runtime_role_worker_result(&store, &result)?;
let mind_result = launch_frontier_mind_result(&store, &result, terminal, suffix)?;
let before = std::fs::read(&store)?;
let before_model = runtime_current_repo_model(&store)?.unwrap();
let receipt = commit_repo_frontier_plan_decision(&store, &mind_result.result_id)?;
assert!(receipt.model_admission_receipt_id.is_empty());
assert_eq!(runtime_current_repo_model(&store)?.unwrap(), before_model);
assert!(select_and_commit_repo_frontier_route(&store, "2026-07-15T09:00:06Z").is_err());
assert!(std::fs::read(&store)?.len() > before.len());
assert!(
select_and_commit_repo_frontier_planning_request(&store, "2026-07-15T09:00:07Z")
.is_err()
);
}
Ok(())
}
#[test]
fn concurrent_mind_admission_retries_converge_on_one_terminal_receipt() -> Result<()> {
let root = tempfile::tempdir()?;
let (store, state, launch, planning) =
frontier_planning_launch_fixture(root.path(), "mind-race")?;
let plan = plan_coordinator_job_launch(
&state,
&launch,
&store,
"launcher-mind-race".into(),
"backend-mind-race".into(),
)?;
commit_coordinator_job_launch(
&store,
&planning.thread_id,
&state,
&launch,
&plan,
"2026-07-15T09:00:03Z".into(),
)?;
let result =
frontier_planning_result(&planning, "backend-mind-race", "2026-07-15T09:00:04Z")?;
put_runtime_role_worker_result(&store, &result)?;
let mind_result =
launch_frontier_mind_result(&store, &result, RepoFrontierPlanDecision::Adopt, "race")?;
let left_store = store.clone();
let right_store = store.clone();
let left_id = mind_result.result_id.clone();
let right_id = mind_result.result_id.clone();
let barrier = std::sync::Arc::new(std::sync::Barrier::new(2));
let left_barrier = barrier.clone();
let right_barrier = barrier.clone();
let left = std::thread::spawn(move || {
crate::runtime_spine::commit_repo_frontier_plan_decision_with_pre_cas(
left_store,
&left_id,
&move || {
left_barrier.wait();
},
)
});
let right = std::thread::spawn(move || {
crate::runtime_spine::commit_repo_frontier_plan_decision_with_pre_cas(
right_store,
&right_id,
&move || {
right_barrier.wait();
},
)
});
let outcomes = [left.join().unwrap(), right.join().unwrap()];
assert_eq!(outcomes.iter().filter(|outcome| outcome.is_ok()).count(), 2);
let mut cache = coordinator_acceptance_cache(&store)?;
cache.pull_all_backing_stores()?;
let decisions = cache
.get_all::<RepoFrontierPlanDecisionReceipt>()?
.into_iter()
.filter(|receipt| receipt.planning_request_id == planning.request_id)
.collect::<Vec<_>>();
assert_eq!(decisions.len(), 1);
let current = runtime_current_repo_model(&store)?.unwrap();
if decisions[0].decision == RepoFrontierPlanDecision::Adopt {
assert_eq!(current.model_revision, planning.model_revision + 1);
assert!(!decisions[0].model_admission_receipt_id.is_empty());
} else {
assert_eq!(current.model_revision, planning.model_revision);
assert!(decisions[0].model_admission_receipt_id.is_empty());
}
Ok(())
}
#[test]
fn immutable_mind_result_rejects_causal_substitution_and_foreign_cargo() -> Result<()> {
let root = tempfile::tempdir()?;
for mutation in 0..7 {
let suffix = format!("mind-hostile-{mutation}");
let (store, state, launch, planning) =
frontier_planning_launch_fixture(root.path(), &suffix)?;
let imagination_job = format!("backend-imagination-{suffix}");
let plan = plan_coordinator_job_launch(
&state,
&launch,
&store,
format!("launcher-imagination-{suffix}"),
imagination_job.clone(),
)?;
commit_coordinator_job_launch(
&store,
&planning.thread_id,
&state,
&launch,
&plan,
"2026-07-15T09:00:03Z".into(),
)?;
let imagination =
frontier_planning_result(&planning, &imagination_job, "2026-07-15T09:00:04Z")?;
put_runtime_role_worker_result(&store, &imagination)?;
let mut hostile = launch_frontier_mind_result(
&store,
&imagination,
RepoFrontierPlanDecision::Adopt,
&suffix,
)?;
match mutation {
0 => hostile.frontier_plan_mind_request_id = Some("swapped-request".into()),
1 => hostile.job_id = "swapped-job".into(),
2 => hostile.role_id = "imagination".into(),
3 => hostile.state_patch_msgpack = Some(vec![0]),
4 => hostile.repo_model_patch_msgpack = Some(vec![0]),
5 => {
let mut payload = hostile.frontier_plan_mind_decision()?.unwrap();
payload.candidate_sha256 = "swapped-candidate-hash".into();
hostile.frontier_plan_mind_decision_msgpack =
Some(rmp_serde::to_vec_named(&payload)?);
}
_ => hostile.item_error = Some("Mind failed after emitting judgment".into()),
}
let before = std::fs::read(&store)?;
assert!(put_runtime_role_worker_result(&store, &hostile).is_err());
assert_eq!(std::fs::read(&store)?, before);
}
Ok(())
}
#[test]
fn concurrent_frontier_planning_launches_leave_only_winner_artifacts() -> Result<()> {
let root = tempfile::tempdir()?;

View file

@ -172,6 +172,18 @@ pub fn append_verification_hands_receipt_context(
route.question,
route.gap,
));
if let Some(plan) = route.adopted_plan.as_ref() {
context.push_str(&format!(
"adoptedCandidateSha256: {}\nadoptedAction: {}\nadoptedCommand: {}\nadoptedChecks: {}\nadoptedStopConditions: {}\nadoptedRollbackSteps: {}\nadoptedCommitMessage: {}\n",
plan.candidate_sha256,
plan.action,
plan.command,
plan.checks.join(" | "),
plan.stop_conditions.join(" | "),
plan.rollback_steps.join(" | "),
plan.commit_message,
));
}
context.push_str(
"Soul is reviewing typed internal CultMesh telemetry for concrete Hands consequence evidence produced after the latest accepted Verification finding.\n",
);
@ -940,6 +952,8 @@ mod tests {
claim_repair_request_id: None,
frontier_planning_request_id: None,
frontier_plan_candidate_msgpack: None,
frontier_plan_mind_request_id: None,
frontier_plan_mind_decision_msgpack: None,
};
crate::put_runtime_role_worker_result(store, &result)?;
crate::commit_repo_model_admission(
@ -1136,6 +1150,7 @@ mod tests {
proposal_modeling_request_id: None,
claim_repair_request_id: None,
frontier_planning_request_id: None,
frontier_plan_mind_request_id: None,
created_at: "2026-06-02T00:00:00Z".to_string(),
},
)?;
@ -1250,6 +1265,9 @@ mod tests {
substrate_gate_grant_receipt_id: "substrate-grant-context".to_string(),
requested_at: "2026-06-12T00:00:01Z".to_string(),
contract: "Test Hands intent.".to_string(),
frontier_route_id: String::new(),
plan_candidate_sha256: String::new(),
plan_action: String::new(),
};
crate::put_substrate_gate_repo_access_grant_receipt(
&runtime_store,
@ -1423,6 +1441,8 @@ mod tests {
claim_repair_request_id: None,
frontier_planning_request_id: None,
frontier_plan_candidate_msgpack: None,
frontier_plan_mind_request_id: None,
frontier_plan_mind_decision_msgpack: None,
};
crate::put_runtime_role_worker_result(&runtime_store, &verification_result)?;
crate::put_soul_verdict_receipt(

View file

@ -10,7 +10,7 @@ pub const HANDS_COMMIT_RECEIPT_TYPE: &str = "epiphany.hands.commit_receipt";
pub const HANDS_PR_RECEIPT_TYPE: &str = "epiphany.hands.pr_receipt";
pub const HANDS_ROLLBACK_RECEIPT_TYPE: &str = "epiphany.hands.rollback_receipt";
pub const HANDS_ACTION_REFUSAL_RECEIPT_TYPE: &str = "epiphany.hands.action_refusal_receipt";
pub const HANDS_ACTION_INTENT_SCHEMA_VERSION: &str = "epiphany.hands.action_intent.v0";
pub const HANDS_ACTION_INTENT_SCHEMA_VERSION: &str = "epiphany.hands.action_intent.v1";
pub const HANDS_ACTION_REVIEW_SCHEMA_VERSION: &str = "epiphany.hands.action_review.v0";
pub const HANDS_COMMAND_RECEIPT_SCHEMA_VERSION: &str = "epiphany.hands.command_receipt.v0";
pub const HANDS_PATCH_RECEIPT_SCHEMA_VERSION: &str = "epiphany.hands.patch_receipt.v0";
@ -45,6 +45,12 @@ pub struct HandsActionIntent {
pub requested_at: String,
#[cultcache(key = 10)]
pub contract: String,
#[cultcache(key = 11, default)]
pub frontier_route_id: String,
#[cultcache(key = 12, default)]
pub plan_candidate_sha256: String,
#[cultcache(key = 13, default)]
pub plan_action: String,
}
#[derive(Debug, Clone, PartialEq, Eq, DatabaseEntry)]
@ -475,6 +481,9 @@ mod tests {
substrate_gate_grant_receipt_id: "substrate-grant-1".to_string(),
requested_at: "2026-06-02T00:00:00Z".to_string(),
contract: "Hands action intent is bounded by Substrate Gate.".to_string(),
frontier_route_id: String::new(),
plan_candidate_sha256: String::new(),
plan_action: String::new(),
};
let review = hands_action_review_for_intent(
"hands-review-1".to_string(),

View file

@ -37,6 +37,8 @@ mod weksa_interlingua;
pub use agent_launch::EPIPHANY_IMAGINATION_OWNER_ROLE;
pub use agent_launch::EPIPHANY_IMAGINATION_ROLE_BINDING_ID;
pub use agent_launch::EPIPHANY_MIND_OWNER_ROLE;
pub use agent_launch::EPIPHANY_MIND_ROLE_BINDING_ID;
pub use agent_launch::EPIPHANY_MODELING_OWNER_ROLE;
pub use agent_launch::EPIPHANY_MODELING_ROLE_BINDING_ID;
pub use agent_launch::EPIPHANY_REORIENT_LAUNCH_BINDING_ID;
@ -52,6 +54,7 @@ pub use agent_launch::EpiphanyReorientationPromptConfig;
pub use agent_launch::EpiphanyRolePromptConfig;
pub use agent_launch::EpiphanySharedPromptConfig;
pub use agent_launch::EpiphanySpecialistPromptConfig;
pub use agent_launch::build_epiphany_frontier_plan_mind_launch_request;
pub use agent_launch::build_epiphany_job_launch_request;
pub use agent_launch::build_epiphany_reorient_launch_instruction;
pub use agent_launch::build_epiphany_reorient_launch_request;
@ -59,6 +62,7 @@ pub use agent_launch::build_epiphany_reorient_launch_request_with_dynamic_contex
pub use agent_launch::build_epiphany_role_launch_request;
pub use agent_launch::build_epiphany_role_launch_request_with_dynamic_context;
pub use agent_launch::epiphany_agent_prompt_with_memory;
pub use agent_launch::epiphany_frontier_plan_mind_output_schema;
pub use agent_launch::epiphany_frontier_planning_output_schema;
pub use agent_launch::epiphany_reorient_launch_output_schema;
pub use agent_launch::epiphany_role_binding_id;
@ -614,6 +618,7 @@ pub use memory_graph::EpiphanyMemoryPatchCandidate;
pub use memory_graph::MEMORY_GRAPH_KEY;
pub use memory_graph::MEMORY_GRAPH_SCHEMA_VERSION;
pub use memory_graph::MEMORY_GRAPH_TYPE;
pub use memory_graph::RepoFrontierAdoptedPlan;
pub use memory_graph::RepoFrontierItem;
pub use memory_graph::RepoFrontierStatus;
pub use memory_graph::RepoMemoryGraphRefresh;
@ -780,6 +785,8 @@ pub use runtime_spine::append_runtime_event;
pub use runtime_spine::canonical_repo_frontier_plan_candidate_id;
pub use runtime_spine::clear_epiphany_job_binding_backend;
pub use runtime_spine::commit_repo_frontier_modeling_request;
pub use runtime_spine::commit_repo_frontier_plan_decision;
pub use runtime_spine::commit_repo_frontier_plan_mind_request;
pub use runtime_spine::commit_repo_frontier_verification_request_for_chain;
pub use runtime_spine::commit_repo_model_admission;
pub use runtime_spine::commit_repo_model_claim_challenge;
@ -978,6 +985,8 @@ pub use surfaces::EpiphanyTokenUsageSnapshot;
pub use surfaces::EpiphanyViewLens;
pub use surfaces::EpiphanyWorkerLaunchDocument;
pub use surfaces::REORIENT_WORKER_OUTPUT_CONTRACT_ID;
pub use surfaces::REPO_FRONTIER_PLAN_MIND_CONTEXT_CONTRACT;
pub use surfaces::REPO_FRONTIER_PLAN_MIND_CONTEXT_SCHEMA_VERSION;
pub use surfaces::REPO_FRONTIER_PLANNING_CONTEXT_CONTRACT;
pub use surfaces::REPO_FRONTIER_PLANNING_CONTEXT_SCHEMA_VERSION;
pub use surfaces::REPO_FRONTIER_PROPOSAL_MODELING_CONTEXT_CONTRACT;
@ -985,6 +994,7 @@ pub use surfaces::REPO_FRONTIER_PROPOSAL_MODELING_CONTEXT_SCHEMA_VERSION;
pub use surfaces::REPO_MODEL_CLAIM_REPAIR_CONTEXT_CONTRACT;
pub use surfaces::REPO_MODEL_CLAIM_REPAIR_CONTEXT_SCHEMA_VERSION;
pub use surfaces::ROLE_WORKER_OUTPUT_CONTRACT_ID;
pub use surfaces::RepoFrontierPlanMindContextProjection;
pub use surfaces::RepoFrontierPlanningContextProjection;
pub use surfaces::RepoFrontierProposalModelingContextProjection;
pub use surfaces::RepoModelClaimRepairContextProjection;

View file

@ -24,6 +24,7 @@ pub use epiphany_state_model::EpiphanyMemoryNodeKind;
pub use epiphany_state_model::EpiphanyMemoryPatchCandidate;
pub use epiphany_state_model::EpiphanyMemoryProfile;
pub use epiphany_state_model::EpiphanyMemorySummary;
pub use epiphany_state_model::RepoFrontierAdoptedPlan;
pub use epiphany_state_model::RepoFrontierItem;
pub use epiphany_state_model::RepoFrontierStatus;
pub use epiphany_state_model::RepoModelPatch;

View file

@ -222,6 +222,43 @@ pub fn derive_repo_model_patch(
current_hash
));
}
match &patch.purpose {
epiphany_state_model::RepoModelPatchPurpose::AdoptFrontierPlan {
planning_request_id,
result_id,
candidate_id,
} => {
if patch.operations.len() != 1 {
return Err(anyhow!(
"AdoptFrontierPlan purpose requires exactly one dedicated operation"
));
}
let RepoModelPatchOperation::AdoptFrontierPlan { adopted_plan, .. } =
&patch.operations[0]
else {
return Err(anyhow!(
"AdoptFrontierPlan purpose requires its dedicated operation"
));
};
if adopted_plan.planning_request_id != *planning_request_id
|| adopted_plan.result_id != *result_id
|| adopted_plan.candidate_id != *candidate_id
{
return Err(anyhow!(
"AdoptFrontierPlan purpose and operation provenance mismatch"
));
}
}
_ if patch.operations.iter().any(|operation| {
matches!(operation, RepoModelPatchOperation::AdoptFrontierPlan { .. })
}) =>
{
return Err(anyhow!(
"only AdoptFrontierPlan purpose may carry the dedicated adoption operation"
));
}
_ => {}
}
let mut next = current.clone();
if next
.lifecycle_receipts
@ -231,7 +268,7 @@ pub fn derive_repo_model_patch(
return Err(anyhow!("repo model patch_id has already been applied"));
}
for operation in &patch.operations {
apply_operation(&mut next, operation, &patch.applied_at)?;
apply_operation(&mut next, operation, &patch.purpose, &patch.applied_at)?;
}
next.model_revision = next
.model_revision
@ -288,6 +325,7 @@ pub fn derive_repo_model_patch(
fn apply_operation(
snapshot: &mut EpiphanyMemoryGraphSnapshot,
operation: &RepoModelPatchOperation,
purpose: &epiphany_state_model::RepoModelPatchPurpose,
applied_at: &str,
) -> Result<()> {
match operation {
@ -320,18 +358,55 @@ fn apply_operation(
.ok_or_else(|| anyhow!("cannot retire missing edge {edge_id}"))?;
edge.lifecycle = EpiphanyMemoryLifecycle::Retired;
}
RepoModelPatchOperation::UpsertFrontier { item } => insert_new(
&mut snapshot.frontier,
item.clone(),
|value| &value.id,
"frontier item",
)?,
RepoModelPatchOperation::ReviseFrontier { item } => revise(
&mut snapshot.frontier,
item.clone(),
|value| &value.id,
"frontier item",
)?,
RepoModelPatchOperation::UpsertFrontier { item } => {
if item.adopted_plan.is_some() {
return Err(anyhow!(
"generic frontier upsert cannot author an adopted plan"
));
}
insert_new(
&mut snapshot.frontier,
item.clone(),
|value| &value.id,
"frontier item",
)?
}
RepoModelPatchOperation::ReviseFrontier { item } => {
let existing = snapshot
.frontier
.iter()
.find(|existing| existing.id == item.id)
.ok_or_else(|| anyhow!("cannot revise missing frontier item {}", item.id))?;
let verdict_may_close_adopted = matches!(
purpose,
epiphany_state_model::RepoModelPatchPurpose::IncorporateFrontierVerdict { .. }
) && existing.adopted_plan.is_some()
&& item.adopted_plan == existing.adopted_plan
&& item.migration_body == existing.migration_body
&& item.question == existing.question
&& item.target_claim_ids == existing.target_claim_ids
&& item.source_scope == existing.source_scope
&& item.recommended_next_organ == existing.recommended_next_organ
&& item.dependency_item_ids == existing.dependency_item_ids
&& item.created_at == existing.created_at
&& item.retired_at == existing.retired_at
&& item.superseded_by == existing.superseded_by;
if (existing.adopted_plan.is_some() && !verdict_may_close_adopted)
|| item.adopted_plan != existing.adopted_plan
|| (existing.recommended_next_organ == "Imagination"
&& item.recommended_next_organ == "Hands")
{
return Err(anyhow!(
"generic frontier revision cannot alter adopted execution anatomy or own plan adoption"
));
}
revise(
&mut snapshot.frontier,
item.clone(),
|value| &value.id,
"frontier item",
)?
}
RepoModelPatchOperation::RetireFrontier {
item_id,
retired_at,
@ -351,6 +426,56 @@ fn apply_operation(
item.updated_at = Some(applied_at.to_string());
item.superseded_by = superseded_by.clone();
}
RepoModelPatchOperation::AdoptFrontierPlan {
frontier_item_id,
expected_frontier_item_hash,
adopted_plan,
} => {
let item = snapshot
.frontier
.iter_mut()
.find(|item| &item.id == frontier_item_id)
.ok_or_else(|| {
anyhow!("cannot adopt plan for missing frontier item {frontier_item_id}")
})?;
let current_hash = format!("{:x}", Sha256::digest(rmp_serde::to_vec_named(&*item)?));
let safe_paths_are_bounded = !adopted_plan.safe_paths.is_empty()
&& adopted_plan
.safe_paths
.windows(2)
.all(|pair| pair[0] < pair[1])
&& adopted_plan.safe_paths.iter().all(|path| {
item.source_scope.iter().any(|scope| {
path == scope
|| path
.starts_with(&format!("{}/", scope.trim_end_matches(['/', '\\'])))
})
});
if current_hash != *expected_frontier_item_hash
|| item.status != RepoFrontierStatus::Active
|| item.recommended_next_organ != "Imagination"
|| item.adopted_plan.is_some()
|| adopted_plan.planning_request_id.trim().is_empty()
|| adopted_plan.result_id.trim().is_empty()
|| adopted_plan.job_id.trim().is_empty()
|| adopted_plan.candidate_id.trim().is_empty()
|| adopted_plan.candidate_sha256.trim().is_empty()
|| adopted_plan.action.trim().is_empty()
|| adopted_plan.command.trim().is_empty()
|| adopted_plan.checks.is_empty()
|| adopted_plan.stop_conditions.is_empty()
|| adopted_plan.rollback_steps.is_empty()
|| adopted_plan.commit_message.trim().is_empty()
|| !safe_paths_are_bounded
{
return Err(anyhow!(
"frontier plan adoption requires the exact active Imagination frontier and complete bounded plan"
));
}
item.adopted_plan = Some(adopted_plan.clone());
item.recommended_next_organ = "Hands".to_string();
item.updated_at = Some(applied_at.to_string());
}
}
Ok(())
}

View file

@ -714,6 +714,60 @@ fn retiring_frontier_target_requires_resolving_frontier_in_same_patch() -> Resul
Ok(())
}
#[test]
fn verdict_incorporation_closes_adopted_frontier_without_rewriting_execution_plan() -> Result<()> {
let mut snapshot = fixture_snapshot();
let claim = snapshot.nodes[0].id.clone();
let mut item = frontier_item("adopted-work", &claim);
item.recommended_next_organ = "Hands".into();
item.adopted_plan = Some(epiphany_state_model::RepoFrontierAdoptedPlan {
planning_request_id: "planning-1".into(),
result_id: "imagination-result-1".into(),
job_id: "imagination-job-1".into(),
candidate_id: "candidate-1".into(),
candidate_sha256: "candidate-hash-1".into(),
safe_paths: item.source_scope.clone(),
action: "Implement exact bounded change".into(),
command: "cargo test --lib".into(),
checks: vec!["focused tests pass".into()],
stop_conditions: vec!["scope changes".into()],
rollback_steps: vec!["revert commit".into()],
commit_message: "Implement exact bounded change".into(),
});
snapshot.frontier = vec![item.clone()];
make_canonical(&mut snapshot, 1);
let mut resolved = item.clone();
resolved.status = RepoFrontierStatus::Resolved;
resolved.evidence_refs = vec!["verification-request-1".into(), "soul-verdict-1".into()];
resolved.updated_at = Some("2026-07-15T12:00:00Z".into());
let patch = RepoModelPatch {
patch_id: "incorporate-adopted-verdict".into(),
base_revision: snapshot.model_revision,
base_hash: memory_graph_model_hash(&snapshot)?,
applied_at: "2026-07-15T12:00:00Z".into(),
purpose: RepoModelPatchPurpose::IncorporateFrontierVerdict {
route_id: "route-1".into(),
soul_verdict_receipt_id: "soul-verdict-1".into(),
},
operations: vec![RepoModelPatchOperation::ReviseFrontier {
item: resolved.clone(),
}],
};
let next = derive_repo_model_patch(&snapshot, &patch)?;
assert_eq!(next.frontier[0].status, RepoFrontierStatus::Resolved);
assert_eq!(next.frontier[0].adopted_plan, item.adopted_plan);
let mut substituted = resolved;
substituted.adopted_plan.as_mut().unwrap().command = "cargo test unrelated".into();
let hostile = RepoModelPatch {
patch_id: "rewrite-adopted-plan".into(),
operations: vec![RepoModelPatchOperation::ReviseFrontier { item: substituted }],
..patch
};
assert!(derive_repo_model_patch(&snapshot, &hostile).is_err());
Ok(())
}
#[test]
fn memory_context_projects_frontier_prerequisites_first_under_budget() {
let mut snapshot = fixture_snapshot();

View file

@ -67,6 +67,12 @@ Heartbeat: every lane, including the Self, can be woken by the harness initiativ
'''
[roles]
mind = '''
Act as one bounded admission-review procedure serving Epiphany Mind for one frontier-plan judgment.
You are not an embodied lane, not Mind itself, not a second planner, and not an implementation worker. Mind remains persistent state and admission authority. Inspect only the exact typed review context: the immutable Imagination result, its embedded candidate, the planning request, and the current authority bindings carried there.
Choose `adopt` only when the candidate is coherent, bounded by its safe paths, executable, falsifiable through its checks, honest about stop and rollback conditions, and suitable to become canonical Hands cargo. Choose `refuse` when it is wrong or unsafe. Choose `hold` when a specific missing fact prevents judgment. Give a concrete rationale grounded in the typed candidate.
Echo every causal identifier and hash exactly. Do not emit state patches, repo-model patches, self patches, replacement plans, or authority belonging to another organ. Your immutable typed result is a judgment proposal; the admission transaction will independently replay its full causal chain before changing persistent state.
'''
imagination = '''
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.

View file

@ -7,18 +7,18 @@ pub const REPO_MODEL_ADMISSION_REVIEW_SCHEMA_VERSION: &str =
"epiphany.mind.repo_model_admission_review.v0";
pub const REPO_MODEL_ADMISSION_RECEIPT_TYPE: &str = "epiphany.mind.repo_model_admission_receipt";
pub const REPO_MODEL_ADMISSION_RECEIPT_SCHEMA_VERSION: &str =
"epiphany.mind.repo_model_admission_receipt.v3";
"epiphany.mind.repo_model_admission_receipt.v4";
pub const REPO_MODEL_MIGRATION_RECEIPT_TYPE: &str = "epiphany.mind.repo_model_migration_receipt";
pub const REPO_MODEL_MIGRATION_RECEIPT_SCHEMA_VERSION: &str =
"epiphany.mind.repo_model_migration_receipt.v0";
pub const REPO_MODEL_ADMISSION_CONTRACT: &str = "epiphany.repo_model_admission.v3";
pub const REPO_MODEL_ADMISSION_CONTRACT: &str = "epiphany.repo_model_admission.v4";
pub const REPO_MODEL_MIGRATION_CONTRACT: &str = "epiphany.repo_model_migration.v0";
pub const REPO_FRONTIER_ROUTE_TYPE: &str = "epiphany.self.repo_frontier_route";
pub const REPO_FRONTIER_ROUTE_SCHEMA_VERSION: &str = "epiphany.self.repo_frontier_route.v0";
pub const REPO_FRONTIER_ROUTE_SCHEMA_VERSION: &str = "epiphany.self.repo_frontier_route.v1";
pub const REPO_FRONTIER_HANDS_AUTHORITY_TYPE: &str = "epiphany.hands.repo_frontier_authority";
pub const REPO_FRONTIER_HANDS_AUTHORITY_SCHEMA_VERSION: &str =
"epiphany.hands.repo_frontier_authority.v0";
pub const REPO_FRONTIER_ROUTE_CONTRACT: &str = "epiphany.repo_frontier_route.v0";
pub const REPO_FRONTIER_ROUTE_CONTRACT: &str = "epiphany.repo_frontier_route.v1";
pub const REPO_FRONTIER_HANDS_AUTHORITY_CONTRACT: &str =
"epiphany.repo_frontier_hands_authority.v0";
pub const REPO_FRONTIER_MODELING_REQUEST_TYPE: &str =
@ -33,8 +33,9 @@ pub const REPO_FRONTIER_PLANNING_REQUEST_SCHEMA_VERSION: &str =
"epiphany.self.repo_frontier_planning_request.v1";
pub const REPO_FRONTIER_PLAN_CANDIDATE_SCHEMA_VERSION: &str =
"epiphany.imagination.repo_frontier_plan_candidate.v0";
pub const REPO_FRONTIER_PLAN_ADOPTION_SCHEMA_VERSION: &str =
"epiphany.mind.repo_frontier_plan_adoption.v0";
pub const REPO_FRONTIER_PLAN_DECISION_RECEIPT_SCHEMA_VERSION: &str =
"epiphany.mind.repo_frontier_plan_decision_receipt.v0";
pub const REPO_FRONTIER_PLAN_DECISION_CONTRACT: &str = "epiphany.repo_frontier_plan_decision.v0";
pub const REPO_FRONTIER_PLANNING_CONTRACT: &str = "epiphany.repo_frontier_planning.v1";
pub const REPO_FRONTIER_WORK_PROPOSAL_CONTRACT: &str =
"epiphany.repo_frontier_work_proposal.inert.v0";
@ -61,6 +62,14 @@ pub const REPO_FRONTIER_PLANNING_LAUNCH_BINDING_SCHEMA_VERSION: &str =
"epiphany.coordinator.repo_frontier_planning_launch_binding.v0";
pub const REPO_FRONTIER_PLANNING_LAUNCH_BINDING_CONTRACT: &str =
"epiphany.repo_frontier_planning_launch_binding.v0";
pub const REPO_FRONTIER_PLAN_MIND_REQUEST_SCHEMA_VERSION: &str =
"epiphany.self.repo_frontier_plan_mind_request.v0";
pub const REPO_FRONTIER_PLAN_MIND_REQUEST_CONTRACT: &str =
"epiphany.repo_frontier_plan_mind_request.v0";
pub const REPO_FRONTIER_PLAN_MIND_LAUNCH_BINDING_SCHEMA_VERSION: &str =
"epiphany.coordinator.repo_frontier_plan_mind_launch_binding.v0";
pub const REPO_FRONTIER_PLAN_MIND_LAUNCH_BINDING_CONTRACT: &str =
"epiphany.repo_frontier_plan_mind_launch_binding.v0";
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
@ -443,35 +452,111 @@ pub enum RepoFrontierPlanDecision {
#[derive(Debug, Clone, PartialEq, Eq, DatabaseEntry)]
#[cultcache(
type = "epiphany.mind.repo_frontier_plan_adoption",
schema = "RepoFrontierPlanAdoption"
type = "epiphany.self.repo_frontier_plan_mind_request",
schema = "RepoFrontierPlanMindRequest"
)]
pub struct RepoFrontierPlanAdoption {
pub struct RepoFrontierPlanMindRequest {
#[cultcache(key = 0)]
pub schema_version: String,
#[cultcache(key = 1)]
pub adoption_id: String,
pub request_id: String,
#[cultcache(key = 2)]
pub candidate_id: String,
#[cultcache(key = 3)]
pub candidate_sha256: String,
#[cultcache(key = 4)]
pub planning_request_id: String,
#[cultcache(key = 3)]
pub imagination_result_id: String,
#[cultcache(key = 4)]
pub imagination_job_id: String,
#[cultcache(key = 5)]
pub model_revision: u64,
pub candidate_id: String,
#[cultcache(key = 6)]
pub model_hash: String,
pub candidate_sha256: String,
#[cultcache(key = 7)]
pub frontier_item_id: String,
pub runtime_id: String,
#[cultcache(key = 8)]
pub frontier_item_hash: String,
pub thread_id: String,
#[cultcache(key = 9)]
pub decision: RepoFrontierPlanDecision,
pub requested_at: String,
#[cultcache(key = 10)]
pub contract: String,
}
#[derive(Debug, Clone, PartialEq, Eq, DatabaseEntry)]
#[cultcache(
type = "epiphany.coordinator.repo_frontier_plan_mind_launch_binding",
schema = "RepoFrontierPlanMindLaunchBinding"
)]
pub struct RepoFrontierPlanMindLaunchBinding {
#[cultcache(key = 0)]
pub schema_version: String,
#[cultcache(key = 1)]
pub binding_record_id: String,
#[cultcache(key = 2)]
pub mind_request_id: String,
#[cultcache(key = 3)]
pub job_id: String,
#[cultcache(key = 4)]
pub binding_id: String,
#[cultcache(key = 5)]
pub runtime_id: String,
#[cultcache(key = 6)]
pub thread_id: String,
#[cultcache(key = 7)]
pub launched_at: String,
#[cultcache(key = 8)]
pub worker_launch_document_sha256: String,
#[cultcache(key = 9)]
pub contract: String,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct RepoFrontierPlanMindDecision {
pub mind_request_id: String,
pub planning_request_id: String,
pub imagination_result_id: String,
pub candidate_id: String,
pub candidate_sha256: String,
pub decision: RepoFrontierPlanDecision,
pub rationale: String,
#[cultcache(key = 11)]
pub decided_at: String,
}
#[derive(Debug, Clone, PartialEq, Eq, DatabaseEntry)]
#[cultcache(
type = "epiphany.mind.repo_frontier_plan_decision_receipt",
schema = "RepoFrontierPlanDecisionReceipt"
)]
pub struct RepoFrontierPlanDecisionReceipt {
#[cultcache(key = 0)]
pub schema_version: String,
#[cultcache(key = 1)]
pub decision_id: String,
#[cultcache(key = 2)]
pub planning_request_id: String,
#[cultcache(key = 3)]
pub source_result_id: String,
#[cultcache(key = 4)]
pub source_job_id: String,
#[cultcache(key = 5)]
pub candidate_id: String,
#[cultcache(key = 6)]
pub candidate_sha256: String,
#[cultcache(key = 7)]
pub model_revision: u64,
#[cultcache(key = 8)]
pub model_hash: String,
#[cultcache(key = 9)]
pub frontier_item_id: String,
#[cultcache(key = 10)]
pub frontier_item_hash: String,
#[cultcache(key = 11)]
pub decision: RepoFrontierPlanDecision,
#[cultcache(key = 12)]
pub rationale: String,
#[cultcache(key = 13)]
pub decided_at: String,
#[cultcache(key = 14, default)]
pub model_admission_receipt_id: String,
#[cultcache(key = 15)]
pub contract: String,
}
@ -558,9 +643,11 @@ pub struct RepoFrontierRoute {
pub target_claim_ids: Vec<String>,
#[cultcache(key = 12)]
pub source_scope: Vec<String>,
#[cultcache(key = 13)]
pub selected_at: String,
#[cultcache(key = 13, default)]
pub adopted_plan: Option<epiphany_state_model::RepoFrontierAdoptedPlan>,
#[cultcache(key = 14)]
pub selected_at: String,
#[cultcache(key = 15)]
pub contract: String,
}
@ -674,6 +761,8 @@ pub struct RepoModelAdmissionReceipt {
pub proposal_modeling_request_id: String,
#[cultcache(key = 18, default)]
pub claim_repair_request_id: String,
#[cultcache(key = 19, default)]
pub frontier_plan_decision_id: String,
}
#[derive(Debug, Clone, PartialEq, Eq, DatabaseEntry)]

File diff suppressed because it is too large Load diff

View file

@ -252,6 +252,7 @@ mod tests {
proposal_modeling_context: None,
claim_repair_context: None,
frontier_planning_context: None,
frontier_plan_mind_context: None,
active_subgoal_id: None,
active_subgoals: Vec::new(),
active_graph_node_ids: Vec::new(),
@ -277,6 +278,7 @@ mod tests {
proposal_modeling_request_id: None,
claim_repair_request_id: None,
frontier_planning_request_id: None,
frontier_plan_mind_request_id: None,
};
let grant = substrate_gate_repo_access_grant_for_launch(
"grant-1".to_string(),

View file

@ -144,6 +144,8 @@ pub use worker_launch::EpiphanyReorientWorkerLaunchDocument;
pub use worker_launch::EpiphanyRoleWorkerLaunchDocument;
pub use worker_launch::EpiphanyWorkerLaunchDocument;
pub use worker_launch::REORIENT_WORKER_OUTPUT_CONTRACT_ID;
pub use worker_launch::REPO_FRONTIER_PLAN_MIND_CONTEXT_CONTRACT;
pub use worker_launch::REPO_FRONTIER_PLAN_MIND_CONTEXT_SCHEMA_VERSION;
pub use worker_launch::REPO_FRONTIER_PLANNING_CONTEXT_CONTRACT;
pub use worker_launch::REPO_FRONTIER_PLANNING_CONTEXT_SCHEMA_VERSION;
pub use worker_launch::REPO_FRONTIER_PROPOSAL_MODELING_CONTEXT_CONTRACT;
@ -151,6 +153,7 @@ pub use worker_launch::REPO_FRONTIER_PROPOSAL_MODELING_CONTEXT_SCHEMA_VERSION;
pub use worker_launch::REPO_MODEL_CLAIM_REPAIR_CONTEXT_CONTRACT;
pub use worker_launch::REPO_MODEL_CLAIM_REPAIR_CONTEXT_SCHEMA_VERSION;
pub use worker_launch::ROLE_WORKER_OUTPUT_CONTRACT_ID;
pub use worker_launch::RepoFrontierPlanMindContextProjection;
pub use worker_launch::RepoFrontierPlanningContextProjection;
pub use worker_launch::RepoFrontierProposalModelingContextProjection;
pub use worker_launch::RepoModelClaimRepairContextProjection;

View file

@ -38,6 +38,10 @@ pub const REPO_FRONTIER_PLANNING_CONTEXT_SCHEMA_VERSION: &str =
"epiphany.worker.repo_frontier_planning_context.v0";
pub const REPO_FRONTIER_PLANNING_CONTEXT_CONTRACT: &str =
"epiphany.repo_frontier_planning_context.v0";
pub const REPO_FRONTIER_PLAN_MIND_CONTEXT_SCHEMA_VERSION: &str =
"epiphany.worker.repo_frontier_plan_mind_context.v0";
pub const REPO_FRONTIER_PLAN_MIND_CONTEXT_CONTRACT: &str =
"epiphany.repo_frontier_plan_mind_context.v0";
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase", tag = "documentKind")]
@ -95,6 +99,8 @@ pub struct EpiphanyRoleWorkerLaunchDocument {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub frontier_planning_context: Option<RepoFrontierPlanningContextProjection>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub frontier_plan_mind_context: Option<RepoFrontierPlanMindContextProjection>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub active_subgoal_id: Option<String>,
#[serde(default)]
pub active_subgoals: Vec<EpiphanySubgoal>,
@ -301,6 +307,32 @@ impl RepoFrontierPlanningContextProjection {
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RepoFrontierPlanMindContextProjection {
pub schema_version: String,
pub contract: String,
pub request: crate::RepoFrontierPlanMindRequest,
pub planning_request: crate::RepoFrontierPlanningRequest,
pub candidate: crate::RepoFrontierPlanCandidate,
}
impl RepoFrontierPlanMindContextProjection {
pub(crate) fn new(
request: &crate::RepoFrontierPlanMindRequest,
planning_request: &crate::RepoFrontierPlanningRequest,
candidate: &crate::RepoFrontierPlanCandidate,
) -> Self {
Self {
schema_version: REPO_FRONTIER_PLAN_MIND_CONTEXT_SCHEMA_VERSION.into(),
contract: REPO_FRONTIER_PLAN_MIND_CONTEXT_CONTRACT.into(),
request: request.clone(),
planning_request: planning_request.clone(),
candidate: candidate.clone(),
}
}
}
pub fn build_reorient_job_launch_request(
input: EpiphanyReorientLaunchRequestInput<'_>,
) -> EpiphanyJobLaunchRequest {
@ -344,6 +376,7 @@ pub fn build_reorient_job_launch_request(
proposal_modeling_request_id: None,
claim_repair_request_id: None,
frontier_planning_request_id: None,
frontier_plan_mind_request_id: None,
}
}

View file

@ -974,6 +974,7 @@ mod tests {
proposal_modeling_context: None,
claim_repair_context: None,
frontier_planning_context: None,
frontier_plan_mind_context: None,
active_subgoal_id: None,
active_subgoals: Vec::new(),
active_graph_node_ids: Vec::new(),
@ -998,6 +999,7 @@ mod tests {
proposal_modeling_request_id: None,
claim_repair_request_id: None,
frontier_planning_request_id: None,
frontier_plan_mind_request_id: None,
created_at: now(),
},
)?;
@ -1060,6 +1062,7 @@ mod tests {
proposal_modeling_context: None,
claim_repair_context: None,
frontier_planning_context: None,
frontier_plan_mind_context: None,
active_subgoal_id: None,
active_subgoals: Vec::new(),
active_graph_node_ids: Vec::new(),
@ -1084,6 +1087,7 @@ mod tests {
proposal_modeling_request_id: None,
claim_repair_request_id: None,
frontier_planning_request_id: None,
frontier_plan_mind_request_id: None,
created_at: now(),
},
)?;
@ -1134,6 +1138,7 @@ mod tests {
proposal_modeling_context: None,
claim_repair_context: None,
frontier_planning_context: None,
frontier_plan_mind_context: None,
active_subgoal_id: None,
active_subgoals: Vec::new(),
active_graph_node_ids: Vec::new(),
@ -1158,6 +1163,7 @@ mod tests {
proposal_modeling_request_id: None,
claim_repair_request_id: None,
frontier_planning_request_id: None,
frontier_plan_mind_request_id: None,
created_at: now(),
},
)?;

View file

@ -1296,6 +1296,12 @@ fn worker_instructions(
fn worker_output_schema_json(document: &EpiphanyWorkerLaunchDocument) -> Result<String> {
let schema = match document {
EpiphanyWorkerLaunchDocument::Role(document) => {
if document.frontier_plan_mind_context.is_some() {
return serde_json::to_string_pretty(
&epiphany_core::epiphany_frontier_plan_mind_output_schema(),
)
.context("failed to render worker output schema");
}
let role_id = role_result_id_for_launch_role(&document.role_id)
.with_context(|| format!("unknown role launch id {:?}", document.role_id))?;
if document.frontier_planning_context.is_some() {
@ -1327,6 +1333,11 @@ fn role_result_id_for_launch_role(
fn worker_output_contract_text(document: &EpiphanyWorkerLaunchDocument) -> &'static str {
match document {
EpiphanyWorkerLaunchDocument::Role(document)
if document.frontier_plan_mind_context.is_some() =>
{
"Required Mind admission-review fields: roleId=mindAdmissionReview, verdict, summary, nextSafeMove, filesInspected, frontierPlanMindRequestId, frontierPlanMindDecision. Echo every causal identifier from the typed context exactly and choose adopt, refuse, or hold with a concrete rationale. This bounded procedure serves Mind; it is not an embodied lane and emits no patches or other organ authority."
}
EpiphanyWorkerLaunchDocument::Role(document)
if document.frontier_planning_context.is_some() =>
{
@ -1367,6 +1378,21 @@ struct RoleWorkerResultIngress {
claim_repair_request_id: Option<String>,
frontier_planning_request_id: Option<String>,
frontier_plan_candidate: Option<RepoFrontierPlanCandidateIngress>,
frontier_plan_mind_request_id: Option<String>,
frontier_plan_mind_decision: Option<RepoFrontierPlanMindDecisionIngress>,
}
#[derive(Debug, Clone, Default, serde::Deserialize)]
#[serde(rename_all = "camelCase", default)]
struct RepoFrontierPlanMindDecisionIngress {
mind_request_id: String,
planning_request_id: String,
imagination_result_id: String,
candidate_id: String,
candidate_sha256: String,
decision: Option<epiphany_core::RepoFrontierPlanDecision>,
rationale: String,
decided_at: String,
}
#[derive(Debug, Clone, Default, serde::Deserialize)]
@ -1511,6 +1537,31 @@ fn role_worker_result_from_ingress(
} else {
(None, None)
};
let (frontier_plan_mind_decision_msgpack, frontier_plan_mind_decision_error) =
if let Some(ingress) = result.frontier_plan_mind_decision.as_ref() {
if let Some(decision) = ingress.decision {
encode_optional_document(
&Some(epiphany_core::RepoFrontierPlanMindDecision {
mind_request_id: ingress.mind_request_id.trim().into(),
planning_request_id: ingress.planning_request_id.trim().into(),
imagination_result_id: ingress.imagination_result_id.trim().into(),
candidate_id: ingress.candidate_id.trim().into(),
candidate_sha256: ingress.candidate_sha256.trim().into(),
decision,
rationale: ingress.rationale.trim().into(),
decided_at: ingress.decided_at.trim().into(),
}),
"frontierPlanMindDecision",
)
} else {
(
None,
Some("frontierPlanMindDecision: missing decision".into()),
)
}
} else {
(None, None)
};
EpiphanyRuntimeRoleWorkerResult {
schema_version: epiphany_core::RUNTIME_ROLE_WORKER_RESULT_SCHEMA_VERSION.to_string(),
result_id: result_id.to_string(),
@ -1540,7 +1591,10 @@ fn role_worker_result_from_ingress(
merge_optional_errors(state_patch_error, self_patch_error),
repo_model_patch_error,
),
frontier_plan_candidate_error,
merge_optional_errors(
frontier_plan_candidate_error,
frontier_plan_mind_decision_error,
),
),
metadata: std::collections::BTreeMap::new(),
repo_model_patch_msgpack,
@ -1557,6 +1611,10 @@ fn role_worker_result_from_ingress(
result.frontier_planning_request_id.as_deref(),
),
frontier_plan_candidate_msgpack,
frontier_plan_mind_request_id: clean_optional_string(
result.frontier_plan_mind_request_id.as_deref(),
),
frontier_plan_mind_decision_msgpack,
}
}
@ -1697,6 +1755,7 @@ mod tests {
proposal_modeling_request_id: None,
claim_repair_request_id: None,
frontier_planning_request_id: None,
frontier_plan_mind_request_id: None,
};
let result = role_worker_result_from_ingress(
&launch,
@ -1761,6 +1820,7 @@ mod tests {
proposal_modeling_request_id: None,
claim_repair_request_id: None,
frontier_planning_request_id: Some("planning-request-1".into()),
frontier_plan_mind_request_id: None,
};
let result = role_worker_result_from_ingress(
&launch,
@ -1790,6 +1850,56 @@ mod tests {
Ok(())
}
#[test]
fn mind_ingress_preserves_exact_typed_judgment() -> Result<()> {
let parsed = parse_assistant_json::<RoleWorkerResultIngress>(
r#"{"roleId":"mindAdmissionReview","verdict":"adopt","summary":"bounded","nextSafeMove":"admit","filesInspected":[],"frontierPlanMindRequestId":"mind-request-1","frontierPlanMindDecision":{"mindRequestId":"mind-request-1","planningRequestId":"planning-request-1","imaginationResultId":"imagination-result-1","candidateId":"candidate-1","candidateSha256":"candidate-hash-1","decision":"adopt","rationale":"Exact candidate is bounded and falsifiable.","decidedAt":"2026-07-15T10:00:00Z"}}"#,
)?;
let launch = EpiphanyRuntimeWorkerLaunchRequest {
schema_version: epiphany_core::RUNTIME_WORKER_LAUNCH_REQUEST_SCHEMA_VERSION.into(),
job_id: "mind-job-1".into(),
binding_id: epiphany_core::EPIPHANY_MIND_ROLE_BINDING_ID.into(),
role: epiphany_core::EPIPHANY_MIND_OWNER_ROLE.into(),
authority_scope: "epiphany.procedure.mind_admission_review".into(),
instruction: "judge".into(),
output_contract_id: epiphany_core::ROLE_WORKER_OUTPUT_CONTRACT_ID.into(),
document_kind: "role".into(),
launch_document_msgpack: Vec::new(),
metadata: std::collections::BTreeMap::new(),
organ_launch_contract: epiphany_core::default_launch_organ_contract(
"epiphany.procedure.mind_admission_review",
"role",
epiphany_core::ROLE_WORKER_OUTPUT_CONTRACT_ID,
),
proposal_modeling_request_id: None,
claim_repair_request_id: None,
frontier_planning_request_id: None,
frontier_plan_mind_request_id: Some("mind-request-1".into()),
};
let result = role_worker_result_from_ingress(
&launch,
"mindAdmissionReview",
"mind-result-1",
&parsed,
Vec::new(),
);
assert_eq!(
result.frontier_plan_mind_request_id.as_deref(),
Some("mind-request-1")
);
let decision = result
.frontier_plan_mind_decision()?
.expect("typed Mind decision");
assert_eq!(
decision.decision,
epiphany_core::RepoFrontierPlanDecision::Adopt
);
assert_eq!(decision.candidate_sha256, "candidate-hash-1");
assert!(result.state_patch_msgpack.is_none());
assert!(result.repo_model_patch_msgpack.is_none());
Ok(())
}
fn test_openai_event(
request_id: &str,
sequence: u64,
@ -1965,6 +2075,7 @@ mod tests {
proposal_modeling_context: None,
claim_repair_context: None,
frontier_planning_context: None,
frontier_plan_mind_context: None,
active_subgoal_id: None,
active_subgoals: Vec::new(),
active_graph_node_ids: Vec::new(),
@ -1987,8 +2098,9 @@ mod tests {
epiphany_core::ROLE_WORKER_OUTPUT_CONTRACT_ID,
),
proposal_modeling_request_id: None,
claim_repair_request_id: None,
frontier_planning_request_id: None,
claim_repair_request_id: None,
frontier_planning_request_id: None,
frontier_plan_mind_request_id: None,
created_at: now(),
},
)?;
@ -2096,6 +2208,7 @@ mod tests {
proposal_modeling_context: None,
claim_repair_context: None,
frontier_planning_context: None,
frontier_plan_mind_context: None,
active_subgoal_id: None,
active_subgoals: Vec::new(),
active_graph_node_ids: Vec::new(),
@ -2120,6 +2233,7 @@ mod tests {
proposal_modeling_request_id: None,
claim_repair_request_id: None,
frontier_planning_request_id: None,
frontier_plan_mind_request_id: None,
created_at: now(),
},
)?;

View file

@ -778,6 +778,12 @@ pub struct RepoFrontierItem {
#[ts(type = "Array<string>")]
pub source_scope: Vec<String>,
pub recommended_next_organ: String,
/// The exact plan admitted by Mind for this frontier item. Imagination may
/// propose this payload, but only the dedicated model transition may make
/// it part of Modeling-owned truth.
#[serde(default, skip_serializing_if = "Option::is_none")]
#[ts(type = "RepoFrontierAdoptedPlan | null")]
pub adopted_plan: Option<RepoFrontierAdoptedPlan>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
#[ts(type = "Array<string>")]
pub dependency_item_ids: Vec<String>,
@ -800,6 +806,30 @@ pub struct RepoFrontierItem {
pub superseded_by: Option<String>,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema, TS, Default)]
pub struct RepoFrontierAdoptedPlan {
pub planning_request_id: String,
pub result_id: String,
pub job_id: String,
pub candidate_id: String,
pub candidate_sha256: String,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
#[ts(type = "Array<string>")]
pub safe_paths: Vec<String>,
pub action: String,
pub command: String,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
#[ts(type = "Array<string>")]
pub checks: Vec<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
#[ts(type = "Array<string>")]
pub stop_conditions: Vec<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
#[ts(type = "Array<string>")]
pub rollback_steps: Vec<String>,
pub commit_message: String,
}
#[derive(Serialize, Deserialize, Clone, Copy, Debug, PartialEq, Eq, JsonSchema, TS, Default)]
#[serde(rename_all = "snake_case")]
#[ts(rename_all = "snake_case")]
@ -836,6 +866,11 @@ pub enum RepoModelPatchPurpose {
soul_verdict_receipt_id: String,
},
RepairClaim,
AdoptFrontierPlan {
planning_request_id: String,
result_id: String,
candidate_id: String,
},
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema, TS)]
@ -873,6 +908,11 @@ pub enum RepoModelPatchOperation {
#[serde(default, skip_serializing_if = "Option::is_none")]
superseded_by: Option<String>,
},
AdoptFrontierPlan {
frontier_item_id: String,
expected_frontier_item_hash: String,
adopted_plan: RepoFrontierAdoptedPlan,
},
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema, TS)]

View file

@ -45,6 +45,11 @@ embodiment titles, role-memory diaries, or Persona state.
- Body is sensed and changed; it does not decide.
- Mind admits durable state; it is not a chatty lane.
- Mind may invoke a bounded, stateless admission-review procedure when a typed
proposal requires model judgment. That procedure serves Mind; it is not an
embodied sub-agent, has no heartbeat or lane memory, cannot `roleAccept` or
`selfPatch`, and its immutable judgment has no consequence until Mind replays
the causal chain and admits it.
- Continuity preserves/rebuilds context across rupture; it is protocol
machinery, not an embodied identity.
- Substrate Gate grants substrate access; it does not inspect evidence, mutate

View file

@ -982,3 +982,54 @@ missing/adjacent/escaped candidate, wrong role, generic patch smuggling, exact
retry, and immutable collision checks pass. Next implement Mind-only terminal
decision plus the dedicated Adopt RepoModel transition from Imagination to
Hands, then delete the old internal candidate/adoption fixture writers.
## Prompted frontier admission review and canonical adoption (2026-07-15)
The repo-frontier planning nerve is complete and the preceding “Next implement
Mind” sentence is superseded. Self binds one exact admitted model/frontier
request; coordinator atomically binds the Imagination launch; Imagination
persists one immutable result with its sole embedded candidate; the runtime
derives a CAS-bound Mind review request; coordinator atomically launches a
bounded non-embodied admission-review procedure; that procedure returns one
immutable typed Adopt/Refuse/Hold judgment; and Mind's admission transaction
replays the entire chain before consequence.
Refuse and Hold are inert terminal receipts. Adopt atomically installs the exact
candidate and provenance on the canonical frontier, emits specialized review
and admission receipts, and alone changes Imagination to Hands. Self derives the
route from that model. Hands intent binds route, candidate hash, plan action,
and safe paths; Soul admission requires the exact plan command and receives the
checks, stop conditions, rollback steps, and commit message. Modeling may close
the frontier after Soul verdict only while preserving adopted execution anatomy.
There is no standalone candidate/adoption truth and no caller-authored decision.
Mind remains persistent state and admission authority, not an embodied chatty
lane. The prompted model call is explicitly a bounded admission-review
procedure serving Mind, with no heartbeat, lane memory, `roleAccept`,
`selfPatch`, or foreign organ patch mouths.
Hostile coverage includes swapped causal ids/hashes/jobs, failed worker output,
foreign cargo, duplicate/racing launch and terminal claims, generic adoption
bypass, post-adoption execution-anatomy mutation, and same-path command
substitution. The composed happy path proves Adopt through exact Hands command,
Verification/Soul, accepted Modeling incorporation, Resolved closure, and
byte-identical plan survival. Final proof: core 330 passed with one intentional
cross-process helper ignored; OpenAI runtime library 10 passed, both runtime
binary suites passed 6 each, and all core binaries check. Soul's final landing
audit passed. Exact concurrent admission retries are forced through a two-party
pre-CAS barrier in test builds; the loser reloads and authenticates the winner's
entire immutable decision/admission chain. The synchronization hook is compiled
only for tests, so production exposes no executable seam at the commit boundary.
The next organ is the production semantic index over typed graph claims so
Modeling owns a live persistent searchable Body map instead of making Hands
rediscover the repository.
The selected semantic substrate is Qdrant: available locally in Docker and
intended on the new Yggdrasil host (64 GB RAM, GTX 1080 for embedding/model
workers). It is a rebuildable projection, never canonical Mind or Modeling
truth. CultCache/CultMesh remains authoritative. Use separate typed Mind and
Modeling namespaces/collections or equivalently hard query partitions so
private doctrine/memory cannot leak into Hands Body retrieval and repository
claims cannot silently become doctrine. Every point must retain source document
id, schema version, canonical hash, provenance, authority/visibility scope, and
embedding-model version.

View file

@ -1,87 +1,77 @@
# Repo Frontier Planning Authority Map
## Current state
## Current authority
The planning family now has a real Self-to-Imagination launch artery. Self's
`RepoFrontierPlanningRequest` binds the uniquely admitted current model, exact
actionable frontier, runtime, and authoritative thread. Coordinator commit
replays those bytes, injects the exact typed Imagination projection, and
atomically persists a request-keyed launch binding whose hash covers the stored
worker launch document. Caller-authored projections, mixed authority carriers,
stale requests, causal substitutions, and duplicate/racing launches are
refused without loser artifacts.
Imagination's output is now a v2 immutable runtime result with an exclusive
planning-request echo and one dedicated canonical MessagePack candidate. Result
persistence replays the current request, launch binding, stored launch bytes,
projection, runtime/thread, model, admission, frontier, candidate identity, and
safe-path scope before its absent-only write. Generic state, Self, RepoModel,
Verification, and Modeling authority cargo are forbidden on this path. The
candidate remains inside the immutable result until Mind admission; no
independent candidate writer participates in production.
The downstream nerve is still incomplete. Mind has no correlated admission;
the old internal candidate/adoption fixture writers still exist for the legacy
test chain; and Adopt still changes no RepoModel bytes or Hands truth.
The public candidate/adoption writers remain removed. The existing internal
functions are test scaffolding only and die when result correlation and Mind
admission replace them.
## Target authority
- Owner — Self selects one dependency-ready, unchallenged, active Imagination
frontier from the uniquely admitted current RepoModel and emits one immutable
planning request.
- Inputs — current RepoModel envelope and hash, its unique Mind admission
receipt, exact frontier item and serialized hash, source scope, current claim
challenges, runtime identity, and authoritative thread.
- Coordinator output — one typed Imagination context projection and one
request-keyed immutable launch binding inside the atomic coordinator launch
transaction.
- Imagination output — one immutable worker result that exclusively echoes the
planning request and contains one typed candidate. It proposes; it does not
route Hands or mutate RepoModel.
- Mind output — one fully correlated Adopt, Refuse, or Hold receipt. Mind alone
constructs and persists the decision after replaying request, launch binding,
worker launch document, immutable result, candidate, current model, and exact
frontier bytes.
- Adopt effect — a narrow RepoModel transition must make the selected frontier
executable without allowing the adoption receipt to become a shadow model.
The downstream Hands route remains derived from admitted model bytes and may
reference the exact adopted plan for bounded action/check/rollback cargo.
- Refuse/Hold effect — immutable decision receipts only. They do not mutate the
model, claim the deterministic Adopt identity, or grant Hands authority.
- Self selects one dependency-ready, unchallenged, active Imagination frontier
from the uniquely admitted current RepoModel. It writes one immutable
`RepoFrontierPlanningRequest` binding the model revision/hash, admission,
frontier bytes, source scope, runtime, and thread.
- Coordinator commit replays that request, injects the exact typed Imagination
projection, and atomically writes a request-keyed launch binding whose hash
covers the stored worker launch document.
- Imagination writes one immutable runtime result with an exclusive planning
request echo and one embedded canonical `RepoFrontierPlanCandidate`. It does
not route Hands or mutate RepoModel.
- The runtime derives one `RepoFrontierPlanMindRequest` from the immutable
Imagination result and candidate hash. Its insert is CAS-bound to the exact
current model envelope.
- Coordinator commit launches one bounded, non-embodied admission-review
procedure serving Mind. It injects the exact request/planning/candidate
projection and atomically writes the request-keyed launch binding. This
procedure is not an embodied Mind lane; Mind remains persistent state and
admission authority.
- The admission reviewer writes one immutable typed Adopt, Refuse, or Hold
judgment. Result persistence replays the request, both worker results, both
launch bindings, stored launch bytes, runtime/thread, candidate identity, and
current model/frontier while rejecting foreign organ cargo.
- `commit_repo_frontier_plan_decision` consumes only that immutable review
result. Refuse and Hold write one inert terminal receipt. Adopt atomically
writes the next canonical RepoModel, its specialized Mind review/admission,
and the terminal decision receipt.
- The dedicated Adopt transition installs the exact candidate cargo and
provenance on `RepoFrontierItem.adopted_plan` and alone changes
Imagination to Hands. Generic frontier writers cannot author or rewrite it.
- Self derives the Hands route from the admitted model. The route copies the
exact plan and safe paths; Hands intent binds route, candidate hash, and plan
action; verification requires the exact admitted command and shows Soul the
checks, stop conditions, rollback steps, and commit message.
- Modeling may incorporate Soul's verdict by changing lifecycle/gap/evidence
fields while preserving the adopted execution anatomy byte-for-byte.
## Derived state
- Planning readiness is derived from current admitted model plus absence of a
current terminal Mind decision.
- Planning readiness is current admitted Imagination frontier plus absence of a
terminal decision receipt.
- Candidate visibility is a projection of the immutable Imagination result.
- Hands readiness is derived from the post-Adopt admitted model and its exact
plan provenance, never from a candidate or adoption document alone.
- Hands readiness and execution cargo derive only from the post-Adopt canonical
model, never from a candidate or decision shadow store.
- Completion remains Soul verdict followed by Modeling verdict incorporation;
adoption is not completion.
## Forbidden writers and substitutions
- No external or generic caller may persist an Imagination candidate or Mind
decision directly.
- Generic Imagination `statePatch.planning.objective_drafts` is not repo
frontier planning authority.
- Schema namespace, prompt prose, result metadata, evidence coincidence, or
"the only current request" cannot substitute for an exact request echo and
launch binding.
- Adopt cannot merely suppress future planning while leaving the frontier and
Hands route unchanged.
- Candidate persistence must share a CAS with the current model expectation;
validation followed by an unrelated absent-only insert is stale-authority
leakage.
- No generic work-order registry or mode router. This is one explicit organ
nerve with one owner at each transition.
- No standalone candidate or adoption store exists in the production path.
- No caller supplies Mind's decision, rationale, or timestamp.
- No prompted admission reviewer may emit state, Self, RepoModel, Verification,
Modeling, or implementation authority cargo.
- Prompt prose, namespaces, metadata, evidence coincidence, or “the current
request” cannot substitute for exact typed echoes and launch bindings.
- Generic Upsert/Revise cannot create an adopted plan or perform
Imagination-to-Hands. Verdict incorporation cannot rewrite execution anatomy.
- Same-path Hands work cannot substitute a different action, candidate, or
command while retaining route authority.
- Mind is not a chatty embodied lane. The bounded admission-review procedure
serves Mind and has no heartbeat, lane memory, `roleAccept`, or `selfPatch`.
## Deletion line before build
## Verification layer
1. Public candidate/adoption persistence exports are gone.
2. Direct internal fixture writers die when result correlation and Mind
admission land.
3. Any Adopt path that does not change the model or downstream executable
truth is removed rather than retained as compatibility behavior.
- Hostile proofs cover stale/swapped model, frontier, request, result, job,
launch binding, projection, candidate hash, escaped paths, failed worker
output, foreign cargo, duplicate/racing launches, competing terminal writes,
generic adoption bypass, post-adoption anatomy mutation, and same-path command
substitution.
- Exact retry authenticates immutable terminal decision plus its historical
review/admission chain without requiring later canonical model revisions to
remain frozen.
- The next organ is the production semantic index over typed graph claims so
Modeling can maintain a live persistent searchable Body map.

Binary file not shown.

View file

@ -714,4 +714,4 @@ current_status:
- Service lifecycle receipt history is now event-only: `load_epiphany_cultmesh_daemon_service_lifecycle_receipts` filters out the `epiphany-local/daemon-service-lifecycle-receipt/latest` mirror, while `load_latest_epiphany_cultmesh_daemon_service_lifecycle_receipt` remains the latest-state reader. Focused unit test `service_lifecycle_receipt_history_excludes_latest_mirror` proves two per-receipt writes return exactly two history records and latest points at the second. Fresh smoke `verse-query-lifecycle-history-filter-smoke` and live overview/triage `local-20260618-145632-497-efac6f0d` / `local-20260618-145632-321-867947af` prove compact swarm sights still expose service lifecycle attention plus the present elevated runbook artifact without daemon pokes or service mutation. Do not use a broad unscoped cargo test filter for this check on Windows; it fans out across bin harnesses and hit a broken pipe during this pass.
- `epiphany-verse-query seed-compact` is the compact seed receipt for wrappers and read-only rites. The older `seed` command still prints the full local Verse context for explicit debugging, but compact wrapper modes now avoid full `seed`/final `query` readback after the combined overview proof exposed Windows debug stack overflow from full-context serialization pressure.
last_completed_repo_swarm_cut: Huginn live-fire has crossed the first real repo Body from Persona pressure to branch-local Hands commit and Soul/Mind closure, and now has repeatable closure and redacted-public-proof mouths. On `E:\Projects\Huginn` branch `epiphany/huginn/first-awakening`, `tools/epiphany_local_run.ps1 -Mode repo-persona-intake` accepted item `huginn-inspection-readback-livefire`, Weksa/Persona intake remained sealed, and `epiphany-work derive-plan` lowered it to model-authored safe family `repo.status_section` for `README.md` only. `tools/epiphany_local_run.ps1 -Mode repo-swarm-run` advanced four bounded pulses: run-from-plan, adopt-from-plan, execute-from-plan, and close-from-execute. Huginn commit `e9b07c38fceabbdc89ea35c2156326c80c0393a2` updated only `README.md`; closure receipt `.epiphany\work\work-close-huginn-inspection-readback-livefire.json` records status `closed`, Soul verdict `passed`, Mind state commit `repo-work-close-huginn-inspection-readback-livefire-mind-commit`, safe family `repo.status_section`, path scope `README.md`, Bifrost publication gate, and `privateStateExposed=false`. Verification also ran Huginn's TypeScript compiler through concrete Node path: `C:\Program Files\nodejs\node.exe E:\Projects\Huginn\node_modules\typescript\bin\tsc -p tsconfig.json` passed. Native verifier `epiphany-repo-livefire-closure-smoke --workspace E:\Projects\Huginn --item huginn-inspection-readback-livefire --expected-path README.md --expected-family repo.status_section --expected-gate awaiting-publication --expected-blocker bifrost-publication-missing` checks closure receipt, Mind map entry, overview gate/blocker, authority seals, and `git show` changed paths, returning `status=ok`, `soulVerdict=passed`, `publicationGate=Bifrost`, and `privateStateExposed=false`. Wrapper `tools/epiphany_local_run.ps1 -Mode repo-livefire-closure -Workspace E:\Projects\Huginn -RepoWorkItem huginn-inspection-readback-livefire -SkipBuild` exposes the same read-only proof through the local operator mouth; artifact `local-20260621-190156-803-2f85ba15` printed commit, path, gate, blocker, Soul verdict, Mind commit receipt, and `privateStateExposed=False` without push, merge, publication, or target mutation. New wrapper `tools/epiphany_local_run.ps1 -Mode repo-work-public-proof -Workspace E:\Projects\Huginn -RepoWorkItem huginn-inspection-readback-livefire -SkipBuild` exports the redacted proof bundle and repo-local Verse index without publishing; artifact `local-20260621-190645-345-4555b1dc` wrote `.epiphany\public\proof-bundles\repo-work-public-proof-huginn-inspection-readback-livefire.json`, proof id `repo-work-public-proof-huginn-inspection-readback-livefire`, SHA-256 `857545b199f3e37eb06c2e757e5cfc201958e46667bb1f8403fd333a22620f63`, nine artifact rows, zero publication rows, and `privateStateExposed=False`. swarm overview readback `local-20260621-190701-140-b9519ec6` sees the `REPO-WORK-PUBLIC-PROOF` row and action row from Huginn's repo-local Verse with the same SHA-256 while Bifrost publication remains missing. Launcher compact modes are now named compact operator-context modes instead of read-only modes, and `bifrost-public-proof` summaries print item, target public Verse, room, proof SHA-256, review receipts, and credit receipts so publication receipts are auditable without claiming upstream sync.
next_action: Continue the repo-frontier planning nerve from notes/repo-frontier-planning-authority-map.md. Self-to-Imagination launch and result arteries are real: request v1 binds model/frontier/runtime/thread; coordinator atomically injects and binds the exact launch; immutable worker result v2 exclusively echoes that request and embeds one canonical typed candidate after full request/launch/model/frontier replay, with generic patch mouths sealed. Next replace the internal candidate/adoption fixture writers with one Mind-only correlated Adopt/Refuse/Hold admission. Adopt must atomically install the exact candidate cargo and provenance into the canonical frontier, change only Imagination to Hands through a dedicated patch purpose/operation, and admit the new RepoModel; routes must copy execution cargo from that model, never consult a candidate/adoption shadow store. Refuse/Hold remain inert immutable receipts. After the nerve lands, add the production semantic index over typed graph claims so Modeling maintains a live searchable body map instead of forcing Hands to rediscover anatomy. Do not revive Proprioception, epiphany-work, metadata adapters, generic work-order routers, or inference from namespaces/prompt prose/evidence coincidence. Keep closure's zero-substring invariant.
next_action: Build the production Qdrant semantic projection over canonical typed state. Modeling needs a live persistent searchable Body map over repo claims/architecture/frontier; Mind needs semantic retrieval over doctrine, durable memory, evidence, decisions, and rehydration cues. CultCache/CultMesh remains authoritative and Qdrant stays rebuildable, with separate typed Mind/Modeling namespaces, provenance, visibility, schema/hash, and embedding-model version. Local Docker already hosts Qdrant; new Yggdrasil will provide the same substrate with 64GB RAM and a GTX 1080 for embedding/model workers. The repo-frontier planning nerve is complete: typed Self request, coordinator-bound Imagination launch, immutable embedded candidate, CAS-bound Mind review request, coordinator-bound non-embodied admission-review procedure, immutable Adopt/Refuse/Hold judgment, atomic canonical Adopt transition, model-derived Hands route, candidate/action/command-bound execution authority, Soul plan-contract visibility, and Modeling verdict closure without plan rewrite. Do not revive Proprioception, epiphany-work, metadata adapters, generic work-order routers, shadow candidate/adoption stores, embodied Mind lanes, or inference from namespaces/prompt prose/evidence coincidence. Keep closure's zero-substring invariant.