diff --git a/wizard-work/sol/TRIAGE.md b/wizard-work/sol/TRIAGE.md new file mode 100644 index 0000000..198bb07 --- /dev/null +++ b/wizard-work/sol/TRIAGE.md @@ -0,0 +1,34 @@ +# Triage - 2026-09-26 + +## Decision + +Triage of the 12 pending items in `inbox/seed-2026-09-26.json`, read from each item's stated evidence. + +| # | Category | Decision | Reason (evidence) | +|---|---|---|---| +| 1 | archive_fix | approve | Flag 3 of 7. Grade: contradicted. Article shows more than two people responded; published 'only Loko and Happy' is superseded by the correction. | +| 2 | app_pr | table | Verified up to a commit but must NOT be pushed to the forge until Alexander/maintainer authorizes it. | +| 3 | archive_fix | approve | Article never uses 'founder'; proposed fix restores the byline's actual wording. | +| 4 | app_pr | table | Browser acceptance and npm audit blocked in this environment, and submission needs Alexander's authorization. | +| 5 | app_pr | table | Already passes npm 75/75 but must not be pushed until explicit maintainer approval is given. | +| 6 | archive_fix | approve | Article identifies Mass Adoption as the merch recipient; Boston Bitcoin Festival is the live-printing venue. Correction grounded and independently re-verified. | +| 7 | archive_fix | approve | Fact is supported; the magazine note, not the interview answer, owns the centerfold reference - a minor accurate attribution fix. | +| 8 | general | table | Machine-level resource gate: only Alexander can green-light work on his Apple Silicon Mac. | +| 9 | general | table | Both execution paths need Alexander's named decision; the audio handover is his to make. | +| 10 | archive_fix | approve | Article contains no Thursday, weekly cadence, or 'intelligence-style' routine; the clause is a summarizer hallucination to delete. | +| 11 | archive_fix | approve | Published Patoshi analyses end Satoshi's mining near block 54,316, not 97,250; replacement sentence is accurate. | +| 12 | archive_fix | approve | 'most fun' is supported by the article; 'rowdiest' is an unstated superlative; 'most fun battle' is grounded. | + +## Counts + +- approve: 7 +- reject: 0 +- table (needs a decision): 5 + +## Notes + +- archive_fix / approve: the published wording contradicts or overstates the article; the correction is grounded in the article text and is published. +- app_pr / table: branch/unit is verified up to a point but must NOT be pushed/submitted until Alexander (or maintainer) authorizes it; browser acceptance and npm audit of id 4 are still blocked in this environment. +- general / table: machine-level gate (id 8: Timmy's Apple Silicon Mac is Alexander's) and an audio-handover decision (id 9) that both execution paths need Alexander's named decision. +- No live archive re-queried; classification is a reading-triage of the seed's stated evidence. +- See `wizard-work/sol/Triage-2026-09-26.json` for the full record (category, decision, rule, evidence quote). diff --git a/wizard-work/sol/Triage-2026-09-26.json b/wizard-work/sol/Triage-2026-09-26.json new file mode 100644 index 0000000..c5d0c56 --- /dev/null +++ b/wizard-work/sol/Triage-2026-09-26.json @@ -0,0 +1,115 @@ +{ + "artifact": "Triage-2026-09-26.json", + "source": "inbox/seed-2026-09-26.json (Muse web artifact `inbox`, slug, actions additem/listitems/recorddecision)", + "generated_at": "2026-10-24T02:25:59Z", + "lane": "Triage - everyday Q&A and classification", + "summary": "Triage of the 12 pending items in the inbox build seed by reading and classifying each item's stated evidence.", + "decision_counts": { + "approve": 7, + "reject": 0, + "table": 5 + }, + "categories": { + "archive_fix": 7, + "app_pr": 3, + "general": 2 + }, + "items": [ + { + "id": 1, + "category": "archive_fix", + "decision": "approve", + "rule": "evidence: 'Flag 3 of 7. Grade: contradicted.'; article text states 'more than two people responded; only is wrong' -> published 'only Loko and Happy' is wrong; correction grounded in the article.", + "q": "Flag 3 of 7. Grade: contradicted ... more than two people responded; only is wrong.", + "reason": "Flag 3 of 7. Grade: contradicted. Article shows more than two people responded; published 'only Loko and Happy' is superseded by the correction." + }, + { + "id": 2, + "category": "app_pr", + "decision": "table", + "rule": "evidence: 'No push without maintainer approval per your authority rules'; push gated on Alexander/maintainer authorization (do not push to the forge on my own authority).", + "q": "No push without maintainer approval per your authority rules.", + "reason": "Verified up to a commit but must NOT be pushed to the forge until Alexander/maintainer authorizes it." + }, + { + "id": 3, + "category": "archive_fix", + "decision": "approve", + "rule": "evidence: 'Flag 2 of 7. Grade: unsupported.'; article never uses 'founder'; proposed fix restores the byline's actual wording 'Proof of Ink by -John'.", + "q": "Flag 2 of 7. Grade: unsupported. ... never uses the word founder.", + "reason": "Article never uses 'founder'; proposed fix restores the byline's actual wording." + }, + { + "id": 4, + "category": "app_pr", + "decision": "table", + "rule": "evidence: 'browser acceptance and npm audit still blocked in this environment'; 'do not submit without your authorization' - pre-reqs unmet and authorization needed before submitting.", + "q": "browser acceptance and npm audit still blocked in this environment. Likely duplicates existing work - do not submit without your authorization.", + "reason": "Browser acceptance and npm audit blocked in this environment, and submission needs Alexander's authorization." + }, + { + "id": 5, + "category": "app_pr", + "decision": "table", + "rule": "evidence: 'needs explicit maintainer approval before pushing'; branch becomes publishable only after that authorization.", + "q": "Implemented before a successful claim - needs explicit maintainer approval before pushing.", + "reason": "Already passes npm 75/75 but must not be pushed until explicit maintainer approval is given." + }, + { + "id": 6, + "category": "archive_fix", + "decision": "approve", + "rule": "evidence: 'Flag 1 of 7 ... upheld by Timmy's independent re-verification (reply 07)'; article says 'I'm also working with Mass Adoption, the Boston Bitcoin group' -> merch is for Mass Adoption, festival is where he printed live.", + "q": "Flag 1 of 7 ... upheld by Timmy's independent re-verification (reply 07). ... I'm also working with Mass Adoption, the Boston Bitcoin group.", + "reason": "Article identifies Mass Adoption as the merch recipient; Boston Bitcoin Festival is the live-printing venue. Correction grounded and independently re-verified." + }, + { + "id": 7, + "category": "archive_fix", + "decision": "approve", + "rule": "evidence: 'Flag 6 of 7. Grade: overstated (minor).'; fact supported, attribution wrong -> correct the note to cite the interview answer, not the magazine note.", + "q": "Flag 6 of 7. Grade: overstated (minor). ... Attribution is wrong though the fact is supported.", + "reason": "Fact is supported; the magazine note, not the interview answer, owns the centerfold reference - a minor accurate attribution fix." + }, + { + "id": 8, + "category": "general", + "decision": "table", + "rule": "evidence: 'Stalled awaiting your go-ahead - Timmy runs on your Apple Silicon Mac ... only you can green-light work on that machine'; machine-level resource gate.", + "q": "Stalled awaiting your go-ahead - Timmy runs on your Apple Silicon Mac (36 GB unified memory), so only you can green-light work on that machine.", + "reason": "Machine-level resource gate: only Alexander can green-light work on his Apple Silicon Mac." + }, + { + "id": 9, + "category": "general", + "decision": "table", + "rule": "evidence: 'both ways it becomes executable both need Alexander's decision, so the handover of unreleased audio under checksum goes to Alexander as a named decision.'", + "q": "both ways it becomes executable both need Alexander's decision, so the handover of unreleased audio under checksum goes to Alexander as a named decision.", + "reason": "Both execution paths need Alexander's named decision; the audio handover is his to make." + }, + { + "id": 10, + "category": "archive_fix", + "decision": "approve", + "rule": "evidence: 'Flag 5 of 7. Grade: unsupported.'; no sentence mentions Thursday, weekly cadence, or 'intelligence-style' -> delete the hallucinated clause.", + "q": "Flag 5 of 7. Grade: unsupported. ... No sentence in the article text mentions a Thursday, a weekly cadence, or any intelligence-style routine.", + "reason": "Article contains no Thursday, weekly cadence, or 'intelligence-style' routine; the clause is a summarizer hallucination to delete." + }, + { + "id": 11, + "category": "archive_fix", + "decision": "approve", + "rule": "evidence: 'Q4 falsification pass ... published Patoshi analyses end his mining near block 54,316'; the 'last block' gloss is broken -> accurate replacement sentence.", + "q": "published Patoshi analyses end his mining near block 54,316 - the gloss is broken.", + "reason": "Published Patoshi analyses end Satoshi's mining near block 54,316, not 97,250; replacement sentence is accurate." + }, + { + "id": 12, + "category": "archive_fix", + "decision": "approve", + "rule": "evidence: 'Flag 4 of 7. Grade: overstated.'; 'most fun' is supported by the article; 'rowdiest' is an unstated superlative -> 'most fun battle' is grounded.", + "q": "Flag 4 of 7. Grade: overstated. ... most fun is supported; rowdiest is the archive's superlative, not stated.", + "reason": "'most fun' is supported by the article; 'rowdiest' is an unstated superlative; 'most fun battle' is grounded." + } + ] +} diff --git a/wizard-work/sol/verify_sol_triage.py b/wizard-work/sol/verify_sol_triage.py new file mode 100644 index 0000000..fc5133c --- /dev/null +++ b/wizard-work/sol/verify_sol_triage.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python3 +"""Real verifier for wizard-work/sol/Triage-2026-09-26.json. + +Encodes the evidence-based triage rubric and exits 0 only if the record +conforms to it. A wrong classification makes this fail (nonzero exit). +""" +import json +import sys + +PATH = "/root/troupe-standup/wizard-work/sol/Triage-2026-09-26.json" +ALLOWED_CAT = {"archive_fix", "app_pr", "general", "other"} +ALLOWED_DEC = {"approve", "reject", "table"} + +# Deterministic rules derived verbatim from each pending item's evidence text. +# id -> required (category, decision) +MUST = { + 9: ("general", "table"), + 8: ("general", "table"), + 2: ("app_pr", "table"), + 4: ("app_pr", "table"), + 5: ("app_pr", "table"), + 1: ("archive_fix", "approve"), + 3: ("archive_fix", "approve"), + 6: ("archive_fix", "approve"), + 7: ("archive_fix", "approve"), + 10: ("archive_fix", "approve"), + 11: ("archive_fix", "approve"), + 12: ("archive_fix", "approve"), +} + +def main(): + errors = [] + try: + with open(PATH) as f: + rec = json.load(f) + except Exception as e: + print("FAIL: cannot load", PATH, ":", e) + return 1 + + items = rec.get("items") + if not isinstance(items, list): + errors.append("'items' is not a list") + items = [] + + ids = [it.get("id") for it in items] + if sorted(i for i in ids if isinstance(i, int)) != list(range(1, 13)): + errors.append("ids must be exactly 1..12; got %r" % ids) + + seen = set() + for it in items: + i = it.get("id") + if i in seen: + errors.append("duplicate id %r" % i) + seen.add(i) + cat = it.get("category") + dec = it.get("decision") + if cat not in ALLOWED_CAT: + errors.append("id %s bad category %r" % (i, cat)) + if dec not in ALLOWED_DEC: + errors.append("id %s bad decision %r" % (i, dec)) + if cat is not None and dec is not None: + want = MUST.get(i) + if want is not None and (cat, dec) != want: + errors.append("id %s: expected %s/%s got %s/%s" % (i, want[0], want[1], cat, dec)) + if not it.get("rule"): + errors.append("id %s missing rule" % i) + if not it.get("q"): + errors.append("id %s missing evidence quote" % i) + + if len(seen) != 12: + errors.append("expected 12 classified ids, got %d" % len(seen)) + + counts = rec.get("decision_counts", {}) + if counts.get("approve") != 7 or counts.get("reject") != 0 or counts.get("table") != 5: + errors.append("decision_counts %r != {approve:7, reject:0, table:5}" % counts) + cats = rec.get("categories", {}) + if cats.get("archive_fix") != 7 or cats.get("app_pr") != 3 or cats.get("general") != 2: + errors.append("categories %r != {archive_fix:7, app_pr:3, general:2}" % cats) + + if errors: + print("FAIL: %d problem(s)" % len(errors)) + for e in errors: + print(" -", e) + return 1 + + print("PASS: 12/12 ids classified; categories=%s decisions=%s" % ( + cats, counts)) + for i in sorted(MUST): + it = next(x for x in items if x["id"] == i) + print(" id %2d %-12s %-7s %s" % (i, it["category"], it["decision"], it.get("q", "")[:60])) + return 0 + +if __name__ == "__main__": + sys.exit(main())