diff --git a/tools/re/check-capture-citations b/tools/re/check-capture-citations index 616f6018..e691e7c8 100755 --- a/tools/re/check-capture-citations +++ b/tools/re/check-capture-citations @@ -41,6 +41,14 @@ CITE = re.compile(r"(?:docs/re/)?captures/[A-Za-z0-9._/-]+") CITE_ERE = r"(docs/re/)?captures/[A-Za-z0-9._/-]+" # Where a citation may live. Prose AND code: tests and tools open these files. SEARCH = ["docs", "crates", "tools", "port", "authored"] +# 🔴 AND NOT THIS FILE. `SEARCH` includes `tools`, so the scan read *itself* -- +# and `selftest()`'s planted fixture below is a literal capture path. The check +# therefore reported a dangling citation to a file that will never exist, and +# exited 1 on a clean checkout, for ever. A gate that is red before anyone +# changes anything teaches people to ignore it. +# Excluding only this one file keeps every other tool in scope; a real citation +# belongs in a page or a tool that opens the capture, never in the checker. +SELF = ":!tools/re/check-capture-citations" def git(*args: str) -> str: @@ -67,7 +75,7 @@ def committed() -> tuple[set[str], set[str]]: def cited() -> set[str]: - raw = git("grep", "-rhoE", CITE_ERE, "--", *SEARCH).splitlines() + raw = git("grep", "-rhoE", CITE_ERE, "--", *SEARCH, SELF).splitlines() out = set() for line in raw: c = line.split(":")[-1] @@ -98,7 +106,7 @@ def named_bare() -> set[str]: out = set() for line in git("grep", "-rhoE", r"[A-Za-z0-9._-]+\.(png|jpg|csv|log|txt|json|jsonl|bin|tsv)", - "--", *SEARCH).splitlines(): + "--", *SEARCH, SELF).splitlines(): out.add(line.split(":")[-1].strip()) return out @@ -151,7 +159,16 @@ def selftest() -> int: print(" %-34s %s (%d citations found)" % ("citation gathering works", "ok" if gathering_ok else "🔴 FAILED", len(refs))) - ok = gathering_ok + # 🔴 REGRESSION GUARD FOR `SELF`. The planted fixture above is a literal + # capture path living in a file `SEARCH` covers. Before the exclusion + # existed the scan counted it as a real citation, so the check reported a + # dangling capture and exited 1 on a clean tree — permanently. If anyone + # drops `SELF`, this goes red here instead of in everybody else's run. + fixture_counted = cases[0][1] in refs + print(" %-34s %s" + % ("own fixtures not counted", "🔴 FAILED" if fixture_counted else "ok")) + + ok = gathering_ok and not fixture_counted for name, path, want in cases: got = resolves(path.rstrip(".,;:)`"), files, dirs) mark = "ok" if got == want else "🔴 FAILED"