Measured at 67f94cc: 19 of the 20 tracked tools answered a --json target inside a nonexistent directory with an uncaught FileNotFoundError at rc 1. Only queue_append_audit.py already refused (rc 2). A traceback is fatal under this repo's contract, and rc 1 is the code that means a graded fault -- so a caller could not tell 'the grade is bad' from 'the artifact was never written'.
Landed: the grade first, its stdout report standing; the write wrapped, one stderr line naming the path, rc 2 (could not grade). gate_blame.py also moves its --json write ahead of the all-UNGRADABLE early return, so a write refusal is not shadowed by the cannot-grade return (an extra ']' and a mis-indented try in that hunk were fixed before commit; the module compiled and its selftest was 21/21).
tools/write_probe.py is the instrument: one probe per tracked tool, verdicts TRACEBACK / RC_OTHER / SILENT / UNNAMED / NO_REACH / OK, NO_PROBE fatal on the same rule as the read axis, and it probes itself. It is leg 6 of verify.py, and selftest_sweep.py now carries both a read probe and a malformed probe for it.
Verification at this commit follows in the next commit with docs/TOOLS.md and the queue record.
The 09:49Z leg ran checkin_check --since <newest day>, on the reasoning that the
newest day is the only day a new fault can appear. Measured false on a clone of
e98a34b: one added checkins/2026-10-02-volt-b.md (BAD_NAME) is invisible to that
floor -- verify --fast rc 0 'checkin_check: 1 files, 0 with a fault', while the
whole-archive run on the same tree is rc 1 with 74 files / 36 faults.
tools/checkin_baseline.tsv (35 data rows, sha256 0f599c5e...) is the faults the
archive already carried; checkin_check --baseline splits each row's classes into
known/new, only a new class makes rc 1, per class not per path; --emit-baseline
prints it to stdout (no new write path); an unreadable ledger is rc 2; stale
entries are advisory. Refreshed leg: same clone, same file -> rc 1 naming exactly
that file; live tree -> 73 files, 0 new, 35 known, rc 0.
Cells: checkin_check 29 -> 35 (35/35), verify 35 -> 37 (37/37), sweep 19/19 +
17/17 rc 0, ruff F,E9 clean. One docstring count removed after
doc_census_check graded it STALE -- the ledger is now the artifact that carries it.
ruff check --select F,E9 tools/ -> 3 errors at 960b852:
checkin_check.py:421 F541 f-string with no placeholder
checkin_check.py:556 F841 jd assigned, never read (dead residue of an unwritten
malformed-JSON refusal cell)
queue_append_audit.py:73 F401 re imported, never used (no 're.' in the file)
Fix: 3 lines removed, 1 line changed, nothing added (numstat 1/2 + 0/1).
Behaviour claim measured, not asserted: all 14 tools' --selftest stdout+stderr
captured before and after (28 files) plus checkin_check.py --dir checkins and
queue_append_audit.py --guard --to HEAD (2 files) -- 30 artifacts, 0 differ after
normalising only checkin_check's mkdtemp suffix. 14 tools / 429 cells / 429 pass
on both sides; verify.py 3/3 PASS rc 0.
Not enforced by the gate: verify.py has no static-check leg, so this property is
observed here only. Adding ruff to the gate would make it a hard dependency
(host without ruff -> UNGRADABLE -> rc 2), so no leg and no new tool.
headings_missing() scanned every line for ^#{1,6}\s+ with no fence state, so a
check-in that quotes the four-heading contract in a fenced block was graded as
carrying all four headings while carrying none as structure. queue_index.py has
skipped fences since it was written; the check-in reader never did.
Pre-fix on the quoted fixture: headings_missing == [] (false green).
Post-fix: ['next','ask']. Blast radius on the record is zero: over all 74 files
in checkins/ the advisory count is 60 before and 60 after, 0 files change grade.
selftest 27 -> 29 cells (c28 quoted heading, c29 unclosed fence), both advertised
counts updated. verify.py 3/3 rc 0 (sweep 14 tools, 14 OK, 0 fatal).
The full doc-census gate at 0b67585 went red on this tool's docstring, not on
its behaviour: STALE "tools/checkin_check.py:46 files claimed 70 at HEAD --
printed 71". Two unpinned mutable counts over checkins/ were behind it.
1. The A1 rationale said "52 of 70 files faulty ... 12 real name faults".
Neither figure is reproducible: checkin_check prints 57 missing-heading
files and BAD_NAME 25 at c374a0a, c213a5d, edaef63 and 588784d alike, and
70 files only at c374a0a (the rest carry 69). The sentence now states the
measured triple and pins it to c374a0a, the last revision that touches this
tool. checkin_check takes no --rev, so a rev-named block is REV_UNCHECKED by
the census tool's own rule -- visible, never graded, and it stops drifting
to STALE as check-ins land.
2. The READ-ONLY paragraph said "the 12 BAD_NAME files": the tool counts
BAD_NAME 25 at every revision tested and at HEAD. That sentence is about
policy, not a census, so the count is removed rather than re-pinned --
"the badly named files are the principals' history".
Measured after both edits: selftest 27/27 rc 0; targeted doc-census gate
--tools tools/checkin_check.py rc 0; full 12-tool gate and selftest sweep
rerun at the commit this message lands in (artifacts under
/root/.hermes/wizard-outputs/volt/2026-10-18-vocab-minimal/).