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:
1 parent
676be46ef8
commit
016d26eae7
7 files changed
+236
-14
No files matched your search
+66
-6
@@ -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()
|
||||
|
||||
Reference in new issue
Block a user