Three checkers in Rust, and every one was miscounting
guards, counts and doccheck
are now obscene-tool subcommands. 17 Python scripts down to
14, 149 tests up from 119, and each port found the same class of bug: a
hand-rolled pattern producing a smaller number, which
no gate can detect because a gate compares against nothing.
| tool | what it missed | effect |
|---|---|---|
guards.py |
symbol column had to be an identifier | 8 rows never examined, incl. 910-bulk/probe |
guards.py |
runner assumed to be check_* |
the blind prober's is run_bulk |
counts.py |
check id matched as [0-9]{3}-[a-z]+/ |
150-memory-map's two checks uncounted - README said
134, truth is 136 |
counts.py |
X\((\w+)\) over the census |
a library ending in X emits a literal
X(X), so the macro parameter was counted
as a symbol - 39,549 against a true 39,548 |
Three tools had each grown their own idea of what a check-table row
looks like, so the row parser is now tool/src/sections.rs
and is shared. The anchor is OBS_CAP - the token that
actually makes a row a row - rather than a guess at the shape.
guards and counts both read it; nine tests pin
the specific rows each old pattern dropped.
The same shape one level out: splitting on L( also
splits inside any identifier ending in L, and
OBS_NIDS_0000_LIBKERNEL( does, which reported 382 libraries
against 372. A marker now only counts when the character before it is
not part of an identifier.
doccheck was ported without a behavioural change and
proved by differential rejection rather than by agreement: both versions
were fed a document naming a missing rule, a missing script, a missing
subcommand and a missing decision, and produced identical output on all
four. Agreement on a clean tree would have proved nothing.
One thing tightened on the way: PROPOSED existed so a
backlog-proposed subcommand would not fail the gate, and its comment
claimed a proposal that ships "fails loudly when the name is added for
real". It did not - a name in both lists was accepted silently, and
consensus had been in both for some time. The Rust reports
it, which is what the comment always said.
Next: compat.py, protocol.py,
protocol-selftest.py, then the analysis scripts, then the
generators.