sol: Triage-2026-09-28 — deterministic classification of the 12 pending inbox-seed items (archive_fix/app_pr/general)

This commit is contained in:
sol committed 2026-10-28 03:20:14 +00:00
1 parent cd6f6a43a7
commit f7844b11ab
5 files changed
+385

No files matched your search

+78
View File
@@ -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)
+37
View File
@@ -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.
@@ -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"
}
]
}
@@ -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"])
+22
View File
@@ -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"))