Project Research continuation from lifecycle

This commit is contained in:
Meta Vens 2026-08-14 03:34:54 +02:00
commit 40beb6a99c
4 changed files with 49 additions and 35 deletions

View file

@ -38,7 +38,6 @@ use epiphany_core::derive_scene;
use epiphany_core::read_accepted_coordinator_state;
use epiphany_core::recommend_crrc_action;
use epiphany_core::recommend_reorientation;
use epiphany_core::RepoFrontierResearchLifecycleStage;
use epiphany_core::runtime_repo_frontier_research_lifecycle;
use epiphany_core::runtime_has_actionable_hands_frontier;
use epiphany_core::runtime_job_snapshot;
@ -482,8 +481,8 @@ fn run_native_status(args: &Args, include_auxiliary_status: bool) -> Result<Valu
let research_lifecycle = runtime_repo_frontier_research_lifecycle(&runtime_store_path)
.context("failed to derive exact Eyes frontier lifecycle from runtime-spine state")?;
let eyes_frontier_ready = matches!(
research_lifecycle.stage,
RepoFrontierResearchLifecycleStage::LaunchReady
research_lifecycle.continuation_action(),
Some(epiphany_core::RepoFrontierResearchContinuationAction::LaunchResearch)
);
let frontier_planning_eligibility = epiphany_core::runtime_repo_frontier_planning_eligibility(
&runtime_store_path,

View file

@ -1046,6 +1046,7 @@ pub use runtime_spine::ARCHIVED_RUNTIME_WORKER_ATTEMPT_SCHEMA_VERSION;
pub use runtime_spine::ARCHIVED_RUNTIME_WORKER_ATTEMPT_TYPE;
pub use runtime_spine::RepoFrontierVerdictModelingLaunchAuthority;
pub use runtime_spine::RepoFrontierResearchLifecycle;
pub use runtime_spine::RepoFrontierResearchContinuationAction;
pub use runtime_spine::RepoFrontierResearchLifecycleStage;
pub use runtime_spine::RuntimeHandsReceiptChainSummary;
pub use runtime_spine::RuntimeSpineEventOptions;

View file

@ -1185,14 +1185,6 @@ fn resident_continuation_launch_was_overtaken(
thread_id: &str,
) -> Result<bool> {
match action {
// Research launch currency belongs to the exact current frontier
// lifecycle. Uncovered means that Mind still lacks accepted coverage;
// it does not mean another worker is launchable while an exact attempt
// is running or awaiting review.
"launchResearch" => Ok(!matches!(
crate::runtime_repo_frontier_research_lifecycle(runtime_store)?.stage,
crate::RepoFrontierResearchLifecycleStage::LaunchReady
)),
// 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.
@ -1216,10 +1208,17 @@ pub(crate) fn resident_self_safe_continuation_action(
runtime_store: &Path,
receipt: &crate::EpiphanyCoordinatorRunReceipt,
) -> Result<Option<String>> {
if matches!(
receipt.final_action.as_str(),
"launchResearch" | "waitForResearchResult" | "reviewResearchResult"
) {
return Ok(crate::runtime_repo_frontier_research_lifecycle(runtime_store)?
.continuation_action()
.map(|action| action.as_str().to_string()));
}
let direct = matches!(
receipt.final_action.as_str(),
"launchResearch"
| "launchModeling"
"launchModeling"
| "launchVerification"
| "startFrontierPlanning"
| "launchImagination"
@ -1238,16 +1237,6 @@ pub(crate) fn resident_self_safe_continuation_action(
return Ok(Some(receipt.final_action.clone()));
}
let action = match receipt.final_action.as_str() {
"reviewResearchResult"
if role_projection_is_terminal_for_continuation(
runtime_store,
&receipt.thread_id,
crate::EpiphanyRoleResultRoleId::Research,
crate::EPIPHANY_RESEARCH_ROLE_BINDING_ID,
)? =>
{
Some("reviewResearchResult")
}
"reviewModelingResult"
if role_projection_is_terminal_for_continuation(
runtime_store,
@ -1268,16 +1257,6 @@ pub(crate) fn resident_self_safe_continuation_action(
{
Some("reviewVerificationResult")
}
"waitForResearchResult"
if role_projection_is_terminal_for_continuation(
runtime_store,
&receipt.thread_id,
crate::EpiphanyRoleResultRoleId::Research,
crate::EPIPHANY_RESEARCH_ROLE_BINDING_ID,
)? =>
{
Some("reviewResearchResult")
}
"waitForModelingResult"
if role_projection_is_terminal_for_continuation(
runtime_store,

View file

@ -9170,6 +9170,21 @@ pub enum RepoFrontierResearchLifecycleStage {
ResultReady,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum RepoFrontierResearchContinuationAction {
LaunchResearch,
ReviewResearchResult,
}
impl RepoFrontierResearchContinuationAction {
pub fn as_str(self) -> &'static str {
match self {
Self::LaunchResearch => "launchResearch",
Self::ReviewResearchResult => "reviewResearchResult",
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RepoFrontierResearchLifecycle {
@ -9179,6 +9194,21 @@ pub struct RepoFrontierResearchLifecycle {
pub worker_job_id: Option<String>,
}
impl RepoFrontierResearchLifecycle {
pub fn continuation_action(&self) -> Option<RepoFrontierResearchContinuationAction> {
match self.stage {
RepoFrontierResearchLifecycleStage::LaunchReady => {
Some(RepoFrontierResearchContinuationAction::LaunchResearch)
}
RepoFrontierResearchLifecycleStage::ResultReady => {
Some(RepoFrontierResearchContinuationAction::ReviewResearchResult)
}
RepoFrontierResearchLifecycleStage::Terminal
| RepoFrontierResearchLifecycleStage::WorkerRunning => None,
}
}
}
/// Projects the next exact actionable Eyes frontier through request, worker,
/// review, and accepted-packet lifecycle. This is the launch-currency owner:
/// an uncovered frontier is not launchable while its current attempt is still
@ -17746,8 +17776,8 @@ pub(crate) mod tests {
&eyes_store,
&continuation_receipt,
)?,
None,
"the exact current terminal result owns review; stale launch authority is gone"
Some("reviewResearchResult".into()),
"the exact lifecycle replaces stale launch provenance with current review authority"
);
let covered = EyesEvidencePacket {
schema_version: EYES_EVIDENCE_PACKET_SCHEMA_VERSION.into(),
@ -17793,6 +17823,11 @@ pub(crate) mod tests {
}
})?;
assert!(runtime_has_uncovered_actionable_eyes_frontier(&eyes_store)?);
assert_eq!(
runtime_repo_frontier_research_lifecycle(&eyes_store)?
.continuation_action(),
Some(RepoFrontierResearchContinuationAction::LaunchResearch)
);
let second_research_request = select_and_commit_repo_frontier_research_request(
&eyes_store,
"2026-07-13T04:06:00Z",