diff --git a/epiphany-core/src/agent_launch.rs b/epiphany-core/src/agent_launch.rs index 5652adf8..37d59b4a 100644 --- a/epiphany-core/src/agent_launch.rs +++ b/epiphany-core/src/agent_launch.rs @@ -1111,6 +1111,7 @@ pub fn build_epiphany_frontier_plan_mind_launch_request( dynamic_prompt_context: None, repository_body_observation_basis: None, proposal_modeling_context: None, + frontier_verdict_modeling_context: None, frontier_planning_context: None, frontier_research_context: None, frontier_plan_mind_context: None, @@ -1164,7 +1165,6 @@ pub fn build_epiphany_frontier_plan_mind_launch_request( admitted_model_direction_consideration_request_id: None, repo_frontier_modeling_request_id: None, repo_frontier_research_request_id: None, - repo_frontier_verdict_modeling_authority: None, }) } @@ -1213,6 +1213,7 @@ pub fn build_epiphany_role_launch_request_with_dynamic_context( dynamic_prompt_context, repository_body_observation_basis: None, proposal_modeling_context: None, + frontier_verdict_modeling_context: None, frontier_planning_context: None, frontier_research_context: None, frontier_plan_mind_context: None, @@ -1265,7 +1266,6 @@ pub fn build_epiphany_role_launch_request_with_dynamic_context( admitted_model_direction_consideration_request_id: None, repo_frontier_modeling_request_id: None, repo_frontier_research_request_id: None, - repo_frontier_verdict_modeling_authority: None, }) } @@ -1430,7 +1430,6 @@ pub fn build_epiphany_job_launch_request( admitted_model_direction_consideration_request_id: None, repo_frontier_modeling_request_id: None, repo_frontier_research_request_id: None, - repo_frontier_verdict_modeling_authority: None, } } @@ -1772,7 +1771,6 @@ mod tests { soul_verdict_receipt_id: "soul-exact".into(), verification_result_id: "verification-result".into(), verification_job_id: "verification-job".into(), - verification_acceptance_receipt_id: "verification-acceptance".into(), allowed_disposition: crate::RepoFrontierVerdictDisposition::Resolved, requested_at: "2026-08-08T00:00:00Z".into(), contract: crate::REPO_FRONTIER_MODELING_REQUEST_CONTRACT.into(), @@ -1798,6 +1796,20 @@ mod tests { retired_at: None, superseded_by: None, }, + soul_verdict: crate::SoulVerdictReceipt { + schema_version: crate::SOUL_VERDICT_RECEIPT_SCHEMA_VERSION.into(), + receipt_id: "soul-exact".into(), + source_result_id: "verification-result".into(), + source_job_id: "verification-job".into(), + verdict: "pass".into(), + summary: "verified".into(), + evidence_ids: Vec::new(), + risks: Vec::new(), + emitted_at: "2026-08-08T00:00:00Z".into(), + contract: "test".into(), + verification_request_id: "verification-exact".into(), + frontier_route_id: "route-exact".into(), + }, }; let schema = epiphany_frontier_verdict_modeling_output_schema(&authority); assert!( diff --git a/epiphany-core/src/bin/epiphany-mvp-coordinator.rs b/epiphany-core/src/bin/epiphany-mvp-coordinator.rs index b871523b..0406d5fd 100644 --- a/epiphany-core/src/bin/epiphany-mvp-coordinator.rs +++ b/epiphany-core/src/bin/epiphany-mvp-coordinator.rs @@ -873,6 +873,47 @@ fn run_coordinator(args: &Args) -> Result { steps.push(step); continue; } + if role_id == "modeling" + && let Some(job_id) = + epiphany_core::current_frontier_verdict_modeling_review_job_id( + &runtime_store, + )? + { + let result = + epiphany_core::runtime_role_worker_result(&runtime_store, &job_id)? + .ok_or_else(|| { + anyhow!( + "frontier verdict Modeling review lost its typed result" + ) + })?; + push_event( + &mut step, + json!({"type": "frontierVerdictModelingResult", "roleId": role_id, "result": result}), + ); + if !args.auto_review { + final_action = json!({ + "action": "reviewModelingResult", + "reason": "The exact frontier verdict Modeling result awaits keyed Mind admission.", + "runtimeJobId": job_id, + }); + append_operator_step_jsonl(&steps_path, &step)?; + steps.push(step); + break; + } + let accepted = epiphany_core::accept_frontier_verdict_modeling_result( + &runtime_store, + &job_id, + &now(), + )?; + push_event( + &mut step, + json!({"type": "frontierVerdictModelingAccept", "roleId": role_id, "commit": accepted}), + ); + final_status = collect_coordinator_status(&runtime_store, &thread_id)?; + append_operator_step_jsonl(&steps_path, &step)?; + steps.push(step); + continue; + } let result = read_role_result(&runtime_store, &thread_id, role_id)?; push_event( &mut step, @@ -1047,7 +1088,8 @@ fn run_coordinator(args: &Args) -> Result { }; let thread_free_modeling = role_id == "modeling" && (proposal_modeling_request_id.is_some() - || status["currentWork"]["bodyModeling"].is_object()); + || status["currentWork"]["bodyModeling"].is_object() + || status["currentWork"]["frontierVerdictModeling"].is_object()); let launch = if role_id == "modeling" && let Some(request_id) = proposal_modeling_request_id { @@ -1089,6 +1131,17 @@ fn run_coordinator(args: &Args) -> Result { "backendJobId": binding.job_id, "bodyModelingLaunchBinding": binding, }) + } else if role_id == "modeling" + && status["currentWork"]["frontierVerdictModeling"].is_object() + { + let job_id = epiphany_core::launch_current_frontier_verdict_modeling_work( + &runtime_store, + &now(), + )?; + json!({ + "bindingId": epiphany_core::EPIPHANY_MODELING_ROLE_BINDING_ID, + "backendJobId": job_id, + }) } else { launch_role( &runtime_store, @@ -1674,7 +1727,6 @@ fn launch_role( .ok_or_else(|| anyhow!("cannot launch role without native coordinator state"))?; let state_loaded_ms = started.elapsed().as_millis(); let role = parse_role_id(role_id)?; - let mut repo_frontier_modeling_request_id = None; let repo_frontier_research_request = if role == epiphany_core::EpiphanyRoleResultRoleId::Research && epiphany_core::runtime_has_actionable_eyes_frontier(runtime_store)? @@ -1685,7 +1737,6 @@ fn launch_role( } else { None }; - let mut repo_frontier_verdict_modeling_authority = None; let expected_revision = expected_revision.and_then(|value| u64::try_from(value).ok()); let focus = epiphany_core::role_launch_context_focus(&state, epiphany_core::epiphany_role_label(role)); @@ -1713,18 +1764,6 @@ fn launch_role( &state, ) .map_err(anyhow::Error::msg)?; - } else if role == epiphany_core::EpiphanyRoleResultRoleId::Modeling { - let modeling_launch_context = epiphany_core::append_modeling_work_loop_telemetry_context( - context, - runtime_store, - &state, - ) - .map_err(anyhow::Error::msg)?; - context = modeling_launch_context.context; - repo_frontier_modeling_request_id = - modeling_launch_context.repo_frontier_modeling_request_id; - repo_frontier_verdict_modeling_authority = - modeling_launch_context.repo_frontier_verdict_modeling_authority; } let role_context_augmented_ms = started.elapsed().as_millis(); let mut request = epiphany_core::build_epiphany_role_launch_request_with_dynamic_context( @@ -1736,7 +1775,6 @@ fn launch_role( Some(context), ) .map_err(anyhow::Error::msg)?; - request.repo_frontier_modeling_request_id = repo_frontier_modeling_request_id; request.repo_frontier_research_request_id = repo_frontier_research_request .as_ref() .map(|selected| selected.request_id.clone()); @@ -1746,7 +1784,6 @@ fn launch_role( ) { document.frontier_research_context = Some(selected.into()); } - request.repo_frontier_verdict_modeling_authority = repo_frontier_verdict_modeling_authority; let request_built_ms = started.elapsed().as_millis(); let launched = service.launch_job( thread_id, @@ -2820,7 +2857,6 @@ mod tests { "render_launch_dynamic_prompt_context", "render_modeling_launch_dynamic_prompt_context", "append_verification_hands_receipt_context", - "append_modeling_work_loop_telemetry_context", ".launch_job(", ".accept_role(", ] { @@ -2829,6 +2865,12 @@ mod tests { "missing native role seam {required:?}" ); } + for forbidden in [ + concat!("append_modeling_work_loop_telemetry_", "context"), + concat!("accepted_research_is_newest_", "unmodeled_boundary"), + ] { + assert!(!source.contains(forbidden)); + } assert!(!native_roles.contains("append_modeling_repo_model_shape_context(")); assert!(!native_roles.contains("AppServerClient")); assert!(!native_roles.contains("thread/epiphany/")); diff --git a/epiphany-core/src/bin/epiphany-mvp-status.rs b/epiphany-core/src/bin/epiphany-mvp-status.rs index 0dc5902e..accbb7ea 100644 --- a/epiphany-core/src/bin/epiphany-mvp-status.rs +++ b/epiphany-core/src/bin/epiphany-mvp-status.rs @@ -550,6 +550,10 @@ fn run_native_status(args: &Args, include_auxiliary_status: bool) -> Result String { + digest_id( + "repo-frontier-verdict-modeling", + &[ + runtime_id, + soul_verdict_receipt_id, + verification_result_id, + frontier_route_id, + ], + ) +} + pub fn admitted_model_direction_request_id( runtime_id: &str, model_projection_digest: &str, diff --git a/epiphany-core/src/coordinator_acceptance.rs b/epiphany-core/src/coordinator_acceptance.rs index c70520dd..8cfd20d5 100644 --- a/epiphany-core/src/coordinator_acceptance.rs +++ b/epiphany-core/src/coordinator_acceptance.rs @@ -276,12 +276,21 @@ pub fn accept_coordinator_role_finding( )); } let verdict = soul_verdict_receipt_from_verification_finding( - format!("soul-verdict-{}", update.accepted_receipt_id), + format!( + "soul-verdict-{}", + finding.runtime_result_id.as_deref().unwrap_or_default() + ), &finding, accepted_at.clone(), ); + let cache = coordinator_acceptance_cache(store)?; + let modeling_request = + crate::runtime_spine::derive_repo_frontier_modeling_request(&cache, &verdict)?; available.push(SOUL_VERDICT_RECEIPT_TYPE.to_string()); - prerequisites.push(EpiphanyAcceptancePrerequisite::Soul(verdict)); + prerequisites.push(EpiphanyAcceptancePrerequisite::SoulFrontierVerdict { + verdict, + modeling_request, + }); } enforce_acceptance_receipt_proofs( &contract, @@ -326,44 +335,12 @@ pub fn accept_coordinator_role_finding( update, }); } else { - let repository_body_observation_basis = result - .repository_body_observation_basis - .clone() - .ok_or_else(|| { - anyhow::anyhow!("Modeling result has no Repository Body observation basis") - })?; - validate_repository_body_observation_basis(store, &repository_body_observation_basis)?; - let proposal = result.repo_model_mutation_proposal()?; - if proposal.is_none() { - return Err(anyhow::anyhow!( - "Modeling result requiring RepoModel change has no semantic mutation proposal" - )); - } - let proposal = proposal.expect("checked above"); - if proposal.proposal_id != format!("repo-model-mutation-proposal-{job_id}") { - return Err(anyhow::anyhow!( - "Modeling RepoModel mutation proposal identity is not runtime-owned" - )); - } - let plan = plan_repo_model_mutation(store, &proposal)?; - let invariant_owner = "Modeling.frontier_verdict"; - match commit_mind_mutation( - store, - &result.decision_context_id, - invariant_owner, - plan.strong_reads, - plan.writes, - &accepted_at, - )? { - EpiphanyMindCommitOutcome::Committed(_) => {} - EpiphanyMindCommitOutcome::Conflict { - document_identities, - } => { - return Err(anyhow::anyhow!( - "RepoModel mutation lost its exact keyed reads: {document_identities:?}" - )); - } - } + crate::accept_frontier_verdict_modeling_result(store, job_id, &accepted_at)?; + return Ok(EpiphanyNativeRoleAcceptance { + state: state.clone(), + finding, + update, + }); } } let commit = mind_state_commit_receipt( @@ -640,7 +617,10 @@ pub enum EpiphanyAcceptancePrerequisite { Eyes(EyesEvidencePacket), EyesSourceLookup(EyesSourceLookupReceipt), SubstrateGate(SubstrateGateRepoAccessGrantReceipt), - Soul(SoulVerdictReceipt), + SoulFrontierVerdict { + verdict: SoulVerdictReceipt, + modeling_request: crate::RepoFrontierModelingRequest, + }, Continuity(ContinuityRecoveryReceipt), } @@ -672,6 +652,19 @@ fn commit_state_with_mind_witness( expected_state, )?; let mut eyes_packet_jobs = BTreeSet::new(); + for prerequisite in prerequisites { + if let EpiphanyAcceptancePrerequisite::SoulFrontierVerdict { + verdict, + modeling_request, + } = prerequisite + && crate::runtime_spine::derive_repo_frontier_modeling_request(&cache, verdict)? + != *modeling_request + { + return Err(anyhow::anyhow!( + "Soul verdict and frontier Modeling request lost exact typed causality" + )); + } + } for prerequisite in prerequisites { if let EpiphanyAcceptancePrerequisite::Eyes(packet) = prerequisite { if packet.source_role_id != "research" @@ -741,7 +734,7 @@ fn commit_state_with_mind_witness( let (commit_envelope, _) = cache.prepare_entry(&commit_receipt.receipt_id, commit_receipt)?; let mut batch = vec![review_envelope, commit_envelope]; for prerequisite in prerequisites { - batch.push(match prerequisite { + let envelope = match prerequisite { EpiphanyAcceptancePrerequisite::Eyes(document) => { cache.prepare_entry(&document.packet_id, document)?.0 } @@ -751,13 +744,22 @@ fn commit_state_with_mind_witness( EpiphanyAcceptancePrerequisite::SubstrateGate(document) => { cache.prepare_entry(&document.receipt_id, document)?.0 } - EpiphanyAcceptancePrerequisite::Soul(document) => { - cache.prepare_entry(&document.receipt_id, document)?.0 + EpiphanyAcceptancePrerequisite::SoulFrontierVerdict { + verdict, + modeling_request, + } => { + batch.push( + cache + .prepare_entry(&modeling_request.request_id, modeling_request)? + .0, + ); + cache.prepare_entry(&verdict.receipt_id, verdict)?.0 } EpiphanyAcceptancePrerequisite::Continuity(document) => { cache.prepare_entry(&document.receipt_id, document)?.0 } - }); + }; + batch.push(envelope); } coordinator_state_transaction::commit_coordinator_state_transaction( &mut cache, @@ -1203,61 +1205,4 @@ mod tests { assert!(cache.get::("commit-9")?.is_some()); Ok(()) } - - #[test] - fn accepted_soul_verdict_preserves_exact_frontier_binding() -> anyhow::Result<()> { - let temp = tempfile::tempdir()?; - let store = temp.path().join("acceptance-soul.cc"); - let state = EpiphanyThreadState { - revision: 11, - ..Default::default() - }; - let review = MindGatewayReview { - schema_version: MIND_GATEWAY_REVIEW_SCHEMA_VERSION.to_string(), - gateway_id: "review-11".to_string(), - source_kind: "role".to_string(), - source_role_id: "verification".to_string(), - decision: MindGatewayDecision::Accept, - allowed_effects: Vec::new(), - refused_effects: Vec::new(), - reasons: Vec::new(), - contract: "test".to_string(), - }; - let commit = mind_state_commit_receipt( - "commit-11".to_string(), - &review, - 11, - Vec::new(), - "2026-07-13T00:00:00Z".to_string(), - ); - let soul = SoulVerdictReceipt { - schema_version: SOUL_VERDICT_RECEIPT_SCHEMA_VERSION.to_string(), - receipt_id: "soul-11".to_string(), - source_result_id: "result-11".to_string(), - source_job_id: "job-11".to_string(), - verdict: "pass".to_string(), - summary: "exact chain verified".to_string(), - evidence_ids: Vec::new(), - risks: Vec::new(), - emitted_at: "2026-07-13T00:00:00Z".to_string(), - contract: "test".to_string(), - verification_request_id: "verification-request-11".to_string(), - frontier_route_id: "frontier-route-11".to_string(), - }; - commit_state_with_mind_witness( - &store, - "thread-11", - &state, - &state, - &review, - &commit, - &[EpiphanyAcceptancePrerequisite::Soul(soul.clone())], - )?; - let cache = coordinator_acceptance_cache(&store)?; - let stored = cache.get_required::("soul-11")?; - assert_eq!(stored, soul); - assert_eq!(stored.verification_request_id, "verification-request-11"); - assert_eq!(stored.frontier_route_id, "frontier-route-11"); - Ok(()) - } } diff --git a/epiphany-core/src/coordinator_launch.rs b/epiphany-core/src/coordinator_launch.rs index 8d0e5047..5469759d 100644 --- a/epiphany-core/src/coordinator_launch.rs +++ b/epiphany-core/src/coordinator_launch.rs @@ -294,9 +294,6 @@ fn commit_coordinator_job_launch_in_cache( .clone(), repo_frontier_modeling_request_id: request.repo_frontier_modeling_request_id.clone(), repo_frontier_research_request_id: request.repo_frontier_research_request_id.clone(), - repo_frontier_verdict_modeling_authority: request - .repo_frontier_verdict_modeling_authority - .clone(), created_at: created_at.clone(), }, )?; diff --git a/epiphany-core/src/coordinator_launch_context.rs b/epiphany-core/src/coordinator_launch_context.rs index e399e409..d4ce1a8d 100644 --- a/epiphany-core/src/coordinator_launch_context.rs +++ b/epiphany-core/src/coordinator_launch_context.rs @@ -10,7 +10,6 @@ use crate::RuntimeHandsReceiptChainSummary; use crate::assemble_repo_model_view; use crate::load_epiphany_cultmesh_cluster_topology; use crate::load_epiphany_cultmesh_status; -use crate::load_latest_epiphany_cultmesh_work_loop_telemetry; use crate::plan_memory_graph_context_cut; use crate::query_epiphany_local_verse_context; use crate::render_epiphany_prompt_context; @@ -21,7 +20,6 @@ use crate::runtime_latest_hands_receipt_chain_after; use crate::write_epiphany_cultmesh_work_loop_telemetry; use chrono::SecondsFormat; use chrono::Utc; -use epiphany_state_model::EpiphanyAcceptanceReceipt; use epiphany_state_model::EpiphanyThreadState; use sha2::Digest; use std::fs; @@ -817,249 +815,6 @@ fn debug_variant_snake_case(value: impl std::fmt::Debug) -> String { output } -#[derive(Debug)] -pub struct ModelingWorkLoopLaunchContext { - pub context: String, - pub repo_frontier_modeling_request_id: Option, - pub repo_frontier_verdict_modeling_authority: - Option, -} - -impl std::ops::Deref for ModelingWorkLoopLaunchContext { - type Target = str; - - fn deref(&self) -> &Self::Target { - &self.context - } -} - -impl PartialEq<&str> for ModelingWorkLoopLaunchContext { - fn eq(&self, other: &&str) -> bool { - self.context == *other - } -} - -pub fn append_modeling_work_loop_telemetry_context( - mut context: String, - runtime_store_path: &Path, - state: &EpiphanyThreadState, -) -> Result { - if accepted_research_is_newest_unmodeled_boundary(state) { - context.push_str("\n\n\n"); - context.push_str("The current Modeling turn is caused by accepted Eyes evidence newer than the last accepted Modeling boundary. Use the accepted Research finding already present in coordinator context to update the body model. This is not a historical Soul-verdict incorporation turn; do not substitute an older frontier verification route.\n"); - context.push_str(""); - return Ok(ModelingWorkLoopLaunchContext { - context, - repo_frontier_modeling_request_id: None, - repo_frontier_verdict_modeling_authority: None, - }); - } - let Some(accepted_verification) = latest_unique_accepted_verification(state)? else { - return Ok(ModelingWorkLoopLaunchContext { - context, - repo_frontier_modeling_request_id: None, - repo_frontier_verdict_modeling_authority: None, - }); - }; - let modeling_request = - crate::commit_repo_frontier_modeling_request(runtime_store_path, &accepted_verification) - .map_err(|error| { - format!("failed to commit typed frontier Modeling request: {error}") - })?; - let route = crate::runtime_repo_frontier_route(runtime_store_path, &modeling_request.route_id) - .map_err(|error| format!("failed to reload Modeling frontier route: {error}"))? - .ok_or_else(|| "Modeling frontier route disappeared after request commit".to_string())?; - let current_model = assemble_repo_model_view(runtime_store_path) - .map_err(|error| format!("failed to load current keyed RepoModel for Modeling: {error}"))?; - let current_item = validate_current_frontier_route(&route, ¤t_model, None)?; - if modeling_request.schema_version != crate::REPO_FRONTIER_MODELING_REQUEST_SCHEMA_VERSION - || modeling_request.contract != crate::REPO_FRONTIER_MODELING_REQUEST_CONTRACT - || modeling_request.model_projection_digest != route.model_projection_digest - || modeling_request.model_source_documents != route.model_source_documents - || modeling_request.frontier_item_id != route.frontier_item_id - || modeling_request.frontier_item_hash != route.frontier_item_hash - { - return Err( - "frontier Modeling request does not exactly bind the current keyed route".to_string(), - ); - } - let disposition = match modeling_request.allowed_disposition { - crate::RepoFrontierVerdictDisposition::Resolved => "resolved", - crate::RepoFrontierVerdictDisposition::Blocked => "blocked", - }; - context.push_str("\n\n\n"); - context.push_str(&format!( - "modelingRequestId: {}\nmodelProjectionDigest: {}\nmodelSourceDocuments: {}\nfrontierRouteId: {}\nfrontierItemId: {}\nfrontierItemHash: {}\nverificationRequestId: {}\nsoulVerdictReceiptId: {}\nverificationResultId: {}\nverificationJobId: {}\nverificationAcceptanceReceiptId: {}\nallowedDisposition: {}\nrouteQuestion: {}\nrouteGap: {}\nidentityMigrationBody: {}\nidentityQuestion: {}\nidentityTargetClaimIds: [{}]\nidentitySourceScope: [{}]\nidentityDependencyItemIds: [{}]\nidentityCreatedAt: {}\nidentityRecommendedNextOrgan: {}\nidentityRetiredAt: {}\nidentitySupersededBy: {}\n", - modeling_request.request_id, - modeling_request.model_projection_digest, - render_repo_model_source_documents(&modeling_request.model_source_documents), - modeling_request.route_id, - modeling_request.frontier_item_id, - modeling_request.frontier_item_hash, - modeling_request.verification_request_id, - modeling_request.soul_verdict_receipt_id, - modeling_request.verification_result_id, - modeling_request.verification_job_id, - modeling_request.verification_acceptance_receipt_id, - disposition, - route.question, - route.gap, - current_item.migration_body, - current_item.question, - current_item.target_claim_ids.join(" | "), - current_item.source_scope.join(" | "), - current_item.dependency_item_ids.join(" | "), - current_item.created_at.as_deref().unwrap_or(""), - current_item.recommended_next_organ, - current_item.retired_at.as_deref().unwrap_or(""), - current_item.superseded_by.as_deref().unwrap_or(""), - )); - context.push_str("Echo repoFrontierModelingRequestId exactly. Use purpose kind incorporate_frontier_verdict with the exact frontierRouteId and soulVerdictReceiptId. Revise only the routed frontier item to allowedDisposition; this request grants no other model mutation.\n"); - context.push_str("Include the exact soulVerdictReceiptId in the top-level evidenceIds. Include both verificationRequestId and soulVerdictReceiptId in the revised frontier item's evidence_refs. Set the revised frontier status exactly to allowedDisposition. Set statePatch to null: this routed request owns only the single RepoModel frontier revision and grants no generic thread-state evidence or observation mutation.\n"); - context.push_str("Copy every identity field exactly from the identity-prefixed values above: migration_body, question, target_claim_ids, source_scope, dependency_item_ids, created_at, recommended_next_organ, retired_at, and superseded_by. `` means the optional field must remain absent. Only status, evidence_refs, gap, and updated_at are verdict-owned changes; do not reinterpret, summarize, reorder, add to, or omit identity-bearing anatomy.\n"); - context.push_str(""); - - let store = local_verse_store_path(runtime_store_path); - let Some(mut telemetry) = - load_latest_epiphany_cultmesh_work_loop_telemetry(&store, EPIPHANY_LOCAL_VERSE_RUNTIME_ID) - .map_err(|error| { - format!( - "failed to load work-loop telemetry from internal CultMesh store {}: {error}", - store.display() - ) - })? - else { - return Ok(ModelingWorkLoopLaunchContext { - context, - repo_frontier_modeling_request_id: Some(modeling_request.request_id.clone()), - repo_frontier_verdict_modeling_authority: Some( - crate::RepoFrontierVerdictModelingLaunchAuthority { - request: modeling_request, - frontier_item: current_item.clone(), - }, - ), - }); - }; - let soul_receipts = latest_accepted_soul_receipts(state); - if !soul_receipts.is_empty() { - telemetry.telemetry_id = format!("{}-soul-{}", telemetry.telemetry_id, state.revision); - telemetry.produced_at_utc = Utc::now().to_rfc3339_opts(SecondsFormat::Secs, true); - telemetry.source_stage = "hands+soul".to_string(); - telemetry.target_stages = vec!["modeling".to_string()]; - telemetry.soul_receipt_ids = soul_receipts - .iter() - .map(|receipt| receipt.id.clone()) - .collect(); - telemetry.summary = format!( - "{} Soul acceptance telemetry attached for Modeling model update.", - telemetry.summary - ); - write_epiphany_cultmesh_work_loop_telemetry(&store, telemetry.clone()).map_err( - |error| { - format!( - "failed to enrich work-loop telemetry in internal CultMesh store {}: {error}", - store.display() - ) - }, - )?; - } - context.push_str("\n\n\n"); - context.push_str( - "Modeling is updating the machine model after Soul has reviewed the latest Hands consequence telemetry. This packet is loaded from the internal CultMesh Verse, not reconstructed from chat memory.\n", - ); - context.push_str(&render_work_loop_telemetry(&telemetry)); - if !soul_receipts.is_empty() { - context.push_str("- soulAcceptedReceipts:\n"); - for receipt in soul_receipts { - context.push_str(&format!( - " - id={} resultId={} jobId={} acceptedAt={} summary={}\n", - receipt.id, - receipt.result_id, - receipt.job_id, - receipt.accepted_at, - receipt.summary.unwrap_or_default() - )); - } - } - context.push_str( - "Update the machine model from this verified consequence before another Hands turn. Do not request a new Eyes step merely to rediscover this already-typed telemetry.\n", - ); - context.push_str(""); - Ok(ModelingWorkLoopLaunchContext { - context, - repo_frontier_modeling_request_id: Some(modeling_request.request_id.clone()), - repo_frontier_verdict_modeling_authority: Some( - crate::RepoFrontierVerdictModelingLaunchAuthority { - request: modeling_request, - frontier_item: current_item.clone(), - }, - ), - }) -} - -fn accepted_research_is_newest_unmodeled_boundary(state: &EpiphanyThreadState) -> bool { - let latest_accepted_at = |role_id: &str| { - state - .acceptance_receipts - .iter() - .filter(|receipt| { - receipt.role_id == role_id - && receipt.surface == "roleAccept" - && receipt.status == "accepted" - }) - .map(|receipt| receipt.accepted_at.as_str()) - .max() - }; - let Some(research_at) = latest_accepted_at("research") else { - return false; - }; - latest_accepted_at("modeling").is_none_or(|modeling_at| research_at > modeling_at) - && latest_accepted_at("verification") - .is_none_or(|verification_at| research_at > verification_at) -} - -fn latest_unique_accepted_verification( - state: &EpiphanyThreadState, -) -> Result, String> { - let accepted = state - .acceptance_receipts - .iter() - .filter(|receipt| { - receipt.role_id == "verification" - && receipt.surface == "roleAccept" - && receipt.status == "accepted" - }) - .collect::>(); - let Some(latest_at) = accepted - .iter() - .map(|receipt| receipt.accepted_at.as_str()) - .max() - else { - return Ok(None); - }; - let latest = accepted - .into_iter() - .filter(|receipt| receipt.accepted_at == latest_at) - .collect::>(); - if latest.len() != 1 { - return Err("latest accepted Verification result is temporally ambiguous; refusing Modeling substitution".to_string()); - } - Ok(Some(latest[0].clone())) -} - -fn latest_accepted_verification_timestamp(state: &EpiphanyThreadState) -> Option<&str> { - state - .acceptance_receipts - .iter() - .filter(|receipt| { - receipt.role_id == "verification" - && receipt.surface == "roleAccept" - && receipt.status == "accepted" - }) - .map(|receipt| receipt.accepted_at.as_str()) - .max() -} - fn latest_accepted_modeling_or_verification_timestamp(state: &EpiphanyThreadState) -> Option<&str> { state .acceptance_receipts @@ -1073,23 +828,6 @@ fn latest_accepted_modeling_or_verification_timestamp(state: &EpiphanyThreadStat .max() } -fn latest_accepted_soul_receipts(state: &EpiphanyThreadState) -> Vec { - let Some(latest_at) = latest_accepted_verification_timestamp(state) else { - return Vec::new(); - }; - state - .acceptance_receipts - .iter() - .filter(|receipt| { - receipt.role_id == "verification" - && receipt.surface == "roleAccept" - && receipt.status == "accepted" - && receipt.accepted_at == latest_at - }) - .cloned() - .collect() -} - fn work_loop_telemetry_from_hands_chain( chain: &RuntimeHandsReceiptChainSummary, runtime_store_path: &Path, @@ -1443,109 +1181,19 @@ mod tests { use crate::EpiphanyMemoryNode; use crate::EpiphanyMemoryNodeKind; use crate::EpiphanyRoleResultRoleId; - use crate::HANDS_ACTION_INTENT_SCHEMA_VERSION; - use crate::HandsActionIntent; use crate::RepoFrontierItem; use crate::RepoFrontierStatus; use crate::RuntimeSpineHeartbeatJobOptions; use crate::RuntimeSpineInitOptions; use crate::build_epiphany_role_launch_request_with_dynamic_context; - use crate::hands_action_review_for_intent; - use crate::hands_command_receipt_for_review; - use crate::hands_commit_receipt_for_review; - use crate::hands_patch_receipt_for_review; use crate::initialize_runtime_spine; use crate::open_runtime_spine_heartbeat_job; - use crate::put_hands_action_intent; - use crate::put_hands_action_review; - use crate::put_hands_command_receipt; - use crate::put_hands_commit_receipt; - use crate::put_hands_patch_receipt; use crate::runtime_worker_launch_request; use crate::seed_epiphany_local_verse_context; use epiphany_state_model::EpiphanyAcceptanceReceipt; use std::fs; use uuid::Uuid; - fn seed_and_authorize_context_hands( - store: &Path, - intent: &HandsActionIntent, - review: &crate::HandsActionReview, - ) -> anyhow::Result<()> { - if crate::runtime_swarm_binding(store)?.is_none() { - crate::runtime_spine::tests::bind_test_runtime_swarm( - store, - "context-hands-test-swarm", - )?; - } - let documents = crate::EpiphanyRepoModelSeedDocuments { - domains: vec![EpiphanyMemoryDomain { - id: "repo".to_string(), - profile: crate::EpiphanyMemoryProfile::RepoArchitecture, - title: "Repository".to_string(), - lifecycle: EpiphanyMemoryLifecycle::Accepted, - ..Default::default() - }], - nodes: vec![EpiphanyMemoryNode { - id: "claim-context-hands".to_string(), - domain_id: "repo".to_string(), - profile: crate::EpiphanyMemoryProfile::RepoArchitecture, - kind: EpiphanyMemoryNodeKind::RuntimeContract, - title: "Context Hands".to_string(), - claim: "Verification consumes a routed Hands chain.".to_string(), - question: "Is the chain exact?".to_string(), - action_implication: "Route the exact source scope.".to_string(), - source_hashes: vec!["anchor:missing".to_string()], - lifecycle: EpiphanyMemoryLifecycle::Accepted, - ..Default::default() - }], - edges: Vec::new(), - summaries: Vec::new(), - frontier: vec![RepoFrontierItem { - id: "context-hands-frontier".to_string(), - migration_body: "Verify the routed Hands chain.".to_string(), - question: "Does verification see the exact receipts?".to_string(), - gap: "Unrouted consequences are invalid.".to_string(), - target_claim_ids: vec!["claim-context-hands".to_string()], - source_scope: intent.requested_paths.clone(), - recommended_next_organ: "Hands".to_string(), - evidence_refs: vec!["context-route-evidence".to_string()], - status: RepoFrontierStatus::Active, - ..Default::default() - }], - lifecycle_receipts: Vec::new(), - }; - let seed = crate::EpiphanyRepoModelSeed::new( - "context-runtime-model-seed", - "context-runtime-model", - "context-hands-test-swarm", - "context-hands-test-workspace", - "sha256:context-hands-test-body", - documents, - )?; - crate::initialize_keyed_repo_model(store, &seed, "2026-06-12T00:00:03Z")?; - let route = crate::select_and_commit_repo_frontier_route(store, "2026-06-12T00:00:05Z")?; - crate::put_repo_frontier_hands_authority( - store, - &crate::RepoFrontierHandsAuthority { - schema_version: crate::REPO_FRONTIER_HANDS_AUTHORITY_SCHEMA_VERSION.to_string(), - authority_id: "context-route-authority".to_string(), - route_id: route.route_id, - model_projection_digest: route.model_projection_digest, - model_source_documents: route.model_source_documents, - frontier_item_id: route.frontier_item_id, - frontier_item_hash: route.frontier_item_hash, - hands_intent_id: intent.intent_id.clone(), - hands_review_id: review.review_id.clone(), - substrate_grant_receipt_id: intent.substrate_gate_grant_receipt_id.clone(), - requested_paths: intent.requested_paths.clone(), - granted_at: "2026-06-12T00:00:06Z".to_string(), - contract: crate::REPO_FRONTIER_HANDS_AUTHORITY_CONTRACT.to_string(), - }, - )?; - Ok(()) - } - #[test] fn native_launch_context_has_no_bridge_or_host_dependency() { let source = include_str!("coordinator_launch_context.rs"); @@ -1780,7 +1428,6 @@ mod tests { admitted_model_direction_consideration_request_id: None, repo_frontier_modeling_request_id: None, repo_frontier_research_request_id: None, - repo_frontier_verdict_modeling_authority: None, created_at: "2026-06-02T00:00:00Z".to_string(), }, )?; @@ -1826,490 +1473,6 @@ mod tests { Ok(()) } - #[test] - fn ordinary_modeling_has_no_verdict_request_and_tied_acceptance_refuses_substitution() { - let missing_store = Path::new("definitely-missing-runtime.cc"); - let ordinary = EpiphanyThreadState::default(); - assert_eq!( - append_modeling_work_loop_telemetry_context( - "ordinary".to_string(), - missing_store, - &ordinary, - ) - .expect("ordinary Modeling does not touch verdict authority"), - "ordinary" - ); - - let receipt = |id: &str, result: &str| EpiphanyAcceptanceReceipt { - id: id.to_string(), - result_id: result.to_string(), - job_id: format!("job-{result}"), - binding_id: "verification-review-worker".to_string(), - surface: "roleAccept".to_string(), - role_id: "verification".to_string(), - status: "accepted".to_string(), - accepted_at: "2026-07-13T07:00:00Z".to_string(), - ..Default::default() - }; - let ambiguous = EpiphanyThreadState { - acceptance_receipts: vec![ - receipt("accept-a", "result-a"), - receipt("accept-b", "result-b"), - ], - ..Default::default() - }; - let error = append_modeling_work_loop_telemetry_context( - "ambiguous".to_string(), - missing_store, - &ambiguous, - ) - .expect_err("equal-time accepted results must not be selected by adjacency"); - assert!(error.contains("temporally ambiguous")); - - let accepted = |role_id: &str, accepted_at: &str| EpiphanyAcceptanceReceipt { - id: format!("accept-{role_id}"), - result_id: format!("result-{role_id}"), - job_id: format!("job-{role_id}"), - binding_id: format!("{role_id}-worker"), - surface: "roleAccept".to_string(), - role_id: role_id.to_string(), - status: "accepted".to_string(), - accepted_at: accepted_at.to_string(), - ..Default::default() - }; - let eyes_handoff = EpiphanyThreadState { - acceptance_receipts: vec![ - accepted("verification", "2026-07-13T07:00:00Z"), - accepted("modeling", "2026-07-13T08:00:00Z"), - accepted("research", "2026-07-13T09:00:00Z"), - ], - ..Default::default() - }; - assert!(accepted_research_is_newest_unmodeled_boundary( - &eyes_handoff - )); - let context = append_modeling_work_loop_telemetry_context( - "eyes".to_string(), - missing_store, - &eyes_handoff, - ) - .expect("accepted Eyes handoff must not bind an older Soul route"); - assert!(context.contains("accepted_eyes_modeling_handoff")); - assert!(context.contains("not a historical Soul-verdict incorporation turn")); - - let soul_handoff = EpiphanyThreadState { - acceptance_receipts: vec![ - accepted("modeling", "2026-07-13T08:00:00Z"), - accepted("research", "2026-07-13T09:00:00Z"), - accepted("verification", "2026-07-13T10:00:00Z"), - ], - ..Default::default() - }; - assert!(!accepted_research_is_newest_unmodeled_boundary( - &soul_handoff - )); - } - - #[test] - fn verification_launch_context_includes_hands_receipt_chain() -> anyhow::Result<()> { - let temp = std::env::temp_dir().join(format!("epiphany-hands-context-{}", Uuid::new_v4())); - fs::create_dir(&temp)?; - let runtime_store = temp.join("runtime-spine.msgpack"); - initialize_runtime_spine( - &runtime_store, - RuntimeSpineInitOptions { - runtime_id: "epiphany-hands-context-test".to_string(), - display_name: "Epiphany Hands Context Test".to_string(), - created_at: "2026-06-12T00:00:00Z".to_string(), - }, - )?; - crate::runtime_spine::tests::bind_test_runtime_swarm( - &runtime_store, - "hands-context-swarm", - )?; - crate::runtime_spine::tests::bind_test_repository_body( - &runtime_store, - "hands-context-workspace", - )?; - let stdout = temp.join("stdout.log"); - let stderr = temp.join("stderr.log"); - fs::write(&stdout, "running 5 tests\ntest result: ok")?; - fs::write(&stderr, "Finished test profile")?; - let intent = HandsActionIntent { - schema_version: HANDS_ACTION_INTENT_SCHEMA_VERSION.to_string(), - intent_id: "hands-intent-context".to_string(), - runtime_job_id: "hands-job-context".to_string(), - binding_id: "implementation-worker".to_string(), - role: "epiphany-hands".to_string(), - authority_scope: "epiphany.role.implementation".to_string(), - requested_action: "continueImplementation".to_string(), - requested_paths: vec!["epiphany-core/src/runtime_spine.rs".to_string()], - 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, - &crate::substrate_gate_coordinator_implementation_grant( - "substrate-grant-context".to_string(), - "hands-job-context".to_string(), - vec!["epiphany-core/src/runtime_spine.rs".to_string()], - "2026-06-12T00:00:00Z".to_string(), - ), - )?; - put_hands_action_intent(&runtime_store, &intent)?; - let review = hands_action_review_for_intent( - "hands-review-context".to_string(), - &intent, - "approved".to_string(), - vec![ - "patch".to_string(), - "command".to_string(), - "commit".to_string(), - ], - vec!["test review".to_string()], - "2026-06-12T00:00:02Z".to_string(), - ); - put_hands_action_review(&runtime_store, &review)?; - seed_and_authorize_context_hands(&runtime_store, &intent, &review)?; - let patch = hands_patch_receipt_for_review( - "hands-patch-context".to_string(), - &intent, - &review, - vec!["epiphany-core/src/runtime_spine.rs".to_string()], - "patch summary".to_string(), - "2026-06-12T00:00:04Z".to_string(), - ); - put_hands_patch_receipt(&runtime_store, &patch)?; - let command = hands_command_receipt_for_review( - "hands-command-context".to_string(), - &intent, - &review, - "cargo test --manifest-path .\\epiphany-core\\Cargo.toml --bin epiphany-mvp-coordinator" - .to_string(), - "0".to_string(), - stdout.display().to_string(), - stderr.display().to_string(), - "command summary".to_string(), - "2026-06-12T00:00:05Z".to_string(), - ); - put_hands_command_receipt(&runtime_store, &command)?; - let commit = hands_commit_receipt_for_review( - "hands-commit-context".to_string(), - &intent, - &review, - "abc123".to_string(), - "codex/test".to_string(), - vec!["epiphany-core/src/runtime_spine.rs".to_string()], - "commit summary".to_string(), - "2026-06-12T00:00:06Z".to_string(), - ); - put_hands_commit_receipt(&runtime_store, &commit)?; - let mut state = EpiphanyThreadState { - revision: 11, - objective: Some("Verify Hands receipts.".to_string()), - acceptance_receipts: vec![EpiphanyAcceptanceReceipt { - id: "accept-modeling-context".to_string(), - result_id: "context-route-result".to_string(), - job_id: "context-route-job".to_string(), - binding_id: "modeling-checkpoint-worker".to_string(), - surface: "roleAccept".to_string(), - role_id: "modeling".to_string(), - status: "accepted".to_string(), - accepted_at: "2026-06-12T00:00:03Z".to_string(), - accepted_observation_id: None, - accepted_evidence_id: None, - summary: Some("accepted current model".to_string()), - }], - ..Default::default() - }; - let context = append_verification_hands_receipt_context( - "".to_string(), - &runtime_store, - &state, - ) - .map_err(anyhow::Error::msg)?; - - assert!(context.contains("")); - assert!(context.contains("hands-patch-context")); - assert!(context.contains("hands-command-context")); - assert!(context.contains("hands-commit-context")); - assert!(context.contains("verificationRequestId:")); - assert!(context.contains("frontierRouteId:")); - assert!(context.contains("modelAuthorityChain:")); - assert!(context.contains("currentKeyedView: projectionDigest=sha256:")); - assert!(context.contains("modelSourceDocuments=epiphany-mind/")); - assert!(!context.contains(&("RepoModel".to_string() + "Admission"))); - assert!(!context.contains("mindAdmissionChain:")); - assert!(context.contains("Does verification see the exact receipts?")); - assert!(context.contains("Unrouted consequences are invalid.")); - assert!(context.contains("resolvedReceiptPayloads")); - assert!(context.contains("resolvedReceiptPayloadPreviews")); - assert!(context.contains("test result: ok")); - assert!(context.contains("sourcePathProof")); - assert!(context.contains("epiphany-core/src/coordinator_launch.rs")); - assert!(context.contains("epiphany-core/src/surfaces/coordinator.rs")); - assert!(context.contains("exact failure-review supersession receipt")); - assert!(context.contains("verificationAssertions")); - let telemetry = load_latest_epiphany_cultmesh_work_loop_telemetry( - local_verse_store_path(&runtime_store), - EPIPHANY_LOCAL_VERSE_RUNTIME_ID, - )? - .expect("Verification launch should write internal CultMesh telemetry"); - assert_eq!( - telemetry.verse_id, - EPIPHANY_CULTMESH_INTERNAL_VERSE_ID.to_string() - ); - assert_eq!(telemetry.hands_patch_receipt_id, "hands-patch-context"); - assert_eq!(telemetry.hands_command_receipt_id, "hands-command-context"); - assert_eq!(telemetry.hands_commit_receipt_id, "hands-commit-context"); - assert_eq!( - telemetry.target_stages, - vec!["soul".to_string(), "modeling".to_string()] - ); - assert!( - telemetry - .receipt_payload_previews - .iter() - .any(|payload| payload.contains("patch: schemaVersion=")) - ); - assert!( - telemetry - .receipt_payload_previews - .iter() - .any(|payload| payload.contains("command: schemaVersion=")) - ); - assert!( - telemetry - .receipt_payload_previews - .iter() - .any(|payload| payload.contains("commit: schemaVersion=")) - ); - assert!(!telemetry.commit_diff_preview.trim().is_empty()); - assert!(telemetry.verification_assertions.iter().any(|assertion| { - assertion.contains("verification_launch_context_includes_hands_receipt_chain") - })); - assert!(telemetry.verification_assertions.iter().any(|assertion| { - assertion.contains("repo_model_incorporates_pass_and_nonpass_soul_verdicts_causally") - && assertion.contains("same receipt") - && assertion.contains("no actionable Hands frontier") - })); - - let verification_request_id = context - .lines() - .find_map(|line| line.strip_prefix("verificationRequestId: ")) - .expect("rendered exact verification request id"); - let verification_request = crate::runtime_repo_frontier_verification_request( - &runtime_store, - verification_request_id, - )? - .expect("persisted exact verification request"); - let verification_launch = crate::build_epiphany_role_launch_request( - "context-thread", - crate::EpiphanyRoleResultRoleId::Verification, - Some(state.revision), - Some(60), - &state, - ) - .map_err(anyhow::Error::msg)?; - crate::open_runtime_spine_heartbeat_job( - &runtime_store, - crate::RuntimeSpineHeartbeatJobOptions { - runtime_id: "epiphany-hands-context-test".to_string(), - display_name: "Epiphany Hands Context Test".to_string(), - session_id: "context-thread".to_string(), - objective: "Verify the exact Hands receipt chain.".to_string(), - coordinator_note: "Fixture immutable Verification launch.".to_string(), - job_id: "verification-job-context".to_string(), - role: verification_launch.owner_role, - binding_id: verification_launch.binding_id, - authority_scope: verification_launch.authority_scope, - instruction: verification_launch.instruction, - launch_document: verification_launch.launch_document, - output_contract_id: verification_launch.output_contract_id, - organ_launch_contract: verification_launch.organ_launch_contract, - proposal_modeling_request_id: None, - frontier_planning_request_id: None, - frontier_plan_mind_request_id: None, - imagination_consideration_request_id: None, - admitted_model_direction_consideration_request_id: None, - repo_frontier_modeling_request_id: None, - repo_frontier_research_request_id: None, - repo_frontier_verdict_modeling_authority: None, - created_at: "2026-06-12T00:00:06Z".to_string(), - }, - )?; - assert!( - has_complete_hands_consequence_after_latest_accepted_boundary(&runtime_store, &state) - .map_err(anyhow::Error::msg)? - ); - let verification_result = crate::EpiphanyRuntimeRoleWorkerResult { - schema_version: crate::RUNTIME_ROLE_WORKER_RESULT_SCHEMA_VERSION.to_string(), - repository_body_observation_basis: None, - result_id: "result-verification-context".to_string(), - job_id: "verification-job-context".to_string(), - role_id: "verification".to_string(), - verdict: "pass".to_string(), - summary: "accepted prior verification".to_string(), - next_safe_move: "Model the verified consequence.".to_string(), - checkpoint_summary: None, - scratch_summary: None, - files_inspected: Vec::new(), - frontier_node_ids: Vec::new(), - evidence_ids: vec!["verification-proof-context".to_string()], - 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_mutation_proposal_msgpack: None, - verification_request_id: Some(verification_request.request_id.clone()), - frontier_route_id: Some(verification_request.route_id.clone()), - repo_frontier_modeling_request_id: None, - proposal_modeling_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, - imagination_consideration_request_id: None, - imagination_consideration_candidate_msgpack: None, - admitted_model_direction_consideration_request_id: None, - admitted_model_direction_consideration_result_msgpack: None, - decision_context_id: "decision-context-fixture".into(), - }; - crate::put_runtime_role_worker_result(&runtime_store, &verification_result)?; - crate::put_soul_verdict_receipt( - &runtime_store, - &crate::SoulVerdictReceipt { - schema_version: crate::SOUL_VERDICT_RECEIPT_SCHEMA_VERSION.to_string(), - receipt_id: "soul-verdict-context".to_string(), - source_result_id: verification_result.result_id.clone(), - source_job_id: verification_result.job_id.clone(), - verdict: verification_result.verdict.clone(), - summary: verification_result.summary.clone(), - evidence_ids: verification_result.evidence_ids.clone(), - risks: verification_result.risks.clone(), - emitted_at: "2026-06-12T00:00:07Z".to_string(), - contract: "accepted exact verification".to_string(), - verification_request_id: verification_request.request_id.clone(), - frontier_route_id: verification_request.route_id.clone(), - }, - )?; - state.acceptance_receipts.push(EpiphanyAcceptanceReceipt { - id: "accept-verification-context".to_string(), - result_id: "result-verification-context".to_string(), - job_id: "verification-job-context".to_string(), - binding_id: "verification-review-worker".to_string(), - surface: "roleAccept".to_string(), - role_id: "verification".to_string(), - status: "accepted".to_string(), - accepted_at: "2026-06-12T00:00:07Z".to_string(), - accepted_observation_id: None, - accepted_evidence_id: None, - summary: Some("accepted exact verification".to_string()), - }); - let mut state_cache = crate::runtime_spine_cache(&runtime_store)?; - state_cache.put( - crate::THREAD_STATE_KEY, - &crate::EpiphanyThreadStateEntry::from_state("context-thread", &state)?, - )?; - - let modeling_context = append_modeling_work_loop_telemetry_context( - "".to_string(), - &runtime_store, - &state, - ) - .map_err(anyhow::Error::msg)?; - assert!(modeling_context.contains("")); - assert!(modeling_context.contains("hands-patch-context")); - assert!(modeling_context.contains("accept-verification-context")); - assert!(modeling_context.contains("Soul acceptance telemetry")); - assert!(modeling_context.contains("")); - let modeling_request_id = modeling_context - .repo_frontier_modeling_request_id - .as_deref() - .expect("Soul-bound Modeling context must return typed launch authority"); - let modeling_authority = modeling_context - .repo_frontier_verdict_modeling_authority - .as_ref() - .expect("Soul-bound Modeling context must carry the exact frontier item"); - let current_basis = crate::assemble_repo_model_view(&runtime_store)?.reasoning_basis(); - assert_eq!(modeling_authority.request.request_id, modeling_request_id); - assert_eq!( - modeling_authority.request.model_projection_digest, - current_basis.projection_digest - ); - assert_eq!( - modeling_authority.request.model_source_documents, - current_basis.source_documents - ); - assert_eq!( - modeling_authority.request.frontier_item_id, - modeling_authority.frontier_item.id - ); - assert_eq!( - modeling_authority.frontier_item.question, - "Does verification see the exact receipts?" - ); - assert!(modeling_context.contains(modeling_request_id)); - assert!(modeling_context.contains("modelProjectionDigest: sha256:")); - assert!(modeling_context.contains("modelSourceDocuments: epiphany-mind/")); - assert!(modeling_context.contains("soulVerdictReceiptId: soul-verdict-context")); - assert!(modeling_context.contains("verificationResultId: result-verification-context")); - assert!( - modeling_context - .contains("verificationAcceptanceReceiptId: accept-verification-context") - ); - assert!(modeling_context.contains("allowedDisposition: resolved")); - assert!( - modeling_context - .contains("Include the exact soulVerdictReceiptId in the top-level evidenceIds") - ); - assert!( - modeling_context - .contains("Include both verificationRequestId and soulVerdictReceiptId") - ); - assert!(modeling_context.contains("Set statePatch to null")); - assert!(modeling_context.contains("identityMigrationBody:")); - assert!( - modeling_context - .contains("identityQuestion: Does verification see the exact receipts?") - ); - assert!(modeling_context.contains("identityCreatedAt:")); - assert!(modeling_context.contains("identityRetiredAt: ")); - assert!(modeling_context.contains("identitySupersededBy: ")); - assert!( - modeling_context.contains( - "Copy every identity field exactly from the identity-prefixed values above" - ) - ); - assert!( - modeling_context.contains( - "Only status, evidence_refs, gap, and updated_at are verdict-owned changes" - ) - ); - let telemetry = load_latest_epiphany_cultmesh_work_loop_telemetry( - local_verse_store_path(&runtime_store), - EPIPHANY_LOCAL_VERSE_RUNTIME_ID, - )? - .expect("Modeling launch should preserve enriched CultMesh telemetry"); - assert_eq!(telemetry.source_stage, "hands+soul"); - assert_eq!(telemetry.target_stages, vec!["modeling".to_string()]); - assert_eq!( - telemetry.soul_receipt_ids, - vec!["accept-verification-context".to_string()] - ); - - fs::remove_dir_all(&temp)?; - Ok(()) - } - #[test] fn verification_launch_refuses_to_invent_a_pre_hands_request() -> anyhow::Result<()> { let temp = std::env::temp_dir().join(format!( diff --git a/epiphany-core/src/current_work.rs b/epiphany-core/src/current_work.rs index ab44c968..1b4193f5 100644 --- a/epiphany-core/src/current_work.rs +++ b/epiphany-core/src/current_work.rs @@ -23,6 +23,7 @@ pub struct EpiphanyCurrentWorkProjection { pub research_continuation_action: Option, pub frontier_planning_stage: RepoFrontierPlanningLifecycleStage, pub proposal_modeling: Option, + pub frontier_verdict_modeling: Option, pub hands_frontier_ready: bool, } @@ -41,6 +42,13 @@ pub struct EpiphanyProposalModelingWorkProjection { pub job_id: Option, } +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct EpiphanyFrontierVerdictModelingWorkProjection { + pub request: crate::RepoFrontierModelingRequest, + pub action: EpiphanyModelingContinuationAction, + pub job_id: Option, +} + #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct EpiphanyBodyModelingWorkProjection { pub work_id: String, @@ -321,10 +329,96 @@ pub fn project_current_work(store_path: impl AsRef) -> Result Result { + let prefix = format!("frontier-verdict-modeling-{request_id}-attempt-"); + job_id + .strip_prefix(&prefix) + .ok_or_else(|| anyhow!("frontier verdict Modeling job identity is not canonical"))? + .parse::() + .map_err(|_| anyhow!("frontier verdict Modeling attempt ordinal is invalid")) +} + +fn current_frontier_verdict_modeling_work( + cache: &CultCache, +) -> Result> { + let mut requests = cache.get_all::()?; + requests.sort_by(|left, right| left.request_id.cmp(&right.request_id)); + let launches = cache.get_all::()?; + let receipts = cache.get_all::()?; + for request in requests { + let mut request_launches = launches + .iter() + .filter(|launch| { + launch.repo_frontier_modeling_request_id.as_deref() + == Some(request.request_id.as_str()) + }) + .map(|launch| { + Ok(( + frontier_verdict_attempt_ordinal(&request.request_id, &launch.job_id)?, + launch, + )) + }) + .collect::>>()?; + request_launches.sort_by_key(|(ordinal, _)| *ordinal); + if let Some((_, launch)) = request_launches.last() + && let Some(result) = + cache.get::(&launch.job_id)? + && receipts.iter().any(|receipt| { + receipt.invariant_owner == "Modeling.frontier_verdict" + && matches!( + &receipt.authority, + crate::EpiphanyMindCommitAuthority::ModelDecisionContext { + decision_context_id + } if decision_context_id == &result.decision_context_id + ) + }) + { + continue; + } + crate::runtime_spine::validate_repo_frontier_modeling_request(cache, &request)?; + let Some((_, launch)) = request_launches.last() else { + return Ok(Some(EpiphanyFrontierVerdictModelingWorkProjection { + request, + action: EpiphanyModelingContinuationAction::Launch, + job_id: None, + })); + }; + let result = cache.get::(&launch.job_id)?; + if let Some(result) = result.as_ref() + && result.repo_frontier_modeling_request_id.as_deref() + != Some(request.request_id.as_str()) + { + return Err(anyhow!( + "frontier verdict Modeling result crossed request authority" + )); + } + let job = cache + .get::(&launch.job_id)? + .ok_or_else(|| anyhow!("frontier verdict Modeling launch lost its runtime job"))?; + let action = match job.status { + crate::EpiphanyRuntimeJobStatus::Failed + | crate::EpiphanyRuntimeJobStatus::Cancelled => { + EpiphanyModelingContinuationAction::Launch + } + crate::EpiphanyRuntimeJobStatus::Completed if result.is_some() => { + EpiphanyModelingContinuationAction::Review + } + _ => EpiphanyModelingContinuationAction::Wait, + }; + return Ok(Some(EpiphanyFrontierVerdictModelingWorkProjection { + request, + action, + job_id: Some(launch.job_id.clone()), + })); + } + Ok(None) +} + fn body_modeling_continuation_action( cache: &CultCache, work_id: &str, @@ -502,6 +596,25 @@ pub fn current_proposal_modeling_review_job_id( .and_then(|work| work.job_id)) } +pub fn frontier_verdict_modeling_continuation_action_for_job( + store_path: impl AsRef, + job_id: &str, +) -> Result> { + Ok(project_current_work(store_path)? + .frontier_verdict_modeling + .filter(|work| work.job_id.as_deref() == Some(job_id)) + .map(|work| work.action)) +} + +pub fn current_frontier_verdict_modeling_review_job_id( + store_path: impl AsRef, +) -> Result> { + Ok(project_current_work(store_path)? + .frontier_verdict_modeling + .filter(|work| work.action == EpiphanyModelingContinuationAction::Review) + .and_then(|work| work.job_id)) +} + pub fn accept_body_modeling_result( store_path: impl AsRef, job_id: &str, @@ -636,6 +749,86 @@ pub fn accept_proposal_modeling_result( } } +pub fn accept_frontier_verdict_modeling_result( + store_path: impl AsRef, + job_id: &str, + accepted_at: &str, +) -> Result { + let store_path = store_path.as_ref(); + let mut cache = crate::runtime_spine_cache(store_path)?; + cache.pull_all_backing_stores()?; + let current = current_frontier_verdict_modeling_work(&cache)? + .filter(|work| { + work.action == EpiphanyModelingContinuationAction::Review + && work.job_id.as_deref() == Some(job_id) + }) + .ok_or_else(|| anyhow!("frontier verdict Modeling result is not current review work"))?; + let result = cache + .get::(job_id)? + .ok_or_else(|| anyhow!("frontier verdict Modeling acceptance lost its typed result"))?; + if !result.role_id.eq_ignore_ascii_case("modeling") + || result.repo_frontier_modeling_request_id.as_deref() + != Some(current.request.request_id.as_str()) + || result.proposal_modeling_request_id.is_some() + { + return Err(anyhow!( + "frontier verdict Modeling result crossed family authority" + )); + } + let proposal = result + .repo_model_mutation_proposal()? + .ok_or_else(|| anyhow!("frontier verdict Modeling result has no mutation proposal"))?; + if proposal.proposal_id != format!("repo-model-mutation-proposal-{job_id}") { + return Err(anyhow!( + "frontier verdict Modeling mutation proposal identity is not runtime-owned" + )); + } + let plan = crate::plan_repo_model_mutation(store_path, &proposal)?; + let expected_frontier_version = current + .request + .model_source_documents + .iter() + .find(|source| { + source.document_type == crate::EpiphanyRepoModelFrontierDocument::TYPE + && source.document_key == current.request.frontier_item_id + }) + .ok_or_else(|| { + anyhow!("frontier verdict Modeling request lost its exact frontier version") + })?; + let planned_frontier = plan + .strong_reads + .iter() + .find(|envelope| { + envelope.r#type == crate::EpiphanyRepoModelFrontierDocument::TYPE + && envelope.key == current.request.frontier_item_id + }) + .ok_or_else(|| { + anyhow!("frontier verdict Modeling mutation omitted its strong frontier read") + })?; + if crate::EpiphanyMindDocumentVersion::from_envelope("epiphany-mind", planned_frontier)? + != *expected_frontier_version + { + return Err(anyhow!( + "frontier verdict Modeling output cannot be rebased onto a changed frontier" + )); + } + match crate::commit_mind_mutation( + store_path, + &result.decision_context_id, + "Modeling.frontier_verdict", + plan.strong_reads, + plan.writes, + accepted_at, + )? { + crate::EpiphanyMindCommitOutcome::Committed(receipt) => Ok(receipt), + crate::EpiphanyMindCommitOutcome::Conflict { + document_identities, + } => Err(anyhow!( + "frontier verdict Modeling admission lost exact keyed reads: {document_identities:?}" + )), + } +} + fn commit_current_work_launch( store_path: &Path, cache: &CultCache, @@ -735,6 +928,7 @@ pub fn launch_current_body_modeling_work( dynamic_prompt_context: None, repository_body_observation_basis: Some(work.body_basis.clone()), proposal_modeling_context: None, + frontier_verdict_modeling_context: None, frontier_planning_context: None, frontier_research_context: None, frontier_plan_mind_context: None, @@ -785,7 +979,6 @@ pub fn launch_current_body_modeling_work( admitted_model_direction_consideration_request_id: None, repo_frontier_modeling_request_id: None, repo_frontier_research_request_id: None, - repo_frontier_verdict_modeling_authority: None, created_at: options.created_at.clone(), }, )?; @@ -904,6 +1097,7 @@ pub fn launch_current_proposal_modeling_work( dynamic_prompt_context: None, repository_body_observation_basis: Some(body_basis), proposal_modeling_context: Some(proposal_context), + frontier_verdict_modeling_context: None, frontier_planning_context: None, frontier_research_context: None, frontier_plan_mind_context: None, @@ -957,7 +1151,6 @@ pub fn launch_current_proposal_modeling_work( admitted_model_direction_consideration_request_id: None, repo_frontier_modeling_request_id: None, repo_frontier_research_request_id: None, - repo_frontier_verdict_modeling_authority: None, created_at: options.created_at.clone(), }, )?; @@ -1017,6 +1210,156 @@ pub fn launch_current_proposal_modeling_work( Ok(binding) } +pub fn launch_current_frontier_verdict_modeling_work( + store_path: impl AsRef, + created_at: &str, +) -> Result { + let store_path = store_path.as_ref(); + if chrono::DateTime::parse_from_rfc3339(created_at).is_err() { + return Err(anyhow!("frontier verdict Modeling launch time is invalid")); + } + let mut cache = crate::runtime_spine_cache(store_path)?; + cache.pull_all_backing_stores()?; + let work = current_frontier_verdict_modeling_work(&cache)? + .filter(|work| work.action == EpiphanyModelingContinuationAction::Launch) + .ok_or_else(|| anyhow!("Mind has no launchable frontier verdict Modeling work"))?; + let request = work.request; + let verdict = cache + .get::(&request.soul_verdict_receipt_id)? + .ok_or_else(|| anyhow!("frontier verdict Modeling launch lost its Soul verdict"))?; + let frontier_document = cache + .get::(&request.frontier_item_id)? + .ok_or_else(|| anyhow!("frontier verdict Modeling launch lost its frontier document"))?; + let frontier_item = frontier_document.value()?; + let mind = crate::assemble_mind_view(store_path)?; + let body_basis = mind + .repository_body_observation + .clone() + .ok_or_else(|| anyhow!("frontier verdict Modeling launch requires admitted Body state"))?; + let identity = cache + .get::(crate::RUNTIME_IDENTITY_KEY)? + .ok_or_else(|| anyhow!("frontier verdict Modeling launch requires runtime identity"))?; + let attempt_ordinal = cache + .get_all::()? + .into_iter() + .filter(|launch| { + launch.repo_frontier_modeling_request_id.as_deref() == Some(request.request_id.as_str()) + }) + .map(|launch| frontier_verdict_attempt_ordinal(&request.request_id, &launch.job_id)) + .collect::>>()? + .into_iter() + .max() + .map_or(0, |ordinal| ordinal + 1); + let job_id = format!( + "frontier-verdict-modeling-{}-attempt-{attempt_ordinal}", + request.request_id + ); + let authority = crate::RepoFrontierVerdictModelingLaunchAuthority { + request: request.clone(), + frontier_item, + soul_verdict: verdict.clone(), + }; + let launch_document = + crate::EpiphanyWorkerLaunchDocument::Role(crate::EpiphanyRoleWorkerLaunchDocument { + thread_id: job_id.clone(), + role_id: "modeling".into(), + state_revision: 0, + objective: None, + dynamic_prompt_context: None, + repository_body_observation_basis: Some(body_basis), + proposal_modeling_context: None, + frontier_verdict_modeling_context: Some(authority), + frontier_planning_context: None, + frontier_research_context: None, + frontier_plan_mind_context: None, + imagination_consideration_context: None, + admitted_model_direction_consideration_context: None, + active_subgoal_id: None, + active_subgoals: Vec::new(), + active_graph_node_ids: Vec::new(), + investigation_checkpoint: None, + scratch: None, + invariants: Vec::new(), + graphs: None, + recent_evidence: Vec::new(), + recent_observations: Vec::new(), + graph_frontier: None, + graph_checkpoint: None, + planning: None, + churn: None, + }); + let authority_scope = "epiphany.role.modeling".to_string(); + let output_contract_id = launch_document.output_contract_id().to_string(); + let prepared = crate::prepare_runtime_spine_heartbeat_job( + &cache, + crate::RuntimeSpineHeartbeatJobOptions { + runtime_id: identity.runtime_id, + display_name: "Epiphany Local".into(), + session_id: crate::EPIPHANY_RUNTIME_ROOT_SESSION_ID.into(), + objective: "Incorporate one exact Soul verdict into its routed frontier".into(), + coordinator_note: + "Frontier verdict current-work launch transaction opened this session.".into(), + job_id: job_id.clone(), + role: crate::EPIPHANY_MODELING_OWNER_ROLE.into(), + binding_id: crate::EPIPHANY_MODELING_ROLE_BINDING_ID.into(), + authority_scope: authority_scope.clone(), + instruction: "Act as Epiphany Modeling. Incorporate the exact typed Soul verdict into only its routed frontier item and return the frontier-verdict result contract.".into(), + launch_document, + output_contract_id: output_contract_id.clone(), + organ_launch_contract: crate::default_launch_organ_contract( + &authority_scope, + "role", + &output_contract_id, + ), + proposal_modeling_request_id: None, + frontier_planning_request_id: None, + frontier_plan_mind_request_id: None, + imagination_consideration_request_id: None, + admitted_model_direction_consideration_request_id: None, + repo_frontier_modeling_request_id: Some(request.request_id.clone()), + repo_frontier_research_request_id: None, + created_at: created_at.to_string(), + }, + )?; + let grant = crate::substrate_gate::substrate_gate_repo_access_grant_for_worker( + format!("substrate-grant-{job_id}"), + job_id.clone(), + crate::EPIPHANY_MODELING_ROLE_BINDING_ID.into(), + crate::EPIPHANY_MODELING_OWNER_ROLE.into(), + authority_scope, + false, + created_at.to_string(), + ); + let snapshot = cache.snapshot_envelopes(); + let mut expected = Vec::new(); + for (document_type, document_key) in [ + ( + crate::RepoFrontierModelingRequest::TYPE, + request.request_id.as_str(), + ), + (crate::SoulVerdictReceipt::TYPE, verdict.receipt_id.as_str()), + ( + crate::EpiphanyRepoModelFrontierDocument::TYPE, + request.frontier_item_id.as_str(), + ), + ] { + let envelope = snapshot + .iter() + .find(|value| value.r#type == document_type && value.key == document_key) + .ok_or_else(|| anyhow!("frontier verdict Modeling launch lost a strong source"))?; + expected.push(envelope.clone()); + } + commit_current_work_launch( + store_path, + &cache, + expected, + prepared.envelopes, + vec![cache.prepare_entry(&grant.receipt_id, &grant)?.0], + "frontier verdict Modeling", + )?; + Ok(job_id) +} + fn build_proposal_modeling_context_projection( request: &crate::RepoFrontierProposalModelingRequest, proposal: &crate::RepoFrontierWorkProposal, @@ -1666,6 +2009,405 @@ mod tests { .get::(crate::THREAD_STATE_KEY)? .is_none() ); + + let model = crate::assemble_repo_model_view(&store)?; + let frontier_item = model + .frontier + .iter() + .find(|item| item.id == "proposal-frontier") + .cloned() + .expect("proposal admission created its frontier"); + let frontier_hash = format!( + "{:x}", + Sha256::digest(rmp_serde::to_vec_named(&frontier_item)?) + ); + let route = crate::RepoFrontierRoute { + schema_version: crate::REPO_FRONTIER_ROUTE_SCHEMA_VERSION.into(), + route_id: "route-proposal-frontier".into(), + next_organ: crate::RepoFrontierNextOrgan::Hands, + model_projection_digest: model.projection_digest.clone(), + model_source_documents: model.source_documents.clone(), + frontier_item_id: frontier_item.id.clone(), + frontier_item_hash: frontier_hash.clone(), + migration_body: frontier_item.migration_body.clone(), + question: frontier_item.question.clone(), + gap: frontier_item.gap.clone(), + target_claim_ids: frontier_item.target_claim_ids.clone(), + source_scope: frontier_item.source_scope.clone(), + adopted_plan: frontier_item.adopted_plan.clone(), + selected_at: "2026-08-17T00:00:14Z".into(), + contract: crate::REPO_FRONTIER_ROUTE_CONTRACT.into(), + }; + let verification_request = crate::RepoFrontierVerificationRequest { + schema_version: crate::REPO_FRONTIER_VERIFICATION_REQUEST_SCHEMA_VERSION.into(), + request_id: "verification-proposal-frontier".into(), + route_id: route.route_id.clone(), + model_projection_digest: route.model_projection_digest.clone(), + model_source_documents: route.model_source_documents.clone(), + frontier_item_id: route.frontier_item_id.clone(), + frontier_item_hash: route.frontier_item_hash.clone(), + hands_intent_id: "hands-intent".into(), + hands_review_id: "hands-review".into(), + hands_patch_receipt_id: "hands-patch".into(), + hands_command_receipt_id: "hands-command".into(), + hands_commit_receipt_id: "hands-commit".into(), + requested_at: "2026-08-17T00:00:15Z".into(), + contract: crate::REPO_FRONTIER_VERIFICATION_REQUEST_CONTRACT.into(), + }; + let verification_result = crate::EpiphanyRuntimeRoleWorkerResult { + schema_version: crate::RUNTIME_ROLE_WORKER_RESULT_SCHEMA_VERSION.into(), + result_id: "verification-result".into(), + job_id: "verification-job".into(), + role_id: "verification".into(), + verdict: "pass".into(), + summary: "verified exact consequence".into(), + next_safe_move: "incorporate verdict".into(), + checkpoint_summary: None, + scratch_summary: None, + files_inspected: Vec::new(), + frontier_node_ids: vec!["body-node".into()], + evidence_ids: vec!["hands-commit".into()], + 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_mutation_proposal_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, + frontier_planning_request_id: None, + frontier_plan_candidate_msgpack: None, + frontier_plan_mind_request_id: None, + frontier_plan_mind_decision_msgpack: None, + repository_body_observation_basis: None, + imagination_consideration_request_id: None, + imagination_consideration_candidate_msgpack: None, + admitted_model_direction_consideration_request_id: None, + admitted_model_direction_consideration_result_msgpack: None, + decision_context_id: "verification-context".into(), + }; + let verdict = crate::SoulVerdictReceipt { + schema_version: crate::SOUL_VERDICT_RECEIPT_SCHEMA_VERSION.into(), + receipt_id: "soul-verdict-verification-result".into(), + source_result_id: verification_result.result_id.clone(), + source_job_id: verification_result.job_id.clone(), + verdict: verification_result.verdict.clone(), + summary: verification_result.summary.clone(), + evidence_ids: verification_result.evidence_ids.clone(), + risks: verification_result.risks.clone(), + emitted_at: "2026-08-17T00:00:16Z".into(), + contract: "test Soul verdict".into(), + verification_request_id: verification_request.request_id.clone(), + frontier_route_id: route.route_id.clone(), + }; + accepted_cache.put(&route.route_id, &route)?; + accepted_cache.put(&verification_request.request_id, &verification_request)?; + accepted_cache.put(&verification_result.job_id, &verification_result)?; + accepted_cache.put(&verdict.receipt_id, &verdict)?; + let verdict_request = crate::commit_repo_frontier_modeling_request(&store, &verdict)?; + assert_eq!( + project_current_work(&store)? + .frontier_verdict_modeling + .expect("Soul verdict creates frontier Modeling work") + .action, + EpiphanyModelingContinuationAction::Launch + ); + let verdict_racers = (0..2) + .map(|_| { + let store = store.clone(); + std::thread::spawn(move || { + launch_current_frontier_verdict_modeling_work(&store, "2026-08-17T00:00:17Z") + }) + }) + .collect::>(); + let verdict_launches = verdict_racers + .into_iter() + .map(|racer| racer.join().expect("verdict launch racer panicked")) + .collect::>(); + let verdict_job_id = verdict_launches + .iter() + .find_map(|result| result.as_ref().ok()) + .cloned() + .expect("one frontier verdict launch racer must commit"); + assert!( + verdict_launches + .iter() + .filter(|result| result.is_ok()) + .count() + == 1 + ); + assert_eq!( + verdict_job_id, + format!( + "frontier-verdict-modeling-{}-attempt-0", + verdict_request.request_id + ) + ); + let mut verdict_cache = crate::runtime_spine_cache(&store)?; + verdict_cache.pull_all_backing_stores()?; + let verdict_launch = verdict_cache + .get::(&verdict_job_id)? + .expect("frontier verdict runtime launch"); + let crate::EpiphanyWorkerLaunchDocument::Role(verdict_document) = + verdict_launch.launch_document()? + else { + panic!("frontier verdict Modeling must be a role pass") + }; + assert!(verdict_document.dynamic_prompt_context.is_none()); + assert_eq!( + verdict_document + .frontier_verdict_modeling_context + .as_ref() + .expect("sealed typed verdict context") + .soul_verdict, + verdict + ); + let verdict_basis = crate::worker_reasoning_basis(&store, &verdict_launch)?; + crate::put_reasoning_basis(&store, &verdict_basis)?; + let mut verdict_native = epiphany_model_adapter::EpiphanyModelRequest::new( + "frontier-verdict-request", + "frontier-verdict-conversation", + "openai-codex", + "gpt-test", + "model", + ); + verdict_native.reasoning_basis_id = Some(verdict_basis.basis_id.clone()); + verdict_native.source_worker_job_id = Some(verdict_job_id.clone()); + let verdict_provider = epiphany_openai_adapter::request_from_native(&verdict_native); + let verdict_context = crate::EpiphanyDecisionContext::new( + &verdict_basis, + verdict_native, + verdict_provider, + Vec::new(), + )?; + verdict_cache.put(&verdict_context.context_id, &verdict_context)?; + + // A separate typed mutation may extend another semantic identity after + // this pass seals its basis. That is concurrency, not staleness: the + // verdict result owns only the routed frontier and its exact + // dependencies. + let mut unrelated_node = model + .nodes + .iter() + .find(|node| node.id == "body-node") + .cloned() + .expect("seeded Body node"); + unrelated_node.id = "concurrent-unrelated-node".into(); + unrelated_node.title = "Concurrent unrelated node".into(); + unrelated_node.claim = "Disjoint keyed Mind writes merge".into(); + unrelated_node.updated_at = Some("2026-08-17T00:00:17.500Z".into()); + let unrelated_proposal = crate::EpiphanyRepoModelMutationProposal::new( + "repo-model-mutation-proposal-concurrent-unrelated", + "concurrent-unrelated-request", + "concurrent-unrelated-result", + vec![verdict.receipt_id.clone()], + body.clone(), + vec![crate::EpiphanyRepoModelMutationOperation::PutNode { + node: unrelated_node, + }], + )?; + let unrelated_plan = crate::plan_repo_model_mutation(&store, &unrelated_proposal)?; + let verdict_provenance = verdict_cache + .get_envelope::(&verdict.receipt_id)? + .expect("typed Soul provenance"); + assert!(matches!( + crate::commit_typed_organ_mind_mutation( + &store, + "Modeling", + verdict_provenance, + "Modeling.concurrent_unrelated_fixture", + unrelated_plan.strong_reads, + unrelated_plan.writes, + "2026-08-17T00:00:17.500Z", + )?, + crate::EpiphanyMindCommitOutcome::Committed(_) + )); + + let mut resolved_item = frontier_item.clone(); + resolved_item.status = RepoFrontierStatus::Resolved; + resolved_item.gap = "The exact consequence passed Soul verification.".into(); + resolved_item.updated_at = Some("2026-08-17T00:00:18Z".into()); + resolved_item + .evidence_refs + .push(verification_request.request_id.clone()); + resolved_item.evidence_refs.push(verdict.receipt_id.clone()); + resolved_item.evidence_refs.sort(); + resolved_item.evidence_refs.dedup(); + let verdict_result_id = "frontier-verdict-result"; + let verdict_mutation = crate::EpiphanyRepoModelMutationProposal::new( + format!("repo-model-mutation-proposal-{verdict_job_id}"), + verdict_request.request_id.clone(), + verdict_result_id, + vec![verdict.receipt_id.clone()], + body.clone(), + vec![crate::EpiphanyRepoModelMutationOperation::PutFrontier { + item: resolved_item, + }], + )?; + let verdict_result = crate::EpiphanyRuntimeRoleWorkerResult { + schema_version: crate::RUNTIME_ROLE_WORKER_RESULT_SCHEMA_VERSION.into(), + result_id: verdict_result_id.into(), + job_id: verdict_job_id.clone(), + role_id: "modeling".into(), + verdict: "checkpoint-update-needed".into(), + summary: "Soul verdict incorporated".into(), + next_safe_move: "admit".into(), + checkpoint_summary: None, + scratch_summary: None, + files_inspected: Vec::new(), + frontier_node_ids: vec!["body-node".into()], + evidence_ids: vec![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_mutation_proposal_msgpack: Some(rmp_serde::to_vec_named(&verdict_mutation)?), + verification_request_id: None, + frontier_route_id: None, + repo_frontier_modeling_request_id: Some(verdict_request.request_id.clone()), + proposal_modeling_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, + repository_body_observation_basis: Some(body.clone()), + imagination_consideration_request_id: None, + imagination_consideration_candidate_msgpack: None, + admitted_model_direction_consideration_request_id: None, + admitted_model_direction_consideration_result_msgpack: None, + decision_context_id: verdict_context.context_id.clone(), + }; + let verdict_process = crate::ProcessInstanceIdentity { + process_id: 43, + creation_token: 8, + created_at_rfc3339: Some("2026-08-17T00:00:18Z".into()), + executable_path: "verdict-worker".into(), + }; + let verdict_activation = "verdict-activation"; + crate::claim_runtime_worker_process( + &store, + &verdict_job_id, + &verdict_process, + &format!("{:x}", Sha256::digest(verdict_activation.as_bytes())), + "2026-08-17T00:00:18Z", + )?; + crate::activate_runtime_worker_process( + &store, + &verdict_job_id, + &verdict_process, + verdict_activation, + "2026-08-17T00:00:19Z", + )?; + crate::put_runtime_role_worker_result(&store, &verdict_result)?; + crate::complete_runtime_job( + &store, + crate::RuntimeSpineJobResultOptions { + result_id: format!("runtime-result-{verdict_job_id}"), + job_id: verdict_job_id.clone(), + completed_at: "2026-08-17T00:00:20Z".into(), + verdict: verdict_result.verdict.clone(), + summary: verdict_result.summary.clone(), + next_safe_move: verdict_result.next_safe_move.clone(), + evidence_refs: verdict_result.evidence_ids.clone(), + artifact_refs: Vec::new(), + decision_context_id: Some(verdict_context.context_id.clone()), + }, + )?; + assert_eq!( + project_current_work(&store)? + .frontier_verdict_modeling + .expect("terminal verdict work awaits admission") + .action, + EpiphanyModelingContinuationAction::Review + ); + + // The same fixture, copied before admission, proves the other half of + // the merge law. If another valid mutation changes this exact frontier, + // the sealed verdict output is stale and must not be silently rebased. + let conflict_store = temp.path().join("frontier-conflict.cc"); + std::fs::copy(&store, &conflict_store)?; + let mut competing_item = frontier_item.clone(); + competing_item.gap = "A competing decision changed this exact frontier.".into(); + competing_item.updated_at = Some("2026-08-17T00:00:20.500Z".into()); + let competing_proposal = crate::EpiphanyRepoModelMutationProposal::new( + "repo-model-mutation-proposal-competing-frontier", + "competing-frontier-request", + "competing-frontier-result", + vec![verdict.receipt_id.clone()], + body.clone(), + vec![crate::EpiphanyRepoModelMutationOperation::PutFrontier { + item: competing_item, + }], + )?; + let competing_plan = crate::plan_repo_model_mutation(&conflict_store, &competing_proposal)?; + let mut conflict_cache = crate::runtime_spine_cache(&conflict_store)?; + conflict_cache.pull_all_backing_stores()?; + let conflict_provenance = conflict_cache + .get_envelope::(&verdict.receipt_id)? + .expect("copied Soul provenance"); + assert!(matches!( + crate::commit_typed_organ_mind_mutation( + &conflict_store, + "Soul", + conflict_provenance, + "Soul.competing_frontier_fixture", + competing_plan.strong_reads, + competing_plan.writes, + "2026-08-17T00:00:20.500Z", + )?, + crate::EpiphanyMindCommitOutcome::Committed(_) + )); + let mut conflict_before = crate::runtime_spine_cache(&conflict_store)?; + conflict_before.pull_all_backing_stores()?; + let conflict_before = conflict_before.snapshot_envelopes(); + assert!( + accept_frontier_verdict_modeling_result( + &conflict_store, + &verdict_job_id, + "2026-08-17T00:00:21Z", + ) + .is_err() + ); + let mut conflict_after = crate::runtime_spine_cache(&conflict_store)?; + conflict_after.pull_all_backing_stores()?; + assert_eq!(conflict_after.snapshot_envelopes(), conflict_before); + + let verdict_commit = accept_frontier_verdict_modeling_result( + &store, + &verdict_job_id, + "2026-08-17T00:00:21Z", + )?; + assert_eq!(verdict_commit.invariant_owner, "Modeling.frontier_verdict"); + assert!( + project_current_work(&store)? + .frontier_verdict_modeling + .is_none() + ); + let final_model = crate::assemble_repo_model_view(&store)?; + assert_eq!( + final_model + .frontier + .iter() + .find(|item| item.id == frontier_item.id) + .expect("frontier persists") + .status, + RepoFrontierStatus::Resolved + ); + assert!( + final_model + .nodes + .iter() + .any(|node| node.id == "concurrent-unrelated-node") + ); Ok(()) } } diff --git a/epiphany-core/src/lib.rs b/epiphany-core/src/lib.rs index 3729c1b5..d52e20a0 100644 --- a/epiphany-core/src/lib.rs +++ b/epiphany-core/src/lib.rs @@ -228,9 +228,7 @@ pub use coordinator_launch::EpiphanyCoordinatorJobLaunchPlan; pub use coordinator_launch::commit_coordinator_job_launch; pub use coordinator_launch::plan_coordinator_job_launch; pub use coordinator_launch_context::EPIPHANY_LOCAL_VERSE_RUNTIME_ID; -pub use coordinator_launch_context::ModelingWorkLoopLaunchContext; pub use coordinator_launch_context::append_modeling_repo_model_shape_context; -pub use coordinator_launch_context::append_modeling_work_loop_telemetry_context; pub use coordinator_launch_context::append_verification_hands_receipt_context; pub use coordinator_launch_context::has_complete_hands_consequence_after_latest_accepted_boundary; pub use coordinator_launch_context::local_verse_store_path; @@ -1109,8 +1107,6 @@ pub use runtime_spine::put_runtime_requested_public_source_intents; pub use runtime_spine::put_runtime_role_worker_result; pub use runtime_spine::put_runtime_tool_execution_intent; pub use runtime_spine::put_runtime_tool_execution_receipt; -#[cfg(test)] -pub(crate) use runtime_spine::put_soul_verdict_receipt; pub use runtime_spine::put_substrate_gate_repo_access_grant_receipt; pub use runtime_spine::relinquish_repo_frontier_hands_route; pub use runtime_spine::repair_legacy_terminal_coordinator_sessions; diff --git a/epiphany-core/src/reasoning_context.rs b/epiphany-core/src/reasoning_context.rs index b7f2a3f0..5920a646 100644 --- a/epiphany-core/src/reasoning_context.rs +++ b/epiphany-core/src/reasoning_context.rs @@ -30,6 +30,8 @@ pub struct EpiphanyRolePassAuthorityProjection { pub dynamic_prompt_context: Option, pub repository_body_observation_basis: Option, pub proposal_modeling_context: Option, + pub frontier_verdict_modeling_context: + Option, pub frontier_planning_context: Option, pub frontier_research_context: Option, pub frontier_plan_mind_context: Option, @@ -46,6 +48,7 @@ impl From for EpiphanyRolePassAuthorityProject dynamic_prompt_context: value.dynamic_prompt_context, repository_body_observation_basis: value.repository_body_observation_basis, proposal_modeling_context: value.proposal_modeling_context, + frontier_verdict_modeling_context: value.frontier_verdict_modeling_context, frontier_planning_context: value.frontier_planning_context, frontier_research_context: value.frontier_research_context, frontier_plan_mind_context: value.frontier_plan_mind_context, @@ -1211,6 +1214,7 @@ mod tests { dynamic_prompt_context: Some("typed projection".into()), repository_body_observation_basis: None, proposal_modeling_context: None, + frontier_verdict_modeling_context: None, frontier_planning_context: None, frontier_research_context: None, frontier_plan_mind_context: None, @@ -1257,7 +1261,6 @@ mod tests { admitted_model_direction_consideration_request_id: None, repo_frontier_modeling_request_id: None, repo_frontier_research_request_id: None, - repo_frontier_verdict_modeling_authority_msgpack: None, }) } diff --git a/epiphany-core/src/repo_model_gateway.rs b/epiphany-core/src/repo_model_gateway.rs index d09c3fcd..a9d7cba0 100644 --- a/epiphany-core/src/repo_model_gateway.rs +++ b/epiphany-core/src/repo_model_gateway.rs @@ -56,9 +56,9 @@ pub const REPO_FRONTIER_EXECUTION_AMENDMENT_RECEIPT_CONTRACT: &str = pub const REPO_FRONTIER_MODELING_REQUEST_TYPE: &str = "epiphany.modeling.repo_frontier_verdict_request"; pub const REPO_FRONTIER_MODELING_REQUEST_SCHEMA_VERSION: &str = - "epiphany.modeling.repo_frontier_verdict_request.v0"; + "epiphany.modeling.repo_frontier_verdict_request.v1"; pub const REPO_FRONTIER_MODELING_REQUEST_CONTRACT: &str = - "epiphany.repo_frontier_verdict_modeling_request.v0"; + "epiphany.repo_frontier_verdict_modeling_request.v1"; pub const REPO_FRONTIER_WORK_PROPOSAL_SCHEMA_VERSION: &str = "epiphany.repo_frontier_work_proposal.v0"; pub const REPO_FRONTIER_PLANNING_REQUEST_SCHEMA_VERSION: &str = @@ -799,12 +799,10 @@ pub struct RepoFrontierModelingRequest { #[cultcache(key = 10)] pub verification_job_id: String, #[cultcache(key = 11)] - pub verification_acceptance_receipt_id: String, - #[cultcache(key = 12)] pub allowed_disposition: RepoFrontierVerdictDisposition, - #[cultcache(key = 13)] + #[cultcache(key = 12)] pub requested_at: String, - #[cultcache(key = 14)] + #[cultcache(key = 13)] pub contract: String, } diff --git a/epiphany-core/src/resident_self.rs b/epiphany-core/src/resident_self.rs index d1574b26..e371747e 100644 --- a/epiphany-core/src/resident_self.rs +++ b/epiphany-core/src/resident_self.rs @@ -67,6 +67,7 @@ impl ResidentSelfPressure { | "imagination-consideration" | "imagination-proposal" | "repo-frontier-proposal-modeling" + | "repo-frontier-verdict-modeling" | RESIDENT_SELF_BODY_MODELING_PRESSURE_KIND | RESIDENT_SELF_ATLAS_MODELING_PRESSURE_KIND | RESIDENT_SELF_ATLAS_SOUL_PRESSURE_KIND @@ -1198,6 +1199,28 @@ pub fn ingest_resident_self_domain_pressure( created_at_millis: now_millis, status: "pending".into(), consumed_by_grant_id: None, private_state_exposed: false, })?); } + if let Some(work) = crate::project_current_work(runtime_store)? + .frontier_verdict_modeling + .filter(|work| work.action == crate::EpiphanyModelingContinuationAction::Launch) + { + inserted += usize::from(enqueue_resident_self_pressure_idempotent( + resident_store, + &ResidentSelfPressure { + schema_version: RESIDENT_SELF_PRESSURE_SCHEMA_VERSION.into(), + pressure_id: format!("repo-frontier-verdict-modeling-{}", work.request.request_id), + kind: "repo-frontier-verdict-modeling".into(), + provenance_ref: format!( + "cultcache://repo-frontier-verdict-modeling/{}", + work.request.request_id + ), + objective: "Launch the exact Soul-verdict-bound Modeling obligation; no unrelated Mind mutation or external consequence.".into(), + created_at_millis: now_millis, + status: "pending".into(), + consumed_by_grant_id: None, + private_state_exposed: false, + }, + )?); + } crate::promote_autonomous_direction_options_for_modeling( runtime_store, repository, @@ -1380,6 +1403,19 @@ pub(crate) fn resident_self_safe_continuation_action( } }); } + if let Some(action) = + crate::frontier_verdict_modeling_continuation_action_for_job(runtime_store, job_id)? + { + return Ok(match action { + crate::EpiphanyModelingContinuationAction::Launch => { + Some("launchModeling".to_string()) + } + crate::EpiphanyModelingContinuationAction::Wait => None, + crate::EpiphanyModelingContinuationAction::Review => { + Some("reviewModelingResult".to_string()) + } + }); + } } } let direct = matches!( @@ -1488,11 +1524,16 @@ fn resident_self_failed_receipt_typed_continuation_action( { return Ok(None); } - let Some(crate::RuntimeTypedRequestRef::ProposalModeling(request_id)) = - resident_self_typed_request_ref(&grant)? - else { + let Some(request) = resident_self_typed_request_ref(&grant)? else { return Ok(None); }; + if !matches!( + request, + crate::RuntimeTypedRequestRef::ProposalModeling(_) + | crate::RuntimeTypedRequestRef::FrontierVerdictModeling(_) + ) { + return Ok(None); + } let acknowledgements = resident .get_all::()? .into_iter() @@ -1511,25 +1552,30 @@ fn resident_self_failed_receipt_typed_continuation_action( "failed coordinator receipt typed continuation lost its exact resident binding" )); } - let Some(evidence) = crate::runtime_typed_request_fulfillment( - runtime_store, - crate::RuntimeTypedRequestRef::ProposalModeling(request_id), - )? - else { + let Some(evidence) = crate::runtime_typed_request_fulfillment(runtime_store, request)? else { return Ok(None); }; - Ok( - match crate::proposal_modeling_continuation_action_for_job(runtime_store, &evidence.job_id)? - { - Some(crate::EpiphanyModelingContinuationAction::Review) => { - Some("reviewModelingResult".to_string()) - } - Some(crate::EpiphanyModelingContinuationAction::Launch) => { - Some("launchModeling".to_string()) - } - Some(crate::EpiphanyModelingContinuationAction::Wait) | None => None, - }, - ) + let action = match request { + crate::RuntimeTypedRequestRef::ProposalModeling(_) => { + crate::proposal_modeling_continuation_action_for_job(runtime_store, &evidence.job_id)? + } + crate::RuntimeTypedRequestRef::FrontierVerdictModeling(_) => { + crate::frontier_verdict_modeling_continuation_action_for_job( + runtime_store, + &evidence.job_id, + )? + } + _ => None, + }; + Ok(match action { + Some(crate::EpiphanyModelingContinuationAction::Review) => { + Some("reviewModelingResult".to_string()) + } + Some(crate::EpiphanyModelingContinuationAction::Launch) => { + Some("launchModeling".to_string()) + } + Some(crate::EpiphanyModelingContinuationAction::Wait) | None => None, + }) } pub fn ingest_resident_self_coordinator_continuation_pressure( @@ -1834,6 +1880,18 @@ fn resident_self_typed_request_ref<'a>( .ok_or_else(|| anyhow!("proposal Modeling grant lost exact request provenance"))?; Some(crate::RuntimeTypedRequestRef::ProposalModeling(request_id)) } + "repo-frontier-verdict-modeling" => { + let request_id = grant + .provenance_ref + .strip_prefix("cultcache://repo-frontier-verdict-modeling/") + .filter(|value| !value.trim().is_empty()) + .ok_or_else(|| { + anyhow!("frontier verdict Modeling grant lost exact request provenance") + })?; + Some(crate::RuntimeTypedRequestRef::FrontierVerdictModeling( + request_id, + )) + } "admitted-model-direction-consideration" => { let request_id = grant .provenance_ref diff --git a/epiphany-core/src/runtime_spine.rs b/epiphany-core/src/runtime_spine.rs index 9830e714..9c21f0d0 100644 --- a/epiphany-core/src/runtime_spine.rs +++ b/epiphany-core/src/runtime_spine.rs @@ -457,8 +457,6 @@ pub struct EpiphanyRuntimeWorkerLaunchRequest { pub admitted_model_direction_consideration_request_id: Option, #[cultcache(key = 17, default)] pub repo_frontier_modeling_request_id: Option, - #[cultcache(key = 18, default)] - pub repo_frontier_verdict_modeling_authority_msgpack: Option>, #[cultcache(key = 19, default)] pub repo_frontier_research_request_id: Option, } @@ -535,19 +533,10 @@ fn worker_process_claim_id(job_id: &str) -> String { pub struct RepoFrontierVerdictModelingLaunchAuthority { pub request: RepoFrontierModelingRequest, pub frontier_item: crate::RepoFrontierItem, + pub soul_verdict: SoulVerdictReceipt, } impl EpiphanyRuntimeWorkerLaunchRequest { - pub fn repo_frontier_verdict_modeling_authority( - &self, - ) -> Result> { - decode_optional_msgpack( - self.repo_frontier_verdict_modeling_authority_msgpack - .as_deref(), - "verdict-bound Modeling launch authority", - ) - } - pub fn launch_document(&self) -> Result { let document: EpiphanyWorkerLaunchDocument = rmp_serde::from_slice(&self.launch_document_msgpack) @@ -1021,8 +1010,6 @@ pub struct RuntimeSpineHeartbeatJobOptions { pub admitted_model_direction_consideration_request_id: Option, pub repo_frontier_modeling_request_id: Option, pub repo_frontier_research_request_id: Option, - pub repo_frontier_verdict_modeling_authority: - Option, pub created_at: String, } @@ -1077,8 +1064,6 @@ pub struct EpiphanyJobLaunchRequest { pub admitted_model_direction_consideration_request_id: Option, pub repo_frontier_modeling_request_id: Option, pub repo_frontier_research_request_id: Option, - pub repo_frontier_verdict_modeling_authority: - Option, } #[derive(Debug, Clone, PartialEq)] @@ -3157,7 +3142,7 @@ pub fn open_runtime_spine_heartbeat_job( validate_repo_frontier_verdict_modeling_launch_authority( &options.role, options.repo_frontier_modeling_request_id.as_deref(), - options.repo_frontier_verdict_modeling_authority.as_ref(), + &options.launch_document, )?; validate_non_empty(&options.binding_id, "binding id")?; validate_non_empty(&options.authority_scope, "authority scope")?; @@ -3250,11 +3235,6 @@ pub fn open_runtime_spine_heartbeat_job( .admitted_model_direction_consideration_request_id, repo_frontier_modeling_request_id: options.repo_frontier_modeling_request_id, repo_frontier_research_request_id: options.repo_frontier_research_request_id, - repo_frontier_verdict_modeling_authority_msgpack: options - .repo_frontier_verdict_modeling_authority - .as_ref() - .map(rmp_serde::to_vec_named) - .transpose()?, }; cache.put(&job_id, &request)?; Ok(job) @@ -3298,7 +3278,7 @@ pub fn prepare_runtime_spine_heartbeat_job( validate_repo_frontier_verdict_modeling_launch_authority( &options.role, options.repo_frontier_modeling_request_id.as_deref(), - options.repo_frontier_verdict_modeling_authority.as_ref(), + &options.launch_document, )?; validate_non_empty(&options.binding_id, "binding id")?; validate_non_empty(&options.authority_scope, "authority scope")?; @@ -3417,11 +3397,6 @@ pub fn prepare_runtime_spine_heartbeat_job( .admitted_model_direction_consideration_request_id, repo_frontier_modeling_request_id: options.repo_frontier_modeling_request_id, repo_frontier_research_request_id: options.repo_frontier_research_request_id, - repo_frontier_verdict_modeling_authority_msgpack: options - .repo_frontier_verdict_modeling_authority - .as_ref() - .map(rmp_serde::to_vec_named) - .transpose()?, }; let envelopes = vec![ cache.prepare_entry(RUNTIME_IDENTITY_KEY, &identity)?.0, @@ -3436,8 +3411,14 @@ pub fn prepare_runtime_spine_heartbeat_job( fn validate_repo_frontier_verdict_modeling_launch_authority( role: &str, request_id: Option<&str>, - authority: Option<&RepoFrontierVerdictModelingLaunchAuthority>, + launch_document: &EpiphanyWorkerLaunchDocument, ) -> Result<()> { + let authority = match launch_document { + EpiphanyWorkerLaunchDocument::Role(document) => { + document.frontier_verdict_modeling_context.as_ref() + } + EpiphanyWorkerLaunchDocument::Reorient(_) => None, + }; match (request_id, authority) { (None, None) => Ok(()), (Some(_), None) => Err(anyhow!( @@ -3462,11 +3443,88 @@ fn validate_repo_frontier_verdict_modeling_launch_authority( "verdict-bound Modeling authority does not carry its exact frontier item" )); } + if authority.request.soul_verdict_receipt_id != authority.soul_verdict.receipt_id { + return Err(anyhow!( + "verdict-bound Modeling authority does not carry its exact Soul verdict" + )); + } Ok(()) } } } +fn validate_repo_frontier_verdict_modeling_mutation( + cache: &CultCache, + launch_document: &EpiphanyWorkerLaunchDocument, + proposal: &crate::EpiphanyRepoModelMutationProposal, +) -> Result<()> { + let authority = match launch_document { + EpiphanyWorkerLaunchDocument::Role(document) => document + .frontier_verdict_modeling_context + .as_ref() + .ok_or_else(|| anyhow!("frontier verdict Modeling result lost its typed context"))?, + EpiphanyWorkerLaunchDocument::Reorient(_) => { + return Err(anyhow!( + "frontier verdict Modeling authority cannot cross a reorientation launch" + )); + } + }; + validate_repo_frontier_modeling_request(cache, &authority.request)?; + let persisted_verdict = cache + .get::(&authority.soul_verdict.receipt_id)? + .ok_or_else(|| anyhow!("frontier verdict Modeling context lost its Soul verdict"))?; + let current_item = cache + .get::(&authority.frontier_item.id)? + .ok_or_else(|| anyhow!("frontier verdict Modeling context lost its frontier item"))? + .value()?; + if persisted_verdict != authority.soul_verdict || current_item != authority.frontier_item { + return Err(anyhow!( + "frontier verdict Modeling context does not bind current typed authority" + )); + } + let operations = proposal.operations()?; + let [crate::EpiphanyRepoModelMutationOperation::PutFrontier { item }] = operations.as_slice() + else { + return Err(anyhow!( + "frontier verdict Modeling result must revise exactly one frontier identity" + )); + }; + let expected_status = match authority.request.allowed_disposition { + RepoFrontierVerdictDisposition::Resolved => crate::RepoFrontierStatus::Resolved, + RepoFrontierVerdictDisposition::Blocked => crate::RepoFrontierStatus::Blocked, + }; + let mut expected_evidence = authority.frontier_item.evidence_refs.clone(); + expected_evidence.push(authority.request.verification_request_id.clone()); + expected_evidence.push(authority.request.soul_verdict_receipt_id.clone()); + expected_evidence.sort(); + expected_evidence.dedup(); + if item.id != authority.frontier_item.id + || item.migration_body != authority.frontier_item.migration_body + || item.question != authority.frontier_item.question + || item.target_claim_ids != authority.frontier_item.target_claim_ids + || item.source_scope != authority.frontier_item.source_scope + || item.recommended_next_organ != authority.frontier_item.recommended_next_organ + || item.adopted_plan != authority.frontier_item.adopted_plan + || item.dependency_item_ids != authority.frontier_item.dependency_item_ids + || item.public_source_refs != authority.frontier_item.public_source_refs + || item.created_at != authority.frontier_item.created_at + || item.retired_at != authority.frontier_item.retired_at + || item.superseded_by != authority.frontier_item.superseded_by + || item.status != expected_status + || item.evidence_refs != expected_evidence + || item.gap.trim().is_empty() + || item + .updated_at + .as_deref() + .is_none_or(|value| chrono::DateTime::parse_from_rfc3339(value).is_err()) + { + return Err(anyhow!( + "frontier verdict Modeling result exceeded its exact routed mutation authority" + )); + } + Ok(()) +} + fn validate_proposal_modeling_launch_carrier( role: &str, binding_id: &str, @@ -4576,6 +4634,9 @@ pub fn put_runtime_role_worker_result( "frontier Modeling request may authorize only semantic RepoModel frontier mutation" )); } + if worker_launch.repo_frontier_modeling_request_id.is_some() { + validate_repo_frontier_verdict_modeling_mutation(&cache, &launch_document, &proposal)?; + } } let has_planning_echo = result.frontier_planning_request_id.is_some(); let has_planning_candidate = result.frontier_plan_candidate_msgpack.is_some(); @@ -5373,6 +5434,7 @@ pub fn runtime_typed_request_fulfillment( RuntimeTypedRequestRef::ProposalModeling(_) => { validate_proposal_modeling_worker_fulfillment(&cache, result)?; } + RuntimeTypedRequestRef::FrontierVerdictModeling(_) => {} RuntimeTypedRequestRef::ImaginationConsideration(_) => { let candidate = result .imagination_consideration_candidate()? @@ -7288,7 +7350,7 @@ pub fn select_and_commit_repo_frontier_route( "Hands frontier route requires safe sorted source scope" )); } - let item_hash = format!("{:x}", Sha256::digest(rmp_serde::to_vec_named(item)?)); + let item_hash = format!("{:x}", Sha256::digest(rmp_serde::to_vec_named(&item)?)); let route_seed = format!("{}:{}:{}", basis.projection_digest, item.id, item_hash); let route_id = format!( "repo-frontier-route-{:x}", @@ -9210,81 +9272,39 @@ pub fn runtime_latest_repo_frontier_relinquishment( Ok(receipts.pop()) } -pub fn commit_repo_frontier_modeling_request( - store_path: impl AsRef, - acceptance: &epiphany_state_model::EpiphanyAcceptanceReceipt, +pub(crate) fn derive_repo_frontier_modeling_request( + cache: &CultCache, + verdict: &SoulVerdictReceipt, ) -> Result { - if acceptance.role_id != "verification" - || acceptance.surface != "roleAccept" - || acceptance.status != "accepted" - || acceptance.result_id.trim().is_empty() - || acceptance.job_id.trim().is_empty() - || chrono::DateTime::parse_from_rfc3339(&acceptance.accepted_at).is_err() + let identity = require_identity(cache)?; + if verdict.schema_version != SOUL_VERDICT_RECEIPT_SCHEMA_VERSION + || verdict.receipt_id.trim().is_empty() + || verdict.source_result_id.trim().is_empty() + || verdict.source_job_id.trim().is_empty() + || chrono::DateTime::parse_from_rfc3339(&verdict.emitted_at).is_err() { return Err(anyhow!( - "frontier Modeling request requires one accepted Verification receipt" + "frontier Modeling request requires one typed Soul verdict" )); } - let mut cache = runtime_spine_cache(store_path.as_ref())?; - cache.pull_all_backing_stores()?; - require_identity(&cache)?; - let state = cache - .get::(crate::THREAD_STATE_KEY)? - .ok_or_else(|| anyhow!("frontier Modeling request requires persisted coordinator state"))? - .state()?; - let persisted_acceptances = state - .acceptance_receipts - .iter() - .filter(|candidate| candidate.id == acceptance.id) - .collect::>(); - if persisted_acceptances.len() != 1 || persisted_acceptances[0] != acceptance { - return Err(anyhow!( - "frontier Modeling request requires exactly one byte-exact persisted acceptance receipt" - )); - } - let acceptance = persisted_acceptances[0]; - let results = cache - .get_all::()? - .into_iter() - .filter(|result| result.result_id == acceptance.result_id) - .collect::>(); - if results.len() != 1 { - return Err(anyhow!( - "frontier Modeling request requires one immutable accepted Verification result" - )); - } - let result = &results[0]; - let verdicts = cache - .get_all::()? - .into_iter() - .filter(|verdict| { - verdict.source_result_id == acceptance.result_id - && verdict.source_job_id == acceptance.job_id - }) - .collect::>(); - if verdicts.len() != 1 { - return Err(anyhow!( - "frontier Modeling request requires exactly one Soul verdict for the accepted result" - )); - } - let verdict = &verdicts[0]; + let result = cache + .get::(&verdict.source_job_id)? + .ok_or_else(|| anyhow!("frontier Modeling request requires its Verification result"))?; let verification_request = cache .get::(&verdict.verification_request_id)? .ok_or_else(|| anyhow!("frontier Modeling request requires the exact Soul request"))?; let route = cache .get::(&verdict.frontier_route_id)? .ok_or_else(|| anyhow!("frontier Modeling request requires the exact frontier route"))?; - let view = require_keyed_repo_model_basis( - &cache, - &route.model_projection_digest, - &route.model_source_documents, - )?; - let item = view - .frontier - .iter() - .find(|item| item.id == route.frontier_item_id) + let item_envelope = cache + .get_envelope::(&route.frontier_item_id)? .ok_or_else(|| anyhow!("frontier Modeling request routed item is missing"))?; - let item_hash = format!("{:x}", Sha256::digest(rmp_serde::to_vec_named(item)?)); + let item = + rmp_serde::from_slice::(&item_envelope.payload)? + .value()?; + let item_version = + crate::EpiphanyMindDocumentVersion::from_envelope("epiphany-mind", &item_envelope)?; + let item_hash = format!("{:x}", Sha256::digest(rmp_serde::to_vec_named(&item)?)); let mut result_evidence = result.evidence_ids.clone(); let mut verdict_evidence = verdict.evidence_ids.clone(); result_evidence.sort(); @@ -9299,11 +9319,11 @@ pub fn commit_repo_frontier_modeling_request( if result.schema_version != RUNTIME_ROLE_WORKER_RESULT_SCHEMA_VERSION || !result.role_id.eq_ignore_ascii_case("verification") || result.item_error.is_some() - || result.job_id != acceptance.job_id + || result.result_id != verdict.source_result_id + || result.job_id != verdict.source_job_id || result.verification_request_id.as_deref() != Some(verification_request.request_id.as_str()) || result.frontier_route_id.as_deref() != Some(route.route_id.as_str()) - || verdict.schema_version != SOUL_VERDICT_RECEIPT_SCHEMA_VERSION || verdict.verdict != result.verdict || verdict.summary != result.summary || verdict.risks != result.risks @@ -9315,6 +9335,7 @@ pub fn commit_repo_frontier_modeling_request( || verification_request.model_source_documents != route.model_source_documents || verification_request.frontier_item_id != route.frontier_item_id || verification_request.frontier_item_hash != route.frontier_item_hash + || !route.model_source_documents.contains(&item_version) || item_hash != route.frontier_item_hash || item.status != crate::RepoFrontierStatus::Active { @@ -9322,15 +9343,11 @@ pub fn commit_repo_frontier_modeling_request( "frontier Modeling request does not exactly bind accepted result, Soul verdict, request, route, item, and current model" )); } - let request_id = format!( - "frontier-modeling-{:x}", - Sha256::digest( - format!( - "{}:{}:{}:{}", - acceptance.id, result.result_id, verdict.receipt_id, route.route_id - ) - .as_bytes() - ) + let request_id = crate::causal_work_identity::frontier_verdict_modeling_request_id( + &identity.runtime_id, + &verdict.receipt_id, + &result.result_id, + &route.route_id, ); let request = RepoFrontierModelingRequest { schema_version: REPO_FRONTIER_MODELING_REQUEST_SCHEMA_VERSION.to_string(), @@ -9344,21 +9361,56 @@ pub fn commit_repo_frontier_modeling_request( soul_verdict_receipt_id: verdict.receipt_id.clone(), verification_result_id: result.result_id.clone(), verification_job_id: result.job_id.clone(), - verification_acceptance_receipt_id: acceptance.id.clone(), allowed_disposition: disposition, - requested_at: acceptance.accepted_at.clone(), + requested_at: verdict.emitted_at.clone(), contract: REPO_FRONTIER_MODELING_REQUEST_CONTRACT.to_string(), }; + Ok(request) +} + +pub(crate) fn validate_repo_frontier_modeling_request( + cache: &CultCache, + request: &RepoFrontierModelingRequest, +) -> Result<()> { + let verdict = cache + .get::(&request.soul_verdict_receipt_id)? + .ok_or_else(|| anyhow!("frontier Modeling request lost its Soul verdict"))?; + if derive_repo_frontier_modeling_request(cache, &verdict)? != *request { + return Err(anyhow!( + "frontier Modeling request is not the canonical typed consequence of its Soul verdict" + )); + } + Ok(()) +} + +pub fn commit_repo_frontier_modeling_request( + store_path: impl AsRef, + verdict: &SoulVerdictReceipt, +) -> Result { + let store_path = store_path.as_ref(); + let mut cache = runtime_spine_cache(store_path)?; + cache.pull_all_backing_stores()?; + let persisted = cache + .get::(&verdict.receipt_id)? + .ok_or_else(|| anyhow!("frontier Modeling request requires its persisted Soul verdict"))?; + if persisted != *verdict { + return Err(anyhow!("frontier Modeling request Soul verdict changed")); + } + let request = derive_repo_frontier_modeling_request(&cache, verdict)?; + let request_id = request.request_id.clone(); let (envelope, _) = cache.prepare_entry(&request_id, &request)?; - let backing = SingleFileMessagePackBackingStore::new(store_path.as_ref()); - let basis = crate::EpiphanyRepoModelBasis { - projection_digest: request.model_projection_digest.clone(), - source_documents: request.model_source_documents.clone(), - }; - let expected = keyed_repo_model_basis_envelopes(&cache, &basis)?; + let verdict_envelope = cache + .get_envelope::(&verdict.receipt_id)? + .ok_or_else(|| anyhow!("frontier Modeling request lost its Soul verdict envelope"))?; + let frontier_envelope = cache + .get_envelope::(&request.frontier_item_id)? + .ok_or_else(|| anyhow!("frontier Modeling request lost its frontier envelope"))?; + let expected = vec![verdict_envelope, frontier_envelope]; let mut writes = expected.clone(); writes.push(envelope); - if backing.compare_and_swap_batch(&expected, writes)? { + if SingleFileMessagePackBackingStore::new(store_path) + .compare_and_swap_batch(&expected, writes)? + { return Ok(request); } let mut reloaded = runtime_spine_cache(store_path)?; @@ -9900,40 +9952,6 @@ pub fn runtime_hands_receipt_chain_matches_current_model( && current) } -// Soul verdicts are terminal acceptance evidence. Production creates them only -// as prerequisites inside the coordinator's atomic Mind acceptance -// transaction; this crate-private writer exists for focused spine fixtures and -// migration tests, not as an independent runtime actuator. -#[cfg(test)] -pub(crate) fn put_soul_verdict_receipt( - store_path: impl AsRef, - receipt: &SoulVerdictReceipt, -) -> Result<()> { - let store_path = store_path.as_ref(); - validate_non_empty(&receipt.receipt_id, "Soul verdict receipt id")?; - validate_non_empty(&receipt.source_result_id, "Soul verdict source result")?; - validate_non_empty(&receipt.source_job_id, "Soul verdict source job")?; - validate_non_empty(&receipt.verdict, "Soul verdict")?; - validate_non_empty(&receipt.emitted_at, "Soul verdict timestamp")?; - let mut cache = runtime_spine_cache(store_path)?; - cache.pull_all_backing_stores()?; - require_identity(&cache)?; - let (envelope, _) = cache.prepare_entry(&receipt.receipt_id, receipt)?; - if SingleFileMessagePackBackingStore::new(store_path) - .compare_and_swap_batch(&[], vec![envelope])? - { - return Ok(()); - } - let mut reloaded = runtime_spine_cache(store_path)?; - reloaded.pull_all_backing_stores()?; - match reloaded.get::(&receipt.receipt_id)? { - Some(existing) if existing == *receipt => Ok(()), - _ => Err(anyhow!( - "Soul verdict receipt id already belongs to different immutable evidence" - )), - } -} - pub fn runtime_soul_verdict_receipt( store_path: impl AsRef, receipt_id: &str, @@ -10151,6 +10169,51 @@ fn validate_archivable_typed_worker_launch( )); } } + "frontier-verdict-modeling" => { + validate_repo_frontier_verdict_modeling_launch_authority( + &launch.role, + Some(request_id), + &document, + )?; + validate_repository_body_launch_carrier(&launch.role, &document)?; + let request = cache + .get::(request_id)? + .ok_or_else(|| { + anyhow!("archived frontier verdict Modeling launch lost its request") + })?; + let authority = match &document { + EpiphanyWorkerLaunchDocument::Role(document) => { + document.frontier_verdict_modeling_context.as_ref() + } + EpiphanyWorkerLaunchDocument::Reorient(_) => None, + } + .ok_or_else(|| anyhow!("archived frontier verdict Modeling launch lost its context"))?; + let verdict = cache + .get::(&request.soul_verdict_receipt_id)? + .ok_or_else(|| { + anyhow!("archived frontier verdict Modeling launch lost its Soul verdict") + })?; + let item_hash = format!( + "{:x}", + Sha256::digest(rmp_serde::to_vec_named(&authority.frontier_item)?) + ); + let expected_request_id = + crate::causal_work_identity::frontier_verdict_modeling_request_id( + &identity.runtime_id, + &request.soul_verdict_receipt_id, + &request.verification_result_id, + &request.route_id, + ); + if authority.request != request + || authority.soul_verdict != verdict + || item_hash != request.frontier_item_hash + || request.request_id != expected_request_id + { + return Err(anyhow!( + "archived frontier verdict Modeling launch provenance mismatch" + )); + } + } "imagination-consideration" => { validate_imagination_consideration_launch_carrier( &launch.role, @@ -10345,6 +10408,9 @@ where let archived_result_id = if fulfilled { let request_ref = match request_kind { "proposal-modeling" => RuntimeTypedRequestRef::ProposalModeling(request_id), + "frontier-verdict-modeling" => { + RuntimeTypedRequestRef::FrontierVerdictModeling(request_id) + } "imagination-consideration" => { RuntimeTypedRequestRef::ImaginationConsideration(request_id) } @@ -10364,14 +10430,15 @@ where "fulfilled worker attempt archive substituted terminal authority" )); } - if request_kind == "proposal-modeling" - && !worker_result_has_keyed_mind_commit( - &cache, - role_result - .as_ref() - .expect("fulfilled result checked above"), - )? - { + if matches!( + request_kind, + "proposal-modeling" | "frontier-verdict-modeling" + ) && !worker_result_has_keyed_mind_commit( + &cache, + role_result + .as_ref() + .expect("fulfilled result checked above"), + )? { return Err(anyhow!( "proposal Modeling attempt remains live until Mind admission owns its result" )); diff --git a/epiphany-core/src/runtime_worker_attempt.rs b/epiphany-core/src/runtime_worker_attempt.rs index 055231c0..ed2f2ae2 100644 --- a/epiphany-core/src/runtime_worker_attempt.rs +++ b/epiphany-core/src/runtime_worker_attempt.rs @@ -57,6 +57,7 @@ impl WorkerProcessStatus { #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum RuntimeTypedRequestRef<'a> { ProposalModeling(&'a str), + FrontierVerdictModeling(&'a str), ImaginationConsideration(&'a str), AdmittedModelDirection(&'a str), } @@ -65,6 +66,7 @@ impl<'a> RuntimeTypedRequestRef<'a> { pub fn request_id(self) -> &'a str { match self { Self::ProposalModeling(id) + | Self::FrontierVerdictModeling(id) | Self::ImaginationConsideration(id) | Self::AdmittedModelDirection(id) => id, } @@ -73,6 +75,7 @@ impl<'a> RuntimeTypedRequestRef<'a> { pub fn kind(self) -> &'static str { match self { Self::ProposalModeling(_) => "proposal-modeling", + Self::FrontierVerdictModeling(_) => "frontier-verdict-modeling", Self::ImaginationConsideration(_) => "imagination-consideration", Self::AdmittedModelDirection(_) => "admitted-model-direction", } @@ -83,6 +86,9 @@ impl<'a> RuntimeTypedRequestRef<'a> { Self::ProposalModeling(id) => { launch.proposal_modeling_request_id.as_deref() == Some(id) } + Self::FrontierVerdictModeling(id) => { + launch.repo_frontier_modeling_request_id.as_deref() == Some(id) + } Self::ImaginationConsideration(id) => { launch.imagination_consideration_request_id.as_deref() == Some(id) } @@ -100,6 +106,9 @@ impl<'a> RuntimeTypedRequestRef<'a> { Self::ProposalModeling(id) => { result.proposal_modeling_request_id.as_deref() == Some(id) } + Self::FrontierVerdictModeling(id) => { + result.repo_frontier_modeling_request_id.as_deref() == Some(id) + } Self::ImaginationConsideration(id) => { result.imagination_consideration_request_id.as_deref() == Some(id) } @@ -119,6 +128,9 @@ impl crate::EpiphanyRuntimeWorkerLaunchRequest { self.proposal_modeling_request_id .as_deref() .map(RuntimeTypedRequestRef::ProposalModeling), + self.repo_frontier_modeling_request_id + .as_deref() + .map(RuntimeTypedRequestRef::FrontierVerdictModeling), self.imagination_consideration_request_id .as_deref() .map(RuntimeTypedRequestRef::ImaginationConsideration), diff --git a/epiphany-core/src/substrate_gate.rs b/epiphany-core/src/substrate_gate.rs index 58abf25a..f0583e8f 100644 --- a/epiphany-core/src/substrate_gate.rs +++ b/epiphany-core/src/substrate_gate.rs @@ -297,6 +297,7 @@ mod tests { dynamic_prompt_context: None, repository_body_observation_basis: None, proposal_modeling_context: None, + frontier_verdict_modeling_context: None, frontier_planning_context: None, frontier_research_context: None, frontier_plan_mind_context: None, @@ -331,7 +332,6 @@ mod tests { admitted_model_direction_consideration_request_id: None, repo_frontier_modeling_request_id: None, repo_frontier_research_request_id: None, - repo_frontier_verdict_modeling_authority: None, }; let grant = substrate_gate_repo_access_grant_for_launch( "grant-1".to_string(), diff --git a/epiphany-core/src/surfaces/coordinator.rs b/epiphany-core/src/surfaces/coordinator.rs index e79bde1e..8c5e03fa 100644 --- a/epiphany-core/src/surfaces/coordinator.rs +++ b/epiphany-core/src/surfaces/coordinator.rs @@ -96,6 +96,7 @@ pub fn derive_coordinator_status( research_continuation_action: input.research_continuation_action, frontier_planning_stage: input.frontier_planning_stage, proposal_modeling_action: input.proposal_modeling_action, + frontier_verdict_modeling_action: input.frontier_verdict_modeling_action, body_modeling_work_ready: input.body_modeling_work_ready, body_modeling_review_ready: input.body_modeling_review_ready, }); @@ -748,6 +749,35 @@ pub fn recommend_coordinator_action( ); } + if let Some(action) = input.frontier_verdict_modeling_action { + return match action { + EpiphanyModelingContinuationAction::Launch => build( + EpiphanyCoordinatorAction::LaunchModeling, + Some(EpiphanyCoordinatorRoleId::Modeling), + Some(EpiphanyCoordinatorSceneAction::RoleLaunch), + false, + true, + "An exact Soul verdict has unresolved keyed frontier Modeling work.", + ), + EpiphanyModelingContinuationAction::Wait => build( + EpiphanyCoordinatorAction::WaitForModelingResult, + Some(EpiphanyCoordinatorRoleId::Modeling), + Some(EpiphanyCoordinatorSceneAction::RoleResult), + false, + false, + "The exact frontier verdict Modeling attempt is still running.", + ), + EpiphanyModelingContinuationAction::Review => build( + EpiphanyCoordinatorAction::ReviewModelingResult, + Some(EpiphanyCoordinatorRoleId::Modeling), + Some(EpiphanyCoordinatorSceneAction::RoleResult), + true, + false, + "The exact frontier verdict Modeling result awaits keyed Mind admission.", + ), + }; + } + if let Some(action) = input.research_continuation_action { return match action { RepoFrontierResearchContinuationAction::LaunchResearch => build( @@ -1095,16 +1125,6 @@ pub fn recommend_coordinator_action( "Mind has admitted a current Hands frontier after source regather; execute that exact route before launching unrelated Modeling.", ); } - if input.research_result_accepted && !input.modeling_result_accepted_after_research { - return build( - EpiphanyCoordinatorAction::LaunchModeling, - Some(EpiphanyCoordinatorRoleId::Modeling), - Some(EpiphanyCoordinatorSceneAction::RoleLaunch), - false, - true, - "Accepted Eyes evidence is newer than the current Modeling boundary; route Modeling once to reconcile the RepoModel before further regather or implementation.", - ); - } if !input.research_result_accepted && matches!( input.signals.research_result_status, @@ -1409,6 +1429,7 @@ mod tests { research_continuation_action: None, frontier_planning_stage: RepoFrontierPlanningLifecycleStage::Unavailable, proposal_modeling_action: None, + frontier_verdict_modeling_action: None, body_modeling_work_ready: false, body_modeling_review_ready: false, } @@ -1890,7 +1911,7 @@ mod tests { } #[test] - fn accepted_eyes_routes_one_causal_modeling_pass_before_manual_regather() { + fn accepted_eyes_alone_cannot_manufacture_modeling_work() { let base = EpiphanyCoordinatorInput { recommendation: recommendation(EpiphanyCrrcAction::RegatherManually), roles: vec![role( @@ -1907,13 +1928,24 @@ mod tests { reorient_finding_accepted: true, ..input() }; - let launch = recommend_coordinator_action(base.clone()); - assert_eq!(launch.action, EpiphanyCoordinatorAction::LaunchModeling); + let without_obligation = recommend_coordinator_action(base.clone()); assert_eq!( - launch.target_role, + without_obligation.action, + EpiphanyCoordinatorAction::RegatherManually + ); + + let exact_modeling_work = recommend_coordinator_action(EpiphanyCoordinatorInput { + frontier_verdict_modeling_action: Some(EpiphanyModelingContinuationAction::Launch), + ..base.clone() + }); + assert_eq!( + exact_modeling_work.action, + EpiphanyCoordinatorAction::LaunchModeling + ); + assert_eq!( + exact_modeling_work.target_role, Some(EpiphanyCoordinatorRoleId::Modeling) ); - assert!(launch.reason.contains("Eyes evidence is newer")); let current_hands_route = recommend_coordinator_action(EpiphanyCoordinatorInput { hands_frontier_ready: true, @@ -1923,12 +1955,6 @@ mod tests { current_hands_route.action, EpiphanyCoordinatorAction::ContinueImplementation ); - - let consumed = recommend_coordinator_action(EpiphanyCoordinatorInput { - modeling_result_accepted_after_research: true, - ..base - }); - assert_eq!(consumed.action, EpiphanyCoordinatorAction::RegatherManually); } #[test] diff --git a/epiphany-core/src/surfaces/coordinator_contract.rs b/epiphany-core/src/surfaces/coordinator_contract.rs index 4c7e3517..2b602948 100644 --- a/epiphany-core/src/surfaces/coordinator_contract.rs +++ b/epiphany-core/src/surfaces/coordinator_contract.rs @@ -168,6 +168,8 @@ pub struct EpiphanyCoordinatorInput { pub frontier_planning_stage: RepoFrontierPlanningLifecycleStage, /// Exact current action for the oldest unresolved proposal Modeling request. pub proposal_modeling_action: Option, + /// Exact current action for one Soul-verdict-bound Modeling request. + pub frontier_verdict_modeling_action: Option, pub body_modeling_work_ready: bool, pub body_modeling_review_ready: bool, } @@ -221,6 +223,7 @@ pub struct EpiphanyCoordinatorStatusInput { pub research_continuation_action: Option, pub frontier_planning_stage: RepoFrontierPlanningLifecycleStage, pub proposal_modeling_action: Option, + pub frontier_verdict_modeling_action: Option, pub body_modeling_work_ready: bool, pub body_modeling_review_ready: bool, } diff --git a/epiphany-core/src/surfaces/worker_launch.rs b/epiphany-core/src/surfaces/worker_launch.rs index bdc71e7d..3f9e48eb 100644 --- a/epiphany-core/src/surfaces/worker_launch.rs +++ b/epiphany-core/src/surfaces/worker_launch.rs @@ -105,6 +105,9 @@ pub struct EpiphanyRoleWorkerLaunchDocument { #[serde(default, skip_serializing_if = "Option::is_none")] pub proposal_modeling_context: Option, #[serde(default, skip_serializing_if = "Option::is_none")] + pub frontier_verdict_modeling_context: + Option, + #[serde(default, skip_serializing_if = "Option::is_none")] pub frontier_planning_context: Option, #[serde(default, skip_serializing_if = "Option::is_none")] pub frontier_research_context: Option, @@ -422,7 +425,6 @@ pub fn build_reorient_job_launch_request( admitted_model_direction_consideration_request_id: None, repo_frontier_modeling_request_id: None, repo_frontier_research_request_id: None, - repo_frontier_verdict_modeling_authority: None, } } diff --git a/epiphany-openai-runtime/src/bin/epiphany-openai-runtime.rs b/epiphany-openai-runtime/src/bin/epiphany-openai-runtime.rs index c11b10f1..7ccd3cb6 100644 --- a/epiphany-openai-runtime/src/bin/epiphany-openai-runtime.rs +++ b/epiphany-openai-runtime/src/bin/epiphany-openai-runtime.rs @@ -1563,7 +1563,6 @@ mod tests { .clone(), repo_frontier_modeling_request_id: launch.repo_frontier_modeling_request_id.clone(), repo_frontier_research_request_id: launch.repo_frontier_research_request_id.clone(), - repo_frontier_verdict_modeling_authority: None, }; let grant = epiphany_core::substrate_gate_repo_access_grant_for_launch( format!("substrate-grant-{}", launch.job_id), @@ -1601,6 +1600,7 @@ mod tests { dynamic_prompt_context: None, repository_body_observation_basis: None, proposal_modeling_context: None, + frontier_verdict_modeling_context: None, frontier_planning_context: None, frontier_research_context: None, frontier_plan_mind_context: None, @@ -1634,7 +1634,6 @@ mod tests { admitted_model_direction_consideration_request_id: None, repo_frontier_modeling_request_id: None, repo_frontier_research_request_id: None, - repo_frontier_verdict_modeling_authority: None, created_at: now(), }, )?; @@ -1712,6 +1711,7 @@ mod tests { dynamic_prompt_context: None, repository_body_observation_basis: None, proposal_modeling_context: None, + frontier_verdict_modeling_context: None, frontier_planning_context: None, frontier_research_context: None, frontier_plan_mind_context: None, @@ -1745,7 +1745,6 @@ mod tests { admitted_model_direction_consideration_request_id: None, repo_frontier_modeling_request_id: None, repo_frontier_research_request_id: None, - repo_frontier_verdict_modeling_authority: None, created_at: now(), }, )?; @@ -1847,6 +1846,7 @@ mod tests { dynamic_prompt_context: None, repository_body_observation_basis: None, proposal_modeling_context: None, + frontier_verdict_modeling_context: None, frontier_planning_context: None, frontier_research_context: None, frontier_plan_mind_context: None, @@ -1880,7 +1880,6 @@ mod tests { admitted_model_direction_consideration_request_id: None, repo_frontier_modeling_request_id: None, repo_frontier_research_request_id: None, - repo_frontier_verdict_modeling_authority: None, created_at: now(), }, )?; diff --git a/epiphany-openai-runtime/src/lib.rs b/epiphany-openai-runtime/src/lib.rs index 4b8e2812..786e86e5 100644 --- a/epiphany-openai-runtime/src/lib.rs +++ b/epiphany-openai-runtime/src/lib.rs @@ -747,8 +747,6 @@ pub fn complete_worker_job_from_assistant_text( if let Some(parsed) = parsed.as_ref() { match (&launch_document, parsed) { (EpiphanyWorkerLaunchDocument::Role(document), WorkerResultIngress::Role(parsed)) => { - let repo_frontier_verdict_modeling_authority = - launch_request.repo_frontier_verdict_modeling_authority()?; let typed_result = role_worker_result_from_ingress( launch_request, &document.role_id, @@ -760,7 +758,7 @@ pub fn complete_worker_job_from_assistant_text( document .admitted_model_direction_consideration_context .as_ref(), - repo_frontier_verdict_modeling_authority.as_ref(), + document.frontier_verdict_modeling_context.as_ref(), &completed_at, &result_id, &decision_context.context_id, @@ -1535,8 +1533,9 @@ fn worker_output_schema_json( .repo_frontier_modeling_request_id .as_deref() .expect("checked verdict-bound Modeling request identity"); - let authority = launch_request - .repo_frontier_verdict_modeling_authority()? + let authority = document + .frontier_verdict_modeling_context + .as_ref() .ok_or_else(|| { anyhow!( "verdict-bound Modeling launch {request_id:?} omitted its typed authority body" @@ -1549,7 +1548,7 @@ fn worker_output_schema_json( authority.request.request_id )); } - epiphany_core::epiphany_frontier_verdict_modeling_output_schema(&authority) + epiphany_core::epiphany_frontier_verdict_modeling_output_schema(authority) } else { epiphany_core::epiphany_role_launch_output_schema(role_id) } @@ -2734,7 +2733,6 @@ mod tests { admitted_model_direction_consideration_request_id: None, repo_frontier_modeling_request_id: None, repo_frontier_research_request_id: None, - repo_frontier_verdict_modeling_authority_msgpack: None, }; let basis = epiphany_core::RepositoryBodyObservationBasis { schema_version: "epiphany.repository_body.v2".into(), @@ -2882,7 +2880,6 @@ mod tests { admitted_model_direction_consideration_request_id: None, repo_frontier_modeling_request_id: None, repo_frontier_research_request_id: None, - repo_frontier_verdict_modeling_authority_msgpack: None, }; let atlas = RoleWorkerResultIngress { role_id: Some("modeling".into()), @@ -3002,6 +2999,7 @@ mod tests { dynamic_prompt_context: None, repository_body_observation_basis: None, proposal_modeling_context: Some(context), + frontier_verdict_modeling_context: None, frontier_planning_context: None, frontier_research_context: None, frontier_plan_mind_context: None, @@ -3044,7 +3042,6 @@ mod tests { admitted_model_direction_consideration_request_id: None, repo_frontier_modeling_request_id: None, repo_frontier_research_request_id: None, - repo_frontier_verdict_modeling_authority_msgpack: None, }; let request = build_worker_model_request( @@ -3103,7 +3100,6 @@ mod tests { admitted_model_direction_consideration_request_id: None, repo_frontier_modeling_request_id: None, repo_frontier_research_request_id: None, - repo_frontier_verdict_modeling_authority_msgpack: None, }; let result = role_worker_result_from_ingress( &launch, @@ -3179,7 +3175,6 @@ mod tests { admitted_model_direction_consideration_request_id: None, repo_frontier_modeling_request_id: None, repo_frontier_research_request_id: None, - repo_frontier_verdict_modeling_authority_msgpack: None, }; let planning_context = epiphany_core::RepoFrontierPlanningContextProjection { schema_version: epiphany_core::REPO_FRONTIER_PLANNING_CONTEXT_SCHEMA_VERSION.into(), @@ -3349,7 +3344,6 @@ mod tests { admitted_model_direction_consideration_request_id: None, repo_frontier_modeling_request_id: None, repo_frontier_research_request_id: None, - repo_frontier_verdict_modeling_authority_msgpack: None, }; let result = role_worker_result_from_ingress( &launch, @@ -3415,6 +3409,7 @@ mod tests { dynamic_prompt_context: None, repository_body_observation_basis: None, proposal_modeling_context: None, + frontier_verdict_modeling_context: None, frontier_planning_context: None, frontier_research_context: None, frontier_plan_mind_context: None, @@ -3457,7 +3452,6 @@ mod tests { admitted_model_direction_consideration_request_id: None, repo_frontier_modeling_request_id: None, repo_frontier_research_request_id: None, - repo_frontier_verdict_modeling_authority_msgpack: None, }; let failed = failed_frontier_planning_role_result(&launch, "candidate mismatch")? .expect("typed planning failure"); @@ -3499,7 +3493,6 @@ mod tests { admitted_model_direction_consideration_request_id: None, repo_frontier_modeling_request_id: None, repo_frontier_research_request_id: None, - repo_frontier_verdict_modeling_authority_msgpack: None, }; let context = epiphany_core::RepoFrontierPlanMindContextProjection { schema_version: epiphany_core::REPO_FRONTIER_PLAN_MIND_CONTEXT_SCHEMA_VERSION.into(), @@ -3751,6 +3744,139 @@ mod tests { scan_started_at: "2026-07-13T00:00:00Z".to_string(), scan_finished_at: "2026-07-13T00:00:01Z".to_string(), }; + initialize_runtime_spine( + &store, + RuntimeSpineInitOptions { + runtime_id: "epiphany-test".into(), + display_name: "Epiphany Test".into(), + created_at: "2026-08-08T00:00:00Z".into(), + }, + )?; + let frontier_item = epiphany_core::RepoFrontierItem { + id: "frontier-1".to_string(), + migration_body: "runtime".to_string(), + question: "Did the verified consequence hold?".to_string(), + gap: "Awaiting verdict incorporation.".to_string(), + target_claim_ids: vec!["claim-1".to_string()], + source_scope: vec!["epiphany-core".to_string()], + recommended_next_organ: "Hands".to_string(), + adopted_plan: None, + dependency_item_ids: Vec::new(), + status: epiphany_core::RepoFrontierStatus::Active, + evidence_refs: vec!["prior-evidence".to_string()], + public_source_refs: Vec::new(), + created_at: Some("2026-08-07T00:00:00Z".to_string()), + updated_at: Some("2026-08-07T00:00:00Z".to_string()), + retired_at: None, + superseded_by: None, + }; + let frontier_item_hash = format!( + "{:x}", + sha2::Sha256::digest(rmp_serde::to_vec_named(&frontier_item)?) + ); + let mut authority_cache = runtime_spine_cache(&store)?; + authority_cache.put( + &frontier_item.id, + &epiphany_core::EpiphanyRepoModelFrontierDocument::new(&frontier_item)?, + )?; + let frontier_version = epiphany_core::EpiphanyMindDocumentVersion::from_envelope( + "epiphany-mind", + &authority_cache + .get_envelope::( + &frontier_item.id, + )? + .expect("persisted frontier envelope"), + )?; + let route = epiphany_core::RepoFrontierRoute { + schema_version: epiphany_core::REPO_FRONTIER_ROUTE_SCHEMA_VERSION.into(), + route_id: "route-1".into(), + next_organ: epiphany_core::RepoFrontierNextOrgan::Hands, + model_projection_digest: "model-projection".into(), + model_source_documents: vec![frontier_version], + frontier_item_id: frontier_item.id.clone(), + frontier_item_hash, + migration_body: frontier_item.migration_body.clone(), + question: frontier_item.question.clone(), + gap: frontier_item.gap.clone(), + target_claim_ids: frontier_item.target_claim_ids.clone(), + source_scope: frontier_item.source_scope.clone(), + adopted_plan: frontier_item.adopted_plan.clone(), + selected_at: "2026-08-08T00:00:00Z".into(), + contract: epiphany_core::REPO_FRONTIER_ROUTE_CONTRACT.into(), + }; + let verification_request = epiphany_core::RepoFrontierVerificationRequest { + schema_version: epiphany_core::REPO_FRONTIER_VERIFICATION_REQUEST_SCHEMA_VERSION.into(), + request_id: "verification-request-1".into(), + route_id: route.route_id.clone(), + model_projection_digest: route.model_projection_digest.clone(), + model_source_documents: route.model_source_documents.clone(), + frontier_item_id: route.frontier_item_id.clone(), + frontier_item_hash: route.frontier_item_hash.clone(), + hands_intent_id: "hands-intent-1".into(), + hands_review_id: "hands-review-1".into(), + hands_patch_receipt_id: "hands-patch-1".into(), + hands_command_receipt_id: "hands-command-1".into(), + hands_commit_receipt_id: "hands-commit-1".into(), + requested_at: "2026-08-08T00:00:00Z".into(), + contract: epiphany_core::REPO_FRONTIER_VERIFICATION_REQUEST_CONTRACT.into(), + }; + let verification_result = EpiphanyRuntimeRoleWorkerResult { + schema_version: epiphany_core::RUNTIME_ROLE_WORKER_RESULT_SCHEMA_VERSION.into(), + result_id: "verification-result-1".into(), + job_id: "verification-job-1".into(), + role_id: "verification".into(), + verdict: "pass".into(), + summary: "verified".into(), + next_safe_move: "incorporate".into(), + checkpoint_summary: None, + scratch_summary: None, + files_inspected: Vec::new(), + frontier_node_ids: vec![frontier_item.id.clone()], + evidence_ids: Vec::new(), + 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_mutation_proposal_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, + frontier_planning_request_id: None, + frontier_plan_candidate_msgpack: None, + frontier_plan_mind_request_id: None, + frontier_plan_mind_decision_msgpack: None, + repository_body_observation_basis: None, + imagination_consideration_request_id: None, + imagination_consideration_candidate_msgpack: None, + admitted_model_direction_consideration_request_id: None, + admitted_model_direction_consideration_result_msgpack: None, + decision_context_id: "verification-context-1".into(), + }; + let soul_verdict = epiphany_core::SoulVerdictReceipt { + schema_version: epiphany_core::SOUL_VERDICT_RECEIPT_SCHEMA_VERSION.into(), + receipt_id: "soul-verdict-1".into(), + source_result_id: verification_result.result_id.clone(), + source_job_id: verification_result.job_id.clone(), + verdict: verification_result.verdict.clone(), + summary: verification_result.summary.clone(), + evidence_ids: verification_result.evidence_ids.clone(), + risks: verification_result.risks.clone(), + emitted_at: "2026-08-08T00:00:00Z".into(), + contract: "test Soul verdict".into(), + verification_request_id: verification_request.request_id.clone(), + frontier_route_id: route.route_id.clone(), + }; + authority_cache.put(&route.route_id, &route)?; + authority_cache.put(&verification_request.request_id, &verification_request)?; + authority_cache.put(&verification_result.job_id, &verification_result)?; + authority_cache.put(&soul_verdict.receipt_id, &soul_verdict)?; + let frontier_request = + epiphany_core::commit_repo_frontier_modeling_request(&store, &soul_verdict)?; open_runtime_spine_heartbeat_job( &store, RuntimeSpineHeartbeatJobOptions { @@ -3770,15 +3896,19 @@ mod tests { role_id: "modeling".to_string(), state_revision: 1, objective: Some("Map the machine.".to_string()), - dynamic_prompt_context: Some( - "\nlocal Verse: bounded\n" - .to_string(), - ), + dynamic_prompt_context: None, repository_body_observation_basis: Some(body_basis.clone()), proposal_modeling_context: None, - frontier_planning_context: None, - frontier_research_context: None, - frontier_plan_mind_context: None, + frontier_verdict_modeling_context: Some( + epiphany_core::RepoFrontierVerdictModelingLaunchAuthority { + request: frontier_request.clone(), + frontier_item: frontier_item.clone(), + soul_verdict: soul_verdict.clone(), + }, + ), + frontier_planning_context: None, + frontier_research_context: None, + frontier_plan_mind_context: None, imagination_consideration_context: None, admitted_model_direction_consideration_context: None, active_subgoal_id: None, @@ -3803,56 +3933,12 @@ mod tests { epiphany_core::ROLE_WORKER_OUTPUT_CONTRACT_ID, ), proposal_modeling_request_id: None, - frontier_planning_request_id: None, - frontier_plan_mind_request_id: None, - imagination_consideration_request_id: None, - admitted_model_direction_consideration_request_id: None, - repo_frontier_modeling_request_id: Some( - "frontier-modeling-request-1".to_string(), - ), + frontier_planning_request_id: None, + frontier_plan_mind_request_id: None, + imagination_consideration_request_id: None, + admitted_model_direction_consideration_request_id: None, + repo_frontier_modeling_request_id: Some(frontier_request.request_id.clone()), repo_frontier_research_request_id: None, - repo_frontier_verdict_modeling_authority: Some( - epiphany_core::RepoFrontierVerdictModelingLaunchAuthority { - request: epiphany_core::RepoFrontierModelingRequest { - schema_version: epiphany_core::REPO_FRONTIER_MODELING_REQUEST_SCHEMA_VERSION.to_string(), - request_id: "frontier-modeling-request-1".to_string(), - model_projection_digest: "model-projection".to_string(), - model_source_documents: Vec::new(), - route_id: "route-1".to_string(), - frontier_item_id: "frontier-1".to_string(), - frontier_item_hash: "frontier-hash".to_string(), - verification_request_id: "verification-request-1".to_string(), - soul_verdict_receipt_id: "soul-verdict-1".to_string(), - verification_result_id: "verification-result-1".to_string(), - verification_job_id: "verification-job-1".to_string(), - verification_acceptance_receipt_id: "verification-acceptance-1".to_string(), - allowed_disposition: epiphany_core::RepoFrontierVerdictDisposition::Resolved, - requested_at: "2026-08-08T00:00:00Z".to_string(), - contract: epiphany_core::REPO_FRONTIER_MODELING_REQUEST_CONTRACT.to_string(), - }, - frontier_item: epiphany_core::RepoFrontierItem { - id: "frontier-1".to_string(), - migration_body: "runtime".to_string(), - question: "Did the verified consequence hold?".to_string(), - gap: "Awaiting verdict incorporation.".to_string(), - target_claim_ids: vec!["claim-1".to_string()], - source_scope: vec!["epiphany-core".to_string()], - recommended_next_organ: "Hands".to_string(), - adopted_plan: Some(epiphany_core::RepoFrontierAdoptedPlan { - command: "cargo test".to_string(), - ..Default::default() - }), - dependency_item_ids: Vec::new(), - status: epiphany_core::RepoFrontierStatus::Active, - evidence_refs: vec!["prior-evidence".to_string()], - public_source_refs: Vec::new(), - created_at: Some("2026-08-07T00:00:00Z".to_string()), - updated_at: Some("2026-08-07T00:00:00Z".to_string()), - retired_at: None, - superseded_by: None, - }, - }, - ), created_at: now(), }, )?; @@ -3953,7 +4039,7 @@ mod tests { .get("repoModelOperations") .is_none() ); - assert!(!output_schema.contains("frontier-modeling-request-1")); + assert!(!output_schema.contains(&frontier_request.request_id)); assert!(!output_schema.contains("incorporate_frontier_verdict")); assert!(!model_request.instructions.contains("Output schema JSON")); assert!(model_request.instructions.contains("frontierVerdictGap")); @@ -3965,11 +4051,24 @@ mod tests { assert_eq!(model_request.reasoning_effort.as_deref(), Some("low")); assert_eq!(model_request.reasoning_summary.as_deref(), Some("concise")); assert!( - model_request + !model_request .instructions .contains("") ); - assert!(model_request.instructions.contains("local Verse: bounded")); + let epiphany_core::EpiphanyReasoningProjection::RolePass(sealed_projection) = + reasoning_basis.projection()? + else { + panic!("frontier verdict Modeling must seal a role projection") + }; + assert_eq!( + sealed_projection + .authority + .frontier_verdict_modeling_context + .as_ref() + .expect("sealed frontier verdict authority") + .frontier_item, + frontier_item + ); assert!( model_request .tools @@ -4091,6 +4190,7 @@ mod tests { ), repository_body_observation_basis: None, proposal_modeling_context: None, + frontier_verdict_modeling_context: None, frontier_planning_context: None, frontier_research_context: None, frontier_plan_mind_context: None, @@ -4124,7 +4224,6 @@ mod tests { admitted_model_direction_consideration_request_id: None, repo_frontier_modeling_request_id: None, repo_frontier_research_request_id: None, - repo_frontier_verdict_modeling_authority: None, created_at: now(), }, )?;