From c3766b8ca087c65b5a551c56dfebfaa75f2ab476 Mon Sep 17 00:00:00 2001 From: volt Date: Sat, 17 Oct 2026 17:23:53 +0000 Subject: [PATCH] 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 --- checkins/2026-10-17-volt.md | 11 +++++++++++ tools/queue_index.py | 30 ++++++++++++++++++++++++++---- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/checkins/2026-10-17-volt.md b/checkins/2026-10-17-volt.md index 4109258..bda7648 100644 --- a/checkins/2026-10-17-volt.md +++ b/checkins/2026-10-17-volt.md @@ -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: `sweep: 11 tools, 10 OK, 0 fatal` (the one non-OK is `doc_census_check.py` NO_CLAIM, 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 :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. diff --git a/tools/queue_index.py b/tools/queue_index.py index 166772b..97a6472 100644 --- a/tools/queue_index.py +++ b/tools/queue_index.py @@ -88,7 +88,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, 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 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). """ 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): return None skip = {os.path.realpath(p) for p in exclude if p} @@ -511,7 +512,12 @@ def run(args): print("index current: %s" % summary(payload)) 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 :...` blobs. + res = outside_ids(repo, args.queue, exclude=(args.write, args.check)) + outside, corpus = res if res else ({}, 0) if args.outside: 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)) @@ -698,6 +704,22 @@ def selftest(): check("--outside names Q63 and the file that carries it", " 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 :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 with open(queue, "a", encoding="utf-8") as fh: 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("--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, 44 cells") + ap.add_argument("--selftest", action="store_true", help="fixture corpus, 46 cells") args = ap.parse_args(argv) if args.selftest: return selftest()