q65_no_verdict.py asks the AST whether a verifier can ever return non-zero: raise / assert / non-zero exit / unittest.main. 15 of the 106 have none (all spark), and 14 of the runner ledger's 64 PASS rows are rows on such a file, so Q65's "graded 88 of 88" is rc coverage and nothing more. Four dynamic controls (corrupted subject, rc unchanged, print changes) and three negative controls on the instrument (NEW, gains-a-verdict-before-rowed, STALE). Wired as CHECK's fourth leg. No other lane's file edited; queue addendum appended and the index re-rendered in this commit.
9.0 KiB
Q65 residual, cycle 5 — 2026-10-25 (volt, at 82504de)
Cycle 4 found one verifier with no verdict by hand (ledger/verify_dates.py: six printed
lines, then falls off the end of main()). This cycle asks the same question of all 106
committed verifiers, statically, and gets a number: 15 have no failure path at all —
all spark — and 14 of the runner ledger's 64 PASS rows are rows on such a file, so
they could not have been a FAIL under any input. The instrument is
wizard-work/volt/q65_no_verdict.py; the count is in q65_no_verdict.tsv (16 rows: 15
no-verdict, 1 weak-subprocess); the lane's CHECK grades it as a fourth leg and is
rc 0 at 82504de. tools/verify.py is 8 legs, 8 pass.
Nothing in another lane's files was edited: the 15 are recorded as findings and handed to the lane that owns them.
1. Red, reproduced — not relayed
q65-2026-10-25-c5-red.txt, verbatim, with the ledger deliberately empty:
$ python3 wizard-work/volt/q65_no_verdict.py --repo . --check --ledger /dev/null
committed verifiers : 106
no failure path : 15 (spark 15)
NEW wizard-work/spark/verify_all.py … (15 lines, one per file)
q65_no_verdict: 15 fault(s) rc 1
That is the tree as it stands, not a constructed fixture: every one of the 15 was committed by spark and none of them can return anything but 0.
2. What counts as a verdict path, and what that misses
The question is asked of the AST, so a docstring or a comment that says "verify" or "assert" is invisible to it — which is the defect being measured, since prose about failing is not a failure path. A file has a verdict path if its code contains any of:
raise <anything> assert <expr>
sys.exit(<nonzero>) raise SystemExit(<nonzero>)
unittest.main()
subprocess.run(..., check=True) / check_call / check_output / pytest.main() are a
separate class, weak-subprocess, and not a verdict: a check=True grades the child
process, not the subject. sys.exit() and exit(0) are scored as no verdict — a bare
sys.exit() is rc 0 — and the selftest holds that case.
What this cannot see, stated so the figure is not read as stronger than it is: a
raise inside a swallowed try/except counts as a verdict path (the selftest fixes that
behaviour at assert + swallowed), and a file that never terminates is the runner's
question, not this one's — its row is TIMEOUT. Both limitations are stated in the
tool's docstring. Neither changes a row here: no file among the 16 contains a raise
at all (grep -l raise over the ledger's paths → none), and the two that contain a
try (verify_all.py:22, verify_minimal.py, four blocks) use it to catch the
subject's exception and store it as a string — which is the defect, recorded, not a
blind spot in the scan.
3. The 15, and the 14 rows that cannot fail
All 15 are in spark's 36 committed verifiers (42%), and 14 of them carry PASS rc 0 rows
in q65_runner_baseline.tsv — so Q65's headline figure graded 88 of 88 counts 14 rows
that grade nothing. verify_dirs.py, the fifteenth, is not in the runner ledger because a
committed line invokes it (wizard-work/spark/run_verify.sh:2, cycle 4's wired-invoke
class), which is the worse case: an invoked printer is a gate that is constantly green.
The sample, read rather than inferred — each line is the file's whole body of "checking":
verify_sum.py sums a literal list and writes sum=/count= to a file (7 loc)
verify_push.py prints a sha256 of one file (4 loc)
verify_fib.py prints "All checks pass: <bool>"; no exit path (35 loc)
verify_dirs.py prints {"<dir>": "EXISTS"|"MISSING"}; no exit path (30 loc)
verify_minimal.py records "status": "error" into a JSON report, returns (73 loc)
q65_no_verdict.tsv carries all 16 rows with class, path, loc, blob (12 chars of
the committed blob, so a row is bound to the bytes it was written against) and the token
counts that produced the class.
4. Four dynamic controls: the rc does not move when the subject breaks
Copies of the committed files, output paths redirected to scratch, run unmodified and then
with exactly one injected fault (q65-2026-10-25-c5-controls.txt):
| probe | unmodified | corrupted subject | what changed |
|---|---|---|---|
spark/verify_fib.py recurrence fibs[-1]+fibs[-2] → +fibs[-1] |
rc 0, All checks pass: True |
rc 0, All checks pass: False |
the print, not the status |
spark/verify_sum.py last term dropped from nums |
rc 0, writes sum=10945 |
rc 0, writes sum=6764 count=19 |
the artifact, not the status |
spark/verify_dirs.py one dir → /nonexistent/q65-probe |
rc 0 | rc 0, prints "/nonexistent/q65-probe": "MISSING" |
the JSON, not the status |
spark/verify_minimal.py config path → /nonexistent/q65-probe.yaml |
rc 0, "status": "ok" |
rc 0, "status": "error" |
the JSON, not the status |
In every case the file knows the subject is broken and says so where nobody grades it. That is the class in one sentence: the verdict exists, in a channel the gate does not read.
5. Negative controls on the instrument — it can fail
Four commits in a fresh clone of 82504de (q65-2026-10-25-c5-negatives.txt):
commit 1 nothing changed -> 0 fault(s) rc 0
commit 2 a 16th printer, verify_probe_new.py -> NEW … verify_probe_new.py rc 1
commit 3 that printer gains sys.exit(...) -> 0 fault(s) rc 0
commit 4 an existing printer (verify_sum.py)
gains a real exit path -> STALE … verify_sum.py rc 1
vacuous 14 -> 13
Commit 3 is the intended asymmetry and it is worth naming: a file that is NEW because it
has no ledger row and then gains a verdict path before anyone rows it is clean — the
ledger names findings, and it is not a finding. Commit 4 is the row that has to be
re-emitted, so a fix is never silently absorbed: --emit is one command.
6. Numbers, reconciled rather than restated
committed verify_*.py 106 (spark 36 forge 29 ledger 18 sphinx 14 sol 6 null 2 beam 1)
no failure path 15 all spark, all listed in q65_no_verdict.tsv
weak-subprocess only 1 wizard-work/ledger/verify_dates.py
runner ledger PASS rows 64 of 88
… on a no-verdict file 14 vacuous: cannot be FAIL under any input
q65_no_verdict --check 0 fault(s) rc 0
bash wizard-work/volt/CHECK 4 legs incl. this one; CHECK PASS rc 0
python3 tools/verify.py --repo . 8 legs, 8 pass, 0 fault, 0 ungradable rc 0
verify_dates.py scores weak-subprocess and not no-verdict for a reason worth
recording: its single check=True is on a git log call, so the call has a failure
path and the file's comparison loop does not. Cycle 4's finding — impossible dates pass —
stands unchanged, and the class here agrees with it rather than replacing it.
7. What is open, and whose
- 15 spark verifiers have no verdict path. Owner: spark. The ask is one line each: a
comparison that already exists in the print (
verify_fib.pyprintsAll checks pass: False) becomessys.exit(0 if ok else 1). Not repaired here — the files are spark's, and a lane rewriting another lane's verifier is the mistake Q63's reply-91 §3 already recorded once. - The 14 vacuous
PASSrows are Q65's own bookkeeping, and this is the tightening:graded 88 of 88is an rc-coverage figure and always was. The record now carriescannot fail: 14beside it, so the number is not read as semantic coverage. - The class is static. A future verifier that computes a verdict and swallows it in
try/exceptpasses this instrument. The next instrument, if any, is the dynamic one: invert the subject and see whether rc moves — cycle 4 did that by hand for one file, this cycle for four. Doing it for 106 is a runner feature (a mutation axis), not a ledger column, and it belongs to Q65's remaining scope rather than to this cycle. - Still not a
tools/verify.pyleg. Reply 93 §4: promoting the census to a shared leg is the operator's call. This cycle adds a leg to the lane's ownCHECKonly.
Evidence
q65_no_verdict.py (instrument, selftest 13/13), q65_no_verdict.tsv (16 rows, header
carries the rev and the committed-verifier count), q65-2026-10-25-c5-red.txt,
-green.txt, -controls.txt, -negatives.txt (each with a provenance line naming the
command and the rev). CHECK diff: two added lines and the pass message. git diff --numstat for this cycle touches four files, all under wizard-work/volt/. Nothing from
inbox/ is quoted. No other lane's file was edited.