Unify Modeling continuation actions

This commit is contained in:
Meta Vens 2026-08-17 22:00:55 +02:00
commit e404c10537
6 changed files with 47 additions and 55 deletions

View file

@ -513,7 +513,7 @@ fn run_coordinator(args: &Args) -> Result<Value> {
let current = epiphany_core::project_current_work(&runtime_store)?
.proposal_modeling
.filter(|work| {
work.action == epiphany_core::EpiphanyProposalModelingContinuationAction::Launch
work.action == epiphany_core::EpiphanyModelingContinuationAction::Launch
})
.ok_or_else(|| anyhow!("proposal Modeling request is not launchable"))?;
if current.request.request_id != request_id {
@ -1055,7 +1055,7 @@ fn run_coordinator(args: &Args) -> Result<Value> {
.proposal_modeling
.filter(|work| {
work.action
== epiphany_core::EpiphanyProposalModelingContinuationAction::Launch
== epiphany_core::EpiphanyModelingContinuationAction::Launch
})
.ok_or_else(|| anyhow!("proposal Modeling work is not launchable"))?;
if current.request.request_id != request_id {

View file

@ -552,7 +552,7 @@ fn run_native_status(args: &Args, include_auxiliary_status: bool) -> Result<Valu
proposal_modeling_action: proposal_modeling_work.map(|work| work.action),
body_modeling_work_ready: current_work.body_modeling.is_some(),
body_modeling_review_ready: current_work.body_modeling_action
== Some(epiphany_core::EpiphanyBodyModelingContinuationAction::Review),
== Some(epiphany_core::EpiphanyModelingContinuationAction::Review),
});
let coordinator_json = coordinator_status_json(&coordinator)?;
let tool_invocations = native_tool_invocation_surface(&runtime_store_path)?;
@ -647,7 +647,7 @@ fn run_native_status(args: &Args, include_auxiliary_status: bool) -> Result<Valu
"nativeHandsConsequenceAfterBoundary": native_hands_consequence_after_boundary,
"imaginationFrontierReady": imagination_frontier_ready,
"pendingProposalModelingRequestId": proposal_modeling_work
.filter(|work| work.action == epiphany_core::EpiphanyProposalModelingContinuationAction::Launch)
.filter(|work| work.action == epiphany_core::EpiphanyModelingContinuationAction::Launch)
.map(|work| work.request.request_id.as_str()),
"verificationResultAccepted": finding_signals.verification_result_accepted,
"verificationResultFailureReviewed": finding_signals.verification_result_failure_reviewed,

View file

@ -19,7 +19,7 @@ pub const BODY_MODELING_LAUNCH_BINDING_SCHEMA_VERSION: &str =
pub struct EpiphanyCurrentWorkProjection {
pub mind_projection_digest: String,
pub body_modeling: Option<EpiphanyBodyModelingWorkProjection>,
pub body_modeling_action: Option<EpiphanyBodyModelingContinuationAction>,
pub body_modeling_action: Option<EpiphanyModelingContinuationAction>,
pub research_continuation_action: Option<RepoFrontierResearchContinuationAction>,
pub frontier_planning_stage: RepoFrontierPlanningLifecycleStage,
pub proposal_modeling: Option<EpiphanyProposalModelingWorkProjection>,
@ -28,7 +28,7 @@ pub struct EpiphanyCurrentWorkProjection {
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum EpiphanyProposalModelingContinuationAction {
pub enum EpiphanyModelingContinuationAction {
Launch,
Wait,
Review,
@ -37,18 +37,10 @@ pub enum EpiphanyProposalModelingContinuationAction {
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct EpiphanyProposalModelingWorkProjection {
pub request: RepoFrontierProposalModelingRequest,
pub action: EpiphanyProposalModelingContinuationAction,
pub action: EpiphanyModelingContinuationAction,
pub job_id: Option<String>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum EpiphanyBodyModelingContinuationAction {
Launch,
Wait,
Review,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct EpiphanyBodyModelingWorkProjection {
pub work_id: String,
@ -307,7 +299,7 @@ pub fn project_current_work(store_path: impl AsRef<Path>) -> Result<EpiphanyCurr
Some(work) => {
let action = body_modeling_continuation_action(&cache, &work.work_id)?;
(
(action == EpiphanyBodyModelingContinuationAction::Launch).then_some(work),
(action == EpiphanyModelingContinuationAction::Launch).then_some(work),
Some(action),
)
}
@ -336,7 +328,7 @@ pub fn project_current_work(store_path: impl AsRef<Path>) -> Result<EpiphanyCurr
fn body_modeling_continuation_action(
cache: &CultCache,
work_id: &str,
) -> Result<EpiphanyBodyModelingContinuationAction> {
) -> Result<EpiphanyModelingContinuationAction> {
let mut bindings = cache
.get_all::<EpiphanyBodyModelingLaunchBinding>()?
.into_iter()
@ -344,26 +336,26 @@ fn body_modeling_continuation_action(
.collect::<Vec<_>>();
bindings.sort_by_key(|binding| binding.attempt_ordinal);
let Some(binding) = bindings.last() else {
return Ok(EpiphanyBodyModelingContinuationAction::Launch);
return Ok(EpiphanyModelingContinuationAction::Launch);
};
let job = cache
.get::<crate::EpiphanyRuntimeJob>(&binding.job_id)?
.ok_or_else(|| anyhow!("Body Modeling launch binding lost its runtime job"))?;
Ok(match job.status {
crate::EpiphanyRuntimeJobStatus::Failed | crate::EpiphanyRuntimeJobStatus::Cancelled => {
EpiphanyBodyModelingContinuationAction::Launch
EpiphanyModelingContinuationAction::Launch
}
crate::EpiphanyRuntimeJobStatus::Completed => {
if cache
.get::<crate::EpiphanyRuntimeRoleWorkerResult>(&binding.job_id)?
.is_some()
{
EpiphanyBodyModelingContinuationAction::Review
EpiphanyModelingContinuationAction::Review
} else {
EpiphanyBodyModelingContinuationAction::Wait
EpiphanyModelingContinuationAction::Wait
}
}
_ => EpiphanyBodyModelingContinuationAction::Wait,
_ => EpiphanyModelingContinuationAction::Wait,
})
}
@ -392,7 +384,7 @@ fn current_proposal_modeling_work(
let Some(binding) = request_bindings.last() else {
return Ok(Some(EpiphanyProposalModelingWorkProjection {
request,
action: EpiphanyProposalModelingContinuationAction::Launch,
action: EpiphanyModelingContinuationAction::Launch,
job_id: None,
}));
};
@ -421,16 +413,16 @@ fn current_proposal_modeling_work(
let action = match job.status {
crate::EpiphanyRuntimeJobStatus::Failed
| crate::EpiphanyRuntimeJobStatus::Cancelled => {
EpiphanyProposalModelingContinuationAction::Launch
EpiphanyModelingContinuationAction::Launch
}
crate::EpiphanyRuntimeJobStatus::Completed if result.is_some() => {
crate::runtime_spine::validate_proposal_modeling_worker_fulfillment(
cache,
result.as_ref().expect("checked terminal result"),
)?;
EpiphanyProposalModelingContinuationAction::Review
EpiphanyModelingContinuationAction::Review
}
_ => EpiphanyProposalModelingContinuationAction::Wait,
_ => EpiphanyModelingContinuationAction::Wait,
};
return Ok(Some(EpiphanyProposalModelingWorkProjection {
request,
@ -444,7 +436,7 @@ fn current_proposal_modeling_work(
pub fn body_modeling_continuation_action_for_job(
store_path: impl AsRef<Path>,
job_id: &str,
) -> Result<Option<EpiphanyBodyModelingContinuationAction>> {
) -> Result<Option<EpiphanyModelingContinuationAction>> {
let mut cache = crate::runtime_spine_cache(store_path)?;
cache.pull_all_backing_stores()?;
let bindings = cache
@ -475,7 +467,7 @@ pub fn body_modeling_continuation_action_for_job(
pub fn current_body_modeling_review_job_id(store_path: impl AsRef<Path>) -> Result<Option<String>> {
let store_path = store_path.as_ref();
if crate::project_current_work(store_path)?.body_modeling_action
!= Some(EpiphanyBodyModelingContinuationAction::Review)
!= Some(EpiphanyModelingContinuationAction::Review)
{
return Ok(None);
}
@ -494,7 +486,7 @@ pub fn current_body_modeling_review_job_id(store_path: impl AsRef<Path>) -> Resu
pub fn proposal_modeling_continuation_action_for_job(
store_path: impl AsRef<Path>,
job_id: &str,
) -> Result<Option<EpiphanyProposalModelingContinuationAction>> {
) -> Result<Option<EpiphanyModelingContinuationAction>> {
Ok(project_current_work(store_path)?
.proposal_modeling
.filter(|work| work.job_id.as_deref() == Some(job_id))
@ -506,7 +498,7 @@ pub fn current_proposal_modeling_review_job_id(
) -> Result<Option<String>> {
Ok(project_current_work(store_path)?
.proposal_modeling
.filter(|work| work.action == EpiphanyProposalModelingContinuationAction::Review)
.filter(|work| work.action == EpiphanyModelingContinuationAction::Review)
.and_then(|work| work.job_id))
}
@ -839,7 +831,7 @@ pub fn launch_current_proposal_modeling_work(
}
let work = project_current_work(store_path)?
.proposal_modeling
.filter(|work| work.action == EpiphanyProposalModelingContinuationAction::Launch)
.filter(|work| work.action == EpiphanyModelingContinuationAction::Launch)
.ok_or_else(|| anyhow!("Mind has no launchable proposal Modeling work"))?;
let mut cache = crate::runtime_spine_cache(store_path)?;
cache.pull_all_backing_stores()?;
@ -1230,7 +1222,7 @@ mod tests {
assert_eq!(current_work.body_modeling, Some(projected_work.clone()));
assert_eq!(
current_work.body_modeling_action,
Some(EpiphanyBodyModelingContinuationAction::Launch)
Some(EpiphanyModelingContinuationAction::Launch)
);
assert_eq!(
current_work.mind_projection_digest,
@ -1260,7 +1252,7 @@ mod tests {
assert!(scheduled_work.body_modeling.is_none());
assert_eq!(
scheduled_work.body_modeling_action,
Some(EpiphanyBodyModelingContinuationAction::Wait)
Some(EpiphanyModelingContinuationAction::Wait)
);
assert!(crate::resident_self_body_modeling_pressure(&store, 2)?.is_none());
let mut scheduled_cache = crate::runtime_spine_cache(&store)?;
@ -1360,7 +1352,7 @@ mod tests {
cache.put(&job.job_id, &job)?;
assert_eq!(
project_current_work(&store)?.body_modeling_action,
Some(EpiphanyBodyModelingContinuationAction::Review)
Some(EpiphanyModelingContinuationAction::Review)
);
let continuation = crate::EpiphanyCoordinatorRunReceipt {
schema_version: crate::COORDINATOR_RUN_RECEIPT_SCHEMA_VERSION.into(),
@ -1440,7 +1432,7 @@ mod tests {
assert_eq!(proposal_work.request, request);
assert_eq!(
proposal_work.action,
EpiphanyProposalModelingContinuationAction::Launch
EpiphanyModelingContinuationAction::Launch
);
let racers = (0..2)
.map(|_| {
@ -1483,7 +1475,7 @@ mod tests {
.proposal_modeling
.expect("launched proposal remains current")
.action,
EpiphanyProposalModelingContinuationAction::Wait
EpiphanyModelingContinuationAction::Wait
);
assert!(
launch_current_proposal_modeling_work(
@ -1645,7 +1637,7 @@ mod tests {
.proposal_modeling
.expect("terminal proposal remains current until admission")
.action,
EpiphanyProposalModelingContinuationAction::Review
EpiphanyModelingContinuationAction::Review
);
let proposal_commit = accept_proposal_modeling_result(
&store,

View file

@ -1210,7 +1210,7 @@ pub fn ingest_resident_self_domain_pressure(
// the next one on a later ingestion cycle.
if let Some(selection) = crate::project_current_work(runtime_store)?
.proposal_modeling
.filter(|work| work.action == crate::EpiphanyProposalModelingContinuationAction::Launch)
.filter(|work| work.action == crate::EpiphanyModelingContinuationAction::Launch)
.map(|work| work.request)
{
inserted += usize::from(enqueue_resident_self_pressure_idempotent(
@ -1358,11 +1358,11 @@ pub(crate) fn resident_self_safe_continuation_action(
crate::body_modeling_continuation_action_for_job(runtime_store, job_id)?
{
return Ok(match action {
crate::EpiphanyBodyModelingContinuationAction::Launch => {
crate::EpiphanyModelingContinuationAction::Launch => {
Some("launchModeling".to_string())
}
crate::EpiphanyBodyModelingContinuationAction::Wait => None,
crate::EpiphanyBodyModelingContinuationAction::Review => {
crate::EpiphanyModelingContinuationAction::Wait => None,
crate::EpiphanyModelingContinuationAction::Review => {
Some("reviewModelingResult".to_string())
}
});
@ -1371,11 +1371,11 @@ pub(crate) fn resident_self_safe_continuation_action(
crate::proposal_modeling_continuation_action_for_job(runtime_store, job_id)?
{
return Ok(match action {
crate::EpiphanyProposalModelingContinuationAction::Launch => {
crate::EpiphanyModelingContinuationAction::Launch => {
Some("launchModeling".to_string())
}
crate::EpiphanyProposalModelingContinuationAction::Wait => None,
crate::EpiphanyProposalModelingContinuationAction::Review => {
crate::EpiphanyModelingContinuationAction::Wait => None,
crate::EpiphanyModelingContinuationAction::Review => {
Some("reviewModelingResult".to_string())
}
});
@ -1521,13 +1521,13 @@ fn resident_self_failed_receipt_typed_continuation_action(
Ok(
match crate::proposal_modeling_continuation_action_for_job(runtime_store, &evidence.job_id)?
{
Some(crate::EpiphanyProposalModelingContinuationAction::Review) => {
Some(crate::EpiphanyModelingContinuationAction::Review) => {
Some("reviewModelingResult".to_string())
}
Some(crate::EpiphanyProposalModelingContinuationAction::Launch) => {
Some(crate::EpiphanyModelingContinuationAction::Launch) => {
Some("launchModeling".to_string())
}
Some(crate::EpiphanyProposalModelingContinuationAction::Wait) | None => None,
Some(crate::EpiphanyModelingContinuationAction::Wait) | None => None,
},
)
}

View file

@ -1,7 +1,7 @@
use epiphany_core::EpiphanyCrrcAction;
use epiphany_core::EpiphanyCrrcSceneAction;
use epiphany_core::EpiphanyCrrcStateStatus;
use epiphany_core::EpiphanyProposalModelingContinuationAction;
use epiphany_core::EpiphanyModelingContinuationAction;
use epiphany_core::EpiphanyReorientFindingInterpretation;
use epiphany_core::EpiphanyRoleBoardLane;
use epiphany_core::EpiphanyRoleFindingInterpretation;
@ -699,7 +699,7 @@ pub fn recommend_coordinator_action(
if let Some(action) = input.proposal_modeling_action {
return match action {
EpiphanyProposalModelingContinuationAction::Launch => build(
EpiphanyModelingContinuationAction::Launch => build(
EpiphanyCoordinatorAction::LaunchModeling,
Some(EpiphanyCoordinatorRoleId::Modeling),
Some(EpiphanyCoordinatorSceneAction::RoleLaunch),
@ -707,7 +707,7 @@ pub fn recommend_coordinator_action(
true,
"The oldest unresolved proposal request is ready for its exact Modeling attempt.",
),
EpiphanyProposalModelingContinuationAction::Wait => build(
EpiphanyModelingContinuationAction::Wait => build(
EpiphanyCoordinatorAction::WaitForModelingResult,
Some(EpiphanyCoordinatorRoleId::Modeling),
Some(EpiphanyCoordinatorSceneAction::RoleResult),
@ -715,7 +715,7 @@ pub fn recommend_coordinator_action(
false,
"The exact proposal Modeling attempt is still running.",
),
EpiphanyProposalModelingContinuationAction::Review => build(
EpiphanyModelingContinuationAction::Review => build(
EpiphanyCoordinatorAction::ReviewModelingResult,
Some(EpiphanyCoordinatorRoleId::Modeling),
Some(EpiphanyCoordinatorSceneAction::RoleResult),
@ -1489,7 +1489,7 @@ mod tests {
fn selected_user_proposal_preempts_generic_regather() {
let decision = recommend_coordinator_action(EpiphanyCoordinatorInput {
recommendation: recommendation(EpiphanyCrrcAction::RegatherManually),
proposal_modeling_action: Some(EpiphanyProposalModelingContinuationAction::Launch),
proposal_modeling_action: Some(EpiphanyModelingContinuationAction::Launch),
..input()
});
assert_eq!(decision.action, EpiphanyCoordinatorAction::LaunchModeling);

View file

@ -6,7 +6,7 @@ use super::EpiphanyPressure;
use super::EpiphanyPressureLevel;
use super::EpiphanyReorientAction;
use super::EpiphanyRoleBoardLane;
use crate::EpiphanyProposalModelingContinuationAction;
use crate::EpiphanyModelingContinuationAction;
use crate::RepoFrontierPlanningLifecycleStage;
use crate::RepoFrontierResearchContinuationAction;
use serde::{Deserialize, Serialize};
@ -167,7 +167,7 @@ pub struct EpiphanyCoordinatorInput {
/// lifecycle. Self may advance it, but only Mind's result can decide adoption.
pub frontier_planning_stage: RepoFrontierPlanningLifecycleStage,
/// Exact current action for the oldest unresolved proposal Modeling request.
pub proposal_modeling_action: Option<EpiphanyProposalModelingContinuationAction>,
pub proposal_modeling_action: Option<EpiphanyModelingContinuationAction>,
pub body_modeling_work_ready: bool,
pub body_modeling_review_ready: bool,
}
@ -220,7 +220,7 @@ pub struct EpiphanyCoordinatorStatusInput {
pub hands_frontier_ready: bool,
pub research_continuation_action: Option<RepoFrontierResearchContinuationAction>,
pub frontier_planning_stage: RepoFrontierPlanningLifecycleStage,
pub proposal_modeling_action: Option<EpiphanyProposalModelingContinuationAction>,
pub proposal_modeling_action: Option<EpiphanyModelingContinuationAction>,
pub body_modeling_work_ready: bool,
pub body_modeling_review_ready: bool,
}