(a) import-resolve: 9 OUTSIDE_REPO faults -> 0 over 138 graded files. The eight
lanes' test files now insert str(Path(__file__).resolve().parent) and resolve
their data paths from __file__; test_hermes.py is rewritten as the host probe it
always was (skills root from HERMES_SKILLS_DIR/HERMES_HOME/~/.hermes/skills, rc 0
found / 77 SKIP / 1 FAIL) instead of binding a module that does not exist.
Falsified: poisoning the repo copy reds the rebound test (rc 1) and leaves HEAD's
host-bound copy green (rc 0), both restored.
(b) path-claims: 225 new -> 0. All 225 came from sol's untracked-file census; each
was measured (0 add-commits on any ref, present on disk untracked, listed verbatim
in the census) and is a NOT_ADDED row under a batch note. One CLEARED row dropped
(spark/lwc_counter.py, resurrected at 3e667eb after Q125 retired it).
Carried in, not authored here: tools/verify.py's ninth leg and the two-line Q98
record (Sentinel's Q98 artifact), so HEAD agrees with Q98's own text.
verify --repo .: 9 legs, 9 pass, 0 fault -- gate OK. Report:
/root/.hermes/wizard-outputs/volt/2026-10-30-q126.md
test_shell_lone_copy_reds_on_its_sibling asserted the fixture path it had just
built while verify_hermes_setup.sh reports the path it resolved with readlink -f.
Under TMPDIR=/root/.hermes/profiles/volt/cache/scratch_link a correct pair read
MISSING and the gate went rc 1 (measured before the repair: that cell was the
only red, 15 others ok). The fixture root is now canonicalised once in setUp
with os.path.realpath; two new cells pin the alias reading instead of assuming
it -- a lone copy reached by a directory symlink names the real sibling that is
absent (rc 1), and the same alias with the sibling present reads PASS (rc 0).
CHECK-env-verifiers now runs the suite twice, ambient TMPDIR and a directory
alias it builds, so the shape that produced the flake is graded every run.
16 cells; negative control (raw mkdtemp restored in a scratch copy) reds the
alias leg and only that leg, rc 1.
snippet.py: check_tools() imports hermes_tools and requires callable(getattr(...));
--require is the negative-control hook; HERMES_HOME/HERMES_PROFILE/--home/--profile
resolve every path; rc 0/1/2. verify_hermes_setup.sh: HERE from $0, sibling
snippet.py graded, --home/--root/--profile, VERDICT line, rc 0/1/2.
New test_env_verifiers.py (14 black-box cells, stub hermes_tools on PYTHONPATH,
synthetic trees) and CHECK-env-verifiers. Pre-repair blobs: 9 cells red for
snippet.py, 6 for the shell script.
The old check imported json, subprocess and datetime -- all stdlib -- so
its failure condition was unreachable, and its version-reporting helper
check_package was defined and never called. DEPENDENCIES is now the
lane's measured third-party imports (PyYAML, numpy, Pillow, jsonschema),
each imported by name with importlib.metadata version; missing -> rc 1,
broken -> rc 1, usage error -> rc 2. email_validator is not declared:
spark's own email_validator.py is a local stdlib-only module.
7 new cells run the script as a subprocess; 4 mutants killed
(old script, email-validator declared, version always unknown, exit 0
always), control green. Queue Q120 closed with the record appended and
docs/queue-index.md re-rendered in the same commit.
A scan of wizard-work/spark for every remaining reference to the 25 paths
retired in a979e63 turns up six files, and each exists only to exercise or
describe one of them. They are retired here rather than repointed, because a
repointed cell would be a new test of the survivor wearing an old tool's name:
check.py imported count_words from word_counter.py through a
sys.path.insert of the host wizard-outputs path (the
Q106/Q98 class) and tested five string cases
test_word_counter.py the same five cases against word_counter.py
test_wordcount.py ran wordcount.py and compared to `wc -w`
verify_snippets.py the lane's "snippet verification", whose one check was
word_counter.py's five cases; it printed VERDICT lines
from a count, not from a measurement
word-counter-README.md documented word-counter.py's interface and a
7-word example, i.e. prose for a file that is gone
scratch_word_counter.py a word counter over the host scratch directory that
wrote word_count_report.json to a fixed host path
What replaces them: wizard-work/spark/test_line_counter.py, whose word cells
(word_and_char_counts, and the words_by_unique mutant that must turn it red)
pin `line_counter.py --words` on a fixture that is in the tree. check.py's and
test_word_counter.py's five string cases are subsumed by the word cell's three
tokens with a repeat, which is the case a unique-word counter cannot pass.
Not retired, and deliberately: word_count_report.json and the fixtures
test_words.txt / test-input.txt / test-empty.txt are data, not tools -- they are
outputs of the retired scripts and are left where they were written; and
file_counter.py, file-counter.py, count_functions.py, json_key_counter.py,
count_verified_skills.py, verify_count.py, passwd_lines.py and generate_stats.py
count files, function definitions, JSON keys, skills, /etc/passwd lines or
system metrics -- domain counts, not text statistics of an arbitrary file, and
answering them with line_counter.py would be a different tool. The boundary is
stated in the Q125 record.
Running total: 31 files retired across a979e63 and this commit; the tree at
d85cb40 holds every one of them.
line_counter.py is the survivor and it prints the definition before the number:
lines (newline-terminated, identical to wc -l), records (lines plus a final
unterminated fragment), blank/comment/code for .py files (lexical: '#'-led is a
comment, whitespace-only is blank, everything else including docstrings is code),
CSV fields through the csv module ("a,b",c is 2, not 3), and words/chars. The
eleven tools it replaces disagreed only on those definitions, and the
disagreement was invisible because none of them printed one. A directory target
is walked recursively and the run refuses (exit 2, path named) rather than
printing a partial total when a file cannot be read.
Retired, and where each behaviour went:
count_python.py file/line walk -> `line_counter.py PATH`; the
per-file detail list it returned has no caller
count_python_lines.py code/comment/blank breakdown -> PATH report
py_loc.py same breakdown, same key names
loc_counter.py same breakdown; its argparse surface goes with it
linecount_pycount.py totals -> lines/records keys, its code count -> `code`
code_stats.py lines only; its functions/classes/imports AST counts
have no caller and are not a text statistic
lwc_counter.py -> `--words` (lines, words, chars)
text_stats.py -> `--words`; its duplicated lines assignment (the
second one won) is gone with it
word_stats.py -> `--words`; unique/top-5 tables have no caller
file_stats.py -> `--words`
file_analyzer.py -> `--words`; its size_bytes is `wc -c`
quick_stats.py -> `--words`; bytes is `wc -c`; unique/top-5 retired
wordcount.py -> `--words` (its JSON envelope is not kept)
word_counter.py -> `--words`
word_counter_simple.py -> `--words`
word-counter.py -> `--words`
wordfreq.py -> `--words`; frequency table retired, no caller
word_freq.py -> `--words`; frequency table retired, no caller
Retired in the same commit because each graded a tool that no longer exists:
test_linecount.py, test_text_stats.py, verify_lines.py, verify_lwc.py,
verify_wordcount.py, verify_word_freq.sh, check_word_count_report.py
verify_line_counter.sh is repaired rather than deleted. It pinned
/root/.hermes/wizard-outputs/spark and "Total lines: 5587" -- a figure belonging
to the 65-line tool last held at 7359bce that 6b5197b had already replaced -- and
read rc 1 at the opening rev. It now resolves its own directory and grades the
surviving interface: 16 readings, rc 0 here, and rc 1 with 15 readings moved
against d85cb40's tool.
test_line_counter.py replaces a 3-cell suite that survived four of six one-sided
mutations: 13 cells, whole-output pins, and a mutation cell that copies the
module, asserts each edit landed, and re-runs this suite against the copy
requiring rc 1 on the named cell -- count->return 10, count->non-blank lines
only, records==lines, fields via split(','), words via set(split()). Five
mutants, five killed. Against d85cb40's tool the same suite reads 0/13, rc 1.
Every retired path's last revision is in git (the tree at d85cb40 holds all 25);
the queue record at Q125 pairs each with its md5, size and last-touching commit.
tools/path_claim_baseline.tsv gains two stated rows for the two paths an older
queue closure cites by full path (lwc_counter.py, verify_lwc.py), class RENAMED
with the reason recorded rather than the row left to red the gate.
Files: wizard-work/spark/line_counter.py, test_line_counter.py,
verify_line_counter.sh (repaired), README.md, VERIFICATION.md, 25 deletions,
tools/path_claim_baseline.tsv.