From 76043b7a3a7eaccbf2c8dd87e332795cff9696e1 Mon Sep 17 00:00:00 2001 From: Volt Date: Sun, 18 Oct 2026 00:26:14 +0000 Subject: [PATCH] tools (volt): doc_census_check -- a --tools filter that matches nothing is rc 2, not '0 tools scanned' + rc 0; 35 cells --- tools/doc_census_check.py | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/tools/doc_census_check.py b/tools/doc_census_check.py index 83b9754..72777e1 100644 --- a/tools/doc_census_check.py +++ b/tools/doc_census_check.py @@ -123,7 +123,7 @@ SCOPE, STATED RATHER THAN IMPLIED USAGE python3 doc_census_check.py [--repo DIR] [--rev HEAD] [--tools NAME...] - [--json OUT] [--no-run] [--selftest] # selftest: 33 cells, one per claim class + [--json OUT] [--no-run] [--selftest] # selftest: 35 cells, one per claim class """ import argparse import ast @@ -625,6 +625,14 @@ def _fixture_checks(): counts({**synthetic, "selftest_leg": False})[4], ["no --selftest: leg 2 absent"]) + # --tools: a filter that matches nothing must not read as a clean scan. + check("tools: a bare basename is reported missing, not scanned as zero", + resolve_tools(["checkin_check.py"], {"tools/checkin_check.py"}), + (["checkin_check.py"], ["checkin_check.py"])) + check("tools: no filter means every tracked tool and nothing missing", + resolve_tools(None, {"tools/b.py", "tools/a.py", "README.md"}), + (["tools/a.py", "tools/b.py"], [])) + print(f"selftest: {cells[0]} cells, {cells[0] - bad[0]} passed, {bad[0]} failed") return 0 if ok else 1 @@ -872,6 +880,17 @@ def counts(rep): len(rep["verdicts"]), notes) +def resolve_tools(requested, tree): + """(tools, missing). A requested name that is not tracked at the rev is + REPORTED, never silently dropped: `--tools checkin_check.py` (a bare + basename instead of a repo-relative path) scanned zero tools and exited 0, + which reads exactly like a clean pass. Measured 2026-10-18 at 8932d06.""" + if not requested: + return sorted(p for p in tree + if p.startswith("tools/") and p.endswith(".py")), [] + return list(requested), [t for t in requested if t not in tree] + + def main(): ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) @@ -889,11 +908,16 @@ def main(): store = git(a.repo, "ls-tree", "-r", "--name-only", a.rev) tree = {p for p in store.decode("utf-8", "replace").split("\n") if p} - tools = a.tools or sorted(p for p in tree - if p.startswith("tools/") and p.endswith(".py")) + tools, missing = resolve_tools(a.tools, tree) if not tools: print(f"no tools found at {a.rev}", file=sys.stderr) return 2 + if missing: + print(f"cannot grade: --tools names nothing tracked at {a.rev}: " + f"{', '.join(missing)}", file=sys.stderr) + print(" names are repo-relative, e.g. --tools tools/checkin_check.py; " + "a filter that matches nothing is not a clean scan", file=sys.stderr) + return 2 cache, reports = {}, [] with tempfile.TemporaryDirectory(prefix="doccensus-") as tmpdir: