70 lines
2.0 KiB
Python
70 lines
2.0 KiB
Python
#!/usr/bin/env python3
|
|
"""Deterministic diff resolution for the adversary graph.
|
|
|
|
Resolves the diff spec (get_diff semantics: staged → unstaged → HEAD~1 for
|
|
"auto"), lists changed files, and captures the bounded diff text every
|
|
criterion branch verifies against. Failures degrade into diff_note — the
|
|
review proceeds fail-closed rather than crashing.
|
|
"""
|
|
|
|
import json
|
|
import os
|
|
import subprocess
|
|
|
|
MAX_DIFF_CHARS = 60000
|
|
|
|
|
|
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", "{}"))
|
|
|
|
|
|
state = load_state()
|
|
proj = state.get("project_dir") or "."
|
|
spec = (state.get("diff_spec") or "auto").strip()
|
|
|
|
|
|
def git(*args):
|
|
r = subprocess.run(["git", "-C", proj, *args], capture_output=True, text=True, timeout=90)
|
|
if r.returncode != 0:
|
|
raise RuntimeError((r.stderr or r.stdout).strip()[:300])
|
|
return r.stdout
|
|
|
|
|
|
out = {"diff_note": ""}
|
|
try:
|
|
if spec in ("auto", ""):
|
|
text = git("diff", "--cached")
|
|
if not text.strip():
|
|
text = git("diff")
|
|
if not text.strip():
|
|
text = git("diff", "HEAD~1")
|
|
elif spec == "staged":
|
|
text = git("diff", "--cached")
|
|
elif spec == "worktree":
|
|
text = git("diff", "HEAD")
|
|
else:
|
|
text = git("diff", spec)
|
|
|
|
files = sorted({
|
|
line[6:].strip()
|
|
for line in text.splitlines()
|
|
if line.startswith("+++ b/")
|
|
})
|
|
out["changed_files"] = files[:300]
|
|
if len(text) > MAX_DIFF_CHARS:
|
|
out["diff_note"] = (
|
|
f" (truncated to {MAX_DIFF_CHARS} chars of {len(text)} — use the fs tools "
|
|
"to inspect files beyond the cut)"
|
|
)
|
|
text = text[:MAX_DIFF_CHARS]
|
|
out["diff_text"] = text if text.strip() else "(empty diff — nothing changed)"
|
|
except Exception as e: # noqa: BLE001
|
|
out["changed_files"] = []
|
|
out["diff_text"] = "(diff unavailable)"
|
|
out["diff_note"] = f" (diff resolution failed for spec {spec!r}: {e})"
|
|
|
|
print(json.dumps(out))
|