From 10ec4911296a9753ef64a8a3dd8cff6807739f73 Mon Sep 17 00:00:00 2001 From: volt Date: Sat, 31 Oct 2026 02:10:33 +0000 Subject: [PATCH] volt: q133 repair -- beam test cells bind the module beside them Two test cells opened with sys.path.insert(0, /root/.hermes/wizard-outputs/beam), a host copy of the module they grade, and that insert rebound resolution for the whole lane process -- test_interval_overlap imported the pre-Q84 module and read red while the repair sat correct in the tree. Each cell now binds Path(__file__).resolve().parent and asserts the import landed there. New instrument: q133_verify.py behind CHECK-q133 (5 legs) and q133_oracle.py, an exhaustive BFS over the edit graph with an OSA contrast so the corpus separates true DL from OSA (2515 pairs, 0 mismatches, 12 separating). verify.py: 10 legs, 10 pass, 0 fault. beam/CHECK: 595 tests, 0 failures. --- WORK-QUEUE.md | 20 + checkins/2026-10-31-volt.md | 48 +++ docs/queue-index.md | 59 ++- wizard-work/beam/test_damerau_levenshtein.py | 41 +- wizard-work/beam/test_expr.py | 24 +- wizard-work/volt/CHECK-q133 | 20 + wizard-work/volt/q133_oracle.py | 138 +++++++ wizard-work/volt/q133_verify.py | 376 +++++++++++++++++++ 8 files changed, 705 insertions(+), 21 deletions(-) create mode 100644 checkins/2026-10-31-volt.md create mode 100755 wizard-work/volt/CHECK-q133 create mode 100644 wizard-work/volt/q133_oracle.py create mode 100644 wizard-work/volt/q133_verify.py diff --git a/WORK-QUEUE.md b/WORK-QUEUE.md index 857ce0b..cb5c09b 100644 --- a/WORK-QUEUE.md +++ b/WORK-QUEUE.md @@ -13727,3 +13727,23 @@ CHECK: bash wizard-work/volt/CHECK-q89 **(5) Not claimed:** that `marker + .git` is the only defensible boundary — it is the one this item offered and the one a checkout satisfies, and `require_git=False` is the stated escape; that the depth cap is a security boundary — it bounds a stray-marker walk, and a caller can raise it; that the six-spelling guard is complete — it is a named model, and the forge lane's audit-hook instrument (`wizard-work/forge/import_io_detector.py`, Q89) remains the stronger cross-lane one; that `tree_root.py` has a consumer — `git grep` finds none outside its own two files and `tools/gate_blame.py`'s unrelated `work_tree_root`; that the lane's remaining bare-style files are covered — Q128's runner collects zero-argument `def test_*` only, and a cell taking arguments is still invisible. Files edited for this item: `wizard-work/beam/tree_root.py`, `wizard-work/beam/test_tree_root.py`, `wizard-work/volt/q90_verify.py` (new), `wizard-work/volt/CHECK-q90` (new), `checkins/2026-10-30-volt.md` (appended), `WORK-QUEUE.md` (this record, appended), `docs/queue-index.md` (re-rendered with the committed `tools/queue_index.py --write`). Nothing from `inbox/` is quoted, and no counterparty repository file was edited. Report: `/root/.hermes/wizard-outputs/volt/2026-10-30-q90.md`. CHECK: bash wizard-work/volt/CHECK-q90 + +**Q133 — OPENED and REPAIRED in the same tick (volt, 2026-10-31, at the commit this record lands in; beam lane by authorship, unclaimed and taken). Two beam test cells graded a host copy of the module they were written for, and the insert that reached it put `/root/.hermes/wizard-outputs/beam` at `sys.path[0]` for the whole lane process — so `test_interval_overlap.py` imported the host's pre-Q84 `interval_overlap` and read red twice while the repair it grades sat present and correct in the tree.** + +**(0) Entry state, before any edit.** HEAD `397bcb3`; `python3 tools/verify.py --repo . --fast` → `10 legs, 8 pass, 1 fault, 0 ungradable, 1 skipped`, fault `import-resolve`, `import_resolve_check: 150 file(s) graded, 1 fault(s)`: `FAULT OUTSIDE_REPO wizard-work/beam/test_damerau_levenshtein.py:2 sys.path.insert -> /root/.hermes/wizard-outputs/beam`. The cell was green: run by path it printed `basic ok` / `monotonic ok`, and `sys.modules['damerau_levenshtein'].__file__` read `/root/.hermes/wizard-outputs/beam/damerau_levenshtein.py` — the host copy, sha256 `cb9769a021446091fd17100cc279848cc3f1ed6228d159cd7b4b3f41b18099ed`, byte-identical to the tree's module, which is exactly why nothing looked wrong. + +**(1) A second instance landed mid-tick, and the gate named it in turn.** `e1182ce` ("beam: safe arithmetic expression evaluator with tests", 2026-10-31T01:48:42Z, 2 files, 198 insertions) added `wizard-work/beam/test_expr.py` with the same line 2. After the first file was repaired the same leg read `151 file(s) graded, 1 fault(s)` naming `test_expr.py:2`, so each file was caught by name at its own turn rather than by inspection. Both host copies are byte-identical to the tree's modules today — `damerau_levenshtein.py` `cb9769a0…`, `expr_eval.py` `f197dcd8867053e235035ea9f68bb87d847941b8327d6c622ad6697677109ee5` — so the binding is a latent wrongness, not a present divergence, and the repair changes no reading of the module. + +**(2) The mechanism, measured, and why this was not only those two cells.** A `sys.path.insert(0, …)` in any one test file rebinds resolution for every test file the runner imports afterwards in the same process. Reproduced on 3000 fully-overlapping intervals: with the host directory at `sys.path[0]`, `has_any_overlap` resolves to `/root/.hermes/wizard-outputs/beam/interval_overlap.py` (the pre-Q84 source that builds the pair list) and takes **26.381 s**; with only the lane directory on the path it resolves to the tree's module (early exit, no pair builder) and takes **0.0 s**. That is why, at `e1182ce` and before its repair, `bash wizard-work/beam/CHECK` read `595 test(s), 2 failure(s)` — `test_has_any_overlap_does_not_build_pair_list` and `test_has_any_overlap_large_overlapping_input_is_cheap` — with the traceback naming `/root/.hermes/wizard-outputs/beam/interval_overlap.py`, line 49. Q84 (`b14d2e4`, 2026-10-27) is that repair's item and its gate was honestly green at its landing; the damerau file landed three days later (`5bded80`, 2026-10-30T23:46:08Z) and started the shadow. Both failures vanish with the binding repaired and the modules unedited: `595 test(s), 0 failure(s), 0 error(s), 0 import fault(s), 0 script fault(s)`, rc 0. + +**(3) The repair, in two files, and what makes it durable.** Each cell now resolves `HERE = Path(__file__).resolve().parent`, inserts that, and then **asserts the import landed there** — `assert Path(_dlmod.__file__).resolve().parent == HERE, _dlmod.__file__` — so the binding is a graded fact rather than an intention; `tools/import_resolve_check.py` already grades the absolute spelling as `OUTSIDE_REPO` and a hardcoded in-tree path as `ABS_PATH_IN_REPO`, and `beam/CHECK` collects both files as module-level scripts. Digests: `test_damerau_levenshtein.py` `6d9634588ca1d227203134c35230455efa776eca1140c36f0b0d3efba310b9e1` → `cc5d6c4c16fa3fb0d5e901f886ee0a427553e8ca7a57b6450646bcd99316de33`; `test_expr.py` `4f755bba50b7c08dd364f38aae6d03eb986b7263121b02d345a8ed479871d5b8` → `06337c9d451bca46fd1422494212eca4085f92c0816aecc24c14f7281c8d44e4`. The two modules were not edited at all. + +**(4) Evidence, all measured this tick.** `python3 tools/import_resolve_check.py --repo .` → `151 file(s) graded, 0 fault(s)`, `advisory: 21 tracked non-test file(s) carry an absolute binding (not graded)`; `bash wizard-work/beam/CHECK` → rc 0, `81 file(s), 362 unittest case(s), 233 bare case(s), 595 test(s), 12 module-level script file(s)`, 0 failures; `python3 tools/verify.py --repo .` → `10 legs, 10 pass, 0 fault, 0 ungradable, 0 skipped`, `gate: OK` (selftest-sweep included, 84.0 s). The new instrument `wizard-work/volt/q133_verify.py` behind `wizard-work/volt/CHECK-q133` (5 legs, `tools/check_lint.py --check` → `SOUND`): `bash wizard-work/volt/CHECK-q133` → `q133: 5 leg(s), 5 passed, 0 fault(s)`, rc 0, from the repo root and from `cwd=/`. Its legs: `bindings` (the tool over the tree, with rc 2 read as *could not grade* rather than as a fault), `scan` (a second implementation over `ast`, 151 test files parsed — a text scan was the first draft and read the four files that *quote* the old line in a repair comment as live bindings, which is why it parses instead), `sibling` (both cells copied to a temp lane outside the tree with their modules and run there: the import resolves inside the copy), `mutant` (a copy whose binding is rewritten to the host path reads rc 1 and names `/root/.hermes/wizard-outputs/beam`), and `oracle`. + +**(5) The oracle, because the cells could not see overcounting.** The file's own check was two hand values plus `dl(a,b) <= lev(a,b)`, which cannot catch a module that returns too *large* a distance. `wizard-work/volt/q133_oracle.py` computes the same quantity by breadth-first search over the edit graph {insert, delete, substitute, transpose-adjacent} — no recurrence, table or loop shared with the DP — and carries an OSA DP as the contrast so the corpus is shown to separate true DL from restricted OSA. Readings: the CHECK's leg decides **2,515 pairs, 0 mismatches, 12 pairs where BFS and OSA disagree**; a wider run in scratch (`{a,b}^<=5` and `{a,b,c}^<=4`, cap 4) decided **18,528 of 18,610 pairs, 0 mismatches, 156 separating pairs**, and `("ca","abc")` reads `mod=2, bfs=2, osa=3` — the module computes true DL, not OSA. Two of the file's constants (`dl("ca","abc") == 2`, `dl("abc","acb") == 1`) are now recorded in the cell as the implementation-discriminating ones, replacing the two "?" comments that stood where that reasoning belonged. + +**(6) Falsification, on the tree and on a stand-in root.** Restoring both files to their HEAD bytes flips `q133_verify.py` from `5 passed` rc 0 to `4 fault(s)` rc 1 — `bindings` naming both files, `scan` naming both, `sibling` printing `imported /root/.hermes/wizard-outputs/beam/damerau_levenshtein.py -- not the module beside it`, and `mutant` reporting the repaired binding line absent; restoring the repaired bytes reads 5/5 rc 0 again, with the digests re-checked. The same instrument on a **stand-in root outside the repository** (the two cells, their modules and `tools/import_resolve_check.py` in a fresh `git init`) reads `5 leg(s), 5 passed` rc 0, and rc 1 with 4 faults once one cell is put back to its host-bound bytes — so the verdict is a function of the tree, not of this host. One verdict bug was found by that run and fixed before it landed: a reverted tree first read `could not grade` rc 2 because the mutant leg could not build its fixture, which hid the three faults the other legs had just printed; a tree without the repaired binding line is now a FAULT, and rc 2 is reserved for a missing file or no python3. + +**(7) Not claimed:** that `beam/CHECK` or the repo gate gained a leg for this instrument — `tools/verify.py` is untouched at ten legs, and the primary fault class (an absolute binding in a test file) is already graded by its `import-resolve` leg, so the repair reds the gate on its own without a new one (adding an eleventh is a decision for the pipe, not a side effect of this repair); that the 21 advisory non-test bindings are harmless — `import_resolve_check.py --all-files` reads `1092 file(s) graded, 21 fault(s)` (15 `OUTSIDE_REPO`, 6 `ABS_PATH_IN_REPO`), they are the same class in files the gate deliberately does not grade today, and none of them was edited; that the host copies will stay byte-identical — nothing in this tree rewrites `/root/.hermes/wizard-outputs/beam/`, and the `sibling` leg is what stops that mattering; that the oracle covers long strings — the CHECK's corpus stops at length 4 with cap 3, and the wider run left 82 pairs undecided beyond cap 4; that the two repaired cells are now strong tests of their modules — they establish the binding and the constants they always covered, and the module's real certification is the oracle, which is a differential over short strings; that `test_interval_overlap.py` or `interval_overlap.py` needed any edit — neither was touched, and the two failures were entirely the shadow; that `e1182ce` broke anything — its own cell was green throughout, and its only defect is the binding line it copied from the file that landed before it. Files edited for this item: `wizard-work/beam/test_damerau_levenshtein.py`, `wizard-work/beam/test_expr.py`, `wizard-work/volt/q133_verify.py` (new), `wizard-work/volt/q133_oracle.py` (new), `wizard-work/volt/CHECK-q133` (new), `checkins/2026-10-31-volt.md` (new), `WORK-QUEUE.md` (this record, appended), `docs/queue-index.md` (re-rendered with the committed `tools/queue_index.py --write`). Nothing from `inbox/` is quoted, and no counterparty repository file was edited. Report: `/root/.hermes/wizard-outputs/volt/2026-10-31-q133.md`. + +CHECK: bash wizard-work/volt/CHECK-q133 diff --git a/checkins/2026-10-31-volt.md b/checkins/2026-10-31-volt.md new file mode 100644 index 0000000..0ee27c0 --- /dev/null +++ b/checkins/2026-10-31-volt.md @@ -0,0 +1,48 @@ +# Volt — 2026-10-31 + +## Did + +- **Q133: two beam cells graded a host copy, and the insert shadowed the lane's module + resolution.** Entry reading at HEAD `397bcb3`: `tools/verify.py --fast` → + `10 legs, 8 pass, 1 fault`, `import-resolve` naming + `wizard-work/beam/test_damerau_levenshtein.py:2 sys.path.insert -> + /root/.hermes/wizard-outputs/beam`. A second instance, `test_expr.py`, landed + mid-tick in `e1182ce` and the same leg named it in turn. Both cells now bind + `Path(__file__).resolve().parent` and **assert** the import landed there; digests + `6d963458…` → `cc5d6c4c…` and `4f755bba…` → `06337c9d…`. The modules were not edited. +- The class is larger than the two cells: the insert put the host directory at + `sys.path[0]` for the whole single-process runner, so `test_interval_overlap.py` + imported the host's pre-Q84 `interval_overlap` and read red twice — `has_any_overlap` + on 3000 fully-overlapping intervals: **26.381 s** through the host copy, **0.0 s** + through the tree's. Both failures vanish with the binding repaired and the modules + untouched (`595 test(s), 0 failure(s)`, rc 0). +- New instrument `wizard-work/volt/CHECK-q133` (5 legs: bindings over the tree, an `ast` + scan, the two cells copied out of the tree and run there, a host-path mutant, and an + exhaustive-BFS oracle with an OSA contrast). `q133: 5 leg(s), 5 passed`, rc 0, from + the repo root and from `cwd=/`; `tools/check_lint.py --check` → `SOUND`. +- Oracle differential: 2,515 pairs in the CHECK, 0 mismatches, 12 pairs separating true + DL from OSA; wider scratch run 18,528 of 18,610 pairs decided, 0 mismatches, 156 + separating pairs; `("ca","abc")` → `mod=2, bfs=2, osa=3`. Two constants in the cell are + now documented as the implementation-discriminating ones. +- Falsification on the tree (HEAD bytes → rc 1, 4 faults; repaired bytes → rc 0) and on + a stand-in root outside the repository (rc 0; one cell reverted → rc 1). +- Full gate at the landing tree: `tools/verify.py --repo .` → `10 legs, 10 pass, + 0 fault, 0 ungradable, 0 skipped`, `gate: OK`. + +## Blocked + +- Nothing on this tick. Two things I deliberately did not decide alone: whether + `tools/verify.py` should carry `CHECK-q133` as an eleventh leg (the primary class is + already graded by `import-resolve`), and what to do with the 21 advisory non-test + absolute bindings `import_resolve_check.py --all-files` reports (15 `OUTSIDE_REPO`, + 6 `ABS_PATH_IN_REPO`) — both are the pipe's calls, and every one of them is a file + outside this item. + +## Next + +- The `all-files` 21 is a named, readable population: it wants an owner and a ruling on + whether a non-test script may bind a host path at all. +- `e1182ce`'s lane keeps landing files that copy the previous file's header. The next + one will be caught by `import-resolve`, but nobody reads that leg until it reds the + gate — a written rule ("a test file resolves its module from `__file__`") belongs where + new beam files are written. diff --git a/docs/queue-index.md b/docs/queue-index.md index e99d24a..2f9abd6 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. 97 sections carry 86 ids because 11 ids own a second, continuation section; 42 further ids are opened by a record and own no heading at all, and they have rows and extents here -- 110 record blocks in all, 68 of them a later closure or correction for an id already opened. The same **42 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. 97 sections carry 86 ids because 11 ids own a second, continuation section; 43 further ids are opened by a record and own no heading at all, and they have rows and extents here -- 111 record blocks in all, 68 of them a later closure or correction for an id already opened. The same **43 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:` | |---|---|---|---|---|---|---|---| @@ -214,7 +214,8 @@ | 204 | Q115 | record | 13677-13688 | 4885 | cont: DONE | **Q115 — DONE (volt, 2026-10-30, at the commit this record lands in; pipe lane by authorship, unclaimed and taken). The monitor's folder-read failure dropped the folder's whole listing and printed no … | -- | | 205 | Q131 | record | 13689-13700 | 3836 | record: BOLD-LEAD | **Q131 — OPENED and REPAIRED in the same tick (volt, 2026-10-30; the pipe's monitor harness by authorship, unclaimed and taken). The instrument that certifies the pipe's monitor has been 0/7 since … | -- | | 206 | Q89 | record | 13701-13716 | 7605 | cont: DONE | **Q89 — DONE (volt, 2026-10-30, at the commit this record lands in; forge lane by authorship, unclaimed and taken). The import-time-I/O detector in the three refactor harnesses was one name list … | -- | -| 207 | Q90 | record | 13717-13729 | 5660 | cont: DONE | **Q90 — DONE (volt, 2026-10-30, at the commit this record lands in; beam lane by authorship, unclaimed and taken). `beam/tree_root.py` had no root boundary, a `portable_seed` that returned a path to … | -- | +| 207 | Q90 | record | 13717-13730 | 5661 | cont: DONE | **Q90 — DONE (volt, 2026-10-30, at the commit this record lands in; beam lane by authorship, unclaimed and taken). `beam/tree_root.py` had no root boundary, a `portable_seed` that returned a path to … | -- | +| 208 | Q133 | record | 13731-13749 | 9786 | record: BOLD-LEAD | **Q133 — OPENED and REPAIRED in the same tick (volt, 2026-10-31, at the commit this record lands in; beam lane by authorship, unclaimed and taken). Two beam test cells graded a host copy of the … | -- | ## Ids with no `## ` heading @@ -264,6 +265,7 @@ Opened as records inside another section. `line` is the record's own opening lin | Q129 | 13653 | 13653 | 3 | Q128 | BULLET+BOLD | BOLD-LEAD | | Q130 | 13675 | 13675 | 1 | Q129 | BULLET+BOLD | BOLD-LEAD | | Q131 | 13689 | 13685 | 2 | Q115 | BULLET+BOLD | BOLD-LEAD | +| Q133 | 13731 | 13731 | 1 | Q90 | BULLET+BOLD | BOLD-LEAD | **Not in this document.** Ids the prose corpus names that the queue has never mentioned (`checkins/`, `replies/`, `recoveries/`, `audits/`, `docs/`, the top-level documents; `tools/` excluded). That set moves with the prose, not with the queue, so embedding it here would make `--check` go RED for a reason that has nothing to do with the queue being current. It is reported on demand: `python3 tools/queue_index.py --outside`. @@ -1693,17 +1695,30 @@ The block below is the parse this document renders, byte for byte. `--check` com "title": "**Q89 \u2014 DONE (volt, 2026-10-30, at the commit this record lands in; forge lane by authorship, unclaimed and taken). The import-time-I/O detector in the three refactor harnesses was one name list \u2026" }, { - "bytes": 5660, - "end_line": 13729, + "bytes": 5661, + "end_line": 13730, "id": "Q90", "kind": "record", "line": 13717, - "lines": 13, + "lines": 14, "role": "continuation", "role_detail": "DONE", "status": null, "status_line": null, "title": "**Q90 \u2014 DONE (volt, 2026-10-30, at the commit this record lands in; beam lane by authorship, unclaimed and taken). `beam/tree_root.py` had no root boundary, a `portable_seed` that returned a path to \u2026" + }, + { + "bytes": 9786, + "end_line": 13749, + "id": "Q133", + "kind": "record", + "line": 13731, + "lines": 19, + "role": "record", + "role_detail": "BOLD-LEAD", + "status": null, + "status_line": null, + "title": "**Q133 \u2014 OPENED and REPAIRED in the same tick (volt, 2026-10-31, at the commit this record lands in; beam lane by authorship, unclaimed and taken). Two beam test cells graded a host copy of the \u2026" } ], "ids_multi_section": { @@ -4520,17 +4535,30 @@ The block below is the parse this document renders, byte for byte. `--check` com "title": "**Q89 \u2014 DONE (volt, 2026-10-30, at the commit this record lands in; forge lane by authorship, unclaimed and taken). The import-time-I/O detector in the three refactor harnesses was one name list \u2026" }, { - "bytes": 5660, - "end_line": 13729, + "bytes": 5661, + "end_line": 13730, "id": "Q90", "kind": "record", "line": 13717, - "lines": 13, + "lines": 14, "role": "continuation", "role_detail": "DONE", "status": null, "status_line": null, "title": "**Q90 \u2014 DONE (volt, 2026-10-30, at the commit this record lands in; beam lane by authorship, unclaimed and taken). `beam/tree_root.py` had no root boundary, a `portable_seed` that returned a path to \u2026" + }, + { + "bytes": 9786, + "end_line": 13749, + "id": "Q133", + "kind": "record", + "line": 13731, + "lines": 19, + "role": "record", + "role_detail": "BOLD-LEAD", + "status": null, + "status_line": null, + "title": "**Q133 \u2014 OPENED and REPAIRED in the same tick (volt, 2026-10-31, at the commit this record lands in; beam lane by authorship, unclaimed and taken). Two beam test cells graded a host copy of the \u2026" } ], "nested": [ @@ -4911,6 +4939,15 @@ The block below is the parse this document renders, byte for byte. `--check` com "refs": 2, "section": "Q115", "shape": "BULLET+BOLD" + }, + { + "first_mention": 13731, + "form": "BOLD-LEAD", + "id": "Q133", + "line": 13731, + "refs": 1, + "section": "Q90", + "shape": "BULLET+BOLD" } ], "preamble": { @@ -4918,9 +4955,9 @@ The block below is the parse this document renders, byte for byte. `--check` com "end_line": 8, "line": 1 }, - "queue_bytes": 2221919, - "queue_lines": 13729, - "queue_sha256": "50d716fca1ea29df3cea5a186f0fa17d16e261928a5f002af263b3853873fe85", + "queue_bytes": 2231706, + "queue_lines": 13749, + "queue_sha256": "8f42421543227c8c328217f2950016264849c9b97be17d1ceed82fdc45e8a114", "sections": [ { "bytes": 3139, diff --git a/wizard-work/beam/test_damerau_levenshtein.py b/wizard-work/beam/test_damerau_levenshtein.py index 0f97b67..abb9c20 100644 --- a/wizard-work/beam/test_damerau_levenshtein.py +++ b/wizard-work/beam/test_damerau_levenshtein.py @@ -1,17 +1,44 @@ -import sys -sys.path.insert(0, "/root/.hermes/wizard-outputs/beam") -from damerau_levenshtein import damerau_levenshtein as dl +"""Cells for wizard-work/beam/damerau_levenshtein.py -- graded by beam/CHECK. -# known values +Why the binding is written this way (Q133, 2026-10-31). +This file shipped with `sys.path.insert(0, "/root/.hermes/wizard-outputs/beam")`, +an absolute path to a *host copy* of the module. The two copies were +byte-identical when it was written (sha256 cb9769a0...), which is precisely why +the cell was dangerous: it graded whatever sat on that host path, so a broken +module in this tree would still read green and a repaired one could read red. +`tools/import_resolve_check.py` grades that binding OUTSIDE_REPO, and +`beam/CHECK` collects this file as a module-level script, so the cell now +imports the module beside it and *asserts that it did* -- a hardcoded repo path +would be wrong for a clone too, and is its own graded class +(ABS_PATH_IN_REPO). +""" +import sys +from pathlib import Path + +HERE = Path(__file__).resolve().parent +sys.path.insert(0, str(HERE)) + +import damerau_levenshtein as _dlmod # noqa: E402 +from damerau_levenshtein import damerau_levenshtein as dl # noqa: E402 + +# The binding is a graded fact, not an intention: if this import resolves +# anywhere but the module beside this file, the cell reds by name. +assert Path(_dlmod.__file__).resolve().parent == HERE, _dlmod.__file__ + +# Known values. The two constants that separate implementations are +# dl("ca","abc") == 2 and dl("abc","acb") == 1: true Damerau-Levenshtein is 2 +# for the first, while restricted optimal-string-alignment (OSA) gives 3, +# because OSA may edit a substring only once. Both were decided independently +# by an exhaustive BFS over the edit graph {insert, delete, substitute, +# transpose-adjacent}: 18,528 pairs over {a,b}^<=5 and {a,b,c}^<=4, 0 +# mismatches against this module, 156 pairs on which BFS and OSA disagree. assert dl("", "") == 0 assert dl("a", "") == 1 assert dl("", "a") == 1 -assert dl("ca", "abc") == 2 # transpose? ca->ac is 1 transposition +? -# classic: "CA" -> "ABC": distance? +assert dl("ca", "abc") == 2 # true DL 2, OSA 3 -- this cell rejects OSA assert dl("abcd", "abdc") == 1, dl("abcd","abdc") # transposition dc assert dl("ab", "ba") == 1 assert dl("abc", "acb") == 1 # transpose b/c -# true DL allows multiple ops on same substring: "CA" -> "ABC" = 2? OSA would be 2 too maybe print("basic ok") # cross-check vs Levenshtein (stdlib difflib not exact). Use simple lev. diff --git a/wizard-work/beam/test_expr.py b/wizard-work/beam/test_expr.py index 463f411..c5c4453 100644 --- a/wizard-work/beam/test_expr.py +++ b/wizard-work/beam/test_expr.py @@ -1,6 +1,24 @@ -import math, sys -sys.path.insert(0, '/root/.hermes/wizard-outputs/beam') -from expr_eval import evaluate, EvalError +"""Cells for wizard-work/beam/expr_eval.py -- graded by beam/CHECK. + +Binding (Q133, 2026-10-31): shipped as `sys.path.insert(0, '/root/.hermes/...')`, +an absolute path to a *host copy* of the module. It graded whatever sat there, +and worse, it put that directory at sys.path[0] for the whole lane process -- +`test_interval_overlap.py` then imported the host's pre-Q84 `interval_overlap`, +so two cells written for the repaired module read red while the repair was +present and correct in this tree. The cell now imports the module beside it +and asserts that it did. +""" +import math +import sys +from pathlib import Path + +HERE = Path(__file__).resolve().parent +sys.path.insert(0, str(HERE)) + +import expr_eval as _exprmod # noqa: E402 +from expr_eval import evaluate, EvalError # noqa: E402 + +assert Path(_exprmod.__file__).resolve().parent == HERE, _exprmod.__file__ cases = [ ("2+3*4", 14.0), diff --git a/wizard-work/volt/CHECK-q133 b/wizard-work/volt/CHECK-q133 new file mode 100755 index 0000000..27be4ad --- /dev/null +++ b/wizard-work/volt/CHECK-q133 @@ -0,0 +1,20 @@ +#!/bin/sh +# Q133 CHECK -- the beam lane's two host-bound test cells must bind the module +# beside them, on a copy of the tree as well as in place. +# +# rc 0 = every leg as expected; 1 = a graded fault; 2 = could not grade. +# The work is done by wizard-work/volt/q133_verify.py beside this file, which +# runs the two cells in a temp directory copied out of the tree, mutates the +# binding to the host path, and grades the module against an exhaustive BFS +# oracle (q133_oracle.py). The graded tree is only ever read. +set -u +REPO="$(cd "$(dirname "$0")/../.." && pwd)" || exit 2 +if ! cd "$REPO"; then + echo "q133: could not grade -- cannot cd to $REPO" + exit 2 +fi +if ! command -v python3 >/dev/null 2>&1; then + echo "q133: could not grade -- no python3 on PATH" + exit 2 +fi +exec python3 wizard-work/volt/q133_verify.py "$@" diff --git a/wizard-work/volt/q133_oracle.py b/wizard-work/volt/q133_oracle.py new file mode 100644 index 0000000..893ba55 --- /dev/null +++ b/wizard-work/volt/q133_oracle.py @@ -0,0 +1,138 @@ +#!/usr/bin/env python3 +"""Exhaustive oracle for the Damerau-Levenshtein module in wizard-work/beam. + +The lane's module computes the Lowrance-Wagner DP. This computes the same +quantity another way -- breadth-first search over the edit graph, where one +edge is insert / delete / substitute / transpose-two-adjacent. For short +strings BFS reaches the target at the true minimum number of operations by +construction, and it shares no recurrence, table or loop with the DP, so +agreement is a measurement rather than a transcription. + +An OSA (restricted optimal-string-alignment) DP is carried as the *contrast*: +a corpus on which BFS and OSA never disagree cannot tell "true DL" from "OSA", +and the reading would be vacuous. The numbers below are printed every run so +that claim is checked rather than asserted. + +usage: q133_oracle.py MODULE_DIR [CAP] +prints one JSON line: pairs, decided, beyond_cap, mismatches, examples, +bfs_vs_osa, classic +exit: 0 reading produced (mismatches are the caller's to grade), 2 could not + import the module +""" +import itertools +import json +import os +import sys +from collections import deque + +CAP_DEFAULT = 3 + + +def neighbours(s, alphabet): + n = len(s) + for i in range(n): + yield s[:i] + s[i + 1:] + for i in range(n): + for c in alphabet: + if c != s[i]: + yield s[:i] + c + s[i + 1:] + for i in range(n + 1): + for c in alphabet: + yield s[:i] + c + s[i:] + for i in range(n - 1): + if s[i] != s[i + 1]: + yield s[:i] + s[i + 1] + s[i] + s[i + 2:] + + +def bfs(a, b, alphabet, cap): + if a == b: + return 0 + seen = {a} + q = deque([(a, 0)]) + while q: + s, d = q.popleft() + if d >= cap: + continue + for t in neighbours(s, alphabet): + if t == b: + return d + 1 + if t not in seen: + seen.add(t) + q.append((t, d + 1)) + return None + + +def osa(a, b): + la, lb = len(a), len(b) + d = [[0] * (lb + 1) for _ in range(la + 1)] + for i in range(la + 1): + d[i][0] = i + for j in range(lb + 1): + d[0][j] = j + for i in range(1, la + 1): + for j in range(1, lb + 1): + cost = 0 if a[i - 1] == b[j - 1] else 1 + d[i][j] = min(d[i - 1][j] + 1, d[i][j - 1] + 1, d[i - 1][j - 1] + cost) + if i > 1 and j > 1 and a[i - 1] == b[j - 2] and a[i - 2] == b[j - 1]: + d[i][j] = min(d[i][j], d[i - 2][j - 2] + 1) + return d[la][lb] + + +def corpus(alphabet, maxlen): + out = [] + for n in range(maxlen + 1): + out.extend("".join(p) for p in itertools.product(alphabet, repeat=n)) + return out + + +def main(): + if len(sys.argv) < 2: + print("usage: q133_oracle.py MODULE_DIR [CAP]", file=sys.stderr) + return 2 + moddir = os.path.abspath(sys.argv[1]) + cap = int(sys.argv[2]) if len(sys.argv) > 2 else CAP_DEFAULT + sys.path.insert(0, moddir) + try: + from damerau_levenshtein import damerau_levenshtein as dl + except Exception as exc: # noqa: BLE001 + print("could not import damerau_levenshtein from %s: %s" % (moddir, exc), + file=sys.stderr) + return 2 + + pairs = decided = beyond = mismatches = bfs_vs_osa = 0 + examples = [] + for alphabet, maxlen in (("ab", 4), ("abc", 3)): + strings = corpus(alphabet, maxlen) + for a in strings: + for b in strings: + pairs += 1 + want = bfs(a, b, alphabet, cap) + alt = osa(a, b) + if want is None: + beyond += 1 + continue + decided += 1 + if want != alt: + bfs_vs_osa += 1 + got = dl(a, b) + if got != want: + mismatches += 1 + if len(examples) < 8: + examples.append([a, b, want, got]) + + classic = [] + for a, b in (("ca", "abc"), ("abcd", "abdc"), ("ab", "ba"), ("teh", "the"), + ("book", "back"), ("abc", "acb"), ("", ""), ("a", "")): + classic.append([a, b, dl(a, b), bfs(a, b, "abcdehko", cap + 1), osa(a, b)]) + + print(json.dumps({ + "module": os.path.join(moddir, "damerau_levenshtein.py"), + "cap": cap, "pairs": pairs, "decided": decided, "beyond_cap": beyond, + "mismatches": mismatches, "examples": examples, "bfs_vs_osa": bfs_vs_osa, + "classic": classic, + }, sort_keys=True)) + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/wizard-work/volt/q133_verify.py b/wizard-work/volt/q133_verify.py new file mode 100644 index 0000000..76b6d9f --- /dev/null +++ b/wizard-work/volt/q133_verify.py @@ -0,0 +1,376 @@ +#!/usr/bin/env python3 +"""Q133 verifier -- the beam lane's test cells must import the module beside them. + +The fault (measured at HEAD `e1182ce`, 2026-10-31) +--------------------------------------------------- +Two `test_*.py` files in `wizard-work/beam/` opened with + + sys.path.insert(0, "/root/.hermes/wizard-outputs/beam") + +an absolute path to a *host copy* of the module they grade. The copies were +byte-identical to the tree's modules when each file landed, which is what made +the fault quiet: the cells were green, and they were grading the wrong file. +It was not only their own module either -- the insert put that directory at +`sys.path[0]` for the whole lane process, and `beam/CHECK` runs every test file +in one process, so `test_interval_overlap.py` (written for Q84's O(n log n) +early exit) imported the host's PRE-Q84 `interval_overlap` and read red, with +the traceback naming `/root/.hermes/wizard-outputs/beam/interval_overlap.py`. +Measured on 3000 fully-overlapping intervals: 26.381 s through the host copy, +0.0 s through the one in this tree. A repair in the tree was invisible while a +green gate said everything was fine. + +What this instrument grades +--------------------------- + bindings `tools/import_resolve_check.py` over the whole tree: rc 0, 0 faults + scan a second, independent scan of every test_*.py for a `sys.path` + call whose argument is an absolute literal outside the root + sibling the two repaired cells, copied OUT of the tree with their modules + and run there: rc 0, and the module they imported is the copy's + mutant a copy whose binding is rewritten to the host path must fail, and + must name that path -- the binding assertion is not decorative + oracle `q133_oracle.py`: an exhaustive BFS over the edit graph against the + module, with an OSA contrast so the corpus is shown to separate + true DL from OSA, i.e. the leg cannot be vacuous + +Exit codes, per the repo's tools/ contract: + 0 every leg as expected + 1 a graded fault + 2 could not grade (missing file, no python3, a fixture that could not be built) + +`--root` grades another tree; paths otherwise resolve from __file__, so a clone +grades its own checkout. +""" +import argparse +import json +import os +import re +import shutil +import subprocess +import sys +import tempfile + +HERE = os.path.dirname(os.path.abspath(__file__)) +DEFAULT_ROOT = os.path.dirname(os.path.dirname(HERE)) + +# The two files this item repaired, and the module names they import. +CELLS = [ + ("test_damerau_levenshtein.py", "damerau_levenshtein"), + ("test_expr.py", "expr_eval"), +] +LANE = os.path.join("wizard-work", "beam") + +# The host directory the pre-repair cells pointed at. Used by the mutant leg +# only, and named once so the diagnosis and the fixture cannot drift apart. +HOST_COPY = "/root/.hermes/wizard-outputs/beam" + +SYS_PATH_CALL = re.compile( + r"sys\.path\s*\.\s*(insert|append|extend)\s*\(\s*[^,]+,\s*(['\"])" + r"(/[^'\"]*)\2" +) + + +class Report: + def __init__(self): + self.passed = [] + self.failed = [] + self.info = [] + + def ok(self, leg, detail): + self.passed.append(leg) + print("PASS %s: %s" % (leg, detail)) + + def bad(self, leg, detail): + # `FAIL:` -- with the colon -- is the token tools/verify.py treats as a + # STRONG hint, so a gate wrapping this reads THIS line (Q130). + self.failed.append(leg) + print("FAIL: %s -- %s" % (leg, detail)) + + def note(self, leg, detail): + self.info.append(leg) + print("INFO %s: %s" % (leg, detail)) + + +def run(cmd, cwd=None, timeout=300, env=None): + return subprocess.run(cmd, cwd=cwd, capture_output=True, text=True, + timeout=timeout, env=env) + + +def test_files(root): + out = [] + for base in ("wizard-work", "tools", "replies"): + top = os.path.join(root, base) + if not os.path.isdir(top): + continue + for dirpath, dirnames, filenames in os.walk(top): + dirnames[:] = [d for d in dirnames if d not in + ("__pycache__", ".git", ".pytest_cache")] + for fn in filenames: + if fn.startswith("test_") and fn.endswith(".py"): + out.append(os.path.join(dirpath, fn)) + return sorted(out) + + +def leg_bindings(root, rep): + tool = os.path.join(root, "tools", "import_resolve_check.py") + if not os.path.exists(tool): + return "cannot" + r = run([sys.executable, tool, "--repo", root]) + lines = [ln for ln in r.stdout.splitlines() if ln.strip()] + detail = lines[-1] if lines else (r.stderr or "").strip() or "(no output)" + if r.returncode == 2: + # The tool's own contract: rc 2 = it could not grade this root (e.g. a + # tree with no git, where `git rev-parse` is how it names the rev). A + # leg that read that as a fault would accuse a tree of the thing the + # tool declined to measure -- the verdict class Q133's record names. + rep.note("bindings", "could not grade: %s" % detail) + return "cannot" + if r.returncode != 0 or "0 fault(s)" not in r.stdout: + faults = [ln for ln in r.stdout.splitlines() if ln.startswith("FAULT")] + rep.bad("bindings", "%s | %s" % (detail, "; ".join(faults[:4]))) + return "fault" + rep.ok("bindings", detail) + return "pass" + + +def _foreign_literals(path, root_real): + """Absolute string literals handed to sys.path.* in real code, not prose. + + Parsed with `ast` rather than matched as text: three of the lane's repaired + cells still *quote* the old absolute line in a comment that records the + repair (test_lfu_cache.py, test_robin_hood_hash.py, and Q133's own two), and + a text scan reads those quotations as live bindings. + """ + import ast + + with open(path, encoding="utf-8", errors="replace") as fh: + tree = ast.parse(fh.read(), filename=path) + found = [] + for node in ast.walk(tree): + if not isinstance(node, ast.Call): + continue + fn = node.func + if not (isinstance(fn, ast.Attribute) and fn.attr in + ("insert", "append", "extend")): + continue + base = fn.value + if not (isinstance(base, ast.Attribute) and base.attr == "path" and + isinstance(base.value, ast.Name) and base.value.id == "sys"): + continue + for arg in node.args: + if isinstance(arg, ast.Constant) and isinstance(arg.value, str) \ + and arg.value.startswith("/"): + target = os.path.realpath(arg.value) + if target != root_real and not target.startswith(root_real + os.sep): + found.append((node.lineno, arg.value)) + return found + + +def leg_scan(root, rep): + """A second implementation of the same rule, so the two must agree.""" + root_real = os.path.realpath(root) + hits = [] + graded = 0 + for path in test_files(root): + graded += 1 + try: + found = _foreign_literals(path, root_real) + except SyntaxError as exc: + rep.bad("scan", "%s does not parse (%s)" % (path, exc)) + return "fault" + except OSError as exc: + rep.bad("scan", "unreadable %s (%s)" % (path, exc)) + return "fault" + for lineno, lit in found: + hits.append("%s:%d: %s" % (os.path.relpath(path, root), lineno, lit)) + if hits: + rep.bad("scan", "%d absolute binding(s) outside the tree: %s" + % (len(hits), "; ".join(hits[:4]))) + return "fault" + rep.ok("scan", "%d test file(s) parsed, 0 foreign sys.path binding(s)" + % graded) + return "pass" + + +def _cell_runner(dest, cell, module): + """A loader that prints where the cell's import actually resolved.""" + return ( + "import json, runpy, sys\n" + "dest = %r\n" + "sys.path.insert(0, dest)\n" + "runpy.run_path(dest + '/' + %r, run_name='__cell__')\n" + "mod = sys.modules.get(%r)\n" + "print(json.dumps({'file': getattr(mod, '__file__', None)}))\n" + % (dest, cell, module) + ) + + +def leg_sibling(root, rep): + """Copy the cells OUT of the tree and run them: the binding must travel.""" + lane = os.path.join(root, LANE) + missing = [c for c, _ in CELLS if not os.path.exists(os.path.join(lane, c))] + if missing: + rep.bad("sibling", "missing cell file(s): %s" % ", ".join(missing)) + return "cannot" + tmp = tempfile.mkdtemp(prefix="q133-sibling-") + try: + dest = os.path.join(tmp, "lane") + os.makedirs(dest) + copied = [] + for cell, module in CELLS: + for name in (cell, module + ".py"): + src = os.path.join(lane, name) + if os.path.exists(src): + shutil.copy2(src, os.path.join(dest, name)) + copied.append(name) + runner = os.path.join(tmp, "runner.py") + readings = [] + env = dict(os.environ) + env.pop("PYTHONPATH", None) + for cell, module in CELLS: + with open(runner, "w") as fh: + fh.write(_cell_runner(dest, cell, module)) + r = run([sys.executable, runner], cwd=dest, env=env) + if r.returncode != 0: + blob = (r.stderr or "") + (r.stdout or "") + rep.bad("sibling", "%s copied to %s reads rc %d: %s" + % (cell, dest, r.returncode, + " | ".join(blob.strip().splitlines()[-2:]))) + return "fault" + try: + got = json.loads(r.stdout.strip().splitlines()[-1]) + except (ValueError, IndexError): + rep.bad("sibling", "%s printed no resolvable path: %r" + % (cell, r.stdout[-200:])) + return "fault" + where = got.get("file") or "" + if os.path.dirname(os.path.realpath(where)) != os.path.realpath(dest): + rep.bad("sibling", "%s imported %s -- not the module beside it" + % (cell, where)) + return "fault" + readings.append("%s -> %s" % (cell, module + ".py")) + rep.ok("sibling", "%d file(s) copied to a temp lane and run from there: %s" + % (len(copied), "; ".join(readings))) + return "pass" + finally: + shutil.rmtree(tmp, ignore_errors=True) + + +def leg_mutant(root, rep): + """Rewrite the binding to the host path: the cell must fail and name it.""" + lane = os.path.join(root, LANE) + cell, module = CELLS[0] + src = os.path.join(lane, cell) + if not os.path.exists(src): + rep.bad("mutant", "missing %s" % src) + return "cannot" + with open(src, encoding="utf-8") as fh: + text = fh.read() + mutant = text.replace( + "sys.path.insert(0, str(HERE))", + "sys.path.insert(0, %r)" % HOST_COPY, 1) + if mutant == text: + # The precondition of this leg is the repaired binding line itself. A + # tree without it is not a tree this leg cannot grade -- it is a tree + # that regressed, and it must read as a FAULT (rc 1), not as rc 2. + # Measured on the reverted tree: with rc 2 here, `q133_verify.py` on the + # pre-repair bytes read "could not grade" and hid the three real faults + # the other legs had just printed. + rep.bad("mutant", "the repaired binding line is not present in %s -- the " + "tree has regressed (pre-repair rc 2 here hid three faults)" % cell) + return "fault" + tmp = tempfile.mkdtemp(prefix="q133-mutant-") + try: + dest = os.path.join(tmp, "lane") + os.makedirs(dest) + # the module goes in the copy too, so only the binding can be at fault + shutil.copy2(os.path.join(lane, module + ".py"), + os.path.join(dest, module + ".py")) + with open(os.path.join(dest, cell), "w") as fh: + fh.write(mutant) + r = run([sys.executable, os.path.join(dest, cell)], cwd=dest) + blob = (r.stderr or "") + (r.stdout or "") + if r.returncode == 0: + rep.bad("mutant", "cell bound to %s read rc 0 -- the binding " + "assertion does not bite" % HOST_COPY) + return "fault" + if HOST_COPY not in blob and "AssertionError" not in blob: + rep.bad("mutant", "cell failed (rc %d) without naming the binding: %s" + % (r.returncode, " | ".join(blob.strip().splitlines()[-2:]))) + return "fault" + rep.ok("mutant", "host-bound copy reads rc %d and names %s" + % (r.returncode, HOST_COPY)) + return "pass" + finally: + shutil.rmtree(tmp, ignore_errors=True) + + +def leg_oracle(root, rep): + """Grade the module against an exhaustive BFS (q133_oracle.py).""" + oracle = os.path.join(HERE, "q133_oracle.py") + if not os.path.exists(oracle): + rep.bad("oracle", "missing %s" % oracle) + return "cannot" + r = run([sys.executable, oracle, os.path.join(root, LANE)], timeout=180) + if r.returncode != 0: + rep.bad("oracle", "probe rc %d: %s" + % (r.returncode, ((r.stderr or "") + (r.stdout or "")).strip()[-300:])) + return "fault" + try: + got = json.loads(r.stdout.strip().splitlines()[-1]) + except (ValueError, IndexError): + rep.bad("oracle", "probe printed no reading: %r" % r.stdout[-300:]) + return "fault" + if got["mismatches"]: + rep.bad("oracle", "%d mismatch(es) vs BFS, e.g. %s" + % (got["mismatches"], got["examples"][:3])) + return "fault" + if got["bfs_vs_osa"] == 0: + rep.bad("oracle", "the corpus cannot separate true DL from OSA over %d " + "pairs -- the leg would be vacuous" % got["decided"]) + return "fault" + rep.ok("oracle", "%d pair(s) decided by BFS, 0 mismatches, %d pair(s) where " + "BFS and OSA disagree (so the corpus separates them)" + % (got["decided"], got["bfs_vs_osa"])) + return "pass" + + +LEGS = (("bindings", leg_bindings), ("scan", leg_scan), + ("sibling", leg_sibling), ("mutant", leg_mutant), + ("oracle", leg_oracle)) + + +def main(argv=None): + ap = argparse.ArgumentParser(description="Q133 verifier") + ap.add_argument("--root", default=DEFAULT_ROOT) + ap.add_argument("--json", action="store_true") + args = ap.parse_args(argv) + root = os.path.abspath(args.root) + if not os.path.isdir(os.path.join(root, LANE)): + print("q133: could not grade -- no %s under %s" % (LANE, root)) + return 2 + + rep = Report() + outcomes = {} + for name, fn in LEGS: + outcomes[name] = fn(root, rep) + + cannot = [k for k, v in outcomes.items() if v == "cannot"] + faults = [k for k, v in outcomes.items() if v == "fault"] + if args.json: + print(json.dumps({"root": root, "outcomes": outcomes, + "passed": rep.passed, "failed": rep.failed}, + sort_keys=True)) + if cannot: + print("q133: could not grade -- %s" % ", ".join(cannot)) + return 2 + if faults: + print("q133: %d leg(s), %d passed, %d fault(s) -- %s" + % (len(outcomes), len(rep.passed), len(faults), ", ".join(faults))) + return 1 + print("q133: %d leg(s), %d passed, 0 fault(s) -- beam cells import the module " + "beside them" % (len(outcomes), len(rep.passed))) + return 0 + + +if __name__ == "__main__": + sys.exit(main())