R-428: the gate that hunts label-matching was matching a label (and CI proved it)
gates / gates (push) Successful in 20s

decoy_coverage_gate.py identified a repository by os.path.basename(root), looked up in a RUNNERS
map. Gitea's act-runner checks the repo out into a directory called `hostexecutor`, so on its FIRST
CI run the gate reported "unknown repo 'hostexecutor'" and went INCONCLUSIVE - correctly refusing to
pass, and blind.

A NAME standing in for a FACT, in the first ten lines of the main loop of the gate written that same
morning to catch exactly that, by a session with the four shapes on screen. That is the point of
R-428 and why it is recorded rather than quietly patched: this class is not carelessness.

FIXED: the repo is now identified by which registered runner FILE exists under the root. Verified
under a renamed directory - 14 gates found where the name-based version found none.

CI also now fetches app-catalog-felhom.eu. The meta-gate walks all four runners, and a gate that
cannot see part of its subject must not report a pass on it - the same reasoning, and the same fix,
as the two sibling fetches already in the workflow.

NOTE ON THE OTHER THREE RED RUNS, all mine and all ordering: felhom-agent and felhom-controller cite
R-421, and I pushed them BEFORE felhom.eu carried that row, so instructions_gate correctly convicted
"cites R-421, which appears in neither register". The register lives in felhom.eu; any repo citing a
new row must be pushed after it. Re-run below.
This commit is contained in:
2026-09-01 12:45:42 +02:00
parent 94555614ab
commit 2d88776227
3 changed files with 30 additions and 7 deletions
+16 -7
View File
@@ -158,13 +158,22 @@ def main(argv):
for root in roots:
root = os.path.abspath(root)
name = os.path.basename(root)
if name not in RUNNERS:
inconclusive.append("unknown repo %r — no runner registered for it" % name)
continue
runner = os.path.join(root, RUNNERS[name])
if not os.path.isfile(runner):
inconclusive.append("%s: runner not found at %s" % (name, runner))
# ⚠ IDENTIFY THE REPO BY ITS RUNNER, NOT BY ITS DIRECTORY NAME.
#
# This gate asked `os.path.basename(root)` and looked the answer up in RUNNERS — a NAME
# standing in for a FACT, which is the exact class this gate was written to catch. It went
# INCONCLUSIVE on its first CI run because Gitea's act-runner checks the repo out into a
# directory called `hostexecutor`. **The gate that hunts label-matching was matching a
# label.** Measured 2026-09-01, CI job 490. Now: whichever registered runner FILE actually
# exists under this root is what the repo is.
name, runner = None, None
for cand, rel in RUNNERS.items():
if os.path.isfile(os.path.join(root, rel)):
name, runner = cand, os.path.join(root, rel)
break
if name is None:
inconclusive.append("no known gate runner found under %s — tried %s"
% (root, ", ".join(sorted(RUNNERS.values()))))
continue
labels = gates_of(runner)
if labels is None: