From bf1798479d6caa40ccfa961ca19ed9075dda1fcc Mon Sep 17 00:00:00 2001 From: kisfenyo Date: Mon, 5 Oct 2026 21:37:22 +0200 Subject: [PATCH] R-422: reuse_refs_check checks .md citations too MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PATH_RE gains .md. The false-positive walk across all four repos found one: an audit document cited by app-catalog's REUSE.md, hidden by the evidence-copy exclusion — excluded trees are now walked for .md documents only, so a .go evidence copy there still never satisfies a citation. The KNOWN HOLE decoy now expects a conviction. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS --- scripts/reuse_refs_check.py | 28 +++++++++++++++++++++++----- scripts/test_gate_decoys.py | 15 ++++++--------- scripts/test_reuse_refs_check.py | 25 +++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 14 deletions(-) diff --git a/scripts/reuse_refs_check.py b/scripts/reuse_refs_check.py index a32caca7..9c2a9ab2 100644 --- a/scripts/reuse_refs_check.py +++ b/scripts/reuse_refs_check.py @@ -37,13 +37,21 @@ scripts/test_reuse_refs_check.py: a citation that exists nowhere still FAILS. """ import io, os, re, sys -# path-looking tokens ending in a checked extension; globs (*) are conventions, not refs -PATH_RE = re.compile(r'[A-Za-z0-9_][A-Za-z0-9_./\-]*/[A-Za-z0-9_./\-]*\.(?:go|py|html|css|yml|yaml|sh)\b') +# path-looking tokens ending in a checked extension; globs (*) are conventions, not refs. +# R-422: `.md` joined the list — a rotted document citation was invisible (measured 2026-09-01: +# `documentation/architecture/99-does-not-exist.md` passed). The false-positive walk across all four +# repos found ONE: an audit document, which the evidence-copy exclusion below hid. See DOC_EXT. +PATH_RE = re.compile(r'[A-Za-z0-9_][A-Za-z0-9_./\-]*/[A-Za-z0-9_./\-]*\.(?:go|py|html|css|yml|yaml|sh|md)\b') # An EVIDENCE COPY of a file is not the file — never let an audit or a test-findings tree satisfy # a citation. `.git`/`vendor`/`node_modules` are excluded as noise. EXCLUDE_NAMES = {".git", "node_modules", "vendor", "audits"} EXCLUDE_RELPATHS = {"documentation/tests"} +# R-422: the exclusion exists so an evidence COPY of a code file cannot satisfy a citation. A document +# under audits/ or documentation/tests is not a copy of anything — it is the cited thing — so `.md` +# files in the excluded trees ARE indexed (and only they). `.git`/`vendor`/`node_modules` stay out. +DOC_EXT = ".md" +NEVER_WALK = {".git", "node_modules", "vendor"} fails = 0 _index_cache = {} @@ -57,14 +65,24 @@ class RepoIndex(object): self.name = os.path.basename(root) self.files = set() # posix-style relpaths self.by_base = {} # basename -> [relpath, ...] + doc_only = set() # excluded trees, walked for .md documents only for dirpath, dirs, filenames in os.walk(root): rel = os.path.relpath(dirpath, root).replace(os.sep, "/") if rel == ".": rel = "" - dirs[:] = [d for d in dirs - if d not in EXCLUDE_NAMES - and ((rel + "/" + d).lstrip("/") not in EXCLUDE_RELPATHS)] + doc_only_here = any(rel == d or rel.startswith(d + "/") for d in doc_only) + keep = [] + for d in dirs: + if d in NEVER_WALK: + continue + drel = (rel + "/" + d).lstrip("/") + if d in EXCLUDE_NAMES or drel in EXCLUDE_RELPATHS: + doc_only.add(drel) # walked for documents only (R-422) + keep.append(d) + dirs[:] = keep for fn in filenames: + if doc_only_here and not fn.endswith(DOC_EXT): + continue p = (rel + "/" + fn).lstrip("/") self.files.add(p) self.by_base.setdefault(fn, []).append(p) diff --git a/scripts/test_gate_decoys.py b/scripts/test_gate_decoys.py index 5297c0d2..dac51288 100644 --- a/scripts/test_gate_decoys.py +++ b/scripts/test_gate_decoys.py @@ -42,7 +42,7 @@ COVERS = { "hub-confirm": "a native confirm() in templates/partials/ (scope was os.listdir)", "manifest-bearer": "a bearer literal in manifests/overlays/ (scope was os.listdir)", "observations": "R-419: prose SAYING it carries no marker, plus both genuine markers", - "reuse-refs": "a cited .go path that does not exist; the .md hole is asserted as R-422", + "reuse-refs": "a cited .go path, and (R-422) a cited .md path, that does not exist", "golden-currency": "R-410: an empty directory with a perfect name, checked by what it COUNTED", "closed-register": ("a verdict cell reading open, a row with no state cell at all, and (RULE 3, " "2026-10-03) a FINISHED row left in OPEN-ITEMS.md — with R-87's shape, a READY " @@ -165,20 +165,17 @@ decoy("observations/genuine-NAF", "observations_gate.py", u"typo, corrected in the same minute.**\n"), args=(ROOT,), expect="accept") # --- reuse-refs: a cited path that does not exist ---------------------------------------------- -# The .go case is REJECTED. The .md case is a KNOWN HOLE (R-422) and is asserted as such below, so -# this file records the hole rather than pretending it is covered. +# Both the .go and (since R-422, 2026-10-05) the .md case are REJECTED. decoy("reuse-refs/missing-go", "reuse_refs_check.py", append_to(os.path.join(ROOT, "REUSE.md"), u"\n- see `hub/internal/api/does_not_exist.go`\n"), args=(ROOT,)) -# --- KNOWN HOLE, asserted so it cannot be forgotten (R-422) ------------------------------------ -# reuse_refs_check.py's PATH_RE matches only go|py|html|css|yml|yaml|sh. A rotted .md citation is -# invisible. This asserts the CURRENT behaviour so the day it is fixed, this test fails and is -# updated deliberately — a hole that nothing asserts is a hole nobody remembers. -decoy("reuse-refs/missing-md (KNOWN HOLE R-422)", "reuse_refs_check.py", +# R-422 CLOSED THE HOLE this decoy used to assert (expect="accept"): PATH_RE now includes .md, so a +# rotted document citation is convicted. Updated deliberately, as the old comment asked. +decoy("reuse-refs/missing-md (R-422)", "reuse_refs_check.py", append_to(os.path.join(ROOT, "REUSE.md"), u"\n- see `documentation/architecture/99-does-not-exist.md`\n"), - args=(ROOT,), expect="accept") + args=(ROOT,)) # --- golden-currency: R-410's own decoy, re-run here so the sweep owns it too ------------------ def _mkdir_decoy(): diff --git a/scripts/test_reuse_refs_check.py b/scripts/test_reuse_refs_check.py index 167f4a72..d39096aa 100644 --- a/scripts/test_reuse_refs_check.py +++ b/scripts/test_reuse_refs_check.py @@ -155,6 +155,31 @@ class ReuseRefsCheckTest(unittest.TestCase): self.assertNotEqual(rc, 0, "an audits/ or documentation/tests/ copy must NOT resolve:\n" + out) self.assertIn("FAILED 2", out) + # ── R-422: document citations are checked ─────────────────────────────────── + def test_absent_md_citation_fails(self): + """The measured hole: a rotted .md citation passed because .md was not a checked extension.""" + self.reuse("see `documentation/architecture/99-does-not-exist.md`\n") + rc, out = self.run_check() + self.assertNotEqual(rc, 0, "a .md citation that exists nowhere must fail:\n" + out) + self.assertIn("99-does-not-exist.md", out) + + def test_md_citation_resolves_including_under_audits(self): + """An audit DOCUMENT is the cited thing, not an evidence copy — it must resolve (the one false + positive the 2026-10-05 walk found, in app-catalog's REUSE.md).""" + write(os.path.join(self.root, "documentation", "architecture", "05-hub.md"), "# x\n") + write(os.path.join(self.root, "documentation", "audits", "SPIKE-x.md"), "# y\n") + self.reuse("see `documentation/architecture/05-hub.md` and `documentation/audits/SPIKE-x.md`\n") + rc, out = self.run_check() + self.assertEqual(rc, 0, out) + + def test_audits_still_hide_code_copies_when_docs_are_indexed(self): + """Indexing .md under audits/ must not let a .go evidence copy there resolve.""" + write(os.path.join(self.root, "documentation", "audits", "pkg", "x.go"), "package pkg\n") + write(os.path.join(self.root, "documentation", "audits", "pkg", "notes.md"), "# n\n") + self.reuse("see `pkg/x.go`\n") + rc, out = self.run_check() + self.assertNotEqual(rc, 0, out) + # ── a clone in isolation must still check itself ──────────────────────────── def test_no_siblings_is_not_a_failure(self): write(os.path.join(self.root, "a", "b.go"), "package a\n")