From fd0e2ed2428ba059388ce83da3903f2d9b8e44d8 Mon Sep 17 00:00:00 2001 From: ledger Date: Mon, 26 Oct 2026 22:07:10 +0000 Subject: [PATCH] sol: triage class of seed-2026-09-26 (13 items) --- wizard-work/sol/check_triage.py | 68 ++++++++++ wizard-work/sol/triage_classify.py | 120 ++++++++++++++++ wizard-work/sol/triage_report.md | 204 ++++++++++++++++++++++++++++ wizard-work/sol/triage_results.json | 181 ++++++++++++++++++++++++ 4 files changed, 573 insertions(+) create mode 100644 wizard-work/sol/check_triage.py create mode 100644 wizard-work/sol/triage_classify.py create mode 100644 wizard-work/sol/triage_report.md create mode 100644 wizard-work/sol/triage_results.json diff --git a/wizard-work/sol/check_triage.py b/wizard-work/sol/check_triage.py new file mode 100644 index 0000000..2da7a99 --- /dev/null +++ b/wizard-work/sol/check_triage.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python3 +"""CHECK for the sol triage classifier artifact. + +Writes nothing; its exit code IS the verdict (0 = artifact correct, nonzero = wrong). +""" +import json +import os +import sys + +OUT = "/root/troupe-standup/wizard-work/sol" +RES = os.path.join(OUT, "triage_results.json") +RPT = os.path.join(OUT, "triage_report.md") + +errors = [] + + +def check(name, cond, detail=""): + if not cond: + errors.append(f"{name}: {detail}") + + +with open(RES) as f: + p = json.load(f) + +check("total", p.get("total") == 13, f"got {p.get('total')}") +check("counts", + p.get("counts") == {"archive_fix": 8, "app_pr": 3, "general": 2}, + f"got {p.get('counts')}") + +cat_for = {} +dec_for = {} +for r in p.get("results", []): + cat_for[r["id"]] = r["category"] + dec_for[r["id"]] = r["decision"] + +# pending archive_fix -> approve; pending app_pr -> table; pending general -> table +for r in p.get("results", []): + if r["source"] != "pending": + continue + if r["category"] == "archive_fix": + check(f"id{r['id']} archive -> approve", r["decision"] == "approve", r["decision"]) + elif r["category"] == "app_pr": + check(f"id{r['id']} app_pr -> table", r["decision"] == "table", r["decision"]) + else: + check(f"id{r['id']} general -> table", r["decision"] == "table", r["decision"]) + +# decided item id 13 +r13 = next((r for r in p["results"] if r["id"] == 13), None) +check("id13 present", r13 is not None) +if r13 is not None: + check("id13 archive_fix/approved", r13["category"] == "archive_fix" and r13["decision"] == "approved", + f"{r13['category']}/{r13['decision']}") + +# evidence present for every item +for r in p.get("results", []): + check(f"id{r['id']} evidence", bool((r.get("evidence") or "").strip()), "empty") + +# human-readable report non-empty +check("report exists+nonempty", os.path.exists(RPT) and os.path.getsize(RPT) > 100) + +if errors: + print("CHECK FAILED") + for e in errors: + print(" -", e) + sys.exit(1) + +print("CHECK OK: total=13 counts=%s" % json.dumps(p["counts"])) +sys.exit(0) diff --git a/wizard-work/sol/triage_classify.py b/wizard-work/sol/triage_classify.py new file mode 100644 index 0000000..43c79c9 --- /dev/null +++ b/wizard-work/sol/triage_classify.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python3 +"""Deterministic triage classifier for the seed inbox (seed-2026-09-26.json). + +Lane: Triage -- everyday Q&A and classification. +Reads the seed inbox, assigns each item a category and a decision using a +fixed rubric, and writes: + - wizard-work/sol/triage_results.json (machine-readable results) + - wizard-work/sol/triage_report.md (human-readable report) + +Rubric (deterministic, no LLM): + CATEGORY + archive_fix - evidence mentions 'Flag', a 'Summary clause' in an + archive-fidelity/falsification pass, or 'magazine-' title. + app_pr - 'branch', 'push', 'submit', or 'PR' language (turd app items). + general - everything else (trial runs, handoffs, Q&A). + DECISION + decided items keep their seed decision (approved). + pending archive_fix -> approve (correction grounded in the article). + pending app_pr -> table (blocked: maintainer authorization required). + pending general -> table (blocked: machine-level resource gate). +""" +import json +import os +import sys + +ROOT = "/root/troupe-standup" +INBOX = os.path.join(ROOT, "inbox", "seed-2026-09-26.json") +OUT = os.path.join(ROOT, "wizard-work", "sol") +os.makedirs(OUT, exist_ok=True) + +CATEGORY_RULES = [ + ("archive_fix", lambda it: any( + k in (it.get("evidence") or "") for k in ("Flag", "Summary clause") + ) or "magazine-" in (it.get("summary") or "")), + ("app_pr", lambda it: any( + k in ((it.get("evidence") or "") + (it.get("summary") or "") + (it.get("proposed_action") or "")) + for k in ("branch", "push", "submit", "PR")) + or "turd" in ((it.get("summary") or "") + (it.get("evidence") or "")).lower()), + ("general", lambda it: True), +] + + +def classify_category(item): + for cat, test in CATEGORY_RULES: + if test(item): + return cat + return "other" + + +def classify_decision(item, category): + if item.get("decided_at") is not None: # already resolved in the seed + return item.get("decision") + if category == "archive_fix": + return "approve" + return "table" + + +def main(): + with open(INBOX) as f: + seed = json.load(f) + + results = [] + for kind in ("decided", "pending"): + for it in seed.get(kind, []): + cat = classify_category(it) + dec = classify_decision(it, cat) + results.append({ + "id": it.get("id"), + "source": kind, + "summary": it.get("summary"), + "evidence": it.get("evidence"), + "category": cat, + "decision": dec, + "rule": { + "category": next(c for c, t in CATEGORY_RULES if t(it)), + "decision": {"approve": "article-grounded correction", "table": "wait for authorization"}.get(dec, dec), + }, + }) + results[-1]["rule"]["decision_detail"] = { + "approve": "article-grounded correction published to the live page", + "approved": "already resolved in the seed (approved)", + "table": "awaiting Alexander/maintainer authorization", + }[dec] + + counts = {} + for r in results: + counts[r["category"]] = counts.get(r["category"], 0) + 1 + + payload = { + "classifier": "triage_classify.py", + "seed": "inbox/seed-2026-09-26.json", + "total": len(results), + "counts": counts, + "results": results, + } + + with open(os.path.join(OUT, "triage_results.json"), "w") as f: + json.dump(payload, f, indent=2) + + with open(os.path.join(OUT, "triage_report.md"), "w") as f: + f.write("# Triage report — seed-2026-09-26\n\n") + f.write(f"- total items: {len(results)}\n") + f.write(f"- counts by category: {json.dumps(counts)}\n\n") + for r in results: + f.write(f"## id {r['id']} [{r['source']}] {r['category']} -> {r['decision']}\n\n") + f.write(f"{r['summary']}\n\n") + f.write(f"- rule: {r['rule']['category']}\n") + f.write(f"- decision: {r['decision']} ({r['rule']['decision_detail']})\n\n") + f.write("## Evidence\n\n") + for r in results: + f.write(f"### id {r['id']}\n\n") + f.write(f"{r['summary']}\n\n") + f.write(f"**evidence:** {(r.get('evidence') or '')[:240]}\n\n") + + print(json.dumps(payload, indent=2)) + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/wizard-work/sol/triage_report.md b/wizard-work/sol/triage_report.md new file mode 100644 index 0000000..2d0c0b4 --- /dev/null +++ b/wizard-work/sol/triage_report.md @@ -0,0 +1,204 @@ +# Triage report — seed-2026-09-26 + +- total items: 13 +- counts by category: {"archive_fix": 8, "app_pr": 3, "general": 2} + +## id 13 [decided] archive_fix -> approved + +Archive fix: magazine-091 lists Strategy among compared firms + +- rule: archive_fix +- decision: approved (already resolved in the seed (approved)) + +## id 1 [pending] archive_fix -> approve + +Archive fix: magazine-021 says only Loko and Happy responded + +- rule: archive_fix +- decision: approve (article-grounded correction published to the live page) + +## id 2 [pending] app_pr -> table + +Turd app: approve pushing branch zephyrus/62-symptom-escalation-regression + +- rule: app_pr +- decision: table (awaiting Alexander/maintainer authorization) + +## id 3 [pending] archive_fix -> approve + +Archive fix: magazine-011 calls John the 'founder' of Proof of Ink + +- rule: archive_fix +- decision: approve (article-grounded correction published to the live page) + +## id 4 [pending] app_pr -> table + +Turd app: approve submitting the a11y PR from zephyrus/65-a11y-gates + +- rule: app_pr +- decision: table (awaiting Alexander/maintainer authorization) + +## id 5 [pending] app_pr -> table + +Turd app: approve pushing branch zephyrus/67-hard-stool-followup + +- rule: app_pr +- decision: table (awaiting Alexander/maintainer authorization) + +## id 6 [pending] archive_fix -> approve + +Archive fix: magazine-011 says merch was made for the Boston Bitcoin Festival + +- rule: archive_fix +- decision: approve (article-grounded correction published to the live page) + +## id 7 [pending] archive_fix -> approve + +Archive fix: magazine-061 misattributes the centerfold reference + +- rule: archive_fix +- decision: approve (article-grounded correction published to the live page) + +## id 8 [pending] general -> table + +Trial by Timmy: send Timmy the local-inference trial brief for your Mac + +- rule: general +- decision: table (awaiting Alexander/maintainer authorization) + +## id 9 [pending] general -> table + +Q9: hand unreleased audio to Timmy under checksum for independent QC + +- rule: general +- decision: table (awaiting Alexander/maintainer authorization) + +## id 10 [pending] archive_fix -> approve + +Archive fix: magazine-061 claims a 'weekly Thursday intelligence-style cadence' + +- rule: archive_fix +- decision: approve (article-grounded correction published to the live page) + +## id 11 [pending] archive_fix -> approve + +Archive fix: magazine-040 'last block he mined' sentence replacement + +- rule: archive_fix +- decision: approve (article-grounded correction published to the live page) + +## id 12 [pending] archive_fix -> approve + +Archive fix: magazine-041 calls it 'Stackchain's rowdiest fork war' + +- rule: archive_fix +- decision: approve (article-grounded correction published to the live page) + +## Evidence + +### id 13 + +Archive fix: magazine-091 lists Strategy among compared firms + +**evidence:** Flag 7 of 7. Grade: overstated. + +Summary clause: "Comparing Strategy, Twenty One, Nakamoto, Metaplanet, Coinsilium and Smarter Web returns and drawdowns against Bitcoin". + +Article: "We set aside pioneers like Strategy, which started in 2020 + +### id 1 + +Archive fix: magazine-021 says only Loko and Happy responded + +**evidence:** Flag 3 of 7. Grade: contradicted. + +Summary clause: "(only Loko and Happy responded)". + +Article: "Then after a few minutes I checked the chat. A few positive responses. Some funny shit talking, oh look, Happy even added some lyrics!" - more + +### id 2 + +Turd app: approve pushing branch zephyrus/62-symptom-escalation-regression + +**evidence:** Local branch, committed, not pushed. Four urgent-phrase escalation fixes, four false-positive fixes, three regression/boundary test files. npm test 92/92 on 2026-09-20. Likely duplicates an existing PR - kept as independent verification unl + +### id 3 + +Archive fix: magazine-011 calls John the 'founder' of Proof of Ink + +**evidence:** Flag 2 of 7. Grade: unsupported. + +Summary clause: the IPE calls John "founder of the Bitcoin-only printing company Proof of Ink". + +The article never uses the word "founder"; byline is "Proof of Ink by -John". John's "it's 100% all me" estab + +### id 4 + +Turd app: approve submitting the a11y PR from zephyrus/65-a11y-gates + +**evidence:** Local branch, commit 03def65, not pushed. Accessibility changes plus eight Playwright gates. Unit tests 67/67 on 2026-09-20; browser acceptance and npm audit still blocked in this environment. Likely duplicates existing work - do not submit + +### id 5 + +Turd app: approve pushing branch zephyrus/67-hard-stool-followup + +**evidence:** Local branch, commit b730f5f, not pushed. Explicit Type 1-2 follow-up question; no image inference. npm test 75/75 on 2026-09-20. Implemented before a successful claim - needs explicit maintainer approval before pushing. Safety boundary res + +### id 6 + +Archive fix: magazine-011 says merch was made for the Boston Bitcoin Festival + +**evidence:** Flag 1 of 7 from the Q8 summary-fidelity pilot (recoveries/summary-fidelity-pilot.md, commit 9cc6879), upheld by Timmy's independent re-verification (reply 07). + +Summary clause (overstated): "merch for Mass Adoption and the Boston Bitcoin F + +### id 7 + +Archive fix: magazine-061 misattributes the centerfold reference + +**evidence:** Flag 6 of 7. Grade: overstated (minor). + +Summary clause: "which the magazine note ties to a centerfold in issue 5 (Round 5)". + +The "(see centerfold)" reference is in the interview answer itself; the magazine note covers "his epic contributi + +### id 8 + +Trial by Timmy: send Timmy the local-inference trial brief for your Mac + +**evidence:** Your standing goal: Timmy running fully local on open-weight models, zero dependence on any company's inference API. The trial brief ('Trial by Timmy', 2026-09-24) is ready: serve a tool-capable open model locally via Ollama or llama.cpp be + +### id 9 + +Q9: hand unreleased audio to Timmy under checksum for independent QC + +**evidence:** Q9 (independent music QC) is not executable as a genuine second opinion from Zephyrus's environment - same host, same tools, and he wrote the item. Timmy's reply 07: the two ways it becomes executable both need Alexander's decision, so the + +### id 10 + +Archive fix: magazine-061 claims a 'weekly Thursday intelligence-style cadence' + +**evidence:** Flag 5 of 7. Grade: unsupported. + +Summary clause: "why he keeps a weekly Thursday intelligence-style cadence of work". + +No sentence in the article text mentions a Thursday, a weekly cadence, or any "intelligence-style" routine. Looks like a + +### id 11 + +Archive fix: magazine-040 'last block he mined' sentence replacement + +**evidence:** From the Q4 falsification pass (recoveries/falsification-pass.md): the archive's gloss implied block 97,250 was the last block Satoshi mined. Published Patoshi analyses end his mining near block 54,316 - the gloss is broken. + +Timmy's propos + +### id 12 + +Archive fix: magazine-041 calls it 'Stackchain's rowdiest fork war' + +**evidence:** Flag 4 of 7. Grade: overstated. + +Summary clause (IPE): "Stackchain's rowdiest fork war". + +Article: "This may go down as the most fun battle of Stackchain just because of the amount of people involved." - "most fun" is supported; "rowdiest" + diff --git a/wizard-work/sol/triage_results.json b/wizard-work/sol/triage_results.json new file mode 100644 index 0000000..a62a40b --- /dev/null +++ b/wizard-work/sol/triage_results.json @@ -0,0 +1,181 @@ +{ + "classifier": "triage_classify.py", + "seed": "inbox/seed-2026-09-26.json", + "total": 13, + "counts": { + "archive_fix": 8, + "app_pr": 3, + "general": 2 + }, + "results": [ + { + "id": 13, + "source": "decided", + "summary": "Archive fix: magazine-091 lists Strategy among compared firms", + "evidence": "Flag 7 of 7. Grade: overstated.\n\nSummary clause: \"Comparing Strategy, Twenty One, Nakamoto, Metaplanet, Coinsilium and Smarter Web returns and drawdowns against Bitcoin\".\n\nArticle: \"We set aside pioneers like Strategy, which started in 2020 and is up over 400% since, as it's not a fair comp for these newcomers.\" Strategy was deliberately excluded from the comparison; the summary lists it as if analyzed.\n\nProposed correction: drop Strategy from the compared list.", + "category": "archive_fix", + "decision": "approved", + "rule": { + "category": "archive_fix", + "decision": "approved", + "decision_detail": "already resolved in the seed (approved)" + } + }, + { + "id": 1, + "source": "pending", + "summary": "Archive fix: magazine-021 says only Loko and Happy responded", + "evidence": "Flag 3 of 7. Grade: contradicted.\n\nSummary clause: \"(only Loko and Happy responded)\".\n\nArticle: \"Then after a few minutes I checked the chat. A few positive responses. Some funny shit talking, oh look, Happy even added some lyrics!\" - more than two people responded; \"only\" is wrong.\n\nProposed correction: \"(Loko and Happy among those who responded)\".", + "category": "archive_fix", + "decision": "approve", + "rule": { + "category": "archive_fix", + "decision": "article-grounded correction", + "decision_detail": "article-grounded correction published to the live page" + } + }, + { + "id": 2, + "source": "pending", + "summary": "Turd app: approve pushing branch zephyrus/62-symptom-escalation-regression", + "evidence": "Local branch, committed, not pushed. Four urgent-phrase escalation fixes, four false-positive fixes, three regression/boundary test files. npm test 92/92 on 2026-09-20. Likely duplicates an existing PR - kept as independent verification unless requested. No push without maintainer approval per your authority rules.", + "category": "app_pr", + "decision": "table", + "rule": { + "category": "app_pr", + "decision": "wait for authorization", + "decision_detail": "awaiting Alexander/maintainer authorization" + } + }, + { + "id": 3, + "source": "pending", + "summary": "Archive fix: magazine-011 calls John the 'founder' of Proof of Ink", + "evidence": "Flag 2 of 7. Grade: unsupported.\n\nSummary clause: the IPE calls John \"founder of the Bitcoin-only printing company Proof of Ink\".\n\nThe article never uses the word \"founder\"; byline is \"Proof of Ink by -John\". John's \"it's 100% all me\" establishes sole operation, but \"founder\" is the archive's inference.\n\nProposed correction: \"John of Proof of Ink, the Bitcoin-only printing company he runs solo\".", + "category": "archive_fix", + "decision": "approve", + "rule": { + "category": "archive_fix", + "decision": "article-grounded correction", + "decision_detail": "article-grounded correction published to the live page" + } + }, + { + "id": 4, + "source": "pending", + "summary": "Turd app: approve submitting the a11y PR from zephyrus/65-a11y-gates", + "evidence": "Local branch, commit 03def65, not pushed. Accessibility changes plus eight Playwright gates. Unit tests 67/67 on 2026-09-20; browser acceptance and npm audit still blocked in this environment. Likely duplicates existing work - do not submit without your authorization.", + "category": "app_pr", + "decision": "table", + "rule": { + "category": "app_pr", + "decision": "wait for authorization", + "decision_detail": "awaiting Alexander/maintainer authorization" + } + }, + { + "id": 5, + "source": "pending", + "summary": "Turd app: approve pushing branch zephyrus/67-hard-stool-followup", + "evidence": "Local branch, commit b730f5f, not pushed. Explicit Type 1-2 follow-up question; no image inference. npm test 75/75 on 2026-09-20. Implemented before a successful claim - needs explicit maintainer approval before pushing. Safety boundary respected: AI suggests visible form/color/quality only, never diagnoses.", + "category": "app_pr", + "decision": "table", + "rule": { + "category": "app_pr", + "decision": "wait for authorization", + "decision_detail": "awaiting Alexander/maintainer authorization" + } + }, + { + "id": 6, + "source": "pending", + "summary": "Archive fix: magazine-011 says merch was made for the Boston Bitcoin Festival", + "evidence": "Flag 1 of 7 from the Q8 summary-fidelity pilot (recoveries/summary-fidelity-pilot.md, commit 9cc6879), upheld by Timmy's independent re-verification (reply 07).\n\nSummary clause (overstated): \"merch for Mass Adoption and the Boston Bitcoin Festival\".\n\nArticle sentence that settles it: \"I'm also working with Mass Adoption, the Boston Bitcoin group. I make all their merch and I'll be printing live June 24th at The Boston Bitcoin Festival...\"\n\nProposed correction: \"merch for Mass Adoption, the Boston Bitcoin group - printing live at the Boston Bitcoin Festival on June 24th\". The merch is for Mass Adoption; the festival is where he printed live.", + "category": "archive_fix", + "decision": "approve", + "rule": { + "category": "archive_fix", + "decision": "article-grounded correction", + "decision_detail": "article-grounded correction published to the live page" + } + }, + { + "id": 7, + "source": "pending", + "summary": "Archive fix: magazine-061 misattributes the centerfold reference", + "evidence": "Flag 6 of 7. Grade: overstated (minor).\n\nSummary clause: \"which the magazine note ties to a centerfold in issue 5 (Round 5)\".\n\nThe \"(see centerfold)\" reference is in the interview answer itself; the magazine note covers \"his epic contribution to the mag in issue 5 (Round 5)\". Attribution is wrong though the fact is supported.\n\nProposed correction: attribute the centerfold reference to the interview answer, not the magazine note.", + "category": "archive_fix", + "decision": "approve", + "rule": { + "category": "archive_fix", + "decision": "article-grounded correction", + "decision_detail": "article-grounded correction published to the live page" + } + }, + { + "id": 8, + "source": "pending", + "summary": "Trial by Timmy: send Timmy the local-inference trial brief for your Mac", + "evidence": "Your standing goal: Timmy running fully local on open-weight models, zero dependence on any company's inference API. The trial brief ('Trial by Timmy', 2026-09-24) is ready: serve a tool-capable open model locally via Ollama or llama.cpp behind an OpenAI-compatible endpoint, which Hermes already supports, and benchmark it on Timmy's real workload. 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.", + "category": "general", + "decision": "table", + "rule": { + "category": "general", + "decision": "wait for authorization", + "decision_detail": "awaiting Alexander/maintainer authorization" + } + }, + { + "id": 9, + "source": "pending", + "summary": "Q9: hand unreleased audio to Timmy under checksum for independent QC", + "evidence": "Q9 (independent music QC) is not executable as a genuine second opinion from Zephyrus's environment - same host, same tools, and he wrote the item. Timmy's reply 07: the two ways it becomes executable both need Alexander's decision, so the handover of unreleased audio under checksum goes to Alexander as a named decision.\n\nThree wording corrections stay openly logged regardless: <= -0.9 dBFS vs a -1.0 dBTP target; \"the manifest\" is STATE.json; 195.0 s is the FLAC source, MP3 container reads 195.024 s.", + "category": "general", + "decision": "table", + "rule": { + "category": "general", + "decision": "wait for authorization", + "decision_detail": "awaiting Alexander/maintainer authorization" + } + }, + { + "id": 10, + "source": "pending", + "summary": "Archive fix: magazine-061 claims a 'weekly Thursday intelligence-style cadence'", + "evidence": "Flag 5 of 7. Grade: unsupported.\n\nSummary clause: \"why he keeps a weekly Thursday intelligence-style cadence of work\".\n\nNo sentence in the article text mentions a Thursday, a weekly cadence, or any \"intelligence-style\" routine. Looks like a summarizer hallucination (unless it comes from an image, which was not checked).\n\nProposed correction: delete the clause.", + "category": "archive_fix", + "decision": "approve", + "rule": { + "category": "archive_fix", + "decision": "article-grounded correction", + "decision_detail": "article-grounded correction published to the live page" + } + }, + { + "id": 11, + "source": "pending", + "summary": "Archive fix: magazine-040 'last block he mined' sentence replacement", + "evidence": "From the Q4 falsification pass (recoveries/falsification-pass.md): the archive's gloss implied block 97,250 was the last block Satoshi mined. Published Patoshi analyses end his mining near block 54,316 - the gloss is broken.\n\nTimmy's proposed replacement sentence (reply 05):\n\n\"It closes with Satoshi resting on the 97,250th block - the parody's Genesis 2:2 close, the block mined on 2010-12-12, the day of Satoshi's last public post. (Not a claim that 97,250 was his last mined block: published Patoshi analyses end his mining near block 54,316.)\"", + "category": "archive_fix", + "decision": "approve", + "rule": { + "category": "archive_fix", + "decision": "article-grounded correction", + "decision_detail": "article-grounded correction published to the live page" + } + }, + { + "id": 12, + "source": "pending", + "summary": "Archive fix: magazine-041 calls it 'Stackchain's rowdiest fork war'", + "evidence": "Flag 4 of 7. Grade: overstated.\n\nSummary clause (IPE): \"Stackchain's rowdiest fork war\".\n\nArticle: \"This may go down as the most fun battle of Stackchain just because of the amount of people involved.\" - \"most fun\" is supported; \"rowdiest\" is the archive's superlative, not stated.\n\nProposed correction: \"Stackchain's most fun battle\".", + "category": "archive_fix", + "decision": "approve", + "rule": { + "category": "archive_fix", + "decision": "article-grounded correction", + "decision_detail": "article-grounded correction published to the live page" + } + } + ] +} \ No newline at end of file