checkin 2026-10-17 (volt): six tools -- unreadable input no longer reads as clean

Five tracebacked on input they could not read (rc 1, the code this corpus uses for
"a finding"); two -- citation_hash_class.py, citation_resolve_check.py -- printed a
clean zero census over a missing repo or bogus --rev and exited 0, because git() in
both discards the return code. Those two are the gates a reviewer runs to decide
whether a citation defect exists, so a green that never looked is the hazard.

queue_index.py / queue_claim_check.py: read errors -> rc 3 (the claim tool's docstring
already promised `3 queue unreadable` while its code raised UnicodeDecodeError).
citation_hash_class.py / citation_resolve_check.py: precondition(repo, rev) -> rc 2,
matching doc_census_check.py and landing_check.py. check_lint.py / census_row_delta.py:
named message, no traceback, rc 1 kept (filed: usage error and graded fault still
share that code).

175 insertions(+), 14 deletions(-). Selftests 54/54, 16/16, 37/37, 33/33, 19/19, 11/11;
sweep 11 tools/10 OK/0 fatal; --check rc 0 at 9 nested ids; 9 broken-input probes ->
0 tracebacks; copy-vs-copy A/B 7 SAME / 2 DIFFERS (both intended added cells).
run.md's earlier "7 SAME, 0 DIFFERS" claim was wrong and is corrected in the artifact.
This commit is contained in:
timmy committed 2026-10-17 19:58:45 +00:00
1 parent 676be46ef8
commit 016d26eae7
7 files changed
+236 -14

No files matched your search

+66 -6
View File
@@ -78,7 +78,12 @@ WHAT IT DOES NOT DO
about the queue's currency and not about the last person to write a checkin.
`--check` exit codes: 0 current, 1 stale (with the delta printed), 2 the
document carries no parseable pinned block.
document carries no parseable pinned block, 3 the queue or the document could
not be read at all (missing path, or bytes that are not UTF-8). An unreadable
input is a precondition failure, never a stale index and never a traceback:
`--queue` at a missing path or at a binary used to raise FileNotFoundError /
UnicodeDecodeError out of `run()` with rc 1, which reads like "stale" to every
caller that only checks the exit code.
READ-ONLY except `--json PATH` and `--write PATH`.
@@ -88,7 +93,7 @@ USAGE
python3 tools/queue_index.py --json out.json
python3 tools/queue_index.py --write docs/queue-index.md
python3 tools/queue_index.py --check docs/queue-index.md
python3 tools/queue_index.py --selftest # fixture corpus, 46 cells
python3 tools/queue_index.py --selftest # fixture corpus, 54 cells
Re-run `--write` after any append to the queue. The document carries the
queue's sha256, so a stale copy is a RED check, never a silent lie.
@@ -480,12 +485,27 @@ def delta(pinned, fresh):
def run(args):
repo = args.repo
queue_path = os.path.join(repo, args.queue)
with open(queue_path, encoding="utf-8") as fh:
text = fh.read()
# A read failure is an exit code, not a traceback. `--queue` pointed at a
# missing path or at bytes that are not UTF-8 raised FileNotFoundError /
# UnicodeDecodeError straight out of run(), so the operator got a stack and
# rc 1 while every other reader in this repo (`queue_claim_check.py:558-563`)
# says `cannot read queue:` and exits 3. The same contract is owed to the
# --check document: a gate that cannot read its input has verified nothing,
# and must not report that as a stale index (rc 1) or a crash.
try:
with open(queue_path, encoding="utf-8") as fh:
text = fh.read()
except (OSError, UnicodeDecodeError) as exc:
print("cannot read queue: %s" % exc, file=sys.stderr)
return 3
payload = parse(text)
if args.check:
doc = open(args.check, encoding="utf-8").read()
try:
doc = open(args.check, encoding="utf-8").read()
except (OSError, UnicodeDecodeError) as exc:
print("cannot read index document: %s" % exc, file=sys.stderr)
return 3
pinned = extract_pinned(doc)
if pinned is None:
print("UNVERIFIABLE: no parseable pinned block in %s" % args.check)
@@ -749,6 +769,46 @@ def selftest():
check("no pin -> exit 2", rc, 2)
check("no pin -> says so", "UNVERIFIABLE" in buf.getvalue(), True)
# --- a read error is an exit code, not a traceback -----------------------
# `--queue` at a missing path or at bytes that are not UTF-8 used to raise
# straight out of run() (FileNotFoundError / UnicodeDecodeError, rc 1). The
# repo's other reader exits 3 with `cannot read queue:`; this tool now does
# the same, and owes the --check document the same answer: an unreadable
# gate input is rc 3, never the rc 1 that means "stale".
bad_q = os.path.join(root, "bad-utf8.md")
with open(bad_q, "wb") as fh:
fh.write(b"\xff\xfe\x80\n")
err = io.StringIO()
with contextlib.redirect_stderr(err):
rc = run(argparse.Namespace(repo=root, queue="missing-queue.md", index=False,
json=None, write=None, check=None, outside=False))
check("missing queue -> exit 3", rc, 3)
check("missing queue -> says cannot read queue",
err.getvalue().startswith("cannot read queue:"), True)
err = io.StringIO()
with contextlib.redirect_stderr(err):
rc = run(argparse.Namespace(repo=root, queue="bad-utf8.md", index=False,
json=None, write=None, check=None, outside=False))
check("non-UTF-8 queue -> exit 3", rc, 3)
check("non-UTF-8 queue -> says cannot read queue",
"cannot read queue:" in err.getvalue(), True)
err = io.StringIO()
with contextlib.redirect_stderr(err):
rc = run(argparse.Namespace(repo=repo, queue="WORK-QUEUE.md", index=False,
json=None, write=None,
check=os.path.join(repo, "missing-index.md"),
outside=False))
check("missing index document -> exit 3", rc, 3)
check("missing index document -> names the document",
"cannot read index document:" in err.getvalue(), True)
err = io.StringIO()
with contextlib.redirect_stderr(err):
rc = run(argparse.Namespace(repo=repo, queue="WORK-QUEUE.md", index=False,
json=None, write=None, check=bad_q, outside=False))
check("non-UTF-8 index document -> exit 3", rc, 3)
check("non-UTF-8 index document -> names the document",
"cannot read index document:" in err.getvalue(), True)
print("selftest: %d cells, %d passed, %d failed" % (cells[0], cells[0] - bad[0], bad[0]))
return 1 if bad[0] else 0
@@ -765,7 +825,7 @@ def main(argv=None):
ap.add_argument("--check", metavar="PATH", help="re-derive and compare a rendered index")
ap.add_argument("--outside", action="store_true",
help="report ids the prose corpus names that the queue never mentions")
ap.add_argument("--selftest", action="store_true", help="fixture corpus, 46 cells")
ap.add_argument("--selftest", action="store_true", help="fixture corpus, 54 cells")
args = ap.parse_args(argv)
if args.selftest:
return selftest()