R-426: decoy-coverage names stale exemptions; dead offbox-rename entry removed
controller/offbox-rename kept its EXEMPT entry after R-425 gave it decoys, so the debt list read longer than the debt. The gate now prints a STALE EXEMPTION line for any exempt gate that has a decoy (named, not convicted: the decoy lands in a sibling repo, and failing this repo's push for it would couple the two). A check in test_gate_decoys.py plants a stale entry and asserts it is named; seen to fail with the notice removed. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
@@ -37,9 +37,6 @@ EXEMPT = {
|
|||||||
("felhom-controller", "docker-v"):
|
("felhom-controller", "docker-v"):
|
||||||
"COVERED IN THE SWEEP, not yet in a suite: an unallowlisted `-v` host path in a new Go file "
|
"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.",
|
"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"):
|
("felhom-controller", "reuse-refs"):
|
||||||
"shared script; its decoy lives in felhom.eu/scripts/test_gate_decoys.py.",
|
"shared script; its decoy lives in felhom.eu/scripts/test_gate_decoys.py.",
|
||||||
("felhom-controller", "instructions"):
|
("felhom-controller", "instructions"):
|
||||||
@@ -134,6 +131,7 @@ def main(argv):
|
|||||||
roots = argv[1:] or ["."]
|
roots = argv[1:] or ["."]
|
||||||
problems, inconclusive, lines = [], [], []
|
problems, inconclusive, lines = [], [], []
|
||||||
total = covered = exempt = 0
|
total = covered = exempt = 0
|
||||||
|
stale = []
|
||||||
|
|
||||||
for root in roots:
|
for root in roots:
|
||||||
root = os.path.abspath(root)
|
root = os.path.abspath(root)
|
||||||
@@ -168,6 +166,12 @@ def main(argv):
|
|||||||
if label in covers:
|
if label in covers:
|
||||||
covered += 1
|
covered += 1
|
||||||
lines.append(" COVERED %-22s %-20s %s" % (name, label, covers[label][:60]))
|
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:
|
elif (name, label) in EXEMPT:
|
||||||
exempt += 1
|
exempt += 1
|
||||||
lines.append(" exempt %-22s %-20s %s" % (name, label, EXEMPT[(name, label)][:60]))
|
lines.append(" exempt %-22s %-20s %s" % (name, label, EXEMPT[(name, label)][:60]))
|
||||||
@@ -179,6 +183,11 @@ def main(argv):
|
|||||||
for l in sorted(lines):
|
for l in sorted(lines):
|
||||||
print(l)
|
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:
|
if inconclusive:
|
||||||
print()
|
print()
|
||||||
for i in inconclusive:
|
for i in inconclusive:
|
||||||
|
|||||||
@@ -414,6 +414,23 @@ elif "decoy-red-proof" not in _out:
|
|||||||
else:
|
else:
|
||||||
print(" ok %-20s a new gate with no decoy is convicted BY NAME" % "decoy-coverage")
|
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) ──────────────────────────────────────────────────────────────────────────
|
# ── guide-quote (R-596) ──────────────────────────────────────────────────────────────────────────
|
||||||
#
|
#
|
||||||
# Its decoys build whole fake workspaces (a guide plus a sibling controller clone), which does not
|
# Its decoys build whole fake workspaces (a guide plus a sibling controller clone), which does not
|
||||||
|
|||||||
Reference in New Issue
Block a user