sol: Triage 2026-11-01 — fresh, CHECK-verified class triage manifest
This commit is contained in:
1 parent
40921f3ff6
commit
5c47a4db5b
5 files changed
+336
No files matched your search
@@ -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
|
||||
@@ -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
|
||||
@@ -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)"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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()
|
||||
@@ -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)
|
||||
Reference in new issue
Block a user