Skip to content

Commit 4910a92

Browse files
fluffy314cursoragent
authored andcommitted
fix(autoresearch): preserve contract on role migration
Invalidate incompatible executable role artifacts without erasing the accepted strategy tournament and research contract provenance needed for certified retries. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 38334d5 commit 4910a92

2 files changed

Lines changed: 56 additions & 1 deletion

File tree

scripts/agent_gan_repl.py

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5196,6 +5196,17 @@ def _run_typed_ir_v2(
51965196
)
51975197

51985198

5199+
def retain_contract_provenance_after_artifact_failure(
5200+
checkpoint: OrchestrationCheckpoint,
5201+
) -> None:
5202+
"""Invalidate executable role artifacts without erasing accepted strategy."""
5203+
checkpoint.validated_artifacts = {
5204+
role: reference
5205+
for role, reference in checkpoint.validated_artifacts.items()
5206+
if role in {"strategy_tournament", "research_contract"}
5207+
}
5208+
5209+
51995210
def run_certified_decomposition(
52005211
ledger: ProofObligationLedger,
52015212
target_id: str,
@@ -5542,14 +5553,34 @@ def run_certified_decomposition(
55425553
flush=True,
55435554
)
55445555
except (OSError, ValueError, TypeError, json.JSONDecodeError) as exc:
5545-
orchestration_checkpoint.validated_artifacts = {}
5556+
retain_contract_provenance_after_artifact_failure(
5557+
orchestration_checkpoint,
5558+
)
55465559
orchestration_checkpoint.state = (
55475560
ProofState.DEFINITION_AUDITOR.value
55485561
)
55495562
orchestration_checkpoint.current_role = "definition_auditor"
55505563
orchestration_checkpoint.last_transition_reason = (
55515564
f"artifact-resume-invalidated:{type(exc).__name__}"
55525565
)
5566+
orchestration_checkpoint.recovery_events.append({
5567+
"event_type": "EXECUTABLE_ARTIFACT_RESUME_INVALIDATED",
5568+
"event_id": hashlib.sha256(
5569+
(
5570+
type(exc).__name__
5571+
+ orchestration_checkpoint.target_obligation_id
5572+
+ orchestration_checkpoint.research_contract_id
5573+
).encode()
5574+
).hexdigest(),
5575+
"reason": type(exc).__name__,
5576+
"preserved_artifact_roles": sorted(
5577+
orchestration_checkpoint.validated_artifacts
5578+
),
5579+
"research_contract_id": (
5580+
orchestration_checkpoint.research_contract_id
5581+
),
5582+
"created_at": time.time(),
5583+
})
55535584
save_orchestration_checkpoint(
55545585
checkpoint_path,
55555586
orchestration_checkpoint,

tests/inference_engine/bridge/test_agent_gan_repl.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@
115115
save_checkpoint,
116116
run_isolated_premise_review,
117117
run_certified_decomposition,
118+
retain_contract_provenance_after_artifact_failure,
118119
persist_verified_decomposition,
119120
validate_evidence_artifact,
120121
)
@@ -3633,6 +3634,29 @@ def test_true_binding_mismatch_preserves_accepted_contract(tmp_path):
36333634
assert preserved.adapter_status == "INTEGRATION_BLOCKED"
36343635

36353636

3637+
def test_artifact_migration_failure_preserves_contract_provenance():
3638+
checkpoint = OrchestrationCheckpoint(
3639+
research_contract_id="RC-root",
3640+
research_contract_hash="contract-hash",
3641+
selected_strategy_plan_id="SP-root",
3642+
selected_strategy_plan_hash="plan-hash",
3643+
)
3644+
checkpoint.validated_artifacts = {
3645+
"definition_auditor": object(),
3646+
"counterexample_worker": object(),
3647+
"strategy_tournament": object(),
3648+
"research_contract": object(),
3649+
}
3650+
retain_contract_provenance_after_artifact_failure(checkpoint)
3651+
assert set(checkpoint.validated_artifacts) == {
3652+
"strategy_tournament",
3653+
"research_contract",
3654+
}
3655+
assert checkpoint.research_contract_id == "RC-root"
3656+
assert checkpoint.research_contract_hash == "contract-hash"
3657+
assert checkpoint.selected_strategy_plan_id == "SP-root"
3658+
3659+
36363660
@pytest.mark.skip(reason="legacy model-authored artifact execution is read-only")
36373661
def test_resume_binding_mismatch_invalidates_cached_artifacts(tmp_path):
36383662
state_path = tmp_path / "orchestration.json"

0 commit comments

Comments
 (0)