@@ -1646,6 +1646,56 @@ def is_nonfatal_semantic_continuation(
16461646 )
16471647
16481648
1649+ def route_contract_to_subgoal_generation (
1650+ checkpoint : OrchestrationCheckpoint ,
1651+ ) -> bool :
1652+ """Require a typed elaborated subgoal before any OProver residency request."""
1653+ if (
1654+ checkpoint .proof_state != ProofState .PROOF_SEARCH
1655+ or not checkpoint .research_contract_id
1656+ or checkpoint .proof_plan_id
1657+ or checkpoint .executable_plan_node_id
1658+ ):
1659+ return False
1660+ if checkpoint .adapter_status :
1661+ if checkpoint .blocked_reason != (
1662+ "PROOF_ADVISOR_UNAVAILABLE:RESIDENCY_PROCESS_MANAGER_REQUIRED"
1663+ ):
1664+ return False
1665+ checkpoint .clear_adapter_blocked (
1666+ "research-contract-awaits-elaborated-subgoal" ,
1667+ )
1668+ event_id = hashlib .sha256 (
1669+ (
1670+ checkpoint .target_obligation_id
1671+ + checkpoint .research_contract_id
1672+ + checkpoint .proposition_hash
1673+ ).encode ()
1674+ ).hexdigest ()
1675+ if any (
1676+ item .get ("event_type" ) == "RESEARCH_CONTRACT_SUBGOAL_REQUIRED"
1677+ and item .get ("event_id" ) == event_id
1678+ for item in checkpoint .recovery_events
1679+ ):
1680+ return False
1681+ checkpoint .transition (
1682+ ProofState .DECOMPOSER ,
1683+ "research-contract:generate-strictly-reducing-elaborated-subgoal" ,
1684+ strategy_reused = True ,
1685+ )
1686+ checkpoint .recovery_events .append ({
1687+ "event_type" : "RESEARCH_CONTRACT_SUBGOAL_REQUIRED" ,
1688+ "event_id" : event_id ,
1689+ "target_obligation_id" : checkpoint .target_obligation_id ,
1690+ "research_contract_id" : checkpoint .research_contract_id ,
1691+ "selected_strategy_plan_id" : checkpoint .selected_strategy_plan_id ,
1692+ "proposition_hash" : checkpoint .proposition_hash ,
1693+ "target_state" : ProofState .DECOMPOSER .value ,
1694+ "created_at" : time .time (),
1695+ })
1696+ return True
1697+
1698+
16491699def should_resume_downstream (
16501700 checkpoint : OrchestrationCheckpoint | None ,
16511701 * ,
@@ -2043,6 +2093,23 @@ def run_iteration(args, iteration: int) -> dict:
20432093 orchestration_state_path ,
20442094 orchestration_checkpoint ,
20452095 )
2096+ if (
2097+ orchestration_checkpoint is not None
2098+ and route_contract_to_subgoal_generation (orchestration_checkpoint )
2099+ ):
2100+ save_orchestration_checkpoint (
2101+ orchestration_state_path ,
2102+ orchestration_checkpoint ,
2103+ )
2104+ print (
2105+ "[proof-live] stage=subgoal-generation "
2106+ f"target={ orchestration_checkpoint .target_obligation_id } "
2107+ f"proposition={ orchestration_checkpoint .target_statement } "
2108+ f"plan={ orchestration_checkpoint .selected_strategy_plan_id } "
2109+ f"contract={ orchestration_checkpoint .research_contract_id } "
2110+ "next=DECOMPOSER reason=elaborated-subgoal-required" ,
2111+ flush = True ,
2112+ )
20462113 if (
20472114 orchestration_checkpoint is not None
20482115 and (
@@ -2504,37 +2571,55 @@ def run_iteration(args, iteration: int) -> dict:
25042571 orchestration_checkpoint .proof_state == ProofState .PROOF_SEARCH
25052572 and orchestration_checkpoint .research_contract_id
25062573 ):
2507- # OProver residency is permitted only behind an accepted,
2508- # elaborated Research Contract. The downstream typed-role GAN
2509- # remains available for definition/evidence expansion.
2510- orchestration_checkpoint .adapter_blocked (
2511- "PROOF_ADVISOR_UNAVAILABLE:"
2512- "RESIDENCY_PROCESS_MANAGER_REQUIRED" ,
2513- status = "INTEGRATION_BLOCKED" ,
2514- )
2515- save_orchestration_checkpoint (
2516- orchestration_state_path ,
2574+ if route_contract_to_subgoal_generation (
25172575 orchestration_checkpoint ,
2518- )
2519- live_status .emit (
2520- phase = "proof_advisor_unavailable" ,
2521- role = "oprover_advisor" ,
2522- state = "idle" ,
2523- active_obligation_id = (
2524- orchestration_checkpoint .target_obligation_id
2525- ),
2526- source = "proof_supervisor" ,
2527- force = True ,
2528- )
2529- return {
2530- "iteration" : iteration ,
2531- "research_outcome" : "BLOCKED" ,
2532- "orchestration_state" : "INTEGRATION_BLOCKED" ,
2533- "transition_reason" : orchestration_checkpoint .blocked_reason ,
2534- "failure_class" : "" ,
2535- "error" : "" ,
2536- "inference_started" : False ,
2537- }
2576+ ):
2577+ save_orchestration_checkpoint (
2578+ orchestration_state_path ,
2579+ orchestration_checkpoint ,
2580+ )
2581+ print (
2582+ "[proof-live] stage=research-contract "
2583+ f"target={ orchestration_checkpoint .target_obligation_id } "
2584+ f"plan={ orchestration_checkpoint .selected_strategy_plan_id } "
2585+ f"contract={ orchestration_checkpoint .research_contract_id } "
2586+ "accepted=true next=DECOMPOSER "
2587+ "reason=elaborated-subgoal-required" ,
2588+ flush = True ,
2589+ )
2590+ else :
2591+ # OProver residency is permitted only after both an accepted
2592+ # contract and a concrete typed proof-plan node exist.
2593+ orchestration_checkpoint .adapter_blocked (
2594+ "PROOF_ADVISOR_UNAVAILABLE:"
2595+ "RESIDENCY_PROCESS_MANAGER_REQUIRED" ,
2596+ status = "INTEGRATION_BLOCKED" ,
2597+ )
2598+ save_orchestration_checkpoint (
2599+ orchestration_state_path ,
2600+ orchestration_checkpoint ,
2601+ )
2602+ live_status .emit (
2603+ phase = "proof_advisor_unavailable" ,
2604+ role = "oprover_advisor" ,
2605+ state = "idle" ,
2606+ active_obligation_id = (
2607+ orchestration_checkpoint .target_obligation_id
2608+ ),
2609+ source = "proof_supervisor" ,
2610+ force = True ,
2611+ )
2612+ return {
2613+ "iteration" : iteration ,
2614+ "research_outcome" : "BLOCKED" ,
2615+ "orchestration_state" : "INTEGRATION_BLOCKED" ,
2616+ "transition_reason" : (
2617+ orchestration_checkpoint .blocked_reason
2618+ ),
2619+ "failure_class" : "" ,
2620+ "error" : "" ,
2621+ "inference_started" : False ,
2622+ }
25382623 experiment_id = (
25392624 f"ar_{ int (time .time ())} _{ iteration } _"
25402625 f"{ hashlib .sha256 (candidate_path .read_bytes ()).hexdigest ()[:8 ]} "
0 commit comments