#!/usr/bin/env python3 """Deterministic triage classifier for the seed inbox (seed-2026-09-26.json). Lane: Triage -- everyday Q&A and classification. Reads the seed inbox, assigns each item a category and a decision using a fixed rubric, and writes: - wizard-work/sol/triage_results.json (machine-readable results) - wizard-work/sol/triage_report.md (human-readable report) Rubric (deterministic, no LLM): CATEGORY archive_fix - evidence mentions 'Flag', a 'Summary clause' in an archive-fidelity/falsification pass, or 'magazine-' title. app_pr - 'branch', 'push', 'submit', or 'PR' language (turd app items). general - everything else (trial runs, handoffs, Q&A). DECISION decided items keep their seed decision (approved). pending archive_fix -> approve (correction grounded in the article). pending app_pr -> table (blocked: maintainer authorization required). pending general -> table (blocked: machine-level resource gate). """ import json import os import sys ROOT = "/root/troupe-standup" INBOX = os.path.join(ROOT, "inbox", "seed-2026-09-26.json") OUT = os.path.join(ROOT, "wizard-work", "sol") os.makedirs(OUT, exist_ok=True) CATEGORY_RULES = [ ("archive_fix", lambda it: any( k in (it.get("evidence") or "") for k in ("Flag", "Summary clause") ) or "magazine-" in (it.get("summary") or "")), ("app_pr", lambda it: any( k in ((it.get("evidence") or "") + (it.get("summary") or "") + (it.get("proposed_action") or "")) for k in ("branch", "push", "submit", "PR")) or "turd" in ((it.get("summary") or "") + (it.get("evidence") or "")).lower()), ("general", lambda it: True), ] def classify_category(item): for cat, test in CATEGORY_RULES: if test(item): return cat return "other" def classify_decision(item, category): if item.get("decided_at") is not None: # already resolved in the seed return item.get("decision") if category == "archive_fix": return "approve" return "table" def main(): with open(INBOX) as f: seed = json.load(f) results = [] for kind in ("decided", "pending"): for it in seed.get(kind, []): cat = classify_category(it) dec = classify_decision(it, cat) results.append({ "id": it.get("id"), "source": kind, "summary": it.get("summary"), "evidence": it.get("evidence"), "category": cat, "decision": dec, "rule": { "category": next(c for c, t in CATEGORY_RULES if t(it)), "decision": {"approve": "article-grounded correction", "table": "wait for authorization"}.get(dec, dec), }, }) results[-1]["rule"]["decision_detail"] = { "approve": "article-grounded correction published to the live page", "approved": "already resolved in the seed (approved)", "table": "awaiting Alexander/maintainer authorization", }[dec] counts = {} for r in results: counts[r["category"]] = counts.get(r["category"], 0) + 1 payload = { "classifier": "triage_classify.py", "seed": "inbox/seed-2026-09-26.json", "total": len(results), "counts": counts, "results": results, } with open(os.path.join(OUT, "triage_results.json"), "w") as f: json.dump(payload, f, indent=2) with open(os.path.join(OUT, "triage_report.md"), "w") as f: f.write("# Triage report — seed-2026-09-26\n\n") f.write(f"- total items: {len(results)}\n") f.write(f"- counts by category: {json.dumps(counts)}\n\n") for r in results: f.write(f"## id {r['id']} [{r['source']}] {r['category']} -> {r['decision']}\n\n") f.write(f"{r['summary']}\n\n") f.write(f"- rule: {r['rule']['category']}\n") f.write(f"- decision: {r['decision']} ({r['rule']['decision_detail']})\n\n") f.write("## Evidence\n\n") for r in results: f.write(f"### id {r['id']}\n\n") f.write(f"{r['summary']}\n\n") f.write(f"**evidence:** {(r.get('evidence') or '')[:240]}\n\n") print(json.dumps(payload, indent=2)) return 0 if __name__ == "__main__": sys.exit(main())