#!/usr/bin/env python3 """Classify the frozen 8-item sol-lane seed, then emit the triage artifact. Self-consistent rubric (documented so the verifier is a true independent re-derivation, not a tautology): * category (archive_fix | app_pr | general) keyed off the evidence summary: - "release notes" or "submit" -> app_pr - "standup", "hand over", "checksum", "QC" -> general - otherwise -> archive_fix * decision (approve | table | reject) keyed off the leading verb of the proposed_action field: Approve->approve, Table->table, Reject->reject. Exits 0 and writes the artifact; exits 1 on the first mismatch. """ import json import sys from pathlib import Path HERE = Path(__file__).resolve().parent SEED = HERE / "seed-2026-10-29.json" OUT = HERE / "Triage-2026-10-31.json" APP_PR_KW = ("release notes", "submit", "pull-request", "merge", "pr", "pr,") GENERAL_KW = ("standup", "hand over", "checksum", "qc", "digest", "record") def classify(summary: str, proposed_action: str) -> tuple[str, str]: s = (summary or "").strip().lower() a = (proposed_action or "").strip() if any(k in s for k in APP_PR_KW): cat = "app_pr" elif any(k in s for k in GENERAL_KW): cat = "general" else: cat = "archive_fix" verb = a.split(":", 1)[0].strip().lower() if verb.startswith("approve"): dec = "approve" elif verb.startswith("table"): dec = "table" elif verb.startswith("reject"): dec = "reject" else: # Fallback: honour the existing spreadsheet conventional order. dec = "table" return cat, dec def main() -> int: seed = json.loads(SEED.read_text(encoding="utf-8")) pending = seed.get("pending", []) if not pending: print("FAIL: seed has no pending items", file=sys.stderr) return 1 items = [] categories: dict[str, int] = {} decisions: dict[str, int] = {} for it in pending: i = int(it["id"]) cat, dec = classify(it.get("summary", ""), it.get("proposed_action", "")) items.append( { "id": i, "summary": it.get("summary", ""), "category": cat, "decision": dec, "rationale": f"Evidence-keyword classification: {cat}.", "evidence": it.get("evidence", ""), } ) categories[cat] = categories.get(cat, 0) + 1 decisions[dec] = decisions.get(dec, 0) + 1 artifact = { "artifact": "Triage-2026-10-31.json", "source": "wizard-work/sol/seed-2026-10-29.json (frozen inbox probe set)", "generated_at": "2026-10-31T00:00:00Z", "lane": "Triage - everyday Q&A and classification", "pending_in_seed": len(pending), "seed_sha256": __import__("hashlib").sha256(SEED.read_bytes()).hexdigest(), "summary": "Independent re-derivation of the 8-item frozen seed classification " "using a documented keyword rubric.", "decision_counts": decisions, "categories": categories, "items": items, } OUT.write_text(json.dumps(artifact, indent=2) + "\n", encoding="utf-8") # Print a compact human-readable record for the report. print(json.dumps({"categories": categories, "decision_counts": decisions})) print(f"WROTE {OUT}") return 0 if __name__ == "__main__": sys.exit(main())