#!/usr/bin/env python3 """Deterministic classifier for the frozen 8-item probe seed. Lane: sol / Triage (everyday Q&A and classification). Rule (evidence-keyword driven, stdlib only): Category: - archive_fix -> evidence describes a defect / omission in deployed content: hero mark, funding table, leaderboard restat, export rows, readme env vars. - app_pr -> evidence is a publish / submit action. - general -> everything else (batch / handover / coordination). Decision: - approve -> proposed_action applies a single corrective change (update / add / fix / publish) and names no second owner. - table -> proposed_action batches a group or hands a file to a named second owner (batch ... digest / hand ... to Timmy). Input: wizard-work/sol/seed-2026-10-29.json (frozen, 8 pending items) Output: wizard-work/sol/Triage-2026-11-01.json (manifest) """ import json import re from pathlib import Path REPO = Path(__file__).resolve().parent.parent.parent SEED = REPO / "wizard-work" / "sol" / "seed-2026-10-29.json" OUT = REPO / "wizard-work" / "sol" / "Triage-2026-11-01.json" # Evidence keywords -> category. Checked in order; first match wins. CATEGORY_RULES = [ ("archive_fix", ["hero", "funding table", "restats", "export drops", "readme omits", "readme", "funding table rows lack"]), ("app_pr", ["publish", "submit", "release-notes"]), ] def classify_category(evidence: str) -> str: low = evidence.lower() for cat, kws in CATEGORY_RULES: if any(k in low for k in kws): return cat return "general" def classify_decision(proposed_action: str) -> str: low = proposed_action.lower() # Handover / batch items name a second owner or a group -> table. if re.search(r"\b(batch|hand|record|send)\b", low): return "table" return "approve" def main() -> None: seed = json.loads(SEED.read_text(encoding="utf-8")) pending = seed["pending"] items = [] for s in pending: evidence = s["evidence"] summary = s["summary"] proposed_action = s["proposed_action"] items.append({ "id": s["id"], "summary": summary, "category": classify_category(evidence), "decision": classify_decision(proposed_action), "rationale": ( f"evidence='{evidence}' -> category rule matched '{classify_category(evidence)}';" f" proposed_action='{proposed_action}' -> decision rule matched '{classify_decision(proposed_action)}'." ), "evidence": evidence, "source": "seed-2026-10-29.json (frozen)", }) decision_counts = {} categories = {} for it in items: decision_counts[it["decision"]] = decision_counts.get(it["decision"], 0) + 1 categories[it["category"]] = categories.get(it["category"], 0) + 1 manifest = { "artifact": "Triage-2026-11-01.json", "source": "wizard-work/sol/seed-2026-10-29.json (frozen 8-item probe set)", "generated_at": "2026-11-01T00:00:00Z", "lane": "Triage - everyday Q&A and classification", "pending_in_seed": len(pending), "summary": "Triage of 8 pending items in the frozen seed, classified by " "evidence-keyword rules.", "decision_counts": decision_counts, "categories": categories, "items": items, } OUT.write_text(json.dumps(manifest, indent=2) + "\n", encoding="utf-8") print(f"Wrote {OUT}") print(f"decision_counts={decision_counts} categories={categories}") if __name__ == "__main__": main()