tools (volt): reply_check's two spelled class counts were both wrong, and four cells now grade them (37 -> 41 cells)

The control plane measured them at 16:52Z: the docstring said 'Five classes
are graded' over a seven-row enumeration and 'Three more are counted and
printed' over four, while FAULTS holds 7 and ADVISORIES holds 4. Prose is not
executed and doc_census_check.py reads only '<digits> <unit>', so a spelled
count has no reader at all.

Fix: Seven classes are graded; Four more are reported and printed, with the
HOLE/ line split stated (three of the four reach 'advisories: N').

Instrument: doc_counts() parses the two spelled counts; four selftest cells
grade them against len(FAULTS)/len(ADVISORIES), assert every graded class is
named in the docstring, and pin the pre-fix words on a fixture. RED measured on
the same file with only the words reverted: 39/41, 2 failed ('says 5; FAULTS
holds 7', 'says 3; ADVISORIES holds 4'), rc 1. GREEN: 41/41 rc 0.

Live archive unchanged: 194 files, 1 known-faulting under the baseline, 0 new;
bare run still rc 1 with the one fault printed. verify.py 5/5 rc 0 (sweep 15
tools, 15 OK). doc_census_check --fail: 0 STALE, rc 0. ruff F,E9 clean.
This commit is contained in:
volt committed 2026-10-19 21:07:35 +00:00
1 parent a3766c60d2
commit 8bee8257d9
1 file changed
+61 -6
+61 -6
View File
@@ -19,7 +19,7 @@ WHY THIS EXISTS
WHAT IT MEASURES (read-only; the only write path is --json) WHAT IT MEASURES (read-only; the only write path is --json)
Every `*.md` under --dir except `README.md` is one ROW. The filename gives Every `*.md` under --dir except `README.md` is one ROW. The filename gives
(date, recipient, number); the first `# ` heading in the file gives what the (date, recipient, number); the first `# ` heading in the file gives what the
file says about itself. Five classes are graded: file says about itself. Seven classes are graded:
NAME_MALFORMED the filename is neither the numbered contract form nor NAME_MALFORMED the filename is neither the numbered contract form nor
the one unnumbered legacy form -- the row is skipped the one unnumbered legacy form -- the row is skipped
@@ -39,9 +39,11 @@ WHAT IT MEASURES (read-only; the only write path is --json)
FAULT: "the next free integer in that recipient's own FAULT: "the next free integer in that recipient's own
series" cannot produce the same integer twice. series" cannot produce the same integer twice.
Three more are counted and printed, and are ADVISORY by construction -- each Four more are reported and printed, and are ADVISORY by construction -- each
is a stated consequence of history that predates the naming rule, not a is a stated consequence of history that predates the naming rule, not a
defect this tool can attribute to a writer: defect this tool can attribute to a writer. Three of the four reach the
`advisories: N` count; HOLE rides the `series:` line instead, because a hole
belongs to a recipient's series and not to any one file:
LEGACY_UNNUMBERED the one legacy form (no `-<N>`). Its number is implicit LEGACY_UNNUMBERED the one legacy form (no `-<N>`). Its number is implicit
in its position, so numbering rules skip it. in its position, so numbering rules skip it.
@@ -86,15 +88,17 @@ BASELINE -- the archive's one fault, stated instead of hidden
The ledger names the tolerance, and the row stays visible in every report. The ledger names the tolerance, and the row stays visible in every report.
SELFTEST SELFTEST
`--selftest` grades 37 cells, building every fixture in a fresh temporary `--selftest` grades 41 cells, building every fixture in a fresh temporary
directory: each fault class fires on a fixture that carries it and only the directory: each fault class fires on a fixture that carries it and only the
classes that belong there (a wrong addressee, a wrong number, a duplicate classes that belong there (a wrong addressee, a wrong number, a duplicate
number, an impossible date, a missing heading, a malformed name, non-UTF-8 number, an impossible date, a missing heading, a malformed name, non-UTF-8
bytes), the advisory classes stay advisory and exit 0 (legacy form, hole, bytes), the advisory classes stay advisory and exit 0 (legacy form, hole,
heading that names nobody), the prefix match accepts a hyphenated handle, heading that names nobody), the prefix match accepts a hyphenated handle,
README.md is not a row, and both rc 2 paths (missing directory, file where a README.md is not a row, and both rc 2 paths (missing directory, file where a
directory belongs) answer 2. A rule that stops firing and a rule that fires directory belongs) answer 2. Four cells grade this docstring's own census --
everywhere both fail a cell. the two spelled class counts against FAULTS/ADVISORIES, every graded class
named here, and the pre-fix words refused on a fixture. A rule that stops
firing and a rule that fires everywhere both fail a cell.
""" """
import argparse import argparse
@@ -119,6 +123,35 @@ FAULTS = ("NAME_MALFORMED", "BAD_DATE", "NO_HEADER", "UNREADABLE",
ADVISORIES = ("LEGACY_UNNUMBERED", "NO_RECIPIENT_IN_HEADING", ADVISORIES = ("LEGACY_UNNUMBERED", "NO_RECIPIENT_IN_HEADING",
"NO_NUMBER_IN_HEADING", "HOLE") "NO_NUMBER_IN_HEADING", "HOLE")
WORD_NUMBERS = {"one": 1, "two": 2, "three": 3, "four": 4, "five": 5, "six": 6,
"seven": 7, "eight": 8, "nine": 9, "ten": 10, "eleven": 11,
"twelve": 12}
# The docstring's two spelled counts, and the sentence each lives in. A spelled
# count is invisible to doc_census_check.py, which reads `<digits> <unit>` only,
# so these are the claims that drift with no instrument watching them: on
# 2026-10-19 the control plane measured `Five` over a seven-row table and
# `Three` over four rows, and carried the class to this lane.
DOC_GRADED_RE = re.compile(r"\b([A-Z][a-z]+) classes are graded\b")
DOC_ADVISORY_RE = re.compile(r"\b([A-Z][a-z]+) more are (?:counted|reported)\b")
def doc_counts(doc=None):
"""The docstring's two spelled counts -> (graded, advisory); None if absent.
`doc` is a parameter rather than `__doc__` read inside the function so the
selftest can grade a fixture docstring -- including the pre-fix `Five` /
`Three` pair -- through the same code path the live docstring takes.
"""
text = __doc__ if doc is None else doc
def word(rx):
m = rx.search(text or "")
return WORD_NUMBERS.get(m.group(1).lower()) if m else None
return word(DOC_GRADED_RE), word(DOC_ADVISORY_RE)
def _real_date(y, m, d): def _real_date(y, m, d):
try: try:
@@ -695,6 +728,28 @@ def selftest():
cell("a ledger naming an unknown class exits 2", cell("a ledger naming an unknown class exits 2",
rc(["--dir", ds, "--baseline", bad2]) == 2) rc(["--dir", ds, "--baseline", bad2]) == 2)
# 38-41: the docstring's own census. The two spelled counts live only in
# prose, so nothing graded them until this cell; the enumeration beside each
# one is the copy a reader follows, and FAULTS/ADVISORIES are what the code
# grades. A class added to either table without its docstring row, or a
# count word left behind, fails here rather than in the next reader's quote.
graded_w, advisory_w = doc_counts()
cell("docstring graded-count word matches FAULTS",
graded_w == len(FAULTS),
"docstring says %r; FAULTS holds %d" % (graded_w, len(FAULTS)))
cell("docstring advisory-count word matches ADVISORIES",
advisory_w == len(ADVISORIES),
"docstring says %r; ADVISORIES holds %d" % (advisory_w, len(ADVISORIES)))
unnamed = [c for c in FAULTS + ADVISORIES if c not in (__doc__ or "")]
cell("every class the code grades is named in the docstring",
not unnamed, unnamed)
# the instrument itself, against the words this file carried before the fix
prefix_doc = (" file says about itself. Five classes are graded:\n"
" Three more are counted and printed, and are ADVISORY.\n")
cell("the pre-fix count words are refused",
doc_counts(prefix_doc) != (len(FAULTS), len(ADVISORIES)),
doc_counts(prefix_doc))
failed = [(label, detail) for label, ok, detail in cells if not ok] failed = [(label, detail) for label, ok, detail in cells if not ok]
print("selftest: %d cells, %d passed, %d failed" % print("selftest: %d cells, %d passed, %d failed" %
(len(cells), len(cells) - len(failed), len(failed))) (len(cells), len(cells) - len(failed), len(failed)))