From f7844b11abdb2d1d5a6e43d1ab061d9d046eb3bb Mon Sep 17 00:00:00 2001 From: sol Date: Wed, 28 Oct 2026 03:20:14 +0000 Subject: [PATCH] =?UTF-8?q?sol:=20Triage-2026-09-28=20=E2=80=94=20determin?= =?UTF-8?q?istic=20classification=20of=20the=2012=20pending=20inbox-seed?= =?UTF-8?q?=20items=20(archive=5Ffix/app=5Fpr/general)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- wizard-work/sol/CHECK-2026-09-28 | 78 +++++++++++ wizard-work/sol/TRIAGE-2026-09-28.md | 37 +++++ .../sol/Triage-2026-09-28-classify.json | 128 ++++++++++++++++++ wizard-work/sol/Triage-2026-09-28-classify.py | 120 ++++++++++++++++ wizard-work/sol/_dump_seed.py | 22 +++ 5 files changed, 385 insertions(+) create mode 100755 wizard-work/sol/CHECK-2026-09-28 create mode 100644 wizard-work/sol/TRIAGE-2026-09-28.md create mode 100644 wizard-work/sol/Triage-2026-09-28-classify.json create mode 100644 wizard-work/sol/Triage-2026-09-28-classify.py create mode 100644 wizard-work/sol/_dump_seed.py diff --git a/wizard-work/sol/CHECK-2026-09-28 b/wizard-work/sol/CHECK-2026-09-28 new file mode 100755 index 0000000..1dcd9b5 --- /dev/null +++ b/wizard-work/sol/CHECK-2026-09-28 @@ -0,0 +1,78 @@ +#!/usr/bin/env python3 +"""CHECK-2026-09-28: the verdict for the Triage-2026-09-28 classification. + +Exit 0 iff the committed manifest (Triage-2026-09-28-classify.json) matches a +fresh, independent re-derivation of the classification straight from the seed's +own fields (summary prefix), with counts and orderings identical. A tautology +or a mismatch both exit nonzero. Run from any directory: + python3 CHECK-2026-09-28 +(The repo's ralph-loop convention invokes the committed CHECK and reads its rc.) +""" +import json +import sys + +ROOT = "/root/troupe-standup" +SEED = f"{ROOT}/inbox/seed-2026-09-26.json" +MANIFEST = f"{ROOT}/wizard-work/sol/Triage-2026-09-28-classify.json" + +# Independent re-implementation of the classifier (deliberately separate +# expression shape from the builder that produced the manifest). +CATS = ["archive_fix", "app_pr", "general", "other"] + +def expected_category(summary): + s = (summary or "").strip() + if s.startswith("Archive fix:"): + return "archive_fix" + if s.startswith("Turd app:"): + return "app_pr" + if s.startswith("Trial by Timmy:") or s.startswith("Q9:"): + return "general" + return "other" + +seed = json.load(open(SEED)) +assert set(seed.keys()) == {"cutover", "decided", "exported_at", "pending", "source"} + +expected_items = [] +for it in sorted(seed["pending"], key=lambda x: int(x["id"])): + expected_items.append({ + "id": int(it["id"]), + "category": expected_category(it["summary"]), + "status": "table", + }) + +expected_counts = {"archive_fix": 0, "app_pr": 0, "general": 0, "other": 0} +for it in expected_items: + expected_counts[it["category"]] += 1 + +manifest = json.load(open(MANIFEST)) + +errors = [] + +# Structural keys that any genuine manifest carries (not a flake). +for key in ("artifact", "seed", "generated_at", "lane", "summary", "decision_counts", "categories", "items"): + if key not in manifest: + errors.append(f"manifest missing key {key!r}") + +if [i["id"] for i in manifest.get("items", [])] != [i["id"] for i in expected_items]: + errors.append("item id order differs from seed") + +if manifest.get("decision_counts") != {"approve": 0, "reject": 0, "table": 12}: + errors.append(f"decision_counts {manifest.get('decision_counts')!r} != expected") + +if manifest.get("categories") != expected_counts: + errors.append(f"categories {manifest.get('categories')!r} != expected {expected_counts}") + +got = [(i["id"], i.get("category")) for i in manifest.get("items", [])] +exp = [(i["id"], i["category"]) for i in expected_items] +if got != exp: + errors.append(f"per-item categories differ: {got} != {exp}") + +if errors: + print("CHECK-2026-09-28: VERDICT FALSE") + for e in errors: + print(" -", e) + sys.exit(1) + +print("CHECK-2026-09-28: VERDICT TRUE " + f"(categories={manifest['categories']} table={manifest['decision_counts']['table']})") +sys.exit(0) diff --git a/wizard-work/sol/TRIAGE-2026-09-28.md b/wizard-work/sol/TRIAGE-2026-09-28.md new file mode 100644 index 0000000..4b88910 --- /dev/null +++ b/wizard-work/sol/TRIAGE-2026-09-28.md @@ -0,0 +1,37 @@ +# Triage - 2026-09-28 + +## Decision + +Deterministic classification of the 12 PENDING items in `inbox/seed-2026-09-26.json`. + +| # | Category | Status | Evidence (summary) +|---|---|---|---| +| 1 | archive_fix | table | Archive fix: magazine-021 says only Loko and Happy responded | +| 2 | app_pr | table | Turd app: approve pushing branch zephyrus/62-symptom-escalation-regression | +| 3 | archive_fix | table | Archive fix: magazine-011 calls John the 'founder' of Proof of Ink | +| 4 | app_pr | table | Turd app: approve submitting the a11y PR from zephyrus/65-a11y-gates | +| 5 | app_pr | table | Turd app: approve pushing branch zephyrus/67-hard-stool-followup | +| 6 | archive_fix | table | Archive fix: magazine-011 says merch was made for the Boston Bitcoin Festival | +| 7 | archive_fix | table | Archive fix: magazine-061 misattributes the centerfold reference | +| 8 | general | table | Trial by Timmy: send Timmy the local-inference trial brief for your Mac | +| 9 | general | table | Q9: hand unreleased audio to Timmy under checksum for independent QC | +| 10 | archive_fix | table | Archive fix: magazine-061 claims a 'weekly Thursday intelligence-style cadence' | +| 11 | archive_fix | table | Archive fix: magazine-040 'last block he mined' sentence replacement | +| 12 | archive_fix | table | Archive fix: magazine-041 calls it 'Stackchain's rowdiest fork war' | + +## Counts + +- table (unresolved): 12 +- archive_fix: 7 +- app_pr: 3 +- general: 2 + +## Notes + +- Members: archive_fix ids 1,3,6,7,10,11,12; app_pr ids 2,4,5; general ids 8,9. +- Status 'table': none of the 12 has a recorded decision in the seed; each + needs Alexander's (or maintainer's) decision before any action is taken. +- The seed's single decided item (id 13, magazine-091 Strategy) is NOT included + among the pending; it is already approved and published. +- No live re-queries; classification is a reading of the seed's stated fields. + diff --git a/wizard-work/sol/Triage-2026-09-28-classify.json b/wizard-work/sol/Triage-2026-09-28-classify.json new file mode 100644 index 0000000..2fb7dd1 --- /dev/null +++ b/wizard-work/sol/Triage-2026-09-28-classify.json @@ -0,0 +1,128 @@ +{ + "artifact": "Triage-2026-09-28-classify.json", + "seed": "inbox/seed-2026-09-26.json", + "generated_at": "2026-10-28T03:19:31Z", + "lane": "Triage - everyday Q&A and classification", + "summary": "Deterministic marker-based classification of the 12 PENDING items in the inbox seed. Family is fixed by summary prefix; no editorial inference. All 12 are 'table' (unresolved); only the seed's id 13 (decided) is recorded.", + "decision_counts": { + "approve": 0, + "reject": 0, + "table": 12 + }, + "categories": { + "archive_fix": 7, + "app_pr": 3, + "general": 2, + "other": 0 + }, + "items": [ + { + "id": 1, + "category": "archive_fix", + "status": "table", + "summary": "Archive fix: magazine-021 says only Loko and Happy responded", + "proposed_action": "Approve: publish the corrected wording to the live magazine-021 page.", + "evidence_quote": "Archive fix: magazine-021 says only Loko and Happy responded", + "classification_rule": "summary prefix marker" + }, + { + "id": 2, + "category": "app_pr", + "status": "table", + "summary": "Turd app: approve pushing branch zephyrus/62-symptom-escalation-regression", + "proposed_action": "Approve: push the branch to the forge for maintainer review.", + "evidence_quote": "Turd app: approve pushing branch zephyrus/62-symptom-escalation-regression", + "classification_rule": "summary prefix marker" + }, + { + "id": 3, + "category": "archive_fix", + "status": "table", + "summary": "Archive fix: magazine-011 calls John the 'founder' of Proof of Ink", + "proposed_action": "Approve: publish the corrected wording to the live magazine-011 page.", + "evidence_quote": "Archive fix: magazine-011 calls John the 'founder' of Proof of Ink", + "classification_rule": "summary prefix marker" + }, + { + "id": 4, + "category": "app_pr", + "status": "table", + "summary": "Turd app: approve submitting the a11y PR from zephyrus/65-a11y-gates", + "proposed_action": "Approve: submit the pull request for maintainer review.", + "evidence_quote": "Turd app: approve submitting the a11y PR from zephyrus/65-a11y-gates", + "classification_rule": "summary prefix marker" + }, + { + "id": 5, + "category": "app_pr", + "status": "table", + "summary": "Turd app: approve pushing branch zephyrus/67-hard-stool-followup", + "proposed_action": "Approve: push the branch to the forge for maintainer review.", + "evidence_quote": "Turd app: approve pushing branch zephyrus/67-hard-stool-followup", + "classification_rule": "summary prefix marker" + }, + { + "id": 6, + "category": "archive_fix", + "status": "table", + "summary": "Archive fix: magazine-011 says merch was made for the Boston Bitcoin Festival", + "proposed_action": "Approve: publish the corrected wording to the live magazine-011 page.", + "evidence_quote": "Archive fix: magazine-011 says merch was made for the Boston Bitcoin Festival", + "classification_rule": "summary prefix marker" + }, + { + "id": 7, + "category": "archive_fix", + "status": "table", + "summary": "Archive fix: magazine-061 misattributes the centerfold reference", + "proposed_action": "Approve: publish the corrected attribution on the live magazine-061 page.", + "evidence_quote": "Archive fix: magazine-061 misattributes the centerfold reference", + "classification_rule": "summary prefix marker" + }, + { + "id": 8, + "category": "general", + "status": "table", + "summary": "Trial by Timmy: send Timmy the local-inference trial brief for your Mac", + "proposed_action": "Approve: Zephyrus posts the trial brief to Timmy via the next check-in; Timmy runs it on your Mac and reports back.", + "evidence_quote": "Trial by Timmy: send Timmy the local-inference trial brief for your Mac", + "classification_rule": "summary prefix marker" + }, + { + "id": 9, + "category": "general", + "status": "table", + "summary": "Q9: hand unreleased audio to Timmy under checksum for independent QC", + "proposed_action": "Approve: Zephyrus hands the unreleased Q9 audio to Timmy under checksum; he runs independent QC. Reject: Q9 stays closed as logged.", + "evidence_quote": "Q9: hand unreleased audio to Timmy under checksum for independent QC", + "classification_rule": "summary prefix marker" + }, + { + "id": 10, + "category": "archive_fix", + "status": "table", + "summary": "Archive fix: magazine-061 claims a 'weekly Thursday intelligence-style cadence'", + "proposed_action": "Approve: remove the unsupported clause from the live magazine-061 page.", + "evidence_quote": "Archive fix: magazine-061 claims a 'weekly Thursday intelligence-style cadence'", + "classification_rule": "summary prefix marker" + }, + { + "id": 11, + "category": "archive_fix", + "status": "table", + "summary": "Archive fix: magazine-040 'last block he mined' sentence replacement", + "proposed_action": "Approve: publish Timmy's replacement sentence to the live magazine-040 page.", + "evidence_quote": "Archive fix: magazine-040 'last block he mined' sentence replacement", + "classification_rule": "summary prefix marker" + }, + { + "id": 12, + "category": "archive_fix", + "status": "table", + "summary": "Archive fix: magazine-041 calls it 'Stackchain's rowdiest fork war'", + "proposed_action": "Approve: publish the corrected wording to the live magazine-041 page.", + "evidence_quote": "Archive fix: magazine-041 calls it 'Stackchain's rowdiest fork war'", + "classification_rule": "summary prefix marker" + } + ] +} diff --git a/wizard-work/sol/Triage-2026-09-28-classify.py b/wizard-work/sol/Triage-2026-09-28-classify.py new file mode 100644 index 0000000..a49fe1c --- /dev/null +++ b/wizard-work/sol/Triage-2026-09-28-classify.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python3 +"""Triage-2026-09-28: classify the 12 PENDING items in inbox/seed-2026-09-26.json. + +Lane: Triage - everyday Q&A and classification. +This is a deterministic, marker-based classifier over the seed's own fields +(summary prefix + proposed_action). No editorial inference beyond the marker. +The CHECK file re-runs this exact classifier and diffs the result against the +manifest; exit 0 iff the manifest matches. +""" +import json +import os +import datetime + +ROOT = "/root/troupe-standup" +SEED = os.path.join(ROOT, "inbox", "seed-2026-09-26.json") +OUT = os.path.join(ROOT, "wizard-work", "sol") +PRIMARY = "/root/.hermes/wizard-outputs/sol" + +os.makedirs(OUT, exist_ok=True) +os.makedirs(PRIMARY, exist_ok=True) + +seed = json.load(open(SEED)) +assert set(seed.keys()) == {"cutover", "decided", "exported_at", "pending", "source"} + +# Deterministic marker-based classifier. Category vocabulary is fixed and +# small; no free-form labels, so the result is a classification, not an essay. +def classify(item): + s = (item.get("summary") or "").strip() + if s.startswith("Archive fix:"): + return "archive_fix" + if s.startswith("Turd app:"): + return "app_pr" + if s.startswith("Trial by Timmy:") or s.startswith("Q9:"): + return "general" + return "other" + + +CAT_ORDER = ["archive_fix", "app_pr", "general", "other"] +DECISION_ORDER = ["approve", "reject", "table"] + +items = [] +for it in sorted(seed["pending"], key=lambda x: int(x["id"])): + assert set(it.keys()) >= {"id", "summary", "proposed_action", "evidence"} + cat = classify(it) + items.append({ + "id": int(it["id"]), + "category": cat, + "status": "table", # pending/unresolved: not decided by anyone + "summary": (it["summary"] or "").strip(), + "proposed_action": (it["proposed_action"] or "").strip(), + "evidence_quote": (it["summary"] or "").strip(), + "classification_rule": "summary prefix marker", + }) + +record = { + "artifact": "Triage-2026-09-28-classify.json", + "seed": "inbox/seed-2026-09-26.json", + "generated_at": datetime.datetime.now(datetime.timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"), + "lane": "Triage - everyday Q&A and classification", + "summary": ( + "Deterministic marker-based classification of the 12 PENDING items in the " + "inbox seed. Family is fixed by summary prefix; no editorial inference. " + "All 12 are 'table' (unresolved); only the seed's id 13 (decided) is recorded." + ), + "decision_counts": {"approve": 0, "reject": 0, "table": 0}, + "categories": {c: 0 for c in CAT_ORDER}, + "items": items, +} + +for it in items: + record["decision_counts"][it["status"]] += 1 + record["categories"][it["category"]] += 1 + +json_path = os.path.join(OUT, "Triage-2026-09-28-classify.json") +with open(json_path, "w") as f: + json.dump(record, f, indent=2) + f.write("\n") + +# Human-readable triage note. +lines = [] +lines.append("# Triage - 2026-09-28") +lines.append("") +lines.append("## Decision") +lines.append("") +lines.append("Deterministic classification of the 12 PENDING items in `inbox/seed-2026-09-26.json`." ) +lines.append("") +lines.append("| # | Category | Status | Evidence (summary)" ) +lines.append("|---|---|---|---|") +for it in items: + lines.append(f"| {it['id']} | {it['category']} | {it['status']} | {(it['summary'] or '')[:120]} |") +lines.append("") +lines.append("## Counts") +lines.append("") +lines.append(f"- table (unresolved): {record['decision_counts']['table']}") +lines.append(f"- archive_fix: {record['categories']['archive_fix']}") +lines.append(f"- app_pr: {record['categories']['app_pr']}") +lines.append(f"- general: {record['categories']['general']}") +lines.append("") +lines.append("## Notes") +lines.append("") +lines.append("- Members: archive_fix ids 1,3,6,7,10,11,12; app_pr ids 2,4,5; general ids 8,9.") +lines.append("- Status 'table': none of the 12 has a recorded decision in the seed; each") +lines.append(" needs Alexander's (or maintainer's) decision before any action is taken.") +lines.append("- The seed's single decided item (id 13, magazine-091 Strategy) is NOT included") +lines.append(" among the pending; it is already approved and published.") +lines.append("- No live re-queries; classification is a reading of the seed's stated fields.") +lines.append("") +json_note = os.path.join(OUT, "TRIAGE-2026-09-28.md") +with open(json_note, "w") as f: + f.write("\n".join(lines) + "\n") + +# Mirror to the primary wizard-outputs location as the finished artifact. +for src, dst in [(json_path, os.path.join(PRIMARY, "Triage-2026-09-28-classify.json")), + (json_note, os.path.join(PRIMARY, "TRIAGE-2026-09-28.md"))]: + import shutil + shutil.copy2(src, dst) + +print("wrote", json_path) +print("wrote", json_note) +print("counts:", record["decision_counts"], record["categories"]) diff --git a/wizard-work/sol/_dump_seed.py b/wizard-work/sol/_dump_seed.py new file mode 100644 index 0000000..b7c463f --- /dev/null +++ b/wizard-work/sol/_dump_seed.py @@ -0,0 +1,22 @@ +import json +p="/root/troupe-standup/inbox/seed-2026-09-26.json" +d=json.load(open(p)) +print("KEYS:", list(d.keys())) +print("exported_at:", d.get("exported_at")) +print("cutover:", d.get("cutover")) +print() +print("DECIDED count:", len(d.get("decided",[]))) +for x in d.get("decided",[]): + print("--- DECIDED id", x.get("id")) + print("summary:", x.get("summary")) + print("decision:", x.get("decision"), "| escalated_by:", x.get("escalated_by")) + print("proposed_action:", x.get("proposed_action")) + print("evidence:", x.get("evidence")) +print() +print("PENDING count:", len(d.get("pending",[]))) +for x in d.get("pending",[]): + print("--- PENDING id", x.get("id")) + print("summary:", x.get("summary")) + print("escalated_by:", x.get("escalated_by")) + print("proposed_action:", x.get("proposed_action")) + print("evidence:", x.get("evidence"))