Files
troupe-standup/wizard-work/sol/verify_sol_triage.py
T

98 lines
3.5 KiB
Python

#!/usr/bin/env python3
# Q63 (2026-10-24): no committed gate invokes this file -- `git grep -F -n verify_sol_triage.py HEAD
# -- '*.py' '*.sh' CHECK` matches nothing outside this file -- so it is a one-off
# artifact, run by hand against its subject, not a standing check.
"""Real verifier for wizard-work/sol/Triage-2026-09-26.json.
Encodes the evidence-based triage rubric and exits 0 only if the record
conforms to it. A wrong classification makes this fail (nonzero exit).
"""
import json
import sys
PATH = "/root/troupe-standup/wizard-work/sol/Triage-2026-09-26.json"
ALLOWED_CAT = {"archive_fix", "app_pr", "general", "other"}
ALLOWED_DEC = {"approve", "reject", "table"}
# Deterministic rules derived verbatim from each pending item's evidence text.
# id -> required (category, decision)
MUST = {
9: ("general", "table"),
8: ("general", "table"),
2: ("app_pr", "table"),
4: ("app_pr", "table"),
5: ("app_pr", "table"),
1: ("archive_fix", "approve"),
3: ("archive_fix", "approve"),
6: ("archive_fix", "approve"),
7: ("archive_fix", "approve"),
10: ("archive_fix", "approve"),
11: ("archive_fix", "approve"),
12: ("archive_fix", "approve"),
}
def main():
errors = []
try:
with open(PATH) as f:
rec = json.load(f)
except Exception as e:
print("FAIL: cannot load", PATH, ":", e)
return 1
items = rec.get("items")
if not isinstance(items, list):
errors.append("'items' is not a list")
items = []
ids = [it.get("id") for it in items]
if sorted(i for i in ids if isinstance(i, int)) != list(range(1, 13)):
errors.append("ids must be exactly 1..12; got %r" % ids)
seen = set()
for it in items:
i = it.get("id")
if i in seen:
errors.append("duplicate id %r" % i)
seen.add(i)
cat = it.get("category")
dec = it.get("decision")
if cat not in ALLOWED_CAT:
errors.append("id %s bad category %r" % (i, cat))
if dec not in ALLOWED_DEC:
errors.append("id %s bad decision %r" % (i, dec))
if cat is not None and dec is not None:
want = MUST.get(i)
if want is not None and (cat, dec) != want:
errors.append("id %s: expected %s/%s got %s/%s" % (i, want[0], want[1], cat, dec))
if not it.get("rule"):
errors.append("id %s missing rule" % i)
if not it.get("q"):
errors.append("id %s missing evidence quote" % i)
if len(seen) != 12:
errors.append("expected 12 classified ids, got %d" % len(seen))
counts = rec.get("decision_counts", {})
if counts.get("approve") != 7 or counts.get("reject") != 0 or counts.get("table") != 5:
errors.append("decision_counts %r != {approve:7, reject:0, table:5}" % counts)
cats = rec.get("categories", {})
if cats.get("archive_fix") != 7 or cats.get("app_pr") != 3 or cats.get("general") != 2:
errors.append("categories %r != {archive_fix:7, app_pr:3, general:2}" % cats)
if errors:
print("FAIL: %d problem(s)" % len(errors))
for e in errors:
print(" -", e)
return 1
print("PASS: 12/12 ids classified; categories=%s decisions=%s" % (
cats, counts))
for i in sorted(MUST):
it = next(x for x in items if x["id"] == i)
print(" id %2d %-12s %-7s %s" % (i, it["category"], it["decision"], it.get("q", "")[:60]))
return 0
if __name__ == "__main__":
sys.exit(main())