checkin 2026-10-17 (volt): Q63 follow-up -- queue_index.py --index/--json no longer crash outside a git work tree (outside_ids returns None; run() fallback to {},0, git stderr silenced), two cells added; selftest 46/46, sweep 10 OK/0 fatal, --check rc 0 unchanged at 9 nested ids

This commit is contained in:
volt committed 2026-10-17 17:23:53 +00:00
1 parent e79cbca627
commit c3766b8ca0
2 files changed
+37 -4

No files matched your search

+11
View File
@@ -455,3 +455,14 @@ while the grid printed 44 — a `COUNT_MISMATCH` fatal in the sweep
(`queue_index.py COUNT_MISMATCH 38 cells 44 cells`). Both strings now read 44. Re-run: (`queue_index.py COUNT_MISMATCH 38 cells 44 cells`). Both strings now read 44. Re-run:
`sweep: 11 tools, 10 OK, 0 fatal` (the one non-OK is `doc_census_check.py` NO_CLAIM, `sweep: 11 tools, 10 OK, 0 fatal` (the one non-OK is `doc_census_check.py` NO_CLAIM,
advisory and unchanged). advisory and unchanged).
**Addendum 2 — the verifier found a crash, so the commit grew one fix.** Writing
`verify_q63.sh` against extracted blobs (`git show <rev>:WORK-QUEUE.md` into a directory with
no `.git`) crashed the tool: `outside_ids()` returns `None` outside a work tree and `run()`
did `outside, corpus = outside_ids(...)` → `TypeError: cannot unpack non-iterable NoneType`.
`--index`/`--json` are supposed to work on an extracted copy, so the unpack now falls back to
`({}, 0)` and `git ls-files` writes its stderr to `DEVNULL` instead of the tool's output. Two
new cells hold it: `--index outside a git work tree exits 0` and `… still summarizes` →
**selftest 46 cells, 46 passed, 0 failed**, sweep `11 tools, 10 OK, 0 fatal`, `--check` still
rc 0 at 9 nested ids. This is a second commit on top of `e79cbca`, not a rewrite of it.
+26 -4
View File
@@ -88,7 +88,7 @@ USAGE
python3 tools/queue_index.py --json out.json python3 tools/queue_index.py --json out.json
python3 tools/queue_index.py --write docs/queue-index.md 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 --check docs/queue-index.md
python3 tools/queue_index.py --selftest # fixture corpus, 44 cells python3 tools/queue_index.py --selftest # fixture corpus, 46 cells
Re-run `--write` after any append to the queue. The document carries the 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. queue's sha256, so a stale copy is a RED check, never a silent lie.
@@ -314,7 +314,8 @@ def outside_ids(repo, queue_path, exclude=(), exclude_tools=True):
that (the document added itself to Q63's file list). that (the document added itself to Q63's file list).
""" """
try: try:
out = subprocess.check_output(["git", "-C", repo, "ls-files"], text=True) out = subprocess.check_output(["git", "-C", repo, "ls-files"], text=True,
stderr=subprocess.DEVNULL)
except (subprocess.CalledProcessError, FileNotFoundError): except (subprocess.CalledProcessError, FileNotFoundError):
return None return None
skip = {os.path.realpath(p) for p in exclude if p} skip = {os.path.realpath(p) for p in exclude if p}
@@ -511,7 +512,12 @@ def run(args):
print("index current: %s" % summary(payload)) print("index current: %s" % summary(payload))
return 0 return 0
outside, corpus = outside_ids(repo, args.queue, exclude=(args.write, args.check)) # `outside` is None outside a git work tree (no corpus to speak of); --index
# and --json still work there, which is what makes the tool usable on an
# extracted copy of the queue -- a bare `unpack NoneType` was a crash until
# this line, found by verifying the tool against `git show <rev>:...` blobs.
res = outside_ids(repo, args.queue, exclude=(args.write, args.check))
outside, corpus = res if res else ({}, 0)
if args.outside: if args.outside:
print("outside the queue: %d id(s) named by the %d tracked *.md files read " print("outside the queue: %d id(s) named by the %d tracked *.md files read "
"(`tools/` excluded), which `WORK-QUEUE.md` never mentions" % (len(outside or {}), corpus or 0)) "(`tools/` excluded), which `WORK-QUEUE.md` never mentions" % (len(outside or {}), corpus or 0))
@@ -698,6 +704,22 @@ def selftest():
check("--outside names Q63 and the file that carries it", check("--outside names Q63 and the file that carries it",
" Q63 notes.md" in out, True) " Q63 notes.md" in out, True)
# --- a tree that is not a git repo must still index -----------------------
# The `outside` leg needs git; --index does not. A verifier that extracts
# `git show <rev>:WORK-QUEUE.md` into a temp dir has no .git, and this used to
# crash on `outside, corpus = outside_ids(...)` returning None.
plain = os.path.join(root, "plain")
os.makedirs(plain)
with open(os.path.join(plain, "WORK-QUEUE.md"), "w", encoding="utf-8") as fh:
fh.write(FIXTURE)
buf = io.StringIO()
with contextlib.redirect_stdout(buf):
rc = run(argparse.Namespace(repo=plain, queue="WORK-QUEUE.md", index=True,
json=None, write=None, check=None, outside=False))
check("--index outside a git work tree exits 0", rc, 0)
check("--index outside a git work tree still summarizes",
"index: 4 sections" in buf.getvalue(), True)
# falsify 1: an append moves the last section's extent # falsify 1: an append moves the last section's extent
with open(queue, "a", encoding="utf-8") as fh: with open(queue, "a", encoding="utf-8") as fh:
fh.write("- an appended line.\n") fh.write("- an appended line.\n")
@@ -743,7 +765,7 @@ def main(argv=None):
ap.add_argument("--check", metavar="PATH", help="re-derive and compare a rendered index") ap.add_argument("--check", metavar="PATH", help="re-derive and compare a rendered index")
ap.add_argument("--outside", action="store_true", ap.add_argument("--outside", action="store_true",
help="report ids the prose corpus names that the queue never mentions") help="report ids the prose corpus names that the queue never mentions")
ap.add_argument("--selftest", action="store_true", help="fixture corpus, 44 cells") ap.add_argument("--selftest", action="store_true", help="fixture corpus, 46 cells")
args = ap.parse_args(argv) args = ap.parse_args(argv)
if args.selftest: if args.selftest:
return selftest() return selftest()