the decoy sweep: 29 gates read, 16 fooled, 10 fixed - and a gate that refuses the next one (R-421)
gates / gates (push) Failing after 17s
gates / gates (push) Failing after 17s
THE CLASS, now a row: an instrument that matches a LABEL rather than the fact it names. Five instances - R-410, R-400, R-378, R-419, R-94 - and EVERY ONE was found by accident, by someone looking at something else. The gates enforce every other rule in this project, including the rule that findings must be written down rather than left in prose. Nothing had ever checked the gates. METHOD, and it is the transferable part: for each gate, construct the label WITHOUT the fact - a directory with the right name and no bake log, a handler case that exists only in a comment, a note whose prose mentions the marker it lacks - run the gate, record what it says. No verdict was reached by reading. Reading is how all five hid. RESULT: 29 distinct scripts (35 registrations; three are shared across three runners). 19 sound, 4 holes left OPEN with rows, 6 that no plausible decoy could be built for and are named UNTESTED rather than called sound. A gate nobody tried to fool is UNKNOWN. SCOPE IS A FACT TOO - the largest single cause, and mundane. Eight gates decided what to look at with os.listdir, one level. Every one was green AND CORRECT today, and every one would have gone blind the moment anyone added a subdirectory. mojibake and docker-v already used os.walk, caught the identical planted file, and are the control that proves the cause was the listing and not the decoy. IN THIS REPO: hub-confirm and manifest-bearer now walk. observations_gate (R-419, CLOSED) requires a marker at a line start or after a sentence boundary and strips inline code spans - a note SAYING it carries no marker no longer satisfies the marker test. closed-register now CONVICTS on a row it cannot parse instead of warning: FOUR rows were in that state, TWO of them written by the session that closed them the day before, and every one was exempt from the only check that reads that file. The rows were repaired first and the conviction added second - registering a failing gate refuses every push. THE META-GATE: decoy_coverage_gate.py refuses a gate registered without a decoy or a named exemption. It convicted ITSELF the moment it was registered, which is how it came to have one. Coverage is a DECLARATION the gate AST-parses, never a grep - searching a test file for a gate's name would be the very shape this sweep exists to find. The 20 uncovered gates are listed by name (R-426). NOT FIXED, each with a row and a decoy asserting TODAY's behaviour so the fix must be deliberate: R-422 reuse-refs (only 7 extensions; a rotted .md citation is invisible), R-423 site (PAGES is a hardcoded list of 7), R-424 one-register (a defect parked as `idea`), R-425 offbox-rename (fixed FILES list). R-427: closed_register_gate checks ONE direction - twelve open rows carry a closed verdict and were NOT moved, because telling finished from partly-finished is a judgement and R-378 is the record of a machine getting it wrong. FIVE DECOYS WITHDRAWN AS ILLEGITIMATE, mine, named in the audit. A decoy nobody would write proves nothing, and manufacturing a finding to fill a row is worse than an honest NO. No product code. No version bump. No image. No golden owed. All four runners green. Register: OPEN 172 -> 178, CLOSED 160 -> 161.
This commit is contained in:
@@ -0,0 +1,227 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""test_gate_decoys.py — can this gate be fooled by a LABEL? (R-421)
|
||||
|
||||
WHY THIS FILE EXISTS. Four times in one week a gate turned out to be matching a name instead of the
|
||||
thing it named — R-410 (a `mkdir` turned the release gate green), R-400 (seven debug controls that
|
||||
answered nothing), R-378 (a status word inside a sentence), R-419 (a phrase inside prose, including
|
||||
prose saying the marker was absent). **All four were found by accident.** The gates are the machinery
|
||||
that enforces everything else in this project, and they were the one part nothing checked.
|
||||
|
||||
A DECOY IS THE LABEL WITHOUT THE FACT. Each test below constructs one, runs the real gate, and
|
||||
asserts it CONVICTS. Where a decoy would pass, that is a live hole.
|
||||
|
||||
⚠ A DECOY MUST BE THE SHAPE A REAL SESSION WOULD PRODUCE. R-419 was not found by an absurd input —
|
||||
it was found by a genuine note explaining that it carried no marker. That is the standard. A decoy
|
||||
nobody would ever write proves nothing, and saying so is a result.
|
||||
|
||||
⚠ EVERY TEST ASSERTS BOTH DIRECTIONS where it can. A gate that rejects the decoy AND rejects the
|
||||
genuine article is worse than the hole it replaced.
|
||||
|
||||
Fixtures are planted in the real tree and removed in a `finally`. The suite asserts the tree is
|
||||
unchanged at the end.
|
||||
|
||||
Run from the repo root: python3 scripts/test_gate_decoys.py
|
||||
Exit 0 all decoys rejected · 1 a decoy passed (a live hole).
|
||||
"""
|
||||
import io
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
# ── WHAT THIS FILE COVERS ────────────────────────────────────────────────────────────────────────
|
||||
# Read by scripts/decoy_coverage_gate.py, which AST-parses this literal rather than grepping for
|
||||
# gate names — a substring search for coverage would be the very shape this sweep exists to find.
|
||||
# A gate named here MUST have a decoy below that has been seen to fail.
|
||||
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",
|
||||
"golden-currency": "R-410: an empty directory with a perfect name, checked by what it COUNTED",
|
||||
"closed-register": "a verdict cell reading open, and a row with no state cell at all",
|
||||
"decoy-coverage": "a gate registered in a runner with no decoy and no exemption (its red-proof)",
|
||||
}
|
||||
fails = []
|
||||
ran = 0
|
||||
|
||||
|
||||
def gate(script, args=()):
|
||||
p = subprocess.run([sys.executable, os.path.join("scripts", script)] + list(args),
|
||||
cwd=ROOT, capture_output=True, text=True)
|
||||
return p.returncode, p.stdout + p.stderr
|
||||
|
||||
|
||||
def decoy(name, script, plant, args=(), expect="convict"):
|
||||
"""plant() is a callable returning a cleanup callable."""
|
||||
global ran
|
||||
ran += 1
|
||||
cleanup = plant()
|
||||
try:
|
||||
rc, out = gate(script, args)
|
||||
finally:
|
||||
cleanup()
|
||||
want_nonzero = (expect == "convict")
|
||||
if (rc != 0) != want_nonzero:
|
||||
fails.append("%s: decoy %s (rc=%d)\n%s" %
|
||||
(name, "PASSED - LIVE HOLE" if want_nonzero else "was wrongly convicted",
|
||||
rc, out[-700:]))
|
||||
else:
|
||||
print(" ok %-20s %s" % (name, "decoy rejected" if want_nonzero else "genuine accepted"))
|
||||
|
||||
|
||||
def plant_file(path, content):
|
||||
def _plant():
|
||||
made = []
|
||||
d = os.path.dirname(path)
|
||||
if d and not os.path.isdir(d):
|
||||
os.makedirs(d)
|
||||
made.append(d)
|
||||
io.open(path, "w", encoding="utf-8").write(content)
|
||||
|
||||
def _clean():
|
||||
if os.path.exists(path):
|
||||
os.remove(path)
|
||||
for m in reversed(made):
|
||||
if os.path.isdir(m) and not os.listdir(m):
|
||||
os.rmdir(m)
|
||||
return _clean
|
||||
return _plant
|
||||
|
||||
|
||||
def append_to(path, extra):
|
||||
def _plant():
|
||||
backup = io.open(path, encoding="utf-8").read()
|
||||
io.open(path, "w", encoding="utf-8").write(backup + extra)
|
||||
return lambda: io.open(path, "w", encoding="utf-8").write(backup)
|
||||
return _plant
|
||||
|
||||
|
||||
T = os.path.join(ROOT, "hub", "internal", "web", "templates")
|
||||
M = os.path.join(ROOT, "manifests")
|
||||
REP = os.path.join(ROOT, "REPORT.md")
|
||||
|
||||
print("decoys — felhom.eu")
|
||||
|
||||
# --- hub-confirm: a native confirm() one directory down (R-421) -------------------------------
|
||||
# Shape 1, name-for-fact: the gate used os.listdir, so its SCOPE was a directory listing rather
|
||||
# than the set of templates. There are no subdirectories today; adding templates/partials/ is an
|
||||
# ordinary act and the gate would have stayed green.
|
||||
decoy("hub-confirm/subdir", "hub_confirm_gate.py",
|
||||
plant_file(os.path.join(T, "partials", "decoy.html"),
|
||||
u'<button onclick="confirm(\'biztos?\')">x</button>\n'))
|
||||
|
||||
# --- manifest-bearer: a bearer literal one directory down --------------------------------------
|
||||
decoy("manifest-bearer/subdir", "manifest_bearer_gate.py",
|
||||
plant_file(os.path.join(M, "overlays", "decoy.yaml"),
|
||||
u"apiVersion: v1\ndata:\n token: %s\n" % ("a1b2c3d4" * 8)))
|
||||
|
||||
# --- observations: R-419 itself, and the genuine markers beside it -----------------------------
|
||||
# Shape 2, substring-for-field. THE decoy that found this class: an honest note SAYING it has no
|
||||
# marker satisfied the marker test.
|
||||
decoy("observations/R-419", "observations_gate.py",
|
||||
append_to(REP, u"\n## Observations\n\n1. **A real finding.** It carries no `FILED:` marker "
|
||||
u"and no `NOT-A-FINDING:` marker, deliberately.\n"), args=(ROOT,))
|
||||
decoy("observations/genuine-FILED", "observations_gate.py",
|
||||
append_to(REP, u"\n## Observations\n\n1. **A real finding.** Something broke. "
|
||||
u"**FILED: R-419**\n"), args=(ROOT,), expect="accept")
|
||||
decoy("observations/genuine-NAF", "observations_gate.py",
|
||||
append_to(REP, u"\n## Observations\n\n1. **A real finding.** Odd. **NOT-A-FINDING: my own "
|
||||
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.
|
||||
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",
|
||||
append_to(os.path.join(ROOT, "REUSE.md"),
|
||||
u"\n- see `documentation/architecture/99-does-not-exist.md`\n"),
|
||||
args=(ROOT,), expect="accept")
|
||||
|
||||
# --- golden-currency: R-410's own decoy, re-run here so the sweep owns it too ------------------
|
||||
def _mkdir_decoy():
|
||||
d = os.path.join(ROOT, "documentation", "tests", "golden-9.9.9-2026-01-01")
|
||||
os.makedirs(d)
|
||||
return lambda: os.path.isdir(d) and os.rmdir(d)
|
||||
|
||||
|
||||
def check_golden_names_the_fake():
|
||||
"""golden-currency exits 0 either way when currency is fine — the QUESTION is what it counted."""
|
||||
global ran
|
||||
ran += 1
|
||||
cleanup = _mkdir_decoy()
|
||||
try:
|
||||
_rc, out = gate("golden_currency_gate.py")
|
||||
finally:
|
||||
cleanup()
|
||||
if "newest golden baked : 9.9.9" in out:
|
||||
fails.append("golden-currency: an EMPTY directory was counted as a bake — R-410 has regressed")
|
||||
elif "NOT counted as bakes" not in out:
|
||||
fails.append("golden-currency: the empty directory was neither counted nor REPORTED; a "
|
||||
"half-finished bake must be visible, not silently ignored")
|
||||
else:
|
||||
print(" ok %-20s empty dir rejected AND named" % "golden-currency")
|
||||
|
||||
|
||||
check_golden_names_the_fake()
|
||||
|
||||
# --- closed-register: the verdict cell is the predicate, deliberately (R-378) -------------------
|
||||
# NOT a hole: R-378's whole lesson is that an open word ANYWHERE in a row convicts rows that are
|
||||
# genuinely closed. This asserts the deliberate behaviour so a future "fix" has to argue with it.
|
||||
decoy("closed-register/body-word (BY DESIGN)", "closed_register_gate.py",
|
||||
append_to(os.path.join(ROOT, "documentation", "backlog", "CLOSED-ITEMS.md"),
|
||||
u"\n| **R-903** | Work continues and it is still READY in the body. | CLOSED 2026-09-01 | none |\n"),
|
||||
expect="accept")
|
||||
# A 4-column row (| ID | Title | Shipped | Evidence |) whose VERDICT cell reads open.
|
||||
decoy("closed-register/verdict-word", "closed_register_gate.py",
|
||||
append_to(os.path.join(ROOT, "documentation", "backlog", "CLOSED-ITEMS.md"),
|
||||
u"\n| **R-904** | A finished thing. | READY - still being worked on | none |\n"))
|
||||
|
||||
# R-421: a row this gate cannot PARSE used to be a warning, and the gate then printed OK. Four rows
|
||||
# were in that state — two of them written by the session that closed them the day before this
|
||||
# sweep — so they were exempt from the only check that reads this file. An unreadable row is now a
|
||||
# conviction. This is the sweep's own shape one level up and it is why the decoy is kept.
|
||||
decoy("closed-register/unreadable-row", "closed_register_gate.py",
|
||||
append_to(os.path.join(ROOT, "documentation", "backlog", "CLOSED-ITEMS.md"),
|
||||
u"\n| **R-905** | A row with no state cell at all. |\n"))
|
||||
|
||||
# --- decoy-coverage: the meta-gate's own red-proof, kept as a test --------------------------------
|
||||
# It must convict a gate registered in a runner with no decoy and no exemption. Without this the
|
||||
# meta-gate is itself an unchecked instrument, which is the joke this whole sweep exists to avoid.
|
||||
# It also convicted ITSELF the moment it was registered, which is how this decoy came to be written.
|
||||
ran += 1
|
||||
_RUNNER = os.path.join(ROOT, "scripts", "repo_gates.py")
|
||||
_b = io.open(_RUNNER, encoding="utf-8").read()
|
||||
_anchor = ' ("observations", os.path.join(SCRIPTS, "observations_gate.py"), [ROOT], True, False),'
|
||||
try:
|
||||
assert _anchor in _b, "the runner's shape changed — this decoy can no longer be built"
|
||||
io.open(_RUNNER, "w", encoding="utf-8").write(_b.replace(
|
||||
_anchor, _anchor + '\n ("decoy-red-proof", os.path.join(SCRIPTS, "nope.py"), [], True, False),', 1))
|
||||
_rc, _out = gate("decoy_coverage_gate.py", (ROOT,))
|
||||
finally:
|
||||
io.open(_RUNNER, "w", encoding="utf-8").write(_b)
|
||||
if _rc == 0:
|
||||
fails.append("decoy-coverage: a NEW gate with no decoy and no exemption was ACCEPTED — the "
|
||||
"meta-gate cannot see the thing it exists for\n%s" % _out[-500:])
|
||||
elif "decoy-red-proof" not in _out:
|
||||
fails.append("decoy-coverage: it convicted, but did not NAME the uncovered gate")
|
||||
else:
|
||||
print(" ok %-20s a new gate with no decoy is convicted BY NAME" % "decoy-coverage")
|
||||
|
||||
print()
|
||||
if fails:
|
||||
for f in fails:
|
||||
print("FAIL: %s" % f)
|
||||
print("\n%d decoy(s) of %d exposed a hole" % (len(fails), ran))
|
||||
sys.exit(1)
|
||||
print("all %d felhom.eu decoys behaved — labels do not satisfy these gates" % ran)
|
||||
Reference in New Issue
Block a user