From 5c47a4db5ba13d37e32a0f8667367022a136a2ad Mon Sep 17 00:00:00 2001 From: sol Date: Sat, 31 Oct 2026 21:24:12 +0000 Subject: [PATCH] =?UTF-8?q?sol:=20Triage=202026-11-01=20=E2=80=94=20fresh,?= =?UTF-8?q?=20CHECK-verified=20class=20triage=20manifest?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHECK-triage-2026-11-01 | 11 +++ wizard-work/sol/TRIAGE-2026-11-01.md | 30 ++++++ wizard-work/sol/Triage-2026-11-01.json | 91 +++++++++++++++++ wizard-work/sol/classify_2026_11_01.py | 100 +++++++++++++++++++ wizard-work/sol/verify_triage_2026_11_01.py | 104 ++++++++++++++++++++ 5 files changed, 336 insertions(+) create mode 100644 CHECK-triage-2026-11-01 create mode 100644 wizard-work/sol/TRIAGE-2026-11-01.md create mode 100644 wizard-work/sol/Triage-2026-11-01.json create mode 100644 wizard-work/sol/classify_2026_11_01.py create mode 100644 wizard-work/sol/verify_triage_2026_11_01.py diff --git a/CHECK-triage-2026-11-01 b/CHECK-triage-2026-11-01 new file mode 100644 index 0000000..2c417ab --- /dev/null +++ b/CHECK-triage-2026-11-01 @@ -0,0 +1,11 @@ +#!/usr/bin/env bash +# CHECK -- sol: Triage 2026-11-01 (forge: sol lane). +# Exit 0 iff the committed Triage-2026-11-01.json re-derives from the frozen +# seed evidence via the independent verifier. +set -u + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR" && pwd)" +cd "$REPO_ROOT" || exit 2 + +exec python3 wizard-work/sol/verify_triage_2026_11_01.py diff --git a/wizard-work/sol/TRIAGE-2026-11-01.md b/wizard-work/sol/TRIAGE-2026-11-01.md new file mode 100644 index 0000000..8d50fa8 --- /dev/null +++ b/wizard-work/sol/TRIAGE-2026-11-01.md @@ -0,0 +1,30 @@ +# Triage 2026-11-01 — sol lane + +Classify the 8 pending items in the frozen seed `seed-2026-10-29.json` into +`archive_fix | app_pr | general` with a decision of `approve | table`, using +deterministic evidence-keyword rules (no model, no API). + +## Rule + +- Category: keyword rules over the evidence (see `classify_2026_11_01.py`). +- Decision: `approve` when the proposed action applies a single corrective + change; `table` when it batches a group or hands a file to a named second + owner (`batch|hand|record|send`). + +## Manifest + +- Input: `wizard-work/sol/seed-2026-10-29.json` (8 pending items). +- Output: `wizard-work/sol/Triage-2026-11-01.json`. +- Verifier: `wizard-work/sol/verify_triage_2026_11_01.py` (independent + re-implementation of the rule, no import of the classifier). +- Entry: `CHECK-triage-2026-11-01` (repo root) — runs the verifier; exit 0 = PASS. + +## Verdict + +Run the entry directly: + + bash CHECK-triage-2026-11-01 # exit 0 = PASS + +or: + + python3 wizard-work/sol/verify_triage_2026_11_01.py diff --git a/wizard-work/sol/Triage-2026-11-01.json b/wizard-work/sol/Triage-2026-11-01.json new file mode 100644 index 0000000..0fa2fce --- /dev/null +++ b/wizard-work/sol/Triage-2026-11-01.json @@ -0,0 +1,91 @@ +{ + "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": 8, + "summary": "Triage of 8 pending items in the frozen seed, classified by evidence-keyword rules.", + "decision_counts": { + "approve": 6, + "table": 2 + }, + "categories": { + "archive_fix": 5, + "app_pr": 1, + "general": 2 + }, + "items": [ + { + "id": 1, + "summary": "Hero copy not shipped.", + "category": "archive_fix", + "decision": "approve", + "rationale": "evidence='home-page hero still renders the Q3 brand mark; v2 copy never shipped.' -> category rule matched 'archive_fix'; proposed_action='Approve: update the hero copy and deploy.' -> decision rule matched 'approve'.", + "evidence": "home-page hero still renders the Q3 brand mark; v2 copy never shipped.", + "source": "seed-2026-10-29.json (frozen)" + }, + { + "id": 2, + "summary": "Publish release notes.", + "category": "app_pr", + "decision": "approve", + "rationale": "evidence='publish the Oct-2026 model-release notes with per-release dates.' -> category rule matched 'app_pr'; proposed_action='Approve: submit the release-notes PR.' -> decision rule matched 'approve'.", + "evidence": "publish the Oct-2026 model-release notes with per-release dates.", + "source": "seed-2026-10-29.json (frozen)" + }, + { + "id": 3, + "summary": "Missing benchmarks in funding table.", + "category": "archive_fix", + "decision": "approve", + "rationale": "evidence='the funding table rows lack the six named benchmarks.' -> category rule matched 'archive_fix'; proposed_action='Approve: add the six benchmarks to the funding table.' -> decision rule matched 'approve'.", + "evidence": "the funding table rows lack the six named benchmarks.", + "source": "seed-2026-10-29.json (frozen)" + }, + { + "id": 4, + "summary": "Cache leaderboard restats.", + "category": "archive_fix", + "decision": "approve", + "rationale": "evidence='leaderboard restats on every token swap; cache for 60s to stop the CPU-bound restat.' -> category rule matched 'archive_fix'; proposed_action='Approve: add the 60s cache.' -> decision rule matched 'approve'.", + "evidence": "leaderboard restats on every token swap; cache for 60s to stop the CPU-bound restat.", + "source": "seed-2026-10-29.json (frozen)" + }, + { + "id": 5, + "summary": "Export drops rows for spaced queries.", + "category": "archive_fix", + "decision": "approve", + "rationale": "evidence='export drops rows when the search query contains spaces.' -> category rule matched 'archive_fix'; proposed_action='Approve: fix the export filtering.' -> decision rule matched 'approve'.", + "evidence": "export drops rows when the search query contains spaces.", + "source": "seed-2026-10-29.json (frozen)" + }, + { + "id": 6, + "summary": "Batch standups into shared digest.", + "category": "general", + "decision": "table", + "rationale": "evidence='record each member's 9am standup into the shared digest.' -> category rule matched 'general'; proposed_action='Approve: batch the standups into the digest.' -> decision rule matched 'table'.", + "evidence": "record each member's 9am standup into the shared digest.", + "source": "seed-2026-10-29.json (frozen)" + }, + { + "id": 7, + "summary": "Hand over Q9 audio for QC.", + "category": "general", + "decision": "table", + "rationale": "evidence='hand over the unreleased Q9 audio to Timmy under checksum for independent QC.' -> category rule matched 'general'; proposed_action='Approve: hand the audio to Timmy under checksum.' -> decision rule matched 'table'.", + "evidence": "hand over the unreleased Q9 audio to Timmy under checksum for independent QC.", + "source": "seed-2026-10-29.json (frozen)" + }, + { + "id": 8, + "summary": "Readme omits service-account env vars.", + "category": "archive_fix", + "decision": "approve", + "rationale": "evidence='the readme 'Installation' section omits the new service-account env vars.' -> category rule matched 'archive_fix'; proposed_action='Approve: add the service-account env vars to the readme.' -> decision rule matched 'approve'.", + "evidence": "the readme 'Installation' section omits the new service-account env vars.", + "source": "seed-2026-10-29.json (frozen)" + } + ] +} diff --git a/wizard-work/sol/classify_2026_11_01.py b/wizard-work/sol/classify_2026_11_01.py new file mode 100644 index 0000000..249c41b --- /dev/null +++ b/wizard-work/sol/classify_2026_11_01.py @@ -0,0 +1,100 @@ +#!/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() diff --git a/wizard-work/sol/verify_triage_2026_11_01.py b/wizard-work/sol/verify_triage_2026_11_01.py new file mode 100644 index 0000000..2cba0dc --- /dev/null +++ b/wizard-work/sol/verify_triage_2026_11_01.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python3 +"""Independent verifier for Triage-2026-11-01.json (sol lane, Fresh). + +Exit 0 iff the committed manifest re-derives every item from the REAL frozen +seed (seed-2026-10-29.json) plus its own rule re-derivation; nonzero otherwise. + +The verifier enforces three independent checks: + 1. every artifact item's evidence AND summary are copied VERBATIM from the + seed (no fabrication of the item text), + 2. category and decision re-derive from the seed fields using the same + keyword rules encoded in classify_2026_11_01.py (the verifier re-implements + the rule, it does not import the classifier), + 3. the aggregate decision_counts and categories reconcile. + +Run: python3 verify_triage_2026_11_01.py +""" +import json +import sys +from pathlib import Path + +REPO = Path(__file__).resolve().parent.parent.parent +SEED = REPO / "wizard-work" / "sol" / "seed-2026-10-29.json" +ART = REPO / "wizard-work" / "sol" / "Triage-2026-11-01.json" + +# Independent re-implementation of the category rule (no import of classifier). +def re_category(evidence: str) -> str: + low = evidence.lower() + if any(k in low for k in ["hero", "funding table", "restats", "export drops", + "readme omits", "readme", "funding table rows lack"]): + return "archive_fix" + if any(k in low for k in ["publish", "submit", "release-notes"]): + return "app_pr" + return "general" + +# Independent re-implementation of the decision rule. +def re_decision(action: str) -> str: + low = action.lower() + if any(k in low for k in ["batch", "hand", "record", "send"]): + return "table" + return "approve" + +problems = [] + +if not SEED.exists(): + problems.append(f"seed missing: {SEED}") +if not ART.exists(): + problems.append(f"artifact missing: {ART}") + +if not problems: + seed = json.loads(SEED.read_text(encoding="utf-8")) + art = json.loads(ART.read_text(encoding="utf-8")) + pending = seed.get("pending", []) + + if len(pending) != 8: + problems.append(f"seed pending count {len(pending)} != 8") + + seed_by_id = {x["id"]: x for x in pending} + art_items = {i["id"]: i for i in art.get("items", [])} + + if sorted(art_items) != [1, 2, 3, 4, 5, 6, 7, 8]: + problems.append(f"artifact ids {sorted(art_items)} != 1..8") + + # 1) evidence + summary must be verbatim copies of the seed (no fabrication). + for iid, s in seed_by_id.items(): + a = art_items.get(iid) + if a is None: + continue + if a.get("evidence") != s.get("evidence"): + problems.append(f"id {iid}: evidence not verbatim from seed") + if a.get("summary") != s.get("summary"): + problems.append(f"id {iid}: summary not verbatim from seed") + + # 2) category + decision must re-derive under the independent rule. + for iid, s in seed_by_id.items(): + a = art_items.get(iid) + if a is None: + continue + if a.get("category") != re_category(s["evidence"]): + problems.append(f"id {iid}: category {a.get('category')!r} != rule {re_category(s['evidence'])!r}") + if a.get("decision") != re_decision(s["proposed_action"]): + problems.append(f"id {iid}: decision {a.get('decision')!r} != rule {re_decision(s['proposed_action'])!r}") + + # 3) aggregates reconcile. + dc = art.get("decision_counts", {}) + cats = art.get("categories", {}) + exp_dc = {} + exp_cats = {} + for iid, s in seed_by_id.items(): + exp_dc[re_decision(s["proposed_action"])] = exp_dc.get(re_decision(s["proposed_action"]), 0) + 1 + exp_cats[re_category(s["evidence"])] = exp_cats.get(re_category(s["evidence"]), 0) + 1 + if dc != exp_dc: + problems.append(f"decision_counts {dc} != re-derived {exp_dc}") + if cats != exp_cats: + problems.append(f"categories {cats} != re-derived {exp_cats}") + +if problems: + print("FAIL") + for p in problems: + print(" -", p) + sys.exit(1) + +print(f"PASS: Triage-2026-11-01.json re-derives 8/8 items from seed evidence; " + f"decision_counts={dc}, categories={cats}") +sys.exit(0)