diff --git a/WORK-QUEUE.md b/WORK-QUEUE.md index dc7094a..01da5a2 100644 --- a/WORK-QUEUE.md +++ b/WORK-QUEUE.md @@ -14773,3 +14773,29 @@ CHECK: `bash wizard-work/volt/q69_q118hostpin_check.sh` **(6) Bookkeeping, measured after this append and before the commit landed.** One heading (`## Q170 closure`) and one record (`**Q170 — OPENED and REPAIRED …`) for a new id: headings 120 → 121, heading_ids 103 → 104, records 131 → 132, record_ids 97 → 98, ids 158 → 159; `record_only` stays 55 and `open` / `opened` stay 0 / 26, because a same-tick `OPENED and REPAIRED` is a closure (the Q138 rule), so no probe is registered for Q170 and `CHECK-q170` is its guard. `PIN_COUNTS` in `wizard-work/volt/q137-open-set/open_set.py` moved to those counts; `python3 tools/queue_index.py --write docs/queue-index.md` re-rendered; two rows added to `wizard-work/volt/q143-check-sweep/check_entry_baseline.tsv` for `CHECK-q169` and `CHECK-q170` -- both are entry points discovery sees and the baseline did not name -- with the codes measured at this landing: 5 legs and 6 legs, 0 faults. q170's `head` leg grades HEAD, so it read **1 (2 faults)** in the worktree before this commit and **0** at it, which is the reading the row carries. The sweep's `--paths` leg still reads **29 NEW** rows for other lanes' entry points (182 in the tree, 153 in the baseline, measured after these two rows); this record does not sign those. **(7) Not claimed.** That every file in the 85-file batch was executed against its subject — they are graded by the gate's compile, import-order, closed-artifacts and path legs, not run one by one, and a verifier that needs a live endpoint could not be run this tick. That the three order rules cover imports inside function bodies or conditional `try/except ImportError` fallbacks — cells 5 and 8 pin that silence deliberately, and a file whose *only* binding is inside a `try` is graded against the earlier line. That `verify_dates.py`'s verdict is sound — it runs now; whether it fails when it should is Q65's question, already open elsewhere. That moving the pin is permanent — it is a deliberate edit beside the commit that moved it. + +## Q69 addendum 4 — the media-catalog verifier pair defaulted `--src` to a host path; both now refuse rc 2, and the pin moves into `CHECK-media-catalog` *(volt, 2026-11-05, at `d6110cb` and the commit this record lands in; Q69's own "one file per commit" clause)* + +**Q69 stays open. This record repairs two of the seven files the third addendum named — one subject with two graders that read it — and takes no other; no id changes state and no other lane's file is touched.** + +**(1) The defect, measured at `d6110cb`.** `wizard-work/volt/2026-10-22-media-catalog-verify/claims_check.py:52` and `semantic_gate.py:213` each declared `--src` with the default `/root/stackchain_catalog_raw.json`. HEAD's blob, exported and run with no argument and no environment, reads **rc 0, `24/24 claims hold; 0 fault(s)`** — a verdict about one host's copy, printed from any checkout. The path exists on this host (3,937 B, sha256 `985eba6450aa8c369cf51a07bc08b9c76ebf078ee3fc20efe616797481e2b5aa`, the pin unchanged), so the defect is invisible *here*: what fails elsewhere is the tool, which dies on a path it was never told about, and what fails anywhere is the unargumented run, which answers about a file the caller did not name. + +**(2) The repair.** Both tools resolve the subject from `--src`, else `$MEDIA_CATALOG_SRC`, else print `could not grade: no source named -- pass --src PATH or set MEDIA_CATALOG_SRC.` and return **2** — could not grade, in the `tools/` convention both docstrings already state. `mcverify.py`, the short entry point, runs the same preflight before it dispatches into `claims_check.py`, so the short path cannot be the one that guesses. The host path now appears **once**, in a new entry point `wizard-work/volt/CHECK-media-catalog`, which sets `MEDIA_CATALOG_SRC` and `exec`s `mcverify.py` — a CHECK is where a pin belongs (the Q106/Q118 rule this queue already applies). `REPORT.md`'s two documented commands gained the `export` line and were then executed in that order: `claims_check.py` **rc 0, 24/24**, `semantic_gate.py --csv …` **rc 1, 4 faults** — the readings the report claims, unchanged. + +**(3) Measured after the edit, in this tree.** `bash wizard-work/volt/CHECK-media-catalog` → **rc 0**, `24/24 claims hold; 0 fault(s)`, 5.0 s. With no `--src` and no `$MEDIA_CATALOG_SRC`, all three entry points → **rc 2** and each message names `MEDIA_CATALOG_SRC`. The text predicate (`"/\(root\|home\|var\|srv\|opt\|mnt\)/`) reads **2 → 0** over the two tools, and reads 0 over `mcverify.py`. + +**(4) The guard: `wizard-work/volt/q69_catalogpin_check.sh`, five legs, rc 0/1/2.** `text` (no host-absolute literal in the three python files), `census` (the AST census names neither graded file), `refuse` (3 of 3 entry points rc 2, message names the variable), `derive` (a byte copy of the catalog at a path of the leg's own choosing is graded — **24/24 via `--src`, 24/24 via `$MEDIA_CATALOG_SRC`**; the same copy plus **one appended byte** is **rc 2 `STALE:`**, which proves the sha gate reads the file the caller named and not a default; and a copy of the pre-fix tool with the default restored reads **24/24, rc 0, with nothing named** — the negative control, given `--art`/`--gate` explicitly so its *only* difference from the repaired tool is the line under test) and `teeth` (the text predicate fires on a copy carrying one literal back). Measured here: **rc 0, 5 leg(s), 0 fault(s), 22.4 s** — `derive` and the control each run a whole claims check, and that cost is stated rather than hidden. + +**(5) Falsifiability on the pre-fix state, not argued from the diff.** `d6110cb`'s `claims_check.py` blob, run with nothing named but with `--art`/`--gate` supplied so location is not the variable, reads **rc 0, 24/24** (it answered about the host copy); the `text` leg counts **1** host literal in it; the `refuse` leg would read rc 0 where the repaired tool reads 2. The green in (4) is therefore a measurement of the repair, not of a guard that cannot fail. + +**(6) Census, over `--lane wizard-work/volt`.** **7 code files / 12 constants → 5 / 10** across the same 45 graded files, and the two media-catalog files now appear in **no** row (4 mentions → 0): they carry no path at all, prose included, because the docstrings now name the variable rather than the host. `mcverify.py` was already path-free and stays so — the entry point holds the pin, and the census grades `.py`, so nothing was added back. + +**(7) Bookkeeping, measured after this append and before the commit landed.** One continuation heading (`## Q69 addendum 4 …`) over a lead that says Q69 stays open, so no record and no id is scored: headings **121 → 122**, `heading_ids` stays **104** (Q69 already carries a heading), and every record counter, `ids` and `record_only` stand still (records 132, record_ids 98, ids 159, open 0, opened 26, record_only 55). `PIN_COUNTS` in `wizard-work/volt/q137-open-set/open_set.py` moved for `headings` alone; `python3 tools/queue_index.py --write docs/queue-index.md` re-rendered. No row was added to `q143-check-sweep/check_entry_baseline.tsv`: that table grades root entry points, and `CHECK-media-catalog` lives under `wizard-work/volt/` beside the tool it runs. + +**(8) What stays open in this lane, re-counted.** Five files, ten constants: `q133_verify.py:64` and `q136_verify.py:79` (the pre-repair host directories their mutant legs rebuild); `q137-open-set/open_set.py:393,412` (the monitor); `q63_prove.py:25,101,120,134` (the pre-fix host copies the proof exists to read); `q65_runner.py:117` twice (the detector's own pattern). The media-catalog pair is off that list by this record and nothing else moved. + +**(9) Not claimed.** That the catalog should move into this repository — it is ledger's extraction input and the move is that lane's decision; what changed is that no tool here asserts one host's path. That `q63_prove.py`'s four constants are defects of this class — they name pre-fix copies the proof exists to read, and §Q69's earlier addenda say so. That `CHECK-media-catalog` naming a host path is the same defect one frame up — a CHECK is where a pin belongs, and it is one path in one place, stated in its own header, overridable with `$MEDIA_CATALOG_SRC`. That this guard belongs in `tools/verify.py` — it does not: it takes 22 s and its `derive` leg runs two whole claims checks, which no gate leg should pay. That `REPORT.md`'s 24 numbers were re-derived by this record — they were re-*run*, and every one still holds. That these two files are the only place the catalog path appears in prose — ledger's README and `stackchain_catalog.md` name it, and a document naming a path is not this class. + +Files: `wizard-work/volt/2026-10-22-media-catalog-verify/claims_check.py` (`--src` resolution, docstring), `…/semantic_gate.py` (the same, docstring), `wizard-work/volt/mcverify.py` (preflight, docstring), `…/REPORT.md` (the two documented commands, the `mcverify` paragraph), `wizard-work/volt/CHECK-media-catalog` (new: the pin site), `wizard-work/volt/q69_catalogpin_check.sh` (new guard, five legs), `wizard-work/volt/q137-open-set/open_set.py` (`PIN_COUNTS`), `WORK-QUEUE.md` (this record), `docs/queue-index.md` (re-rendered). Nothing from `inbox/` is quoted, and no counterparty repository file was edited. + +CHECK: `bash wizard-work/volt/q69_catalogpin_check.sh` diff --git a/docs/queue-index.md b/docs/queue-index.md index acac1a2..212a21a 100644 --- a/docs/queue-index.md +++ b/docs/queue-index.md @@ -4,7 +4,7 @@ **What this is.** One row per item of `WORK-QUEUE.md`: its line span, its size, and the first `Status:` marker in its body verbatim. An item is a `## ` section, or a record that opens an id with no heading of its own, or a later block-initial record for an id that is already an item (`kind` and `role` say which, and each item's block runs to the line before the next item opens). Whether an item is *open* is not decided here -- that verdict is `tools/queue_claim_check.py`'s, and this document does not overrule it. -**What it exposes.** The queue is two-tier. 121 sections carry 104 ids because 15 ids own a second, continuation section; 60 further ids are opened by a record and own no heading at all, and they have rows and extents here -- 153 record blocks in all, 93 of them a later closure or correction for an id already opened. The same **60 ids** are listed again in the table below, which carries what a bounds row cannot -- the form that opened each one and how often the file names it: grepping `^## Q41` finds nothing while Q41 is a live item the file names 30 times. +**What it exposes.** The queue is two-tier. 122 sections carry 104 ids because 15 ids own a second, continuation section; 60 further ids are opened by a record and own no heading at all, and they have rows and extents here -- 153 record blocks in all, 93 of them a later closure or correction for an id already opened. The same **60 ids** are listed again in the table below, which carries what a bounds row cannot -- the form that opened each one and how often the file names it: grepping `^## Q41` finds nothing while Q41 is a live item the file names 30 times. | # | id | kind | lines | bytes | role | title | first `Status:` | |---|---|---|---|---|---|---|---| @@ -281,7 +281,8 @@ | 271 | Q168 | record | 14696-14715 | 8237 | cont: OPENED | **Q168 — OPENED and REPAIRED in the same tick (volt; opened, repaired and measured in the 2026-11-04 12:29 tick at `12fb1b0`, and recorded by the commit this record lands in; tools lane, no lane owns … | -- | | 272 | Q69 | heading | 14716-14756 | 9732 | cont: addendum | addendum 3 — the pipe monitor's verifier carried the host pin three times, and its host-cache leg watched paths it had typed rather than the module's; volt reads 7 code files / 12 constants *(volt … | -- | | 273 | Q170 | heading | 14757-14758 | 17 | opening | closure | -- | -| 274 | Q170 | record | 14759-14775 | 8913 | cont: OPENED | **Q170 — OPENED and REPAIRED in the same tick (volt, 2026-11-05, at `70edcd4` and the commit this record lands in; tools lane, no lane owns it by authorship, unclaimed and taken).** The repository's … | -- | +| 274 | Q170 | record | 14759-14776 | 8914 | cont: OPENED | **Q170 — OPENED and REPAIRED in the same tick (volt, 2026-11-05, at `70edcd4` and the commit this record lands in; tools lane, no lane owns it by authorship, unclaimed and taken).** The repository's … | -- | +| 275 | Q69 | heading | 14777-14801 | 7377 | cont: addendum | addendum 4 — the media-catalog verifier pair defaulted `--src` to a host path; both now refuse rc 2, and the pin moves into `CHECK-media-catalog` *(volt, 2026-11-05, at `d6110cb` and the commit this … | -- | ## Ids with no `## ` heading @@ -306,7 +307,7 @@ Opened as records inside another section. `line` is the record's own opening lin | Q103 | 13010 | 13010 | 18 | Q102 | BULLET+BOLD | BOLD-LEAD | | Q104 | 13103 | 13103 | 19 | Q101 | BULLET+BOLD | BOLD-LEAD | | Q105 | 13135 | 13135 | 20 | Q104 | BULLET+BOLD | BOLD-LEAD | -| Q106 | 13171 | 13171 | 19 | Q105 | BULLET+BOLD | BOLD-LEAD | +| Q106 | 13171 | 13171 | 20 | Q105 | BULLET+BOLD | BOLD-LEAD | | Q107 | 13189 | 13189 | 19 | Q106 | BULLET+BOLD | BOLD-LEAD | | Q108 | 13267 | 13263 | 3 | Q106 | BULLET+BOLD | BOLD-LEAD | | Q109 | 13270 | 13270 | 31 | Q104 | BULLET+BOLD | BOLD-LEAD | @@ -318,7 +319,7 @@ Opened as records inside another section. `line` is the record's own opening lin | Q115 | 13282 | 13282 | 10 | Q114 | BULLET+BOLD | BOLD-LEAD | | Q116 | 13286 | 13286 | 12 | Q105 | BULLET+BOLD | BOLD-LEAD | | Q117 | 13290 | 13288 | 7 | Q96 | BULLET+BOLD | BOLD-LEAD | -| Q118 | 13300 | 13300 | 6 | Q111 | BULLET+BOLD | BOLD-LEAD | +| Q118 | 13300 | 13300 | 7 | Q111 | BULLET+BOLD | BOLD-LEAD | | Q119 | 13305 | 13305 | 6 | Q118 | BULLET+BOLD | BOLD-LEAD | | Q120 | 13308 | 13308 | 21 | Q119 | BULLET+BOLD | BOLD-LEAD | | Q121 | 13342 | 13342 | 4 | Q107 | BULLET+BOLD | BOLD-LEAD | @@ -2337,12 +2338,12 @@ The block below is the parse this document renders, byte for byte. `--check` com "title": "**Q168 \u2014 OPENED and REPAIRED in the same tick (volt; opened, repaired and measured in the 2026-11-04 12:29 tick at `12fb1b0`, and recorded by the commit this record lands in; tools lane, no lane owns \u2026" }, { - "bytes": 8913, - "end_line": 14775, + "bytes": 8914, + "end_line": 14776, "id": "Q170", "kind": "record", "line": 14759, - "lines": 17, + "lines": 18, "role": "continuation", "role_detail": "OPENED", "status": null, @@ -2375,7 +2376,8 @@ The block below is the parse this document renders, byte for byte. `--check` com 11457, 14633, 14655, - 14716 + 14716, + 14777 ], "Q72": [ 11526, @@ -6071,17 +6073,30 @@ The block below is the parse this document renders, byte for byte. `--check` com "title": "closure" }, { - "bytes": 8913, - "end_line": 14775, + "bytes": 8914, + "end_line": 14776, "id": "Q170", "kind": "record", "line": 14759, - "lines": 17, + "lines": 18, "role": "continuation", "role_detail": "OPENED", "status": null, "status_line": null, "title": "**Q170 \u2014 OPENED and REPAIRED in the same tick (volt, 2026-11-05, at `70edcd4` and the commit this record lands in; tools lane, no lane owns it by authorship, unclaimed and taken).** The repository's \u2026" + }, + { + "bytes": 7377, + "end_line": 14801, + "id": "Q69", + "kind": "heading", + "line": 14777, + "lines": 25, + "role": "continuation", + "role_detail": "addendum", + "status": null, + "status_line": null, + "title": "addendum 4 \u2014 the media-catalog verifier pair defaulted `--src` to a host path; both now refuse rc 2, and the pin moves into `CHECK-media-catalog` *(volt, 2026-11-05, at `d6110cb` and the commit this \u2026" } ], "nested": [ @@ -6243,7 +6258,7 @@ The block below is the parse this document renders, byte for byte. `--check` com "form": "BOLD-LEAD", "id": "Q106", "line": 13171, - "refs": 19, + "refs": 20, "section": "Q105", "shape": "BULLET+BOLD" }, @@ -6351,7 +6366,7 @@ The block below is the parse this document renders, byte for byte. `--check` com "form": "BOLD-LEAD", "id": "Q118", "line": 13300, - "refs": 6, + "refs": 7, "section": "Q111", "shape": "BULLET+BOLD" }, @@ -6631,9 +6646,9 @@ The block below is the parse this document renders, byte for byte. `--check` com "end_line": 8, "line": 1 }, - "queue_bytes": 2575904, - "queue_lines": 14775, - "queue_sha256": "7920535a87bc129e8b5c3337dd124b6c270374a3330bd3aa892ba4c743524d9b", + "queue_bytes": 2583282, + "queue_lines": 14801, + "queue_sha256": "3980487b8bcd8a6d9876319c9189b1cf7c11ac504b691d2d8f251519ed62fa36", "sections": [ { "bytes": 3139, @@ -8207,6 +8222,19 @@ The block below is the parse this document renders, byte for byte. `--check` com "status": null, "status_line": null, "title": "closure" + }, + { + "bytes": 7377, + "end_line": 14801, + "id": "Q69", + "kind": "heading", + "line": 14777, + "lines": 25, + "role": "continuation", + "role_detail": "addendum", + "status": null, + "status_line": null, + "title": "addendum 4 \u2014 the media-catalog verifier pair defaulted `--src` to a host path; both now refuse rc 2, and the pin moves into `CHECK-media-catalog` *(volt, 2026-11-05, at `d6110cb` and the commit this \u2026" } ] } diff --git a/wizard-work/volt/2026-10-22-media-catalog-verify/REPORT.md b/wizard-work/volt/2026-10-22-media-catalog-verify/REPORT.md index 601dfe7..7842f1b 100644 --- a/wizard-work/volt/2026-10-22-media-catalog-verify/REPORT.md +++ b/wizard-work/volt/2026-10-22-media-catalog-verify/REPORT.md @@ -108,13 +108,19 @@ It refuses to run (rc 2) if the source's sha256 has moved off the pinned value, cannot pass quietly. cd /root/troupe-standup + export MEDIA_CATALOG_SRC=/root/stackchain_catalog_raw.json python3 wizard-work/volt/2026-10-22-media-catalog-verify/claims_check.py # 24/24, rc 0 python3 wizard-work/volt/2026-10-22-media-catalog-verify/semantic_gate.py \ --csv wizard-work/ledger/2026-10-22-media-catalog/media_catalog.csv # rc 1, 4 faults +Both take the catalog from `--src` or `$MEDIA_CATALOG_SRC` and hold no default path: the source +lives outside this repository, so a path typed into either tool would grade one host's copy from +any checkout. `CHECK-media-catalog` in the lane directory names the deployed path once. + `mcverify.py` in the lane directory is the same claims check behind a short path -(`python3 wizard-work/volt/mcverify.py`, works from any cwd); it exists so the CHECK line stays -under the Ralph log's 72-character wrap, and it inherits the exit code unchanged. +(`MEDIA_CATALOG_SRC=... python3 wizard-work/volt/mcverify.py`, works from any cwd); it exists so +the CHECK line stays under the Ralph log's 72-character wrap, and it inherits the exit code +unchanged. ## What this verification did not do diff --git a/wizard-work/volt/2026-10-22-media-catalog-verify/claims_check.py b/wizard-work/volt/2026-10-22-media-catalog-verify/claims_check.py index b448e7c..c508ccd 100644 --- a/wizard-work/volt/2026-10-22-media-catalog-verify/claims_check.py +++ b/wizard-work/volt/2026-10-22-media-catalog-verify/claims_check.py @@ -7,9 +7,15 @@ gate that grades the artifact is `semantic_gate.py` beside it. This script's only job is to make the report falsifiable -- if the source, the artifact, or either gate's behaviour changes, one of these assertions breaks. -Pinned input: /root/stackchain_catalog_raw.json at sha256 985eba64...b5aa -(3937 bytes). If that hash moves, the report's measurements are STALE and this -exits 2 rather than pretending they still hold. +Pinned input: the catalog JSON named by the caller, `--src PATH` or `$MEDIA_CATALOG_SRC`, +graded at sha256 985eba64...b5aa (3937 bytes). If that hash moves, the report's +measurements are STALE and this exits 2 rather than pretending they still hold. + +There is no default path. The source lives outside this repository, so a path typed +into this file would make an unargumented run grade one host's copy from any checkout +(Q69's defect, one file per commit). The deployed path is named once, in +`wizard-work/volt/CHECK-media-catalog`, which is a check entry point; nothing here +knows a host. Usage: python3 claims_check.py [--src PATH] [--art DIR] [--gate PATH] Exit: 0 every claim holds | 1 a claim is false | 2 could not grade @@ -49,10 +55,15 @@ def main(): import argparse ap = argparse.ArgumentParser() - ap.add_argument("--src", default="/root/stackchain_catalog_raw.json") + ap.add_argument("--src", default=None, + help="catalog JSON to grade (falls back to $MEDIA_CATALOG_SRC)") ap.add_argument("--art", default=ART_DEFAULT) ap.add_argument("--gate", default=GATE_DEFAULT) args = ap.parse_args() + args.src = args.src or os.environ.get("MEDIA_CATALOG_SRC") + if not args.src: + print("could not grade: no source named -- pass --src PATH or set MEDIA_CATALOG_SRC.") + return 2 try: raw = open(args.src, "rb").read() diff --git a/wizard-work/volt/2026-10-22-media-catalog-verify/semantic_gate.py b/wizard-work/volt/2026-10-22-media-catalog-verify/semantic_gate.py index 3793be9..4f11bc1 100644 --- a/wizard-work/volt/2026-10-22-media-catalog-verify/semantic_gate.py +++ b/wizard-work/volt/2026-10-22-media-catalog-verify/semantic_gate.py @@ -29,6 +29,11 @@ rules are not documented anywhere in it): Exit codes, matching tools/ convention: 0 clean, 1 ran and graded a fault, 2 could not grade (missing/unreadable input). + +The source is named by the caller (`--src PATH`, else `$MEDIA_CATALOG_SRC`); there is +no default path. It lives outside this repository, and a path typed in here would make +an unargumented run grade one host's copy from any checkout (Q69). The deployed path +is named once, in `wizard-work/volt/CHECK-media-catalog`. """ import argparse @@ -210,13 +215,18 @@ def grade(src_path, csv_path): def main(): ap = argparse.ArgumentParser(description="grade a media catalog's content against its source") - ap.add_argument("--src", default="/root/stackchain_catalog_raw.json") + ap.add_argument("--src", default=None, + help="catalog JSON to grade (falls back to $MEDIA_CATALOG_SRC)") ap.add_argument("--csv", default=os.path.join( os.path.dirname(os.path.abspath(__file__)), "media_catalog.csv")) ap.add_argument("--write-repaired", metavar="PATH", help="write a contract-conforming CSV here (proves the gate is satisfiable)") ap.add_argument("--truncate", type=int, default=110) args = ap.parse_args() + args.src = args.src or os.environ.get("MEDIA_CATALOG_SRC") + if not args.src: + print("could not grade: no source named -- pass --src PATH or set MEDIA_CATALOG_SRC.") + return 2 if args.write_repaired: try: diff --git a/wizard-work/volt/CHECK-media-catalog b/wizard-work/volt/CHECK-media-catalog new file mode 100755 index 0000000..e391d2c --- /dev/null +++ b/wizard-work/volt/CHECK-media-catalog @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +# CHECK -- the media-catalog claims check (24 claims in REPORT.md, rc 0 = all hold). +# +# This file is the ONE place this lane names the catalog's path on the host: the +# source lives outside the repository, and Q69's defect is a path typed into a tool +# that then grades one host's copy from any checkout. The tools name no path; the +# pin lives here, in an entry point, and callers override it with $MEDIA_CATALOG_SRC. +# +# rc 0 every claim holds | rc 1 a claim is false | rc 2 could not grade +set -u + +ROOT="$(cd "$(dirname "$0")/../.." && pwd)" +SRC="${MEDIA_CATALOG_SRC:-/root/stackchain_catalog_raw.json}" + +if [ ! -f "$SRC" ]; then + echo "no catalog at $SRC; cannot grade (set MEDIA_CATALOG_SRC to name one)" >&2 + exit 2 +fi + +MEDIA_CATALOG_SRC="$SRC" exec python3 "$ROOT/wizard-work/volt/mcverify.py" diff --git a/wizard-work/volt/mcverify.py b/wizard-work/volt/mcverify.py index 3403069..eaec758 100644 --- a/wizard-work/volt/mcverify.py +++ b/wizard-work/volt/mcverify.py @@ -4,10 +4,16 @@ Exists only so the CHECK line stays under the Ralph log's 72-character wrap: it runs `2026-10-22-media-catalog-verify/claims_check.py` unchanged, from any cwd, and inherits its exit code (0 = every claim in REPORT.md still holds). + +It names no path of its own: the catalog it grades comes from `--src` or +`$MEDIA_CATALOG_SRC`, and with neither it refuses rc 2 rather than guessing +whose host to read (Q69). The deployed path lives in `CHECK-media-catalog` +beside this file, which is a check entry point. """ import os import runpy +import sys TARGET = os.path.join( os.path.dirname(os.path.abspath(__file__)), @@ -16,4 +22,9 @@ TARGET = os.path.join( ) if __name__ == "__main__": + if not (any(a == "--src" or a.startswith("--src=") for a in sys.argv[1:]) + or os.environ.get("MEDIA_CATALOG_SRC")): + print("could not grade: no source named -- pass --src PATH or set " + "MEDIA_CATALOG_SRC.") + sys.exit(2) runpy.run_path(TARGET, run_name="__main__") diff --git a/wizard-work/volt/q137-open-set/open_set.py b/wizard-work/volt/q137-open-set/open_set.py index ccdd938..2012473 100644 --- a/wizard-work/volt/q137-open-set/open_set.py +++ b/wizard-work/volt/q137-open-set/open_set.py @@ -661,7 +661,14 @@ PIN_OPENED = [51, 52, 53, 65, 100, 101, 102, 103, 104, 105, 106, 107, 109, # CHECK-q170 is its guard). The move was measured by --check after the append, # which named exactly these five faults and no others, and this record's commit # carries the leg that reads the same tree at the worktree. -PIN_COUNTS = {"headings": 121, "heading_ids": 104, "records": 132, +# Q69 addendum 4 (2026-11-05): the same shape as addendum 3 -- a section heading +# (## Q69 addendum 4 ...) over a lead that says Q69 stays open, so no record and +# no id is scored: headings 121 -> 122 with heading_ids staying 104 (Q69 already +# carries a heading), and every record counter, ids and record_only unchanged: +# records 132, record_ids 98, ids 159, record_only 55, open 0, opened 26. +# Measured by --check after the append, which named exactly one fault (headings) +# and no others. +PIN_COUNTS = {"headings": 122, "heading_ids": 104, "records": 132, "record_ids": 98, "ids": 159, "open": 0, "opened": 26, "record_only": 55} diff --git a/wizard-work/volt/q69_catalogpin_check.sh b/wizard-work/volt/q69_catalogpin_check.sh new file mode 100755 index 0000000..825a021 --- /dev/null +++ b/wizard-work/volt/q69_catalogpin_check.sh @@ -0,0 +1,137 @@ +#!/usr/bin/env bash +# CHECK -- the Q69 repair of the media-catalog verifier pair's host pin. +# +# `claims_check.py:52` (before) and `semantic_gate.py:213` (before) each carried +# `--src` defaulting to `/root/stackchain_catalog_raw.json`. The Q69 defect: that +# file lives outside this repository, so an unargumented run graded one host's copy +# from any checkout, and a copy of the tree on a host without that path died on a +# path it was never told about. Both now take the subject from `--src` or +# `$MEDIA_CATALOG_SRC`, and refuse rc 2 when neither is given; the host path is +# named once, in `CHECK-media-catalog`, which is a check entry point. +# +# Five legs, each falsifiable on its own: +# text the three python files carry no host-absolute string literal +# census the AST census lists no row for either graded file (rows are mentions) +# refuse with no --src and no $MEDIA_CATALOG_SRC, all three entry points are +# rc 2 and the message names the variable +# derive a byte copy of the catalog at a path of THIS leg's choosing is graded +# (via --src, then via $MEDIA_CATALOG_SRC); one appended byte flips the +# same copy to rc 2 STALE, which proves the sha gate reads the named +# file and not a default; and a copy of the pre-fix tool, default +# restored, reads rc 0 with nothing named -- the negative control, +# because a leg that cannot reproduce the defect cannot report its end +# teeth the text leg's predicate fires on a copy carrying the literal back +# rc 0 clean, rc 1 a fault it graded, rc 2 it could not grade at all. +# +# Wall time: ~15 s -- `derive` and the control each run a whole claims check, +# which is where the media catalog's 24 claims are actually measured. +set -u + +ROOT="$(cd "$(dirname "$0")/../.." && pwd)" +LANE="wizard-work/volt" +MC="$LANE/2026-10-22-media-catalog-verify" +CENSUS="$LANE/q69_hostroot_census.py" +CLAIMS="$ROOT/$MC/claims_check.py" +GATE="$ROOT/$MC/semantic_gate.py" +RUN="$ROOT/$LANE/mcverify.py" +ENTRY="$ROOT/$LANE/CHECK-media-catalog" +SRC="/root/stackchain_catalog_raw.json" + +faults=0 +leg() { printf '%-7s %s\n' "$1" "$2"; } + +for f in "$CLAIMS" "$GATE" "$RUN" "$ENTRY" "$ROOT/$CENSUS" "$SRC"; do + if [ ! -f "$f" ]; then + echo "q69-catalog: missing $f; cannot grade" >&2 + exit 2 + fi +done + +TMP="$(mktemp -d "${TMPDIR:-/tmp}/q69-catalog.XXXXXX")" || exit 2 +trap 'rm -rf "$TMP"' EXIT + +# text -- no host-absolute literal survives in any of the three python files +hits=0 +for f in "$CLAIMS" "$GATE" "$RUN"; do + n="$(grep -c '"/\(root\|home\|var\|srv\|opt\|mnt\)/' "$f")" + hits=$((hits + n)) +done +if [ "$hits" -eq 0 ]; then + leg text "ok (0 host-absolute literal in 3 files)" +else + leg text "FAULT ($hits host-absolute literal)"; faults=$((faults + 1)) +fi + +# census -- the AST census names neither graded file +python3 "$ROOT/$CENSUS" --lane "$LANE" --json "$TMP/census.json" >"$TMP/census.out" 2>&1 +crc=$? +if [ "$crc" -eq 0 ]; then + rows="$(grep -c 'media-catalog' "$TMP/census.json")" + if [ "$rows" -eq 0 ]; then + leg census "ok (0 row names either media-catalog file)" + else + leg census "FAULT ($rows row(s) name a media-catalog file)"; faults=$((faults + 1)) + fi +else + leg census "FAULT (census rc $crc -- $(tail -1 "$TMP/census.out"))"; faults=$((faults + 1)) +fi + +# refuse -- no subject named is rc 2 with the way to name one, never a default +refused=0 +for f in "$CLAIMS" "$GATE" "$RUN"; do + rout="$(env -u MEDIA_CATALOG_SRC python3 "$f" 2>&1)"; rrc=$? + if [ "$rrc" -eq 2 ] && printf '%s\n' "$rout" | grep -q 'MEDIA_CATALOG_SRC'; then + refused=$((refused + 1)) + else + leg refuse "FAULT ($(basename "$f") rc $rrc: $(printf '%s\n' "$rout" | tail -1))" + faults=$((faults + 1)) + fi +done +if [ "$refused" -eq 3 ]; then + leg refuse "ok (3/3 rc 2, each message names MEDIA_CATALOG_SRC)" +fi + +# derive -- the subject is the file the caller names, proved by the sha gate +mkdir -p "$TMP/copy" +cp "$SRC" "$TMP/copy/catalog.json" || exit 2 +d_flag="$(env -u MEDIA_CATALOG_SRC python3 "$CLAIMS" --src "$TMP/copy/catalog.json" 2>&1)"; d_frc=$? +d_env="$(MEDIA_CATALOG_SRC="$TMP/copy/catalog.json" python3 "$CLAIMS" 2>&1)"; d_erc=$? +cp "$TMP/copy/catalog.json" "$TMP/copy/dirty.json" && printf ' ' >>"$TMP/copy/dirty.json" +d_st="$(env -u MEDIA_CATALOG_SRC python3 "$CLAIMS" --src "$TMP/copy/dirty.json" 2>&1)"; d_src=$? +sed 's|default=None,|default="'"$SRC"'",|' "$CLAIMS" >"$TMP/prefix.py" +# The control differs from the repaired tool in ONE line -- the --src default. It is +# given --art and --gate because the tool derives those from its own __file__, and the +# control is a copy in $TMP; without them the copy would fail on its own location and +# the leg would read as if the pre-fix behaviour were rc 1 rather than the rc 0 it is. +c_out="$(env -u MEDIA_CATALOG_SRC python3 "$TMP/prefix.py" \ + --art "$ROOT/wizard-work/ledger/2026-10-22-media-catalog" --gate "$GATE" 2>&1)"; c_rc=$? +named="$(printf '%s\n' "$d_flag" | grep -c '^24/24 claims hold')" +named_env="$(printf '%s\n' "$d_env" | grep -c '^24/24 claims hold')" +stale="$(printf '%s\n' "$d_st" | grep -c '^STALE: source sha256')" +control="$(printf '%s\n' "$c_out" | grep -c '^24/24 claims hold')" +d_copy_used="$(printf '%s\n' "$d_flag$d_env" | grep -c "$TMP/copy/catalog.json")" +if [ "$d_frc" -eq 0 ] && [ "$d_erc" -eq 0 ] && [ "$named" -eq 1 ] && [ "$named_env" -eq 1 ] \ + && [ "$d_src" -eq 2 ] && [ "$stale" -eq 1 ] \ + && [ "$c_rc" -eq 0 ] && [ "$control" -eq 1 ]; then + leg derive "ok (named: --src 0, env 0; +1 byte rc 2 STALE; pre-fix default rc 0 with nothing named)" +else + leg derive "FAULT (--src rc $d_frc 24/24=$named; env rc $d_erc 24/24=$named_env; dirty rc $d_src STALE=$stale; control rc $c_rc 24/24=$control; copy named in output=$d_copy_used)" + faults=$((faults + 1)) +fi + +# teeth -- the text leg's predicate is not one that cannot fire +cp "$CLAIMS" "$TMP/pinned.py" || exit 2 +printf 'DEFAULT_SRC = "%s"\n' "$SRC" >>"$TMP/pinned.py" +poison="$(grep -c '"/\(root\|home\|var\|srv\|opt\|mnt\)/' "$TMP/pinned.py")" +if [ "$poison" -ge 1 ]; then + leg teeth "ok (poisoned copy reads $poison, clean copy reads 0)" +else + leg teeth "FAULT (poisoned copy reads 0 -- the text leg cannot fail)"; faults=$((faults + 1)) +fi + +if [ "$faults" -eq 0 ]; then + echo "q69-catalog: 5 leg(s), 0 fault(s)" + exit 0 +fi +echo "q69-catalog: 5 leg(s), $faults fault(s)" +exit 1