diff --git a/scripts/decoy_coverage_gate.py b/scripts/decoy_coverage_gate.py index 503e1ba9..0ee8a021 100644 --- a/scripts/decoy_coverage_gate.py +++ b/scripts/decoy_coverage_gate.py @@ -37,9 +37,6 @@ EXEMPT = { ("felhom-controller", "docker-v"): "COVERED IN THE SWEEP, not yet in a suite: an unallowlisted `-v` host path in a new Go file " "was REJECTED (it uses os.walk). R-426 tracks moving it in.", - ("felhom-controller", "offbox-rename"): - "R-425 — the FILES list is fixed, so banned branding in a NEW offbox file is unscanned. The " - "decoy passes today.", ("felhom-controller", "reuse-refs"): "shared script; its decoy lives in felhom.eu/scripts/test_gate_decoys.py.", ("felhom-controller", "instructions"): @@ -134,6 +131,7 @@ def main(argv): roots = argv[1:] or ["."] problems, inconclusive, lines = [], [], [] total = covered = exempt = 0 + stale = [] for root in roots: root = os.path.abspath(root) @@ -168,6 +166,12 @@ def main(argv): if label in covers: covered += 1 lines.append(" COVERED %-22s %-20s %s" % (name, label, covers[label][:60])) + # R-426 (2026-10-06): an exemption for a gate that HAS a decoy is a dead entry that keeps + # the debt list longer than the debt (controller/offbox-rename sat here after R-425 gave it + # decoys). Named, not convicted: the decoy lands in a sibling repo, and failing THIS repo's + # push for another repo's good news would couple the two for no safety gain. + if (name, label) in EXEMPT: + stale.append((name, label)) elif (name, label) in EXEMPT: exempt += 1 lines.append(" exempt %-22s %-20s %s" % (name, label, EXEMPT[(name, label)][:60])) @@ -179,6 +183,11 @@ def main(argv): for l in sorted(lines): print(l) + if stale: + print() + for repo, label in stale: + print(" STALE EXEMPTION: %s / %s has a decoy now — delete its EXEMPT entry (R-426)" % (repo, label)) + if inconclusive: print() for i in inconclusive: diff --git a/scripts/test_gate_decoys.py b/scripts/test_gate_decoys.py index 8d1f3eea..27dccb05 100644 --- a/scripts/test_gate_decoys.py +++ b/scripts/test_gate_decoys.py @@ -414,6 +414,23 @@ elif "decoy-red-proof" not in _out: else: print(" ok %-20s a new gate with no decoy is convicted BY NAME" % "decoy-coverage") +# ...and its STALE-EXEMPTION notice (R-426, 2026-10-06): an EXEMPT entry for a gate that has a decoy must be +# NAMED, or the debt list reads longer than the debt (controller/offbox-rename sat there after R-425). +ran += 1 +_DCG = os.path.join(ROOT, "scripts", "decoy_coverage_gate.py") +_dcg = io.open(_DCG, encoding="utf-8").read() +try: + assert "EXEMPT = {\n" in _dcg, "the EXEMPT literal's shape changed — this check can no longer be built" + io.open(_DCG, "w", encoding="utf-8").write(_dcg.replace( + "EXEMPT = {\n", 'EXEMPT = {\n ("felhom.eu", "site"): "decoy: a stale entry for a covered gate",\n', 1)) + _rc, _out = gate("decoy_coverage_gate.py", (ROOT,)) +finally: + io.open(_DCG, "w", encoding="utf-8").write(_dcg) +if "STALE EXEMPTION: felhom.eu / site" not in _out: + fails.append("decoy-coverage: an EXEMPT entry for a COVERED gate was not named as stale\n%s" % _out[-400:]) +else: + print(" ok %-20s a stale exemption is NAMED" % "decoy-coverage") + # ── guide-quote (R-596) ────────────────────────────────────────────────────────────────────────── # # Its decoys build whole fake workspaces (a guide plus a sibling controller clone), which does not