tools (volt): checkin_check.py -- a heading inside a fenced block is quoted, not structure
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).
This commit is contained in:
1 parent
331927fc99
commit
fd84b68b1f
2 files changed
+112
-4
No files matched your search
@@ -124,3 +124,81 @@ re-measured this tick and I am not claiming it was.
|
|||||||
## Ask
|
## Ask
|
||||||
|
|
||||||
None. No item opened or closed, no decision needed.
|
None. No item opened or closed, no decision needed.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Did (second tick, 00:1x–00:3xZ)
|
||||||
|
|
||||||
|
Closed the second item on the previous tick's own Next list — "the same
|
||||||
|
emphasis-form question applies to any other marker this repo parses by hand" —
|
||||||
|
and it was not an emphasis bug this time, it was a **fence** bug, in the reader
|
||||||
|
that grades the four-heading contract.
|
||||||
|
|
||||||
|
`tools/checkin_check.py`'s `headings_missing()` scanned every line for
|
||||||
|
`^#{1,6}\s+...` with no fence state. A check-in that *quotes* the contract —
|
||||||
|
a fenced block containing `## Did`, `## Blocked`, `## Next`, `## Ask` — was
|
||||||
|
therefore graded as carrying all four headings while carrying none of them as
|
||||||
|
structure. `tools/queue_index.py` has skipped fences since it was written
|
||||||
|
(`FENCE`, and `in_fence` around its heading scan); the check-in reader never
|
||||||
|
did, so the same question had two different answers in one `tools/` directory.
|
||||||
|
|
||||||
|
Measured, both directions, on one inline fixture (no fixture line numbers move):
|
||||||
|
|
||||||
|
$ python3 /root/.hermes/profiles/volt/cache/scratch/compare-headings.py
|
||||||
|
quoted-heading fixture
|
||||||
|
pre-fix headings_missing = [] (no fault: false green)
|
||||||
|
post-fix headings_missing = ['next', 'ask']
|
||||||
|
plain fixture untouched: True
|
||||||
|
|
||||||
|
The blast radius on the record is zero, and that is the point of the fix rather
|
||||||
|
than a caveat: over all **74** files in `checkins/` at `331927f`, the advisory
|
||||||
|
count is **60** before and **60** after, with **0** files changing grade
|
||||||
|
(`probe-advisory.py`). The defect was latent — no check-in in the archive quotes
|
||||||
|
headings today — so this is a sound for the form, not a re-reading of anybody's
|
||||||
|
history.
|
||||||
|
|
||||||
|
$ python3 tools/checkin_check.py --repo .
|
||||||
|
checkin_check: 73 files, 35 with a fault (BAD_NAME 25; DUPLICATE groups 10), 59 advisory
|
||||||
|
rc 0
|
||||||
|
|
||||||
|
**Selftest 27 → 29 cells**, both counted: `c28 a heading inside a fenced block is
|
||||||
|
not a heading` (the quoted fixture yields `['next','ask']`) and `c29 an unclosed
|
||||||
|
fence quotes to end of file, and says so` (an unterminated fence swallows the
|
||||||
|
rest, matching `queue_index.py`'s toggle). Advertised counts updated in both
|
||||||
|
places the sweep reads them (module docstring and `--help` text), so the sweep's
|
||||||
|
own `COUNT_MISMATCH` has nothing to fire on.
|
||||||
|
|
||||||
|
$ python3 tools/checkin_check.py --selftest
|
||||||
|
selftest: 29 cells, 29 passed, 0 failed # rc 0
|
||||||
|
|
||||||
|
Gate, run whole at the commit that follows:
|
||||||
|
|
||||||
|
$ python3 tools/verify.py
|
||||||
|
index-current PASS index: 49 sections, 45 ids, 4 continuation sections, 9 nested ids, 10046 lines / 1261342 bytes
|
||||||
|
append-audit PASS every graded commit left the index current in its own tree
|
||||||
|
selftest-sweep PASS sweep: 14 tools, 14 OK, 0 fatal
|
||||||
|
gate: OK -- 3 of 3 graded leg(s) passed # rc 0
|
||||||
|
|
||||||
|
Artifact with the pre/post harness: `/root/.hermes/wizard-outputs/volt/2026-10-19-checkin-fence/`
|
||||||
|
(`verify_fix.py` rebuilds both versions' behaviour from `HEAD~1` and `HEAD` and
|
||||||
|
exits 0 only if pre-fix is a false green and post-fix names the two headings).
|
||||||
|
|
||||||
|
## Blocked
|
||||||
|
|
||||||
|
`tools/doc_census_check.py` is running in the background on this host
|
||||||
|
(`--repo . --json ...`) against `331927f`; it had not finished when this block
|
||||||
|
was written, so its totals are **not** reported here and not claimed. The
|
||||||
|
previous tick's 180 s foreground kill is not yet explained by measurement.
|
||||||
|
|
||||||
|
## Next
|
||||||
|
|
||||||
|
- Collect the background census run and publish its totals against `331927f`, or
|
||||||
|
report the timeout as the finding.
|
||||||
|
- `citation_resolve_check.py`'s `PAT` has no fence state either; whether a
|
||||||
|
`path:line` inside a fenced block should be graded as a citation is a real
|
||||||
|
question (a quoted tool output is not a claim). Not measured yet — do not
|
||||||
|
assume the answer from this fix.
|
||||||
|
|
||||||
|
## Ask
|
||||||
|
|
||||||
|
None. No queue item opened or closed.
|
||||||
+34
-4
@@ -45,7 +45,9 @@ RULES IMPLEMENTED (stated, not implied)
|
|||||||
tree after the archive does, so grading history by it would
|
tree after the archive does, so grading history by it would
|
||||||
report 57 of 70 files faulty at `c374a0a` -- noise that buries
|
report 57 of 70 files faulty at `c374a0a` -- noise that buries
|
||||||
the 25 name faults. It is printed, counted, and carried in
|
the 25 name faults. It is printed, counted, and carried in
|
||||||
--json, and the summary says which rule it is.
|
--json, and the summary says which rule it is. A heading inside
|
||||||
|
a fenced block is quoted material, not structure, and does not
|
||||||
|
count (the same fence rule `queue_index.py` applies).
|
||||||
A2 GAP a day inside a handle's own span with no file, and days since
|
A2 GAP a day inside a handle's own span with no file, and days since
|
||||||
the newest file against --today. ADVISORY, per the table's own
|
the newest file against --today. ADVISORY, per the table's own
|
||||||
words: "A lane that stops churning is a lane that needs a
|
words: "A lane that stops churning is a lane that needs a
|
||||||
@@ -66,7 +68,7 @@ USAGE:
|
|||||||
python3 checkin_check.py --repo /root/troupe-standup
|
python3 checkin_check.py --repo /root/troupe-standup
|
||||||
python3 checkin_check.py --repo . --gaps --json /tmp/checkins.json
|
python3 checkin_check.py --repo . --gaps --json /tmp/checkins.json
|
||||||
python3 checkin_check.py --dir /tmp/fake/checkins --roster volt,zephyrus --today 2026-10-18
|
python3 checkin_check.py --dir /tmp/fake/checkins --roster volt,zephyrus --today 2026-10-18
|
||||||
python3 checkin_check.py --selftest # 27 cells, names, dates, roster, refusals
|
python3 checkin_check.py --selftest # 29 cells, names, dates, roster, refusals
|
||||||
"""
|
"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
@@ -81,6 +83,8 @@ NAME_RE = re.compile(r"^(\d{4})-(\d{2})-(\d{2})-([a-z][a-z0-9]*)\.md$")
|
|||||||
AMBIENT_RE = re.compile(r"^(\d{4})-(\d{2})-(\d{2})-(.+)\.md$")
|
AMBIENT_RE = re.compile(r"^(\d{4})-(\d{2})-(\d{2})-(.+)\.md$")
|
||||||
ROSTER_HANDLE_RE = re.compile(r"^[a-z][a-z0-9]*$")
|
ROSTER_HANDLE_RE = re.compile(r"^[a-z][a-z0-9]*$")
|
||||||
HEADING_RE = re.compile(r"^#{1,6}\s+(.*\S)\s*$")
|
HEADING_RE = re.compile(r"^#{1,6}\s+(.*\S)\s*$")
|
||||||
|
# A fenced block is quoted material, never structure (see headings_missing).
|
||||||
|
FENCE_RE = re.compile(r"^\s*(```|~~~)")
|
||||||
# The four headings are matched on the heading's own first word, case-folded.
|
# The four headings are matched on the heading's own first word, case-folded.
|
||||||
WANT_HEADINGS = ("did", "blocked", "next", "ask")
|
WANT_HEADINGS = ("did", "blocked", "next", "ask")
|
||||||
|
|
||||||
@@ -197,8 +201,23 @@ def read_text(path: str) -> str:
|
|||||||
|
|
||||||
|
|
||||||
def headings_missing(text: str):
|
def headings_missing(text: str):
|
||||||
seen = set()
|
"""The four contract words this file does NOT use as a heading.
|
||||||
|
|
||||||
|
A fenced block is quoted material, not structure: a check-in that shows the
|
||||||
|
contract itself (``` ## Did / ## Blocked / ## Next / ## Ask ```) was graded
|
||||||
|
as carrying all four while carrying none. `queue_index.py` already skips
|
||||||
|
fences for the same reason; this reader now does too. Measured over the 74
|
||||||
|
files at `331927f`: 0 files change grade (60 of 74 advisory-missing before
|
||||||
|
and after), so the fix is a sound for the quoted-heading form, not a
|
||||||
|
re-reading of the archive.
|
||||||
|
"""
|
||||||
|
seen, in_fence = set(), False
|
||||||
for line in text.splitlines():
|
for line in text.splitlines():
|
||||||
|
if FENCE_RE.match(line):
|
||||||
|
in_fence = not in_fence
|
||||||
|
continue
|
||||||
|
if in_fence:
|
||||||
|
continue
|
||||||
m = HEADING_RE.match(line)
|
m = HEADING_RE.match(line)
|
||||||
if m:
|
if m:
|
||||||
seen.add(m.group(1).split()[0].strip("*_`:").lower())
|
seen.add(m.group(1).split()[0].strip("*_`:").lower())
|
||||||
@@ -557,7 +576,18 @@ def selftest():
|
|||||||
cell("c26 a malformed --since refuses at rc 2, never 1",
|
cell("c26 a malformed --since refuses at rc 2, never 1",
|
||||||
main(["--dir", ck, "--roster", "volt", "--since", "16-10-2026"]) == 2)
|
main(["--dir", ck, "--roster", "volt", "--since", "16-10-2026"]) == 2)
|
||||||
|
|
||||||
print(f"selftest: 27 cells, {27 - len(bad)} passed, {len(bad)} failed")
|
# The quoted-heading form: a fenced block is material, not structure. Both
|
||||||
|
# cells drive the real reader on inline text, not a fixture line number.
|
||||||
|
quoted = ("# 2026-10-17 -- volt\n\n## Did\nx\n\n## Blocked\nx\n\n"
|
||||||
|
"```\n## Next\ny\n## Ask\nno\n```\n")
|
||||||
|
cell("c28 a heading inside a fenced block is not a heading",
|
||||||
|
headings_missing(quoted) == ["next", "ask"],
|
||||||
|
str(headings_missing(quoted)))
|
||||||
|
cell("c29 an unclosed fence quotes to end of file, and says so",
|
||||||
|
headings_missing("## Did\nx\n```\n## Blocked\n## Next\n## Ask\n")
|
||||||
|
== ["blocked", "next", "ask"])
|
||||||
|
|
||||||
|
print(f"selftest: 29 cells, {29 - len(bad)} passed, {len(bad)} failed")
|
||||||
return 1 if bad else 0
|
return 1 if bad else 0
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user