burn-down round 2: R-593 papra field copy, R-760 vikunja healthcheck reason, R-594 English allow-list, R-605 refusal exit 3, R-781 onboarding decoy clone, R-806 scheme; stale runner test fixed
gates / gates (push) Successful in 4s

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:
2026-10-05 19:15:02 +02:00
parent 29ac711d26
commit 4828dc754d
16 changed files with 536 additions and 50 deletions
+17 -4
View File
@@ -51,7 +51,7 @@ mandated in `CLAUDE.md` the way `site_gates.py` is.
**R-161 stays OPEN at reduced scope:** this is convention, run by a person. Real automatic
enforcement is owed when a second person touches templates.
EXIT CODES. Each gate returns 0 clean / 1 convicted / 2 inconclusive. This runner exits **non-zero if
EXIT CODES. Each gate returns 0 clean / 1 convicted / 2 inconclusive (3 = the harness refused to run, R-605). This runner exits **non-zero if
any gate is non-zero**, and reports 2 distinctly as INCONCLUSIVE — an undetermined result is never a
pass (an app that wrote nothing has not been shown correct; a throttled registry has not shown an
image alive), but it is also not a conviction, and the operator reading the summary needs to know
@@ -119,7 +119,9 @@ GATES = [
("family-gate", "check-family-gate.py", False, True, False),
]
VERDICT = {0: "OK", 1: "FAILED", 2: "INCONCLUSIVE"}
# 3 (R-605): the gate's HARNESS refused to run — its canary failed or it had nothing to judge — so NO app was
# evaluated. It used to share 2's label, and the 2026-09-17 chaos night could not tell afterwards which had happened.
VERDICT = {0: "OK", 1: "FAILED", 2: "INCONCLUSIVE", 3: "DID-NOT-RUN"}
def run_gate(label, script, args):
@@ -195,6 +197,13 @@ def main(argv):
args.append("--range=" + rng)
results.append((label, run_gate(label, script, args)))
return summarise(results)
def summarise(results):
"""Print the summary for [(label, rc)] and return the runner's exit: 0 all OK, 1 any conviction, else 2. A gate
whose harness refused (3) is named apart from one that ran and could not decide (2) — R-605, pinned by
test_catalog_gates.py."""
print("\n" + "=" * 78)
print("== summary")
print("=" * 78)
@@ -208,11 +217,15 @@ def main(argv):
print("\nall catalog gates OK")
return 0
convicted = [l for l, rc in results if rc == 1]
undecided = [l for l, rc in results if rc not in (0, 1)]
refused = [l for l, rc in results if rc == 3]
undecided = [l for l, rc in results if rc not in (0, 1, 3)]
if convicted:
print("\nCONVICTED: %s" % ", ".join(convicted))
if undecided:
print("UNDETERMINED (never a pass): %s" % ", ".join(undecided))
print("UNDETERMINED (it ran; some results could not be decided — never a pass): %s" % ", ".join(undecided))
if refused:
print("DID NOT RUN (the harness refused — its canary failed or it had nothing to judge; NO app was "
"evaluated — never a pass): %s" % ", ".join(refused))
return worst