feat: Significant code review suite rewrite with improved graph agent features
This commit is contained in:
41 files changed
+3572
-709
No files matched your search
@@ -0,0 +1,148 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Contract gate for the adversary's per-criterion verify chain.
|
||||
|
||||
Validates each criterion verdict against the contract:
|
||||
- a single JSON object with status in {MET, PARTIAL, UNMET, DIVERGED}
|
||||
- MET requires non-empty evidence (the change AND the proving test)
|
||||
- non-MET requires a non-empty complaint
|
||||
|
||||
The authoritative id is stamped from the criterion item — the model's echo is
|
||||
never trusted. Malformed output is rejected back to check_criterion exactly
|
||||
once with the reason; a second failure records PARTIAL (unproven) so a
|
||||
malformed item can never sink the map or masquerade as MET.
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
|
||||
STATUSES = {"MET", "PARTIAL", "UNMET", "DIVERGED"}
|
||||
MAX_RETRIES = 1
|
||||
|
||||
|
||||
def load_state():
|
||||
if path := os.environ.get("GRAPH_STATE_FILE"):
|
||||
with open(path) as f:
|
||||
return json.load(f)
|
||||
return json.loads(os.environ.get("GRAPH_STATE", "{}"))
|
||||
|
||||
|
||||
def criterion_fields(state):
|
||||
c = state.get("criterion")
|
||||
if isinstance(c, dict):
|
||||
cid = c.get("id")
|
||||
text = c.get("text")
|
||||
return (
|
||||
cid.strip() if isinstance(cid, str) and cid.strip() else "unknown",
|
||||
text.strip() if isinstance(text, str) else "",
|
||||
)
|
||||
return "unknown", ""
|
||||
|
||||
|
||||
def extract_json(text):
|
||||
if not isinstance(text, str) or not text.strip():
|
||||
raise ValueError("criterion-check output is empty or not text")
|
||||
text = re.sub(r"```[a-zA-Z]*", "", text).replace("```", "")
|
||||
start, end = text.find("{"), text.rfind("}")
|
||||
if start == -1 or end <= start:
|
||||
raise ValueError("no JSON object found in criterion-check output")
|
||||
return json.loads(text[start : end + 1])
|
||||
|
||||
|
||||
def validate(obj):
|
||||
if not isinstance(obj, dict):
|
||||
raise ValueError("criterion-check output is not a JSON object")
|
||||
status = obj.get("status")
|
||||
if status not in STATUSES:
|
||||
raise ValueError(f"status must be one of {sorted(STATUSES)}, got {status!r}")
|
||||
evidence = obj.get("evidence") if isinstance(obj.get("evidence"), str) else ""
|
||||
complaint = obj.get("complaint") if isinstance(obj.get("complaint"), str) else ""
|
||||
if status == "MET" and not evidence.strip():
|
||||
raise ValueError(
|
||||
"MET requires non-empty evidence citing the satisfying change AND the "
|
||||
"test proving the behavior (file:line)"
|
||||
)
|
||||
if status != "MET" and not complaint.strip():
|
||||
raise ValueError(
|
||||
f"{status} requires a non-empty complaint (what the diff does/omits at "
|
||||
"file:line, and what would make it conform)"
|
||||
)
|
||||
return status, evidence, complaint
|
||||
|
||||
|
||||
def main():
|
||||
state = load_state()
|
||||
cid, ctext = criterion_fields(state)
|
||||
attempts = state.get("gate_attempts")
|
||||
if not isinstance(attempts, int):
|
||||
attempts = 0
|
||||
|
||||
try:
|
||||
status, evidence, complaint = validate(extract_json(state.get("crit_verdict")))
|
||||
print(
|
||||
json.dumps(
|
||||
{
|
||||
"crit_verdict": {
|
||||
"id": cid,
|
||||
"text": ctext,
|
||||
"status": status,
|
||||
"evidence": evidence,
|
||||
"complaint": complaint,
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
return
|
||||
except Exception as e: # noqa: BLE001
|
||||
reason = str(e)
|
||||
|
||||
if attempts < MAX_RETRIES:
|
||||
print(
|
||||
json.dumps(
|
||||
{
|
||||
"_next": "check_criterion",
|
||||
"gate_attempts": attempts + 1,
|
||||
"gate_feedback": (
|
||||
"PREVIOUS RESPONSE REJECTED by the verdict gate: " + reason +
|
||||
". Respond with ONLY the JSON object described in your instructions."
|
||||
),
|
||||
}
|
||||
)
|
||||
)
|
||||
return
|
||||
|
||||
print(
|
||||
json.dumps(
|
||||
{
|
||||
"crit_verdict": {
|
||||
"id": cid,
|
||||
"text": ctext,
|
||||
"status": "PARTIAL",
|
||||
"evidence": "",
|
||||
"complaint": (
|
||||
"criterion check output failed machine validation after retry: "
|
||||
+ reason
|
||||
+ " — treat this criterion as unproven"
|
||||
),
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
try:
|
||||
main()
|
||||
except Exception as e: # noqa: BLE001 — the gate must never crash the chain
|
||||
print(
|
||||
json.dumps(
|
||||
{
|
||||
"crit_verdict": {
|
||||
"id": "unknown",
|
||||
"text": "",
|
||||
"status": "PARTIAL",
|
||||
"evidence": "",
|
||||
"complaint": f"criterion gate error: {e} — treat as unproven",
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
Reference in new issue
Block a user