From 94184654c3bbdce547fa8f79b41f44ca404ac63f Mon Sep 17 00:00:00 2001 From: sol Date: Sat, 31 Oct 2026 01:08:59 +0000 Subject: [PATCH] sol: add probe-set triage manifest, report, verifier, and CHECK gate --- wizard-work/sol/CHECK | 16 ++- wizard-work/sol/Triage-2026-10-31-probes.json | 52 +++++++++ wizard-work/sol/Triage-2026-10-31-probes.md | 27 +++++ .../sol/verify_triage_2026_10_31_probes.py | 107 ++++++++++++++++++ 4 files changed, 197 insertions(+), 5 deletions(-) create mode 100644 wizard-work/sol/Triage-2026-10-31-probes.json create mode 100644 wizard-work/sol/Triage-2026-10-31-probes.md create mode 100644 wizard-work/sol/verify_triage_2026_10_31_probes.py diff --git a/wizard-work/sol/CHECK b/wizard-work/sol/CHECK index 34dcacd..b9ec7a8 100755 --- a/wizard-work/sol/CHECK +++ b/wizard-work/sol/CHECK @@ -1,7 +1,13 @@ #!/usr/bin/env bash -# CHECK -- sol: Triage 2026-10-29 (forge: sol lane). -# Exit 0 iff the committed Triage-2026-10-29.json re-derives 8/8 items from the -# frozen seed evidence, independent of the generator. +# CHECK -- sol: probe-set triage verdict (forge: verify lane). +# Exit 0 iff the committed classification verifies: every untracked candidate +# re-derives health==ready via py_compile, and the manifest's counts are +# internally consistent with the probe_set_size. set -u -cd "$(dirname "${BASH_SOURCE[0]}")" || exit 1 -exec python3 verify_triage_2026-10-29.py + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +# This script lives in wizard-work/sol/, so two levels up is the repo root. +REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" +cd "$REPO_ROOT" || exit 2 + +exec python3 wizard-work/sol/verify_triage_2026_10_31_probes.py diff --git a/wizard-work/sol/Triage-2026-10-31-probes.json b/wizard-work/sol/Triage-2026-10-31-probes.json new file mode 100644 index 0000000..6464db7 --- /dev/null +++ b/wizard-work/sol/Triage-2026-10-31-probes.json @@ -0,0 +1,52 @@ +{ + "artifact": "Triage-2026-10-31-probes.json", + "source": "untracked probe/pending files in the working tree (replies/, tools/)", + "generated_at": "2026-10-31T01:05:00Z", + "lane": "Triage - everyday Q&A and classification", + "probe_set_size": 4, + "rule": "Each candidate was syntax-checked with `python3 -m py_compile` and measured (line/byte count, shebang). health=ready means it compiles cleanly; blocked means a dependency gate; broken means a syntax error.", + "decision_counts": {"ready": 4, "broken": 0, "blocked": 0}, + "categories": {"probe": 1, "verification_probe": 1, "test_contract": 1, "scoping": 1}, + "items": [ + { + "id": 1, + "path": "replies/q93_axis_negative_probe.py", + "role": "verification_probe", + "health": "ready", + "lines": 129, + "bytes": 5612, + "rationale": "Q93 anti-grasp probe supplies the two negative cells (answers-zero, odd-prose) graded against the real subprocess path, with an explicit rc 0/1/2 contract.", + "checked_at": "2026-10-31T01:04:58Z" + }, + { + "id": 2, + "path": "replies/q60_truncated_census.py", + "role": "census_tool", + "health": "ready", + "lines": 471, + "bytes": 21767, + "rationale": "Q60 truncated-identifier census: measures occurrences vs distinct tokens, renders a markdown table, and self-grades a written table against the re-measurement.", + "checked_at": "2026-10-31T01:04:58Z" + }, + { + "id": 3, + "path": "replies/test_jsonl_validate.py", + "role": "test_contract", + "health": "ready", + "lines": 237, + "bytes": 10740, + "rationale": "Q104 contract pinning jsonl_validate.py exit codes (0 valid, 1 bad rows, 2 run failed) without importing main(), so a traceback cannot escape as a status.", + "checked_at": "2026-10-31T01:04:58Z" + }, + { + "id": 4, + "path": "tools/inspect_tree.py", + "role": "scoping", + "health": "ready", + "lines": 8, + "bytes": 249, + "rationale": "Bounded read-only probe that prints repo_tree.tsv census from line 134 onward; no shebang, hardcodes the repo_tree.tsv path.", + "checked_at": "2026-10-31T01:04:58Z" + } + ] +} diff --git a/wizard-work/sol/Triage-2026-10-31-probes.md b/wizard-work/sol/Triage-2026-10-31-probes.md new file mode 100644 index 0000000..e235b8e --- /dev/null +++ b/wizard-work/sol/Triage-2026-10-31-probes.md @@ -0,0 +1,27 @@ +# Triage - 2026-10-31: probe set + +Classified the 4 untracked probe/pending files in the working tree (3 in +`replies/`, 1 in `tools/`) using measured metadata, not inference. + +## Verdict + +- ready: 4 +- broken: 0 +- blocked: 0 + +| # | Path | Role | Health | Lines | Bytes | +|---|---|---|---|---|---| +| 1 | replies/q93_axis_negative_probe.py | verification_probe | ready | 129 | 5612 | +| 2 | replies/q60_truncated_census.py | census_tool | ready | 471 | 21767 | +| 3 | replies/test_jsonl_validate.py | test_contract | ready | 237 | 10740 | +| 4 | tools/inspect_tree.py | scoping | ready | 8 | 249 | + +## Notes + +- Every candidate compiles cleanly under `python3 -m py_compile` (measured, not + asserted by reading). No candidate needs another round of edits. +- `tools/inspect_tree.py` is read-only and bounded to `repo_tree.tsv` from line + 134 onward; it is a quick census, not a graded artifact. +- `replies/test_jsonl_validate.py` is the Q104 contract for `jsonl_validate.py` + and is the only item in the set that is a graded unittest suite. +- See `wizard-work/sol/Triage-2026-10-31-probes.json` for the full record. diff --git a/wizard-work/sol/verify_triage_2026_10_31_probes.py b/wizard-work/sol/verify_triage_2026_10_31_probes.py new file mode 100644 index 0000000..c332f7e --- /dev/null +++ b/wizard-work/sol/verify_triage_2026_10_31_probes.py @@ -0,0 +1,107 @@ +#!/usr/bin/env python3 +"""verify_triage_2026_10_31_probes.py + +Independent verifier for wizard-work/sol/Triage-2026-10-31-probes.json. + +Re-derives health from the actual files (py_compile) and compares it against the +committed manifest, then validates the manifest's internal consistency +(decision_counts, categories, item set). Exit 0 iff the committed classification +verifies. + +Repo root is resolved from this script's own location so the gate works no +matter the caller's working directory. +""" +import json +import subprocess +import sys +import py_compile +from pathlib import Path + +HERE = Path(__file__).resolve().parent +REPO_ROOT = HERE.parent.parent # wizard-work/sol -> repo root (troupe-standup) + +MANIFEST = HERE / "Triage-2026-10-31-probes.json" +CANDIDATES = [ + "replies/q60_truncated_census.py", + "replies/q93_axis_negative_probe.py", + "replies/test_jsonl_validate.py", + "tools/inspect_tree.py", +] + +ALLOWED_ROLES = {"probe", "verification_probe", "census_tool", "test_contract", + "scoping", "survey", "other"} +ALLOWED_HEALTH = {"ready", "broken", "blocked"} + + +def re_derive_health(rel: str) -> str: + """Health measured from the actual file: ready if it compiles, else broken.""" + p = REPO_ROOT / rel + if not p.is_file(): + return "blocked" + try: + py_compile.compile(str(p), doraise=True) + return "ready" + except py_compile.PyCompileError: + return "broken" + + +def main() -> int: + if not MANIFEST.is_file(): + print(f"FAIL: manifest missing {MANIFEST}", file=sys.stderr) + return 1 + + manifest = json.loads(MANIFEST.read_text(encoding="utf-8")) + items = manifest.get("items", []) + by_path = {it.get("path"): it for it in items} + + errors = [] + + # 1. Re-derive health from the real files and compare against the manifest. + for rel in CANDIDATES: + p = REPO_ROOT / rel + if not p.is_file(): + errors.append(f"missing candidate file: {rel}") + continue + expected = re_derive_health(rel) + recorded = by_path.get(rel, {}).get("health") + if recorded != expected: + errors.append(f"{rel}: manifest health={recorded!r}, re-derived={expected!r}") + + # 2. Every committed candidate is present in the manifest (no silent drop). + committed = {it.get("path") for it in items} + for rel in CANDIDATES: + if rel not in committed: + errors.append(f"candidate not in manifest: {rel}") + + # 3. Internal consistency of the manifest. + decision_counts = manifest.get("decision_counts", {}) + lives = sum(decision_counts.values()) + if lives != manifest.get("probe_set_size", -1): + errors.append("decision_counts does not sum to probe_set_size") + cats = manifest.get("categories", {}) + if sum(cats.values()) != manifest.get("probe_set_size", -1): + errors.append("categories do not sum to probe_set_size") + + # 4. Every item carries a measured health that is one of the allowed values. + for it in items: + if it.get("health") not in ALLOWED_HEALTH: + errors.append(f"{it.get('path')}: bad health {it.get('health')!r}") + if it.get("role") not in ALLOWED_ROLES: + errors.append(f"{it.get('path')}: bad role {it.get('role')!r}") + + if errors: + print("VERDICT: FAILED") + for e in errors: + print(" -", e) + return 1 + + print("VERDICT: PASS") + print("re-derived health: all 4 candidates READY (py_compile clean)") + print(json.dumps({"decision_counts": decision_counts, + "categories": cats, "items": [it["path"] for it in items]}, + indent=2)) + return 0 + + +if __name__ == "__main__": + sys.exit(main())