Skip to content

Commit 5e52475

Browse files
fluffy314cursoragent
authored andcommitted
feat(autoresearch): resolve proof plans autonomously
Turn theorem evidence and atomic definition gaps into deterministic, versioned plan candidates so proof search can progress without activating supervisor dispatch yet. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 5afd103 commit 5e52475

18 files changed

Lines changed: 6950 additions & 0 deletions

autoresearch/prefill/architecture_v7.py

Lines changed: 455 additions & 0 deletions
Large diffs are not rendered by default.

autoresearch/prefill/atomic_definition.py

Lines changed: 554 additions & 0 deletions
Large diffs are not rendered by default.

autoresearch/prefill/creative_decomposition.py

Lines changed: 649 additions & 0 deletions
Large diffs are not rendered by default.

autoresearch/prefill/definition_resolution.py

Lines changed: 735 additions & 0 deletions
Large diffs are not rendered by default.

autoresearch/prefill/evidence_planner.py

Lines changed: 470 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
"""Host-owned gate between a strategy tournament and proof search."""
2+
from __future__ import annotations
3+
4+
import hashlib
5+
import json
6+
from dataclasses import asdict, dataclass
7+
from enum import Enum
8+
from typing import Iterable, Mapping
9+
10+
from autoresearch.prefill.strategy_tournament import (
11+
PlanExecutionStatus,
12+
StrategyPlan,
13+
)
14+
15+
16+
CONTRACT_VERSION = 2
17+
18+
19+
def _digest(value: object) -> str:
20+
return hashlib.sha256(json.dumps(
21+
value, ensure_ascii=False, sort_keys=True, separators=(",", ":"),
22+
).encode()).hexdigest()
23+
24+
25+
class ContractRejection(str, Enum):
26+
MISSING_DEFINITION = "MISSING_DEFINITION"
27+
UNELABORATED_TARGET = "UNELABORATED_TARGET"
28+
PROPOSITION_HASH_MISMATCH = "PROPOSITION_HASH_MISMATCH"
29+
UNRESOLVED_DEPENDENCY = "UNRESOLVED_DEPENDENCY"
30+
UNRESOLVED_THEOREM_CARD = "UNRESOLVED_THEOREM_CARD"
31+
MISSING_SUCCESS_CRITERION = "MISSING_SUCCESS_CRITERION"
32+
MISSING_FAILURE_CRITERION = "MISSING_FAILURE_CRITERION"
33+
MISSING_PROOF_OBLIGATION = "MISSING_PROOF_OBLIGATION"
34+
HIDDEN_ASSUMPTION = "HIDDEN_ASSUMPTION"
35+
NON_REDUCING_TARGET = "NON_REDUCING_TARGET"
36+
ENVIRONMENT_HASH_MISMATCH = "ENVIRONMENT_HASH_MISMATCH"
37+
PLAN_HASH_MISMATCH = "PLAN_HASH_MISMATCH"
38+
PLANNING_ONLY = "PLANNING_ONLY"
39+
40+
41+
@dataclass(frozen=True)
42+
class ResearchContract:
43+
contract_version: int
44+
contract_id: str
45+
plan_id: str
46+
plan_hash: str
47+
target_ref: str
48+
theorem_id: str
49+
proposition_hash: str
50+
proof_obligation_id: str
51+
definition_ids: tuple[str, ...]
52+
definition_gap_ids: tuple[str, ...]
53+
definition_auditor_hash: str
54+
dependency_ids: tuple[str, ...]
55+
theorem_card_ids: tuple[str, ...]
56+
assumption_ids: tuple[str, ...]
57+
success_criterion_id: str
58+
failure_criterion_id: str
59+
parent_obligation_ref: str
60+
parent_complexity: int
61+
target_complexity: int
62+
environment_hash: str
63+
content_hash: str
64+
65+
66+
@dataclass(frozen=True)
67+
class ContractDecision:
68+
accepted: bool
69+
reason_codes: tuple[str, ...]
70+
route_state: str
71+
contract: ResearchContract | None
72+
73+
74+
def gate_research_contract(
75+
plan: StrategyPlan,
76+
*,
77+
elaborated_theorem_id: str,
78+
elaborated_proposition_hash: str,
79+
proof_obligation_id: str,
80+
registered_definition_ids: Iterable[str],
81+
resolved_dependency_ids: Iterable[str],
82+
verified_theorem_card_ids: Iterable[str],
83+
allowed_assumption_ids: Iterable[str],
84+
environment_hash: str,
85+
expected_plan_hash: str,
86+
) -> ContractDecision:
87+
reasons: list[str] = []
88+
definitions = set(registered_definition_ids)
89+
dependencies = set(resolved_dependency_ids)
90+
cards = set(verified_theorem_card_ids)
91+
assumptions = set(allowed_assumption_ids)
92+
if not set(plan.required_definition_ids) <= definitions:
93+
reasons.append(ContractRejection.MISSING_DEFINITION.value)
94+
if plan.execution_status != PlanExecutionStatus.EXECUTABLE.value:
95+
reasons.append(ContractRejection.PLANNING_ONLY.value)
96+
if (
97+
plan.plan_class == "REFRAME_DEFINITIONS_OR_REPRESENTATION"
98+
and not (
99+
plan.proposition_transformation_ref
100+
or plan.case_partition_ids
101+
)
102+
):
103+
reasons.append(ContractRejection.PLANNING_ONLY.value)
104+
if not elaborated_theorem_id or not elaborated_proposition_hash:
105+
reasons.append(ContractRejection.UNELABORATED_TARGET.value)
106+
if not set(plan.dependency_ids) <= dependencies:
107+
reasons.append(ContractRejection.UNRESOLVED_DEPENDENCY.value)
108+
if not set(plan.theorem_card_ids) <= cards:
109+
reasons.append(ContractRejection.UNRESOLVED_THEOREM_CARD.value)
110+
if not plan.success_criterion_id:
111+
reasons.append(ContractRejection.MISSING_SUCCESS_CRITERION.value)
112+
if not plan.abandonment_criterion_id:
113+
reasons.append(ContractRejection.MISSING_FAILURE_CRITERION.value)
114+
if not proof_obligation_id:
115+
reasons.append(ContractRejection.MISSING_PROOF_OBLIGATION.value)
116+
if not set(plan.assumption_ids) <= assumptions:
117+
reasons.append(ContractRejection.HIDDEN_ASSUMPTION.value)
118+
if plan.target_complexity >= plan.parent_complexity:
119+
reasons.append(ContractRejection.NON_REDUCING_TARGET.value)
120+
if plan.environment_hash != environment_hash:
121+
reasons.append(ContractRejection.ENVIRONMENT_HASH_MISMATCH.value)
122+
if plan.content_hash != expected_plan_hash:
123+
reasons.append(ContractRejection.PLAN_HASH_MISMATCH.value)
124+
if reasons:
125+
reason_set = set(reasons)
126+
if reason_set & {
127+
ContractRejection.MISSING_DEFINITION.value,
128+
ContractRejection.UNELABORATED_TARGET.value,
129+
ContractRejection.MISSING_PROOF_OBLIGATION.value,
130+
ContractRejection.PLANNING_ONLY.value,
131+
}:
132+
route = "DECOMPOSER"
133+
elif reason_set & {
134+
ContractRejection.PROPOSITION_HASH_MISMATCH.value,
135+
ContractRejection.UNRESOLVED_DEPENDENCY.value,
136+
}:
137+
route = "MATH_IR_TRANSLATION"
138+
elif reason_set & {
139+
ContractRejection.ENVIRONMENT_HASH_MISMATCH.value,
140+
ContractRejection.PLAN_HASH_MISMATCH.value,
141+
}:
142+
route = "HOST_TYPED_IR_GATE"
143+
else:
144+
route = "STRATEGY_TOURNAMENT"
145+
return ContractDecision(False, tuple(dict.fromkeys(reasons)), route, None)
146+
body: Mapping[str, object] = {
147+
"contract_version": CONTRACT_VERSION,
148+
"plan_id": plan.plan_id,
149+
"plan_hash": plan.content_hash,
150+
"target_ref": plan.target_ref,
151+
"theorem_id": elaborated_theorem_id,
152+
"proposition_hash": elaborated_proposition_hash,
153+
"proof_obligation_id": proof_obligation_id,
154+
"definition_ids": plan.required_definition_ids,
155+
"definition_gap_ids": plan.definition_gap_ids,
156+
"definition_auditor_hash": plan.definition_auditor_hash,
157+
"dependency_ids": plan.dependency_ids,
158+
"theorem_card_ids": plan.theorem_card_ids,
159+
"assumption_ids": plan.assumption_ids,
160+
"success_criterion_id": plan.success_criterion_id,
161+
"failure_criterion_id": plan.abandonment_criterion_id,
162+
"parent_obligation_ref": plan.parent_obligation_ref,
163+
"parent_complexity": plan.parent_complexity,
164+
"target_complexity": plan.target_complexity,
165+
"environment_hash": environment_hash,
166+
}
167+
content_hash = _digest(body)
168+
contract = ResearchContract(
169+
contract_id="RC-" + content_hash[:20],
170+
content_hash=content_hash,
171+
**body, # type: ignore[arg-type]
172+
)
173+
return ContractDecision(True, ("ACCEPTED",), "PROOF_SEARCH", contract)
174+
175+
176+
def verify_contract_binding(
177+
contract: ResearchContract,
178+
*,
179+
proposition_hash: str,
180+
environment_hash: str,
181+
) -> None:
182+
if contract.proposition_hash != proposition_hash:
183+
raise ValueError(ContractRejection.PROPOSITION_HASH_MISMATCH.value)
184+
if contract.environment_hash != environment_hash:
185+
raise ValueError(ContractRejection.ENVIRONMENT_HASH_MISMATCH.value)
186+
body = asdict(contract)
187+
content_hash = body.pop("content_hash")
188+
body.pop("contract_id")
189+
if _digest(body) != content_hash:
190+
raise ValueError("RESEARCH_CONTRACT_CONTENT_HASH_MISMATCH")

0 commit comments

Comments
 (0)