volt: path_claim_check --baseline default is now applied (bare run == named run); selftest cell c20; false RED under --fail-on-missing gone

This commit is contained in:
volt committed 2026-10-21 00:35:08 +00:00
1 parent 6cd2114377
commit b882336fa6
3 files changed
+104 -18

No files matched your search

+71 -7
View File
@@ -66,16 +66,20 @@ EXIT CODES
1 --fail-on-missing and at least one MISSING path is not in the baseline, or
names a class the ledger does not tolerate.
2 could not grade: not a git work tree, a revision that does not resolve, a
corpus with no markdown, a baseline that cannot be read or names an
unknown class. Never 0, and never a silent empty census.
corpus with no markdown, a NAMED baseline that cannot be read or names an
unknown class. Never 0, and never a silent empty census. A repo that
carries no ledger of its own is not this: `--baseline` defaults to
tools/path_claim_baseline.tsv resolved against --repo, and a tree without
that file is graded with no ledger after one note on stderr.
USAGE
python3 path_claim_check.py [--repo DIR] [--rev HEAD] [--corpus PATH...]
[--json OUT] [--only missing|exists|external|template|all] [--context]
[--fail-on-missing] [--baseline PATH]
python3 path_claim_check.py --selftest # 19 cells
python3 path_claim_check.py --repo . --fail-on-missing \\
--baseline tools/path_claim_baseline.tsv
--baseline defaults to tools/path_claim_baseline.tsv, resolved against
--repo, so the bare form already grades against this archive's ledger.
python3 path_claim_check.py --selftest # 20 cells
python3 path_claim_check.py --repo . --fail-on-missing
"""
import argparse
import collections
@@ -87,6 +91,16 @@ import sys
DEFAULT_REPO = "/root/troupe-standup"
# The ledger this archive carries, REPO-relative: resolved against --repo, not
# against the caller's cwd, so a bare run against a clone reads that clone's
# ledger. Until 2026-10-21 this was advertised in USAGE and never applied --
# `--baseline` had no default, so a bare invocation graded against an empty
# ledger and, under --fail-on-missing, returned rc 1 for an archive whose own
# rows excuse seven of the ten MISSING paths. A default a reader can cite and
# the code does not apply is the worst kind: it makes the tool lie in the
# direction of a defect.
DEFAULT_BASELINE = "tools/path_claim_baseline.tsv"
# The extensions this archive actually names. A closed list, for the reason
# citation_resolve_check.py gives: an open `\\.[a-z]+` swallows clock times,
# decimals and domain names.
@@ -319,6 +333,30 @@ def report(rows, stats, rev, sha, corpus, ledger, path, only, context):
print(" ...%s..." % r["context"])
def resolve_baseline(repo, path):
"""The ledger to grade against, or None when this repo carries none.
`path` is repo-relative by contract (DEFAULT_BASELINE), so it is joined onto
`repo` before the existence test: a bare run from another cwd must read the
tree it is grading, never a file beside the caller. An absolute path is
taken as given. A caller who NAMED a ledger that is not there gets the path
back unchanged, so load_baseline refuses it with rc 2 -- a mistyped ledger
must never read as "no ledger". A repo that simply carries none (a fixture
tree) is a stated reading: one note on stderr, no ledger, and the census
still prints, because the count is the finding.
"""
if not path:
return None
cand = path if os.path.isabs(path) else os.path.join(repo, path)
if os.path.exists(cand):
return cand
if path == DEFAULT_BASELINE:
print("note: no ledger at %s -- every MISSING path counts as new" % cand,
file=sys.stderr)
return None
return cand
def main():
ap = argparse.ArgumentParser(description=__doc__,
formatter_class=argparse.RawDescriptionHelpFormatter)
@@ -330,7 +368,9 @@ def main():
"all"], default="missing")
ap.add_argument("--context", action="store_true")
ap.add_argument("--fail-on-missing", action="store_true")
ap.add_argument("--baseline")
ap.add_argument("--baseline", default=DEFAULT_BASELINE,
help="ledger to grade MISSING rows against (default: "
"%s, resolved against --repo)" % DEFAULT_BASELINE)
ap.add_argument("--selftest", action="store_true")
a = ap.parse_args()
@@ -349,7 +389,8 @@ def main():
if not corpus:
raise CannotGrade("cannot grade: no markdown corpus at %s in %s"
% (a.rev, a.repo))
ledger = load_baseline(a.baseline) if a.baseline else None
ledger = resolve_baseline(a.repo, a.baseline)
ledger = load_baseline(ledger) if ledger else None
rows, stats = scan(a.repo, a.rev, corpus, store)
except CannotGrade as exc:
print(str(exc), file=sys.stderr)
@@ -517,6 +558,29 @@ def selftest():
rc == 0 and "tolerated EXAMPLE" in out and "1 matched" in out,
"rc=%d %s" % (rc, out[-300:]))
# --- the default ledger is the one the tree carries ---------------------
# Until 2026-10-21 `--baseline` had NO default while USAGE advertised one:
# a bare run graded against an empty ledger, so `--fail-on-missing` returned
# rc 1 for a tree whose own rows excused the path. This pins bare == named.
with open(os.path.join(repo, "tools", "path_claim_baseline.tsv"), "w") as fh:
fh.write("# fixture: the ledger this tree carries\n"
"docs/absent.md\tPLANTED\tfixture row, carried by the tree\n")
subprocess.run(["git", "-C", repo, "add", "-A"], capture_output=True)
subprocess.run(["git", "-C", repo, "-c", "user.email=t@t", "-c", "user.name=t",
"commit", "-qm", "ledger"], capture_output=True)
def summary(text):
return [ln for ln in text.splitlines() if ln.startswith("path_claim_check:")]
bare_rc, bare_out = run("--repo", repo, "--fail-on-missing")
named_rc, named_out = run("--repo", repo, "--fail-on-missing", "--baseline",
os.path.join(repo, "tools", "path_claim_baseline.tsv"))
cell("c20 the repo's own ledger is the default: bare run == named run",
bare_rc == named_rc == 0 and summary(bare_out) == summary(named_out)
and "1 matched" in bare_out,
"bare rc=%d %r | named rc=%d %r"
% (bare_rc, summary(bare_out), named_rc, summary(named_out)))
print("selftest: %d cells, %d passed, %d failed" % (n, n - bad, bad))
return 0 if bad == 0 else 1