Bind frontier planning launches atomically

This commit is contained in:
Meta Vens 2026-07-15 01:03:59 +01:00
commit 6cbe47313c
13 changed files with 675 additions and 27 deletions

View file

@ -603,6 +603,7 @@ pub fn build_epiphany_role_launch_request_with_dynamic_context(
dynamic_prompt_context,
proposal_modeling_context: None,
claim_repair_context: None,
frontier_planning_context: None,
active_subgoal_id: state.active_subgoal_id.clone(),
active_subgoals: state
.subgoals
@ -645,6 +646,7 @@ pub fn build_epiphany_role_launch_request_with_dynamic_context(
max_runtime_seconds,
proposal_modeling_request_id: None,
claim_repair_request_id: None,
frontier_planning_request_id: None,
})
}
@ -749,6 +751,7 @@ pub fn build_epiphany_job_launch_request(
max_runtime_seconds,
proposal_modeling_request_id: None,
claim_repair_request_id: None,
frontier_planning_request_id: None,
}
}

View file

@ -111,6 +111,33 @@ fn commit_coordinator_job_launch_in_cache(
} else {
None
};
let frontier_planning_launch =
if let Some(request_id) = request.frontier_planning_request_id.as_deref() {
let (planning, identity) =
validate_frontier_planning_launch(cache, current_state, request, request_id)?;
let projection = RepoFrontierPlanningContextProjection::from_request(&planning);
match &mut effective_launch_document {
EpiphanyWorkerLaunchDocument::Role(document) => {
if document.proposal_modeling_context.is_some()
|| document.claim_repair_context.is_some()
{
return Err(anyhow!(
"frontier planning context is exclusive of Modeling authority contexts"
));
}
document.frontier_planning_context = Some(projection);
}
EpiphanyWorkerLaunchDocument::Reorient(_) => {
return Err(anyhow!(
"reorient launch cannot carry frontier planning context"
));
}
}
let bytes = rmp_serde::to_vec_named(&effective_launch_document)?;
Some((planning, identity, format!("{:x}", Sha256::digest(bytes))))
} else {
None
};
let prepared = prepare_runtime_spine_heartbeat_job(
&cache,
RuntimeSpineHeartbeatJobOptions {
@ -135,6 +162,7 @@ fn commit_coordinator_job_launch_in_cache(
organ_launch_contract: request.organ_launch_contract.clone(),
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(),
created_at: created_at.clone(),
},
)?;
@ -208,6 +236,33 @@ fn commit_coordinator_job_launch_in_cache(
.0,
);
}
if let Some((planning, identity, worker_launch_document_sha256)) = frontier_planning_launch {
let launch_binding = RepoFrontierPlanningLaunchBinding {
schema_version: REPO_FRONTIER_PLANNING_LAUNCH_BINDING_SCHEMA_VERSION.into(),
binding_record_id: format!("repo-frontier-planning-launch-{}", planning.request_id),
planning_request_id: planning.request_id,
job_id: plan.backend_job_id.clone(),
binding_id: request.binding_id.clone(),
runtime_id: identity.runtime_id,
thread_id: planning.thread_id,
launched_at: created_at.clone(),
worker_launch_document_sha256,
contract: REPO_FRONTIER_PLANNING_LAUNCH_BINDING_CONTRACT.into(),
};
if cache
.get::<RepoFrontierPlanningLaunchBinding>(&launch_binding.binding_record_id)?
.is_some()
{
return Err(anyhow!(
"frontier planning request is already bound to a launch"
));
}
batch.push(
cache
.prepare_entry(&launch_binding.binding_record_id, &launch_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),
@ -240,13 +295,15 @@ pub fn plan_coordinator_job_launch(
launcher_job_id: String,
backend_job_id: String,
) -> Result<EpiphanyCoordinatorJobLaunchPlan> {
let (caller_proposal_projection, caller_repair_projection) = match &request.launch_document {
EpiphanyWorkerLaunchDocument::Role(document) => (
document.proposal_modeling_context.as_ref(),
document.claim_repair_context.as_ref(),
),
EpiphanyWorkerLaunchDocument::Reorient(_) => (None, None),
};
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),
};
if caller_proposal_projection.is_some() {
return Err(anyhow!(
"caller-prepopulated proposal Modeling context is forbidden; coordinator commit owns projection"
@ -257,9 +314,23 @@ pub fn plan_coordinator_job_launch(
"caller-prepopulated claim repair context is forbidden; coordinator commit owns projection"
));
}
if request.proposal_modeling_request_id.is_some() && request.claim_repair_request_id.is_some() {
if caller_planning_projection.is_some() {
return Err(anyhow!(
"proposal Modeling and claim repair launches are mutually exclusive"
"caller-prepopulated frontier planning 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(),
]
.into_iter()
.filter(|present| *present)
.count()
> 1
{
return Err(anyhow!(
"proposal Modeling, claim repair, and frontier planning launches are mutually exclusive"
));
}
if let Some(expected) = request.expected_revision
@ -278,6 +349,10 @@ pub fn plan_coordinator_job_launch(
let mut cache = runtime_spine_cache(runtime_store)?;
cache.pull_all_backing_stores()?;
validate_claim_repair_launch(&cache, state, request, request_id)?;
} else if let Some(request_id) = request.frontier_planning_request_id.as_deref() {
let mut cache = runtime_spine_cache(runtime_store)?;
cache.pull_all_backing_stores()?;
validate_frontier_planning_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.
}
@ -335,6 +410,60 @@ pub fn plan_coordinator_job_launch(
})
}
fn validate_frontier_planning_launch(
cache: &CultCache,
state: &EpiphanyThreadState,
launch: &EpiphanyJobLaunchRequest,
request_id: &str,
) -> Result<(RepoFrontierPlanningRequest, EpiphanyRuntimeIdentity)> {
if match &launch.launch_document {
EpiphanyWorkerLaunchDocument::Role(document) => {
document.frontier_planning_context.is_some()
}
EpiphanyWorkerLaunchDocument::Reorient(_) => false,
} {
return Err(anyhow!("caller cannot author frontier planning context"));
}
if launch.owner_role != EPIPHANY_IMAGINATION_OWNER_ROLE
|| launch.binding_id != EPIPHANY_IMAGINATION_ROLE_BINDING_ID
{
return Err(anyhow!(
"frontier planning may only be carried by the Imagination role launch"
));
}
let planning = cache
.get::<RepoFrontierPlanningRequest>(request_id)?
.ok_or_else(|| anyhow!("frontier planning request {request_id:?} does not exist"))?;
crate::runtime_spine::validate_current_repo_frontier_planning_request(cache, &planning)?;
let identity = cache
.get::<EpiphanyRuntimeIdentity>(RUNTIME_IDENTITY_KEY)?
.ok_or_else(|| anyhow!("frontier planning launch requires runtime identity"))?;
let persisted_state = cache
.get::<crate::EpiphanyThreadStateEntry>(crate::THREAD_STATE_KEY)?
.ok_or_else(|| anyhow!("frontier planning launch requires authoritative thread state"))?;
let persisted_state_value = persisted_state.state()?;
if planning.request_id != request_id
|| planning.runtime_id != identity.runtime_id
|| planning.thread_id != persisted_state.thread_id
|| persisted_state_value != *state
|| launch.launch_document.thread_id() != planning.thread_id
{
return Err(anyhow!(
"frontier planning launch provenance binding mismatch"
));
}
if cache
.get_all::<RepoFrontierPlanningLaunchBinding>()?
.iter()
.any(|binding| binding.planning_request_id == request_id)
{
return Err(anyhow!(
"frontier planning request is already bound to a launch"
));
}
Ok((planning, identity))
}
fn validate_claim_repair_launch(
cache: &CultCache,
state: &EpiphanyThreadState,
@ -666,6 +795,49 @@ pub(crate) mod tests {
Ok((store, state, launch, repair))
}
fn frontier_planning_launch_fixture(
root: &Path,
suffix: &str,
) -> Result<(
std::path::PathBuf,
EpiphanyThreadState,
EpiphanyJobLaunchRequest,
RepoFrontierPlanningRequest,
)> {
let (store, _) =
crate::runtime_spine::tests::claim_challenge_fixture(root, suffix, "Imagination")?;
let planning = crate::select_and_commit_repo_frontier_planning_request(
&store,
"2026-07-15T09:00:02Z",
)?;
let mut cache = coordinator_acceptance_cache(&store)?;
cache.pull_all_backing_stores()?;
let mut state = cache
.get_required::<EpiphanyThreadStateEntry>(THREAD_STATE_KEY)?
.state()?;
for link in &mut state.runtime_links {
if link.binding_id == EPIPHANY_IMAGINATION_ROLE_BINDING_ID
&& link.runtime_result_id.is_none()
{
link.runtime_result_id = Some(format!("prior-imagination-result-{suffix}"));
}
}
cache.put(
THREAD_STATE_KEY,
&EpiphanyThreadStateEntry::from_state(&planning.thread_id, &state)?,
)?;
let mut launch = build_epiphany_role_launch_request(
&planning.thread_id,
EpiphanyRoleResultRoleId::Imagination,
Some(state.revision),
Some(60),
&state,
)
.map_err(|error| anyhow!(error))?;
launch.frontier_planning_request_id = Some(planning.request_id.clone());
Ok((store, state, launch, planning))
}
fn research_launch(state: &EpiphanyThreadState) -> EpiphanyJobLaunchRequest {
build_epiphany_role_launch_request(
"thread-1",
@ -1016,6 +1188,228 @@ pub(crate) mod tests {
Ok(())
}
#[test]
fn frontier_planning_launch_is_coordinator_owned_exact_and_single_use() -> Result<()> {
let root = tempfile::tempdir()?;
let (store, state, launch, planning) =
frontier_planning_launch_fixture(root.path(), "exact")?;
for mutation in 0..5 {
let mut forged = launch.clone();
match mutation {
0 => forged.owner_role = "Modeling".into(),
1 => forged.binding_id = "wrong-binding".into(),
2 => {
if let EpiphanyWorkerLaunchDocument::Role(document) =
&mut forged.launch_document
{
document.frontier_planning_context = Some(
RepoFrontierPlanningContextProjection::from_request(&planning),
);
}
}
3 => forged.claim_repair_request_id = Some("dual-repair".into()),
_ => forged.proposal_modeling_request_id = Some("dual-proposal".into()),
}
let before = std::fs::read(&store)?;
assert!(
plan_coordinator_job_launch(
&state,
&forged,
&store,
format!("launcher-forged-{mutation}"),
format!("backend-forged-{mutation}"),
)
.is_err()
);
assert_eq!(std::fs::read(&store)?, before);
}
let plan = plan_coordinator_job_launch(
&state,
&launch,
&store,
"launcher-planning".into(),
"backend-planning".into(),
)?;
let committed = commit_coordinator_job_launch(
&store,
&planning.thread_id,
&state,
&launch,
&plan,
"2026-07-15T09:00:03Z".into(),
)?;
let persisted = runtime_worker_launch_request(&store, "backend-planning")?
.expect("planning worker launch");
let projection = match persisted.launch_document()? {
EpiphanyWorkerLaunchDocument::Role(document) => document
.frontier_planning_context
.expect("coordinator-owned planning context"),
EpiphanyWorkerLaunchDocument::Reorient(_) => panic!("planning cannot reorient"),
};
assert_eq!(projection.request_id, planning.request_id);
assert_eq!(projection.runtime_id, planning.runtime_id);
assert_eq!(projection.thread_id, planning.thread_id);
let cache = coordinator_acceptance_cache(&store)?;
let binding_key = format!("repo-frontier-planning-launch-{}", planning.request_id);
let binding = cache
.get::<RepoFrontierPlanningLaunchBinding>(&binding_key)?
.expect("request-keyed planning launch binding");
assert_eq!(binding.job_id, "backend-planning");
assert_eq!(binding.runtime_id, planning.runtime_id);
assert_eq!(binding.thread_id, planning.thread_id);
assert_eq!(
binding.worker_launch_document_sha256,
format!("{:x}", Sha256::digest(&persisted.launch_document_msgpack))
);
let mut second = build_epiphany_role_launch_request(
&planning.thread_id,
EpiphanyRoleResultRoleId::Imagination,
Some(committed.epiphany_state.revision),
Some(60),
&committed.epiphany_state,
)
.map_err(|error| anyhow!(error))?;
second.frontier_planning_request_id = Some(planning.request_id);
let before = std::fs::read(&store)?;
assert!(
plan_coordinator_job_launch(
&committed.epiphany_state,
&second,
&store,
"launcher-second".into(),
"backend-second".into(),
)
.is_err()
);
assert_eq!(std::fs::read(&store)?, before);
Ok(())
}
#[test]
fn frontier_planning_launch_refuses_swapped_request_bytes_without_writes() -> Result<()> {
let root = tempfile::tempdir()?;
for mutation in 0..8 {
let (store, state, launch, planning) =
frontier_planning_launch_fixture(root.path(), &format!("causal-{mutation}"))?;
let mut corrupt = planning.clone();
match mutation {
0 => corrupt.model_hash = "swapped-model".into(),
1 => corrupt.admission_receipt_id = "swapped-admission".into(),
2 => corrupt.frontier_item_id = "swapped-frontier".into(),
3 => corrupt.frontier_item_hash = "swapped-frontier-hash".into(),
4 => corrupt.selected_organ = "Hands".into(),
5 => corrupt.source_scope.push("outside/scope".into()),
6 => corrupt.runtime_id = "swapped-runtime".into(),
_ => corrupt.thread_id = "swapped-thread".into(),
}
let mut cache = coordinator_acceptance_cache(&store)?;
cache.put(&corrupt.request_id, &corrupt)?;
let before = std::fs::read(&store)?;
assert!(
plan_coordinator_job_launch(
&state,
&launch,
&store,
format!("launcher-causal-{mutation}"),
format!("backend-causal-{mutation}"),
)
.is_err(),
"planning causal mutation {mutation} must be refused"
);
assert_eq!(std::fs::read(&store)?, before);
}
Ok(())
}
#[test]
fn concurrent_frontier_planning_launches_leave_only_winner_artifacts() -> Result<()> {
let root = tempfile::tempdir()?;
let (store, state, launch, planning) =
frontier_planning_launch_fixture(root.path(), "race")?;
let left_plan = plan_coordinator_job_launch(
&state,
&launch,
&store,
"launcher-left".into(),
"backend-left".into(),
)?;
let right_plan = plan_coordinator_job_launch(
&state,
&launch,
&store,
"launcher-right".into(),
"backend-right".into(),
)?;
let spawn = |store: std::path::PathBuf,
state: EpiphanyThreadState,
launch: EpiphanyJobLaunchRequest,
plan: EpiphanyCoordinatorJobLaunchPlan,
thread: String,
at: &'static str| {
std::thread::spawn(move || {
commit_coordinator_job_launch(&store, &thread, &state, &launch, &plan, at.into())
})
};
let left = spawn(
store.clone(),
state.clone(),
launch.clone(),
left_plan,
planning.thread_id.clone(),
"2026-07-15T09:00:03Z",
);
let right = spawn(
store.clone(),
state,
launch,
right_plan,
planning.thread_id,
"2026-07-15T09:00:04Z",
);
let outcomes = [left.join().unwrap(), right.join().unwrap()];
assert_eq!(outcomes.iter().filter(|outcome| outcome.is_ok()).count(), 1);
let mut cache = coordinator_acceptance_cache(&store)?;
cache.pull_all_backing_stores()?;
let bindings = cache
.get_all::<RepoFrontierPlanningLaunchBinding>()?
.into_iter()
.filter(|binding| binding.planning_request_id == planning.request_id)
.collect::<Vec<_>>();
assert_eq!(bindings.len(), 1);
let winner = bindings[0].job_id.as_str();
let loser = if winner == "backend-left" {
"backend-right"
} else {
assert_eq!(winner, "backend-right");
"backend-left"
};
for job_id in [winner] {
assert!(cache.get::<EpiphanyRuntimeJob>(job_id)?.is_some());
assert!(
cache
.get::<EpiphanyRuntimeWorkerLaunchRequest>(job_id)?
.is_some()
);
assert!(
cache
.get::<EpiphanyRuntimeEvent>(&format!("event-job-opened-{job_id}"))?
.is_some()
);
}
assert!(cache.get::<EpiphanyRuntimeJob>(loser)?.is_none());
assert!(
cache
.get::<EpiphanyRuntimeWorkerLaunchRequest>(loser)?
.is_none()
);
assert!(
cache
.get::<EpiphanyRuntimeEvent>(&format!("event-job-opened-{loser}"))?
.is_none()
);
Ok(())
}
#[test]
fn claim_repair_launch_refuses_every_swapped_causal_field_without_new_writes() -> Result<()> {
let root = tempfile::tempdir()?;

View file

@ -1133,6 +1133,7 @@ mod tests {
organ_launch_contract: launch_request.organ_launch_contract.clone(),
proposal_modeling_request_id: None,
claim_repair_request_id: None,
frontier_planning_request_id: None,
created_at: "2026-06-02T00:00:00Z".to_string(),
},
)?;

View file

@ -976,11 +976,14 @@ 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_PLANNING_CONTEXT_CONTRACT;
pub use surfaces::REPO_FRONTIER_PLANNING_CONTEXT_SCHEMA_VERSION;
pub use surfaces::REPO_FRONTIER_PROPOSAL_MODELING_CONTEXT_CONTRACT;
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::RepoFrontierPlanningContextProjection;
pub use surfaces::RepoFrontierProposalModelingContextProjection;
pub use surfaces::RepoModelClaimRepairContextProjection;
pub use surfaces::build_reorient_acceptance_bundle;

View file

@ -30,12 +30,12 @@ pub const REPO_FRONTIER_MODELING_REQUEST_CONTRACT: &str =
pub const REPO_FRONTIER_WORK_PROPOSAL_SCHEMA_VERSION: &str =
"epiphany.repo_frontier_work_proposal.v0";
pub const REPO_FRONTIER_PLANNING_REQUEST_SCHEMA_VERSION: &str =
"epiphany.self.repo_frontier_planning_request.v0";
"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_PLANNING_CONTRACT: &str = "epiphany.repo_frontier_planning.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";
pub const REPO_FRONTIER_PROPOSAL_MODELING_REQUEST_SCHEMA_VERSION: &str =
@ -57,6 +57,10 @@ pub const REPO_MODEL_CLAIM_REPAIR_LAUNCH_BINDING_SCHEMA_VERSION: &str =
"epiphany.coordinator.repo_model_claim_repair_launch_binding.v0";
pub const REPO_MODEL_CLAIM_REPAIR_LAUNCH_BINDING_CONTRACT: &str =
"epiphany.repo_model_claim_repair_launch_binding.v0";
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";
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
@ -355,6 +359,38 @@ pub struct RepoFrontierPlanningRequest {
pub requested_at: String,
#[cultcache(key = 10)]
pub contract: String,
#[cultcache(key = 11)]
pub runtime_id: String,
#[cultcache(key = 12)]
pub thread_id: String,
}
#[derive(Debug, Clone, PartialEq, Eq, DatabaseEntry)]
#[cultcache(
type = "epiphany.coordinator.repo_frontier_planning_launch_binding",
schema = "RepoFrontierPlanningLaunchBinding"
)]
pub struct RepoFrontierPlanningLaunchBinding {
#[cultcache(key = 0)]
pub schema_version: String,
#[cultcache(key = 1)]
pub binding_record_id: String,
#[cultcache(key = 2)]
pub planning_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, DatabaseEntry)]

View file

@ -1,5 +1,8 @@
use crate::EpiphanyWorkerLaunchDocument;
use crate::agent_launch::{EPIPHANY_MODELING_OWNER_ROLE, EPIPHANY_MODELING_ROLE_BINDING_ID};
use crate::agent_launch::{
EPIPHANY_IMAGINATION_OWNER_ROLE, EPIPHANY_IMAGINATION_ROLE_BINDING_ID,
EPIPHANY_MODELING_OWNER_ROLE, EPIPHANY_MODELING_ROLE_BINDING_ID,
};
use crate::agent_memory::AGENT_MEMORY_TYPE;
use crate::continuity_gateway::ContinuityRecoveryReceipt;
use crate::continuity_gateway::*;
@ -59,7 +62,7 @@ use crate::repo_model_gateway::{
REPO_MODEL_MIGRATION_CONTRACT, REPO_MODEL_MIGRATION_RECEIPT_SCHEMA_VERSION,
REPO_MODEL_MIGRATION_RECEIPT_TYPE, RepoFrontierHandsAuthority, RepoFrontierModelingRequest,
RepoFrontierNextOrgan, RepoFrontierPlanAdoption, RepoFrontierPlanCandidate,
RepoFrontierPlanDecision, RepoFrontierPlanningRequest,
RepoFrontierPlanDecision, RepoFrontierPlanningLaunchBinding, RepoFrontierPlanningRequest,
RepoFrontierProposalModelingLaunchBinding, RepoFrontierProposalModelingRequest,
RepoFrontierRoute, RepoFrontierVerdictDisposition, RepoFrontierWorkProposal,
RepoModelAdmissionReceipt, RepoModelAdmissionReview, RepoModelClaimChallenge,
@ -328,6 +331,8 @@ pub struct EpiphanyRuntimeWorkerLaunchRequest {
pub proposal_modeling_request_id: Option<String>,
#[cultcache(key = 12, default)]
pub claim_repair_request_id: Option<String>,
#[cultcache(key = 13, default)]
pub frontier_planning_request_id: Option<String>,
}
impl EpiphanyRuntimeWorkerLaunchRequest {
@ -683,6 +688,7 @@ pub struct RuntimeSpineHeartbeatJobOptions {
pub organ_launch_contract: EpiphanyLaunchOrganContract,
pub proposal_modeling_request_id: Option<String>,
pub claim_repair_request_id: Option<String>,
pub frontier_planning_request_id: Option<String>,
pub created_at: String,
}
@ -732,6 +738,7 @@ pub struct EpiphanyJobLaunchRequest {
pub max_runtime_seconds: Option<u64>,
pub proposal_modeling_request_id: Option<String>,
pub claim_repair_request_id: Option<String>,
pub frontier_planning_request_id: Option<String>,
}
#[derive(Debug, Clone, PartialEq)]
@ -786,6 +793,7 @@ pub fn runtime_spine_cache(store_path: impl AsRef<Path>) -> Result<CultCache> {
cache.register_entry_type::<RepoFrontierProposalModelingRequest>()?;
cache.register_entry_type::<RepoFrontierProposalModelingLaunchBinding>()?;
cache.register_entry_type::<RepoFrontierPlanningRequest>()?;
cache.register_entry_type::<RepoFrontierPlanningLaunchBinding>()?;
cache.register_entry_type::<RepoFrontierPlanCandidate>()?;
cache.register_entry_type::<RepoFrontierPlanAdoption>()?;
cache.register_entry_type::<RepoFrontierVerificationRequest>()?;
@ -1054,6 +1062,12 @@ pub fn open_runtime_spine_heartbeat_job(
options.claim_repair_request_id.as_deref(),
&options.launch_document,
)?;
validate_frontier_planning_launch_carrier(
&options.role,
&options.binding_id,
options.frontier_planning_request_id.as_deref(),
&options.launch_document,
)?;
validate_non_empty(&options.binding_id, "binding id")?;
validate_non_empty(&options.authority_scope, "authority scope")?;
validate_non_empty(&options.instruction, "instruction")?;
@ -1139,6 +1153,7 @@ pub fn open_runtime_spine_heartbeat_job(
organ_launch_contract,
proposal_modeling_request_id: options.proposal_modeling_request_id,
claim_repair_request_id: options.claim_repair_request_id,
frontier_planning_request_id: options.frontier_planning_request_id,
};
cache.put(&job_id, &request)?;
Ok(job)
@ -1166,6 +1181,12 @@ pub fn prepare_runtime_spine_heartbeat_job(
options.claim_repair_request_id.as_deref(),
&options.launch_document,
)?;
validate_frontier_planning_launch_carrier(
&options.role,
&options.binding_id,
options.frontier_planning_request_id.as_deref(),
&options.launch_document,
)?;
validate_non_empty(&options.binding_id, "binding id")?;
validate_non_empty(&options.authority_scope, "authority scope")?;
validate_non_empty(&options.instruction, "instruction")?;
@ -1277,6 +1298,7 @@ pub fn prepare_runtime_spine_heartbeat_job(
organ_launch_contract: options.organ_launch_contract,
proposal_modeling_request_id: options.proposal_modeling_request_id,
claim_repair_request_id: options.claim_repair_request_id,
frontier_planning_request_id: options.frontier_planning_request_id,
};
let envelopes = vec![
cache.prepare_entry(RUNTIME_IDENTITY_KEY, &identity)?.0,
@ -1354,6 +1376,39 @@ fn validate_claim_repair_launch_carrier(
Ok(())
}
fn validate_frontier_planning_launch_carrier(
role: &str,
binding_id: &str,
planning_request_id: Option<&str>,
launch_document: &EpiphanyWorkerLaunchDocument,
) -> Result<()> {
let projection = match launch_document {
EpiphanyWorkerLaunchDocument::Role(document) => document.frontier_planning_context.as_ref(),
EpiphanyWorkerLaunchDocument::Reorient(_) => None,
};
let Some(request_id) = planning_request_id else {
if projection.is_some() {
return Err(anyhow!(
"frontier planning context requires its typed request id"
));
}
return Ok(());
};
validate_non_empty(request_id, "frontier planning request id")?;
if role != EPIPHANY_IMAGINATION_OWNER_ROLE || binding_id != EPIPHANY_IMAGINATION_ROLE_BINDING_ID
{
return Err(anyhow!(
"frontier planning request may only be transported by the Imagination role launch"
));
}
let projection = projection
.ok_or_else(|| anyhow!("frontier planning request requires its typed context"))?;
if projection.request_id != request_id {
return Err(anyhow!("frontier planning context/request mismatch"));
}
Ok(())
}
pub fn runtime_job_snapshot(
store_path: impl AsRef<Path>,
job_id: &str,
@ -2748,7 +2803,11 @@ pub fn select_and_commit_repo_frontier_planning_request(
let runtime_store = runtime_store.as_ref();
let mut cache = runtime_spine_cache(runtime_store)?;
cache.pull_all_backing_stores()?;
require_identity(&cache)?;
let identity = require_identity(&cache)?;
let thread = cache
.get::<crate::EpiphanyThreadStateEntry>(crate::THREAD_STATE_KEY)?
.ok_or_else(|| anyhow!("planning request requires authoritative thread state"))?;
thread.state()?;
let backing = SingleFileMessagePackBackingStore::new(runtime_store);
let model_envelope = backing
.pull_all()?
@ -2792,7 +2851,13 @@ pub fn select_and_commit_repo_frontier_planning_request(
}
let request_id = format!(
"repo-frontier-planning-{:x}",
Sha256::digest(format!("{model_hash}:{}:{item_hash}", item.id).as_bytes())
Sha256::digest(
format!(
"{}:{}:{model_hash}:{}:{item_hash}",
identity.runtime_id, thread.thread_id, item.id
)
.as_bytes(),
)
);
let request = RepoFrontierPlanningRequest {
schema_version: REPO_FRONTIER_PLANNING_REQUEST_SCHEMA_VERSION.into(),
@ -2806,6 +2871,8 @@ pub fn select_and_commit_repo_frontier_planning_request(
source_scope: item.source_scope.clone(),
requested_at: at.into(),
contract: REPO_FRONTIER_PLANNING_CONTRACT.into(),
runtime_id: identity.runtime_id,
thread_id: thread.thread_id,
};
if let Some(existing) = cache.get::<RepoFrontierPlanningRequest>(&request_id)? {
let mut retry = request.clone();
@ -2834,6 +2901,72 @@ pub fn select_and_commit_repo_frontier_planning_request(
Ok(request)
}
pub(crate) fn validate_current_repo_frontier_planning_request(
cache: &CultCache,
request: &RepoFrontierPlanningRequest,
) -> Result<()> {
chrono::DateTime::parse_from_rfc3339(&request.requested_at)
.map_err(|_| anyhow!("planning request timestamp must be RFC3339"))?;
let identity = require_identity(cache)?;
let thread = cache
.get::<crate::EpiphanyThreadStateEntry>(crate::THREAD_STATE_KEY)?
.ok_or_else(|| anyhow!("planning request requires authoritative thread state"))?;
thread.state()?;
let entry = cache
.get::<crate::EpiphanyMemoryGraphEntry>(crate::MEMORY_GRAPH_KEY)?
.ok_or_else(|| anyhow!("planning request requires canonical model"))?;
crate::validate_memory_graph_entry(&entry)?;
let model = entry.snapshot()?;
let model_hash = crate::memory_graph_model_hash(&model)?;
let receipts = cache
.get_all::<RepoModelAdmissionReceipt>()?
.into_iter()
.filter(|receipt| {
receipt.schema_version == REPO_MODEL_ADMISSION_RECEIPT_SCHEMA_VERSION
&& receipt.contract == REPO_MODEL_ADMISSION_CONTRACT
&& receipt.admitted_revision == model.model_revision
&& receipt.admitted_hash == model_hash
})
.collect::<Vec<_>>();
if receipts.len() != 1 {
return Err(anyhow!(
"planning request requires exactly one current admission receipt"
));
}
let challenges = current_repo_model_claim_challenges(cache, &model, &model_hash)?;
let item = actionable_imagination_frontier_item(&model, &challenges)
.ok_or_else(|| anyhow!("planning request frontier is no longer actionable"))?;
let item_hash = format!("{:x}", Sha256::digest(rmp_serde::to_vec_named(item)?));
let expected_request_id = format!(
"repo-frontier-planning-{:x}",
Sha256::digest(
format!(
"{}:{}:{model_hash}:{}:{item_hash}",
identity.runtime_id, thread.thread_id, item.id
)
.as_bytes(),
)
);
if request.schema_version != REPO_FRONTIER_PLANNING_REQUEST_SCHEMA_VERSION
|| request.contract != REPO_FRONTIER_PLANNING_CONTRACT
|| request.request_id != expected_request_id
|| request.model_revision != model.model_revision
|| request.model_hash != model_hash
|| request.admission_receipt_id != receipts[0].receipt_id
|| request.frontier_item_id != item.id
|| request.frontier_item_hash != item_hash
|| request.selected_organ != "Imagination"
|| request.source_scope != item.source_scope
|| request.runtime_id != identity.runtime_id
|| request.thread_id != thread.thread_id
{
return Err(anyhow!(
"planning request does not exactly bind current model, frontier, runtime, and thread"
));
}
Ok(())
}
fn actionable_imagination_frontier_item<'a>(
model: &'a crate::EpiphanyMemoryGraphSnapshot,
challenges: &[RepoModelClaimChallenge],
@ -9853,6 +9986,7 @@ pub(crate) mod tests {
dynamic_prompt_context: None,
proposal_modeling_context: None,
claim_repair_context: None,
frontier_planning_context: None,
active_subgoal_id: None,
active_subgoals: Vec::new(),
active_graph_node_ids: vec!["node-model".to_string()],
@ -9876,6 +10010,7 @@ pub(crate) mod tests {
),
proposal_modeling_request_id: None,
claim_repair_request_id: None,
frontier_planning_request_id: None,
created_at: "2026-05-06T00:02:00Z".to_string(),
},
)?;
@ -9946,6 +10081,7 @@ pub(crate) mod tests {
dynamic_prompt_context: None,
proposal_modeling_context: None,
claim_repair_context: None,
frontier_planning_context: None,
active_subgoal_id: None,
active_subgoals: Vec::new(),
active_graph_node_ids: vec!["runtime-spine".to_string()],
@ -10032,6 +10168,7 @@ pub(crate) mod tests {
dynamic_prompt_context: None,
proposal_modeling_context: None,
claim_repair_context: None,
frontier_planning_context: None,
active_subgoal_id: None,
active_subgoals: Vec::new(),
active_graph_node_ids: Vec::new(),

View file

@ -251,6 +251,7 @@ mod tests {
dynamic_prompt_context: None,
proposal_modeling_context: None,
claim_repair_context: None,
frontier_planning_context: None,
active_subgoal_id: None,
active_subgoals: Vec::new(),
active_graph_node_ids: Vec::new(),
@ -275,6 +276,7 @@ mod tests {
max_runtime_seconds: None,
proposal_modeling_request_id: None,
claim_repair_request_id: None,
frontier_planning_request_id: None,
};
let grant = substrate_gate_repo_access_grant_for_launch(
"grant-1".to_string(),

View file

@ -144,11 +144,14 @@ 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_PLANNING_CONTEXT_CONTRACT;
pub use worker_launch::REPO_FRONTIER_PLANNING_CONTEXT_SCHEMA_VERSION;
pub use worker_launch::REPO_FRONTIER_PROPOSAL_MODELING_CONTEXT_CONTRACT;
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::RepoFrontierPlanningContextProjection;
pub use worker_launch::RepoFrontierProposalModelingContextProjection;
pub use worker_launch::RepoModelClaimRepairContextProjection;
pub use worker_launch::build_reorient_job_launch_request;

View file

@ -34,6 +34,10 @@ pub const REPO_MODEL_CLAIM_REPAIR_CONTEXT_SCHEMA_VERSION: &str =
"epiphany.worker.repo_model_claim_repair_context.v0";
pub const REPO_MODEL_CLAIM_REPAIR_CONTEXT_CONTRACT: &str =
"epiphany.repo_model_claim_repair_context.v0";
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";
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase", tag = "documentKind")]
@ -89,6 +93,8 @@ pub struct EpiphanyRoleWorkerLaunchDocument {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub claim_repair_context: Option<RepoModelClaimRepairContextProjection>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub frontier_planning_context: Option<RepoFrontierPlanningContextProjection>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub active_subgoal_id: Option<String>,
#[serde(default)]
pub active_subgoals: Vec<EpiphanySubgoal>,
@ -256,6 +262,45 @@ impl RepoModelClaimRepairContextProjection {
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RepoFrontierPlanningContextProjection {
pub schema_version: String,
pub contract: String,
pub request_id: String,
pub model_revision: u64,
pub model_hash: String,
pub admission_receipt_id: String,
pub frontier_item_id: String,
pub frontier_item_hash: String,
pub selected_organ: String,
#[serde(default)]
pub source_scope: Vec<String>,
pub requested_at: String,
pub runtime_id: String,
pub thread_id: String,
}
impl RepoFrontierPlanningContextProjection {
pub(crate) fn from_request(request: &crate::RepoFrontierPlanningRequest) -> Self {
Self {
schema_version: REPO_FRONTIER_PLANNING_CONTEXT_SCHEMA_VERSION.into(),
contract: REPO_FRONTIER_PLANNING_CONTEXT_CONTRACT.into(),
request_id: request.request_id.clone(),
model_revision: request.model_revision,
model_hash: request.model_hash.clone(),
admission_receipt_id: request.admission_receipt_id.clone(),
frontier_item_id: request.frontier_item_id.clone(),
frontier_item_hash: request.frontier_item_hash.clone(),
selected_organ: request.selected_organ.clone(),
source_scope: request.source_scope.clone(),
requested_at: request.requested_at.clone(),
runtime_id: request.runtime_id.clone(),
thread_id: request.thread_id.clone(),
}
}
}
pub fn build_reorient_job_launch_request(
input: EpiphanyReorientLaunchRequestInput<'_>,
) -> EpiphanyJobLaunchRequest {
@ -298,6 +343,7 @@ pub fn build_reorient_job_launch_request(
max_runtime_seconds: input.max_runtime_seconds,
proposal_modeling_request_id: None,
claim_repair_request_id: None,
frontier_planning_request_id: None,
}
}

View file

@ -948,3 +948,20 @@ embedded receipt binds back to the artifact target and audit; forged
cardinality: Epiphany inherits a CultMesh command id, so the coordinator must
ensure one typed command id per crossing rather than letting multiple posts share
one canonical `crossing_<command>` receipt.
## Repo frontier planning launch artery (2026-07-15)
Self's planning request is now v1 and binds the exact current RepoModel,
admission receipt, actionable Imagination frontier, runtime identity, and
authoritative thread. Coordinator launch commit replays that entire chain from
one transaction snapshot, forbids caller-authored planning projection and
mixed Modeling/repair/planning authority, injects the typed Imagination context,
and atomically persists a request-keyed
`RepoFrontierPlanningLaunchBinding`. Its SHA-256 covers the exact launch bytes
stored for the worker. Hostile tests cover swapped model/admission/frontier/
scope/organ/runtime/thread fields, wrong role/binding, prepopulated projection,
dual authority, single-use replay, and two concurrent launches; only one wins
and the loser leaves no job, worker launch, or opened event. Full core proof:
322 passed, 1 ignored. Next build the exclusive immutable Imagination result
echo carrying the typed candidate, then Mind-only Adopt/Refuse/Hold admission
and the narrow Adopt model transition that makes Hands routing true.

View file

@ -1,18 +1,24 @@
# Repo Frontier Planning Authority Map
## Current wound
## Current state
The planning family has typed documents but not a live organ chain. Self can
persist an exact `RepoFrontierPlanningRequest`. Nothing launches Imagination
from it. `RepoFrontierPlanCandidate` and `RepoFrontierPlanAdoption` were exposed
through public persistence functions, allowing callers to author documents in
Imagination and Mind namespaces without either organ participating. Adopt then
blocked duplicate planning requests but changed no model bytes and affected no
Hands route. The type names were substituting for cognition.
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.
The public candidate/adoption writers are removed. The existing internal
functions remain temporarily as test scaffolding while the real nerve replaces
them; they are not production authority.
The downstream nerve is still incomplete. Imagination has no exclusive
immutable result carrying the candidate; Mind has no correlated admission; the
old internal candidate/adoption fixture writers still exist; 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

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: Build the repo-frontier planning nerve from the authority map in notes/repo-frontier-planning-authority-map.md. Self's exact current-model planning request is the only sound existing owner. Public put_repo_frontier_plan_candidate and put_repo_frontier_plan_adoption exports are cut because they let callers impersonate Imagination and Mind; the remaining internal functions are fixture scaffolding and must die when replaced. Next add one coordinator-owned typed Imagination context projection and request-keyed atomic launch binding, one exclusive planning-request echo on an immutable v1 worker result containing the candidate, and one Mind-only correlated Adopt/Refuse/Hold admission. Adopt must cause a narrow RepoModel transition that makes downstream Hands truth real; it cannot merely suppress later planning while routes ignore it. Refuse/Hold remain inert immutable receipts. Generic Imagination statePatch.planning is not this authority. 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: Continue the repo-frontier planning nerve from notes/repo-frontier-planning-authority-map.md. The Self-to-Imagination launch artery is now real: planning request v1 binds runtime/thread, coordinator commit replays current model/admission/frontier/challenges/state, injects the typed projection, and atomically persists one request-keyed launch binding with the exact stored launch-document hash; hostile substitutions and a two-launch race leave no loser artifacts. Next add one exclusive planning-request echo on immutable worker result v1 containing the typed candidate, then replace the internal candidate/adoption fixture writers with Mind-only correlated Adopt/Refuse/Hold admission. Adopt must cause a narrow RepoModel transition that makes downstream Hands truth real; 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.