Bind Research continuation to causal frontier

This commit is contained in:
Meta Vens 2026-08-13 20:45:53 +02:00
commit a4a41006a2
2 changed files with 138 additions and 30 deletions

View file

@ -1151,7 +1151,7 @@ pub fn ingest_resident_self_domain_pressure(
Ok(inserted)
}
fn role_result_is_terminal_for_continuation(
fn role_projection_is_terminal_for_continuation(
runtime_store: &Path,
thread_id: &str,
role: crate::EpiphanyRoleResultRoleId,
@ -1179,7 +1179,38 @@ fn role_result_is_terminal_for_continuation(
))
}
fn resident_self_safe_continuation_action(
fn resident_continuation_launch_was_overtaken(
runtime_store: &Path,
action: &str,
thread_id: &str,
) -> Result<bool> {
match action {
// Research launch currency belongs to the exact current frontier
// request. A terminal result on the stable role binding may belong to
// an older frontier and cannot suppress new causal work.
"launchResearch" => Ok(!crate::runtime_has_uncovered_actionable_eyes_frontier(
runtime_store,
)?),
// These legacy checkpoint lanes do not yet expose an exact current
// request projection. Keep their existing role-slot behavior explicit
// rather than pretending it is the same authority as Research.
"launchModeling" => role_projection_is_terminal_for_continuation(
runtime_store,
thread_id,
crate::EpiphanyRoleResultRoleId::Modeling,
crate::EPIPHANY_MODELING_ROLE_BINDING_ID,
),
"launchVerification" => role_projection_is_terminal_for_continuation(
runtime_store,
thread_id,
crate::EpiphanyRoleResultRoleId::Verification,
crate::EPIPHANY_VERIFICATION_ROLE_BINDING_ID,
),
_ => Ok(false),
}
}
pub(crate) fn resident_self_safe_continuation_action(
runtime_store: &Path,
receipt: &crate::EpiphanyCoordinatorRunReceipt,
) -> Result<Option<String>> {
@ -1195,35 +1226,18 @@ fn resident_self_safe_continuation_action(
| "commitFrontierPlanDecision"
);
if direct {
let overtaken_by_terminal_result = match receipt.final_action.as_str() {
"launchResearch" => role_result_is_terminal_for_continuation(
runtime_store,
&receipt.thread_id,
crate::EpiphanyRoleResultRoleId::Research,
crate::EPIPHANY_RESEARCH_ROLE_BINDING_ID,
)?,
"launchModeling" => role_result_is_terminal_for_continuation(
runtime_store,
&receipt.thread_id,
crate::EpiphanyRoleResultRoleId::Modeling,
crate::EPIPHANY_MODELING_ROLE_BINDING_ID,
)?,
"launchVerification" => role_result_is_terminal_for_continuation(
runtime_store,
&receipt.thread_id,
crate::EpiphanyRoleResultRoleId::Verification,
crate::EPIPHANY_VERIFICATION_ROLE_BINDING_ID,
)?,
_ => false,
};
if overtaken_by_terminal_result {
if resident_continuation_launch_was_overtaken(
runtime_store,
&receipt.final_action,
&receipt.thread_id,
)? {
return Ok(None);
}
return Ok(Some(receipt.final_action.clone()));
}
let action = match receipt.final_action.as_str() {
"reviewResearchResult"
if role_result_is_terminal_for_continuation(
if role_projection_is_terminal_for_continuation(
runtime_store,
&receipt.thread_id,
crate::EpiphanyRoleResultRoleId::Research,
@ -1233,7 +1247,7 @@ fn resident_self_safe_continuation_action(
Some("reviewResearchResult")
}
"reviewModelingResult"
if role_result_is_terminal_for_continuation(
if role_projection_is_terminal_for_continuation(
runtime_store,
&receipt.thread_id,
crate::EpiphanyRoleResultRoleId::Modeling,
@ -1243,7 +1257,7 @@ fn resident_self_safe_continuation_action(
Some("reviewModelingResult")
}
"reviewVerificationResult"
if role_result_is_terminal_for_continuation(
if role_projection_is_terminal_for_continuation(
runtime_store,
&receipt.thread_id,
crate::EpiphanyRoleResultRoleId::Verification,
@ -1253,7 +1267,7 @@ fn resident_self_safe_continuation_action(
Some("reviewVerificationResult")
}
"waitForResearchResult"
if role_result_is_terminal_for_continuation(
if role_projection_is_terminal_for_continuation(
runtime_store,
&receipt.thread_id,
crate::EpiphanyRoleResultRoleId::Research,
@ -1263,7 +1277,7 @@ fn resident_self_safe_continuation_action(
Some("reviewResearchResult")
}
"waitForModelingResult"
if role_result_is_terminal_for_continuation(
if role_projection_is_terminal_for_continuation(
runtime_store,
&receipt.thread_id,
crate::EpiphanyRoleResultRoleId::Modeling,
@ -1273,7 +1287,7 @@ fn resident_self_safe_continuation_action(
Some("reviewModelingResult")
}
"waitForVerificationResult"
if role_result_is_terminal_for_continuation(
if role_projection_is_terminal_for_continuation(
runtime_store,
&receipt.thread_id,
crate::EpiphanyRoleResultRoleId::Verification,

View file

@ -16678,6 +16678,93 @@ pub(crate) mod tests {
research_request
);
assert!(runtime_has_uncovered_actionable_eyes_frontier(&eyes_store)?);
// A completed Research role projection may belong to an older
// frontier. It cannot suppress the exact current frontier request.
let stale_job_id = "eyes-stale-role-projection-job";
let mut transitioned_state = transitioned.state()?;
transitioned_state.runtime_links.retain(|link| {
link.binding_id != crate::EPIPHANY_RESEARCH_ROLE_BINDING_ID
});
transitioned_state.runtime_links.push(epiphany_state_model::EpiphanyRuntimeLink {
id: "runtime-link-eyes-stale-role-projection-job".into(),
binding_id: crate::EPIPHANY_RESEARCH_ROLE_BINDING_ID.into(),
surface: "jobLaunch".into(),
role_id: crate::EPIPHANY_RESEARCH_OWNER_ROLE.into(),
authority_scope: "research".into(),
runtime_job_id: stale_job_id.into(),
runtime_result_id: Some(format!("result-{stale_job_id}")),
linked_subgoal_ids: Vec::new(),
linked_graph_node_ids: Vec::new(),
});
transitioned = crate::EpiphanyThreadStateEntry::from_state(
"later-coordinator-incarnation",
&transitioned_state,
)?;
cache.put(crate::THREAD_STATE_KEY, &transitioned)?;
cache.put(
stale_job_id,
&EpiphanyRuntimeJob {
schema_version: RUNTIME_SPINE_SCHEMA_VERSION.into(),
job_id: stale_job_id.into(),
session_id: "eyes-stale-role-projection-session".into(),
role: crate::EPIPHANY_RESEARCH_OWNER_ROLE.into(),
status: EpiphanyRuntimeJobStatus::Failed,
created_at: "2026-07-13T03:00:00Z".into(),
updated_at: "2026-07-13T03:00:01Z".into(),
summary: "An older Research attempt failed.".into(),
artifact_refs: Vec::new(),
metadata: BTreeMap::new(),
},
)?;
cache.put(
&format!("result-{stale_job_id}"),
&EpiphanyRuntimeJobResult {
schema_version: RUNTIME_SPINE_SCHEMA_VERSION.into(),
result_id: format!("result-{stale_job_id}"),
job_id: stale_job_id.into(),
session_id: "eyes-stale-role-projection-session".into(),
role: crate::EPIPHANY_RESEARCH_OWNER_ROLE.into(),
verdict: "failed".into(),
summary: "Older Research failure.".into(),
completed_at: "2026-07-13T03:00:01Z".into(),
next_safe_move: "Launch the current frontier request.".into(),
evidence_refs: Vec::new(),
artifact_refs: Vec::new(),
metadata: BTreeMap::new(),
},
)?;
let continuation_receipt = EpiphanyCoordinatorRunReceipt {
schema_version: COORDINATOR_RUN_RECEIPT_SCHEMA_VERSION.into(),
receipt_id: "receipt-current-frontier-after-stale-research".into(),
session_id: "coordinator-later-coordinator-incarnation-resident-deadbeef".into(),
thread_id: "later-coordinator-incarnation".into(),
mode: "execute".into(),
status: "planned".into(),
final_action: "launchResearch".into(),
final_reason: Some("The exact current Eyes frontier is uncovered.".into()),
step_count: 1,
created_at: "2026-07-13T04:04:01Z".into(),
model_provider: Some("test".into()),
runtime_store: eyes_store.display().to_string(),
artifact_refs: Vec::new(),
sealed_artifact_refs: Vec::new(),
metadata: BTreeMap::new(),
resident_grant_id: Some("grant-current-frontier".into()),
resident_launch_digest: Some("sha256:deadbeef".into()),
resident_policy_digest: Some("policy-current-frontier".into()),
resident_argv_digest: Some("argv-current-frontier".into()),
resident_objective_digest: Some("objective-current-frontier".into()),
resident_release_commit: Some("commit-current-frontier".into()),
resident_release_manifest_digest: Some("manifest-current-frontier".into()),
resident_executable_digest: Some("executable-current-frontier".into()),
};
assert_eq!(
crate::resident_self::resident_self_safe_continuation_action(
&eyes_store,
&continuation_receipt,
)?,
Some("launchResearch".into())
);
let job_id = "eyes-current-frontier-job";
let launch_document = EpiphanyWorkerLaunchDocument::Role(
crate::EpiphanyRoleWorkerLaunchDocument {
@ -16755,6 +16842,13 @@ pub(crate) mod tests {
};
cache.put(&covered.packet_id, &covered)?;
assert!(!runtime_has_uncovered_actionable_eyes_frontier(&eyes_store)?);
assert_eq!(
crate::resident_self::resident_self_safe_continuation_action(
&eyes_store,
&continuation_receipt,
)?,
None
);
let (planning_store, planning_challenge) =
claim_challenge_fixture(root.path(), "planning-gate", "Imagination")?;