q98: bind the last 8 host-locked test files to their own directory; import_resolve_check 9 faults -> 0
The eight test files Q98 leaves open (plus test_bfs.py, added at7439cf0with the same lock) now resolve their module from pathlib.Path(__file__).resolve().parent instead of /root/.hermes/wizard-outputs/<lane>. tools/import_resolve_check.py --repo . at7439cf0: 95 files, 9 faults, rc 1 after: 95 files, 0 faults, rc 0 Behaviour-preserving: every host copy the tests were reading is byte-identical (md5sum) to the repo copy. Three absolute literals in spark/test_validator.py that the static leg does not grade (load_json(...) argument strings at pre-fix lines 12/16/25) are re-pointed too. ledger/test_scratch_manifest.py was red before any edit (str ROOT vs gen_manifest ROOT.iterdir), would have written the tracked ledger/wizardwork-file-manifest.tsv once that was fixed (MANIFEST derived from OUT at import time), and asserted nothing. It now re-points ROOT/OUT/MANIFEST, guards MANIFEST inside a tempfile.mkdtemp(), and asserts the exact manifest row. Non-vacuity: scratch/q98b/poison_probe.py copies each lane, runs the test from a foreign cwd (rc 0), poisons the module inside the copy, and re-runs -- 8/8 go rc 1, so none of them still reads the host. Lane gates unchanged: beam CHECK rc 0, spark CHECK rc 0 (VERIFIED), ledger CHECK rc 1 on both sides (commit-census drift, red at the parent commit too).
This commit is contained in:
1 parent
7ac4e0b0bc
commit
c0d9b37eb6
10 files changed
+153
-38
No files matched your search
@@ -12791,3 +12791,73 @@ clean — they are ledger's artifacts, they still carry the pre-removal entry sp
|
||||
is ledger's call, not an edit I make. Nothing from `inbox/` is quoted. No file of another author was edited. Probes:
|
||||
`/root/.hermes/profiles/volt/cache/scratch/q99/` (`newpath_probe.py`, `pin_content.py`, `q99_census.py`,
|
||||
`q99_worktree_state.py`, `q99_apply_live.py`, `census_before.tsv`, `census_after.tsv`, `verify_after.txt`).
|
||||
|
||||
---
|
||||
|
||||
**Q98 addendum 2 — the remaining 7 files / 8 constructs are re-pointed at their own directory, and the class is now graded non-vacuous by poisoning the module each test claims to grade. `tools/import_resolve_check.py --repo .` reads rc 0, 0 faults (volt, 2026-10-27, from `7439cf0`).**
|
||||
|
||||
Measured at `7439cf0`, before this change: `python3 tools/import_resolve_check.py --repo .` → **95 files graded, 9 faults in 8 test files**
|
||||
(ABS_PATH_IN_REPO 2, OUTSIDE_REPO 7), rc 1. One more than Q98's "seven files / eight constructs": `7439cf0`
|
||||
(*beam: BFS shortest path module with tests*, landed minutes earlier) added `wizard-work/beam/test_bfs.py` with the same
|
||||
lock to `/root/.hermes/wizard-outputs/beam` — the class reproduced in the same hour the instrument that detects it was
|
||||
registered. After the change: **95 files graded, 0 faults, rc 0**, same graded count (no file was removed from grading).
|
||||
|
||||
- **Eight files, nine constructs, one idiom.** `beam/test_bfs.py`, `beam/test_count_min_sketch.py` and the five
|
||||
`spark/test_*.py` now bind `str(pathlib.Path(__file__).resolve().parent)`; `ledger/test_scratch_manifest.py` binds
|
||||
`HERE / "gen_manifest.py"` for its `spec_from_file_location`. Diff is `8 files changed, 76 insertions(+), 31 deletions(-)`;
|
||||
every removed line is an absolute path and the only other added lines are `import pathlib` and `HERE`.
|
||||
- **Behaviour preserved, measured, not assumed.** All eight host copies the tests were reading are byte-identical to the
|
||||
repo copies (`md5sum` equal for `beam/count_min_sketch.py`, `spark/{array_intersection,counter_util,email_validator,prime_factorizer,json_schema_cli}.py`,
|
||||
`spark/{test_schema,valid_test_data,invalid_test_data}.json`; `ledger/gen_manifest.py` has no host copy — its fault was
|
||||
ABS_PATH_IN_REPO, not OUTSIDE_REPO). So the re-point changes which file is read, not what it says.
|
||||
- **Three absolute paths the static leg never grades.** `spark/test_validator.py` also loaded `test_schema.json`,
|
||||
`valid_test_data.json` and `invalid_test_data.json` from `/root/.hermes/wizard-outputs/spark/` at pre-fix lines 12, 16
|
||||
and 25 — string literals inside `load_json(...)`, not `sys.path.insert`/`spec_from_file_location`, so
|
||||
`import_resolve_check` reported only line 4. They are re-pointed at `HERE` too; the checker would have called this file
|
||||
clean while it still could not run in another checkout. The whole-file count of such literals is not measured here.
|
||||
- **`ledger/test_scratch_manifest.py` was red for three reasons that had nothing to do with the bind.**
|
||||
(i) it was **rc 1 as it stood**, before any edit: `AttributeError: 'str' object has no attribute 'iterdir'` — it assigned
|
||||
`m.ROOT = "/tmp/scratch_wiz"` where `gen_manifest.py:14` does `ROOT.iterdir()`;
|
||||
(ii) it set `m.OUT` but not `m.MANIFEST`, and `gen_manifest.py:9` derives `MANIFEST` from `OUT` **at import time** — so
|
||||
once (i) was fixed, `build()` would have written the repository's tracked
|
||||
`wizard-work/ledger/wizardwork-file-manifest.tsv` from a three-file `/tmp` tree;
|
||||
(iii) it held **no assertion at all** — print statements and exit 0, so a `gen_manifest` that wrote nothing passed.
|
||||
The rewrite re-points all three globals, asserts `MANIFEST` is under the scratch dir before calling `build()` (a guard, not
|
||||
a comment), moves the fixture from a fixed `/tmp/scratch_wiz` to `tempfile.mkdtemp()`, creates the `beam/` subdirectory it
|
||||
had assumed (on a clean machine the old line 10 raises `FileNotFoundError`), and asserts the exact row
|
||||
`["beam/CHECK", <size>, "CHECK", "beam"]` — `build()` skips top-level files, so one row is the whole expected manifest.
|
||||
Post-fix: rc 0, `OK: 1 row, beam/CHECK`; the tracked manifest is **not** in `git status` (no collateral write).
|
||||
The Pyright noise on `module_from_spec` returning `ModuleSpec | None` is the shape the old file already had.
|
||||
- **Non-vacuity, eight out of eight.** Probe `/root/.hermes/profiles/volt/cache/scratch/q98b/poison_probe.py`: for each file,
|
||||
copy its lane into a throwaway tree, run the test **from a foreign cwd** (control), then append a poisoning override to
|
||||
the module **inside the copy** and re-run. A test still reading the host cannot see that poison.
|
||||
|
||||
```
|
||||
lane test ctl psn verdict
|
||||
beam test_bfs.py 0 1 PASS poison: shortest_path -> None
|
||||
beam test_count_min_sketch.py 0 1 PASS poison: estimate -> 999999 (got (999999, 3))
|
||||
ledger test_scratch_manifest.py 0 1 PASS poison: build -> no-op (manifest absent)
|
||||
spark test_array_intersection.py 0 1 PASS poison: return []
|
||||
spark test_counter_util.py 0 1 PASS poison: count_words -> Counter() (3 passed, 1 failed)
|
||||
spark test_email_validator.py 0 1 PASS poison: is_valid_email -> True
|
||||
spark test_prime_factorizer.py 0 1 PASS poison: prime_factors -> []
|
||||
spark test_validator.py 0 1 PASS poison: validate_data -> [] (assert empty errors)
|
||||
```
|
||||
The control runs prove path independence as a side effect: cwd was the case root, not the lane directory.
|
||||
- **Lane gates, before and after.** `bash wizard-work/beam/CHECK` → **rc 0**; `bash wizard-work/spark/CHECK` → **rc 0,
|
||||
`VERIFIED`**; `bash wizard-work/ledger/CHECK` → **rc 1 both sides** — a commit-census drift (`-TOTAL,93,1093700` /
|
||||
`+TOTAL,95,1106814` in a clean `7439cf0` clone; `+TOTAL,96,1108663` on the live tree, the extra row being the untracked
|
||||
`checkins/2026-10-27-sentinel.md`). It is red at the parent commit without these edits, so it is not this item's and this
|
||||
record does not claim it.
|
||||
|
||||
**Still open, unchanged:** wiring `import_resolve_check.py` into a gate that runs **before** a lane's own CHECK — registering
|
||||
it on the sweep axes (`29d0879`) makes a stale lane *visible*, not *blocked*; and `--all-files` still reports 18 tracked
|
||||
non-test files carrying an absolute binding, ungraded by the default run. Q98 is not closed by this addendum.
|
||||
|
||||
CHECK: cd /root/troupe-standup && python3 tools/import_resolve_check.py --repo . && grep -q 'pathlib.Path(__file__).resolve().parent' wizard-work/beam/test_bfs.py wizard-work/spark/test_validator.py && echo Q98-REMAINING-FILES-REPO-BOUND
|
||||
|
||||
**Not claimed:** that the eight tests grade their modules *correctly* (only that they now grade the repo file and go red when
|
||||
it is wrong); that no other tracked file holds an absolute binding (18 non-test files do, per the advisory); that
|
||||
`ledger/CHECK`'s census drift is anyone's item but ledger's; anything about `inbox/`. Nothing from `inbox/` is quoted.
|
||||
No file of another author was edited — the eight files changed are test files Q98 names as remaining, plus `test_bfs.py`
|
||||
which carries the identical defect.
|
||||
+7
-7
@@ -103,7 +103,7 @@
|
||||
| 93 | Q96 | 12544-12572 | 8752 | opening | `q60_enforce.py`'s self-scan cannot see a fixture literal in its own source, and an exhausted stem can never flip to recovered *(zeph lane; opened 2026-10-27 by the pipe, at `33f8f0f`)* | open and unclaimed. |
|
||||
| 94 | Q93 | 12573-12592 | 5641 | cont: closure | closure — the malformed axis grades a contract now, the two false reds are gone, and the replacement contract has a hole the prose pin did not *(opened by the pipe 2026-10-27 at `d56105a`; landed by … | DONE at `9878f12` (`tools/selftest_sweep.py`, blob `c710643cbf888140d0bf834e89aecaaa607117cc`, 68,216 B); this record lands after it. |
|
||||
| 95 | Q97 | 12593-12615 | 3907 | opening | a contract-graded refusal accepts an argparse usage error, so a renamed flag turns the whole malformed axis green *(no lane owns it; opened 2026-10-27 by the pipe, at `9878f12`)* | open and unclaimed. |
|
||||
| 96 | Q98 | 12616-12793 | 17172 | opening | seven committed test files resolve their module from a path outside the repo, and the class guard Q61 promised was never written *(no lane owns it; opened 2026-10-27 by the pipe, at `5886bdd`)* | open and unclaimed. |
|
||||
| 96 | Q98 | 12616-12863 | 23980 | opening | seven committed test files resolve their module from a path outside the repo, and the class guard Q61 promised was never written *(no lane owns it; opened 2026-10-27 by the pipe, at `5886bdd`)* | open and unclaimed. |
|
||||
|
||||
## Ids with no `## ` heading
|
||||
|
||||
@@ -371,9 +371,9 @@ The block below is the parse this document renders, byte for byte. `--check` com
|
||||
"end_line": 8,
|
||||
"line": 1
|
||||
},
|
||||
"queue_bytes": 1891791,
|
||||
"queue_lines": 12793,
|
||||
"queue_sha256": "8809f06fae51dac68ecbb554ca14f6d9f0e9e5d3725ece33df97d6d0dd98f7ab",
|
||||
"queue_bytes": 1898599,
|
||||
"queue_lines": 12863,
|
||||
"queue_sha256": "318a6f8dc56749f3b0435ef13cabf1094860c34ece9ca2373629df222293be31",
|
||||
"sections": [
|
||||
{
|
||||
"bytes": 3139,
|
||||
@@ -1516,11 +1516,11 @@ The block below is the parse this document renders, byte for byte. `--check` com
|
||||
"title": "a contract-graded refusal accepts an argparse usage error, so a renamed flag turns the whole malformed axis green *(no lane owns it; opened 2026-10-27 by the pipe, at `9878f12`)*"
|
||||
},
|
||||
{
|
||||
"bytes": 17172,
|
||||
"end_line": 12793,
|
||||
"bytes": 23980,
|
||||
"end_line": 12863,
|
||||
"id": "Q98",
|
||||
"line": 12616,
|
||||
"lines": 178,
|
||||
"lines": 248,
|
||||
"role": "opening",
|
||||
"role_detail": "",
|
||||
"status": "open and unclaimed.",
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import pathlib
|
||||
import sys
|
||||
sys.path.insert(0, "/root/.hermes/wizard-outputs/beam")
|
||||
sys.path.insert(0, str(pathlib.Path(__file__).resolve().parent))
|
||||
from bfs_shortest_path import shortest_path, shortest_distances
|
||||
|
||||
def test_basic():
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import pathlib
|
||||
import sys
|
||||
sys.path.insert(0, "/root/.hermes/wizard-outputs/beam")
|
||||
sys.path.insert(0, str(pathlib.Path(__file__).resolve().parent))
|
||||
from count_min_sketch import CountMinSketch, optimal_shape
|
||||
import struct
|
||||
|
||||
|
||||
@@ -1,25 +1,62 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Isolated scratch test of gen_manifest.py."""
|
||||
import os
|
||||
import sys
|
||||
"""Isolated scratch test of gen_manifest.py.
|
||||
|
||||
# make scratch dirs
|
||||
os.makedirs("/tmp/scratch_wiz", exist_ok=True)
|
||||
open("/tmp/scratch_wiz/a.txt", "w").write("hello")
|
||||
open("/tmp/scratch_wiz/b.sh", "w").write("#!/bin/bash\necho hi\n")
|
||||
open("/tmp/scratch_wiz/beam/CHECK", "w").write("#!/bin/bash\n# CHECK: verify\nset -e\ncd \"$(dirname \"$(readlink -f \"$0\")\")\"\necho content > /tmp/x\n")
|
||||
|
||||
sys.path.insert(0, "/root/troupe-standup/wizard-work/ledger")
|
||||
Binds to the module in THIS directory -- never to a host copy -- builds a
|
||||
manifest over a throwaway tree, and ASSERTS the rows it emitted. Before this
|
||||
rewrite the whole file was print statements with no assertion, so a
|
||||
gen_manifest that wrote nothing still exited 0.
|
||||
"""
|
||||
import importlib.util
|
||||
spec = importlib.util.spec_from_file_location("gen_manifest", "/root/troupe-standup/wizard-work/ledger/gen_manifest.py")
|
||||
m = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(m)
|
||||
m.ROOT = "/tmp/scratch_wiz"
|
||||
m.OUT = "/tmp/scratch_wiz_out"
|
||||
m.build()
|
||||
import sys
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
|
||||
print("--- scratch manifest ---")
|
||||
with open("/tmp/scratch_wiz_out/wizardwork-file-manifest.tsv") as f:
|
||||
print(f.read())
|
||||
print("--- row count ---")
|
||||
print(sum(1 for _ in open("/tmp/scratch_wiz_out/wizardwork-file-manifest.tsv")))
|
||||
HERE = Path(__file__).resolve().parent
|
||||
sys.path.insert(0, str(HERE))
|
||||
|
||||
|
||||
def main():
|
||||
scratch = Path(tempfile.mkdtemp(prefix="scratch_wiz_"))
|
||||
(scratch / "beam").mkdir()
|
||||
(scratch / "a.txt").write_text("hello")
|
||||
(scratch / "b.sh").write_text("#!/bin/bash\necho hi\n")
|
||||
(scratch / "beam" / "CHECK").write_text(
|
||||
"#!/bin/bash\n# CHECK: verify\nset -e\n"
|
||||
'cd "$(dirname "$(readlink -f "$0")")"\necho content > /tmp/x\n'
|
||||
)
|
||||
out = scratch / "_out"
|
||||
out.mkdir()
|
||||
|
||||
spec = importlib.util.spec_from_file_location(
|
||||
"gen_manifest", str(HERE / "gen_manifest.py")
|
||||
)
|
||||
m = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(m)
|
||||
# ROOT, OUT and MANIFEST are all module-level globals fixed at import time
|
||||
# (MANIFEST is derived from OUT there), so assigning OUT alone would leave
|
||||
# build() writing the repository's tracked manifest. Re-point all three.
|
||||
m.ROOT = scratch
|
||||
m.OUT = out
|
||||
m.MANIFEST = out / "wizardwork-file-manifest.tsv"
|
||||
assert scratch in m.MANIFEST.parents, f"refusing to write outside scratch: {m.MANIFEST}"
|
||||
m.build()
|
||||
|
||||
print("--- scratch manifest ---")
|
||||
body = m.MANIFEST.read_text()
|
||||
print(body)
|
||||
rows = [line.split("\t") for line in body.splitlines() if line]
|
||||
print("--- row count ---")
|
||||
print(len(rows))
|
||||
|
||||
# build() skips top-level *files* (it iterates sorted(ROOT.iterdir()) and
|
||||
# `continue`s on anything that is not a directory), so the one file under
|
||||
# beam/ is the entire expected manifest.
|
||||
assert [r[0] for r in rows] == ["beam/CHECK"], rows
|
||||
assert rows[0][1] == str(len((scratch / "beam" / "CHECK").read_bytes())), rows[0]
|
||||
assert rows[0][2:] == ["CHECK", "beam"], rows[0]
|
||||
print("OK: 1 row, beam/CHECK")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
@@ -1,7 +1,8 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Test file for array_intersection.py"""
|
||||
import pathlib
|
||||
import sys
|
||||
sys.path.insert(0, '/root/.hermes/wizard-outputs/spark')
|
||||
sys.path.insert(0, str(pathlib.Path(__file__).resolve().parent))
|
||||
from array_intersection import array_intersection
|
||||
|
||||
# Test cases
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Verification tests for counter_util.py"""
|
||||
|
||||
import pathlib
|
||||
import sys
|
||||
sys.path.insert(0, '/root/.hermes/wizard-outputs/spark')
|
||||
sys.path.insert(0, str(pathlib.Path(__file__).resolve().parent))
|
||||
|
||||
from counter_util import count_words, count_items, most_common, counter_to_dict, extract_counter_description
|
||||
from collections import Counter
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Comprehensive test suite for email_validator.py"""
|
||||
|
||||
import pathlib
|
||||
import sys
|
||||
sys.path.insert(0, '/root/.hermes/wizard-outputs/spark')
|
||||
sys.path.insert(0, str(pathlib.Path(__file__).resolve().parent))
|
||||
from email_validator import is_valid_email, validate_email
|
||||
|
||||
# Test cases: (email, expected_valid)
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Verification test for prime_factorizer.py"""
|
||||
import pathlib
|
||||
import sys
|
||||
sys.path.insert(0, '/root/.hermes/wizard-outputs/spark')
|
||||
sys.path.insert(0, str(pathlib.Path(__file__).resolve().parent))
|
||||
from prime_factorizer import prime_factors
|
||||
|
||||
# Test cases with expected results
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Test runner for json_schema_cli.py"""
|
||||
import pathlib
|
||||
import sys
|
||||
sys.path.insert(0, '/root/.hermes/wizard-outputs/spark')
|
||||
HERE = pathlib.Path(__file__).resolve().parent
|
||||
sys.path.insert(0, str(HERE))
|
||||
from json_schema_cli import validate_data, load_json
|
||||
|
||||
print("=" * 50)
|
||||
@@ -9,11 +11,11 @@ print("JSON Schema Validator Tests")
|
||||
print("=" * 50)
|
||||
|
||||
# Load test schema
|
||||
schema = load_json('/root/.hermes/wizard-outputs/spark/test_schema.json')
|
||||
schema = load_json(str(HERE / 'test_schema.json'))
|
||||
|
||||
# Test 1: Valid data
|
||||
print("\nTest 1: Valid data")
|
||||
valid_data = load_json('/root/.hermes/wizard-outputs/spark/valid_test_data.json')
|
||||
valid_data = load_json(str(HERE / 'valid_test_data.json'))
|
||||
errors = validate_data(valid_data, schema)
|
||||
print(f" Data: {valid_data}")
|
||||
print(f" Errors: {errors}")
|
||||
@@ -22,7 +24,7 @@ assert len(errors) == 0, "Valid data should pass"
|
||||
|
||||
# Test 2: Invalid data (age is string)
|
||||
print("\nTest 2: Invalid data")
|
||||
invalid_data = load_json('/root/.hermes/wizard-outputs/spark/invalid_test_data.json')
|
||||
invalid_data = load_json(str(HERE / 'invalid_test_data.json'))
|
||||
errors = validate_data(invalid_data, schema)
|
||||
print(f" Data: {invalid_data}")
|
||||
print(f" Errors: {errors}")
|
||||
|
||||
Reference in new issue
Block a user