From 40d00bc5aba751b9bade24d737a696a556311623 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Sun, 23 Aug 2026 20:47:28 +0200 Subject: [PATCH] Collapse duplicate planning eligibility --- epiphany-core/src/lib.rs | 2 - epiphany-core/src/repo_model_gateway.rs | 22 ----- epiphany-core/src/runtime_spine.rs | 118 +++--------------------- 3 files changed, 11 insertions(+), 131 deletions(-) diff --git a/epiphany-core/src/lib.rs b/epiphany-core/src/lib.rs index ee4e6514..5c45f8ad 100644 --- a/epiphany-core/src/lib.rs +++ b/epiphany-core/src/lib.rs @@ -337,11 +337,9 @@ pub use runtime_spine::runtime_hands_command_receipt; pub use runtime_spine::runtime_hands_commit_receipt; pub use runtime_spine::runtime_hands_patch_receipt; pub use runtime_spine::runtime_has_actionable_hands_frontier; -pub use runtime_spine::runtime_has_actionable_imagination_frontier; pub use runtime_spine::runtime_job_snapshot; pub use runtime_spine::runtime_registered_document_types; pub use runtime_spine::runtime_reorient_worker_result; -pub use runtime_spine::runtime_repo_frontier_planning_eligibility; pub use runtime_spine::runtime_repo_frontier_planning_lifecycle; pub use runtime_spine::runtime_repo_frontier_research_lifecycle; pub use runtime_spine::runtime_requested_public_source_refs_for_worker; diff --git a/epiphany-core/src/repo_model_gateway.rs b/epiphany-core/src/repo_model_gateway.rs index f83e3d5a..10811409 100644 --- a/epiphany-core/src/repo_model_gateway.rs +++ b/epiphany-core/src/repo_model_gateway.rs @@ -574,28 +574,6 @@ pub struct RepoFrontierPlanningLifecycle { pub decision_id: Option, } -/// Read-only Self projection explaining why an unresolved Imagination frontier -/// is or is not eligible for the canonical planning-request commit primitive. -/// This carries no planning authority and persists no substitute state. -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct RepoFrontierPlanningCandidateEligibility { - pub frontier_item_id: String, - pub eligible: bool, - pub status_valid: bool, - pub recommended_next_organ_valid: bool, - pub repository_scope_valid: bool, - pub challenged_target_claim_ids: Vec, - pub unresolved_dependency_item_ids: Vec, -} - -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct RepoFrontierPlanningEligibility { - pub current_model_count: usize, - pub candidates: Vec, -} - #[derive(Debug, Clone, PartialEq, Eq, DatabaseEntry)] #[cultcache( type = "epiphany.self.repo_frontier_plan_mind_request", diff --git a/epiphany-core/src/runtime_spine.rs b/epiphany-core/src/runtime_spine.rs index 34134a27..9f046c8c 100644 --- a/epiphany-core/src/runtime_spine.rs +++ b/epiphany-core/src/runtime_spine.rs @@ -38,7 +38,6 @@ use crate::repo_model_gateway::{ RepoFrontierHandsAuthority, RepoFrontierModelingRequest, RepoFrontierNextOrgan, RepoFrontierPlanCandidate, RepoFrontierPlanDecision, RepoFrontierPlanDecisionReceipt, RepoFrontierPlanMindDecision, RepoFrontierPlanMindLaunchBinding, RepoFrontierPlanMindRequest, - RepoFrontierPlanningCandidateEligibility, RepoFrontierPlanningEligibility, RepoFrontierPlanningFailureReview, RepoFrontierPlanningLaunchBinding, RepoFrontierPlanningLifecycle, RepoFrontierPlanningLifecycleStage, RepoFrontierPlanningRequest, RepoFrontierProposalModelingLaunchBinding, RepoFrontierProposalModelingRequest, @@ -7056,7 +7055,7 @@ fn frontier_item_is_actionable_for_organ( /// Hands. Status projection must use this instead of assuming that a clear /// CRRC lane implies implementation authority. pub fn runtime_has_actionable_hands_frontier(runtime_store: impl AsRef) -> Result { - runtime_has_actionable_frontier_for_organ(runtime_store, "Hands") + runtime_has_actionable_frontier_for_organ(runtime_store, "Hands", true) } @@ -7700,108 +7699,6 @@ fn repo_frontier_research_request_is_actionable( Ok(current_repo_frontier_research_request(cache, request)?.is_some()) } -/// Read-only Self signal for proposal planning. It uses the same eligibility -/// predicate as the planning-request committer, including unchallenged target -/// claims, so status cannot advertise authority that the commit path rejects. -pub fn runtime_has_actionable_imagination_frontier( - runtime_store: impl AsRef, -) -> Result { - let eligibility = runtime_repo_frontier_planning_eligibility(runtime_store)?; - Ok(eligibility.current_model_count == 1 - && eligibility - .candidates - .iter() - .any(|candidate| candidate.eligible)) -} - -/// Read-only Self signal explaining the exact canonical blockers on every -/// active Imagination frontier. It derives from the same admitted RepoModel, -/// current claim-challenge set, repository-scope predicate, and dependency rule as -/// planning selection; it neither creates nor repairs authority. -pub fn runtime_repo_frontier_planning_eligibility( - runtime_store: impl AsRef, -) -> Result { - let runtime_store = runtime_store.as_ref(); - let mut cache = runtime_spine_cache(runtime_store)?; - cache.pull_all_backing_stores()?; - require_identity(&cache)?; - let Ok((view, basis)) = current_keyed_repo_model(&cache) else { - return Ok(RepoFrontierPlanningEligibility { - current_model_count: 0, - candidates: Vec::new(), - }); - }; - let model = view.memory_context_projection(); - let model_count = 1; - let challenges = current_repo_model_claim_challenges(&cache, &model, &basis)?; - let terminal = |status: crate::RepoFrontierStatus| { - matches!( - status, - crate::RepoFrontierStatus::Resolved - | crate::RepoFrontierStatus::Retired - | crate::RepoFrontierStatus::Superseded - ) - }; - let mut candidates = model - .frontier - .iter() - .filter(|item| { - matches!( - item.status, - crate::RepoFrontierStatus::Active | crate::RepoFrontierStatus::Proposed - ) && item - .recommended_next_organ - .eq_ignore_ascii_case("Imagination") - }) - .map(|item| { - let status_valid = item.status == crate::RepoFrontierStatus::Active; - let recommended_next_organ_valid = item.recommended_next_organ == "Imagination"; - let repository_scope_valid = - crate::memory_graph::frontier_item_has_routeable_repository_scope(item); - let mut challenged_target_claim_ids = challenges - .iter() - .filter(|challenge| item.target_claim_ids.contains(&challenge.target_claim_id)) - .map(|challenge| challenge.target_claim_id.clone()) - .collect::>(); - challenged_target_claim_ids.sort(); - challenged_target_claim_ids.dedup(); - let mut unresolved_dependency_item_ids = item - .dependency_item_ids - .iter() - .filter(|dependency_id| { - !model - .frontier - .iter() - .find(|candidate| candidate.id.as_str() == dependency_id.as_str()) - .is_some_and(|dependency| terminal(dependency.status)) - }) - .cloned() - .collect::>(); - unresolved_dependency_item_ids.sort(); - unresolved_dependency_item_ids.dedup(); - RepoFrontierPlanningCandidateEligibility { - frontier_item_id: item.id.clone(), - eligible: model_count == 1 - && status_valid - && recommended_next_organ_valid - && repository_scope_valid - && challenged_target_claim_ids.is_empty() - && unresolved_dependency_item_ids.is_empty(), - status_valid, - recommended_next_organ_valid, - repository_scope_valid, - challenged_target_claim_ids, - unresolved_dependency_item_ids, - } - }) - .collect::>(); - candidates.sort_by(|a, b| a.frontier_item_id.cmp(&b.frontier_item_id)); - Ok(RepoFrontierPlanningEligibility { - current_model_count: model_count, - candidates, - }) -} - fn repo_frontier_planning_failure_review_id(result_id: &str) -> String { format!("repo-frontier-planning-failure-review-{result_id}") } @@ -7980,7 +7877,7 @@ pub fn runtime_repo_frontier_planning_lifecycle( ..empty(RepoFrontierPlanningLifecycleStage::Terminal) }); } - if runtime_has_actionable_imagination_frontier(runtime_store)? { + if runtime_has_actionable_frontier_for_organ(runtime_store, "Imagination", true)? { return Ok(empty(RepoFrontierPlanningLifecycleStage::Ready)); } let latest_terminal = decisions.iter().max_by(|a, b| { @@ -8151,6 +8048,7 @@ pub fn runtime_repo_frontier_planning_lifecycle( fn runtime_has_actionable_frontier_for_organ( runtime_store: impl AsRef, organ: &str, + require_unchallenged_targets: bool, ) -> Result { let runtime_store = runtime_store.as_ref(); let mut cache = runtime_spine_cache(runtime_store)?; @@ -8160,12 +8058,18 @@ fn runtime_has_actionable_frontier_for_organ( return Ok(false); }; let model = view.memory_context_projection(); - let challenges = if organ == "Hands" { + let challenges = if require_unchallenged_targets { current_repo_model_claim_challenges(&cache, &model, &basis)? } else { Vec::new() }; - Ok(actionable_frontier_item_for_organ(&model, &challenges, organ, organ == "Hands").is_some()) + Ok(actionable_frontier_item_for_organ( + &model, + &challenges, + organ, + require_unchallenged_targets, + ) + .is_some()) } pub fn put_runtime_reorient_worker_result(