Files
felhom.eu/scripts/register_shape_gate.py
T
admin 3159892fab
gates / gates (push) Successful in 27s
Both rulings built: same-tag re-tests (decision 52), image retention + the install hold (controller 0.284.2); golden 0.284.2
- Decision 52: catalog 6a3ead9 (re-test entries, gates, decoys, the monthly command); proven end to end on 9202
  through the leg; runbook monthly-floating-retest.md; nothing to re-test on the engine lines today.
- Decision 53 + R-741: controller v0.284.2 (0.284.0/0.284.1 never floored — two wiring faults found live on 9202);
  floor 0.284.2; one-time sweep 9202 26.6 -> 5.7 GB, demo-hp 24.3 -> 13.5 GB; the install hold proven as a stranger.
- Golden 0.284.2 baked, round-trip identical, vouched (agent 0.138.0, min_agent 0.131.0); the gate prints OK.
- Rows 377 -> 383: opened R-743..R-748, closed R-736, R-737, R-740, R-741, R-748; narrowed R-739, R-698, R-446.
- register_shape_gate: a lettered id (R-88a) is a row too (R-748), with a decoy seen red.

Evidence: documentation/audits/night-rulings-2026-09-30/, documentation/tests/golden-0.284.2-2026-09-30/.
Report: REPORT-night-rulings-2026-09-30.md.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-09-30 23:26:21 +02:00

133 lines
6.3 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""register_shape_gate.py — OPEN-ITEMS.md is a TABLE, and a table has a shape (R-627, 2026-09-22).
WHAT IT CONVICTS ON (a FAIL, exit 1), four rules and nothing else:
RULE 1 — every register row (`| **R-nnn** | …`) ends with `|`, so it HAS a state cell.
RULE 2 — reserved. **There is deliberately no cell-COUNT rule, and that is a measurement, not an
omission.** The first draft counted cells and convicted 125 innocent rows: register cells
carry literal `|` characters inside their prose and their shell snippets (`owner: CC |
…`, `--format '{{.Names}}|{{.Image}}'`), so splitting a row on `|` does not yield its
cells. A count that cannot be computed is not a check. RULE 1 catches the thing that
actually breaks — a row whose state cell was eaten — because such a row stops ending
with a pipe.
RULE 3 — no `R-` identifier appears on more than one row.
RULE 4 — no blank line sits between two register rows. A blank line ENDS a markdown table, so
the rows after it render as a separate table — and, worse, a script that walks "the
table" stops there.
WHY IT EXISTS, and the cost that bought it. On 2026-09-21 the update night appended measured
results to eight existing rows with a regex that matched a row's trailing state cell. On two rows
(**R-446** and **R-458**) it consumed the state cell and did not put it back; the cell reappeared as
a stray FOURTH cell on a duplicated copy of a different row (**R-626** and **R-625**), and a blank
line was left between each pair. The register then reported **317 rows for 315 findings**, two rows
carried no state at all, and two findings existed twice with contradictory state cells.
**Nothing caught it.** `one_register_gate.py` compares OPEN-ITEMS against ROADMAP; `closed_register_gate.py`
forbids an id in BOTH OPEN and CLOSED — neither asks whether the file is a well-formed table, and
neither notices an id duplicated WITHIN OPEN-ITEMS. It was found the next morning by a person
reading the file. **A register that silently mis-states how many findings exist is the one file in
this project that must not be able to do that**, because every standing rule says "grep the register
before minting" and every count in every report is read off it.
WHAT THIS GATE CANNOT SEE — the residual holes, named rather than implied:
1. **A row whose state cell is WRONG but present.** Shape is not meaning. A row that says READY
when it is closed passes here and is `closed_register_gate.py`'s business.
2. **A row whose text was truncated mid-sentence** but still ends with a valid state cell. Only a
human or a diff against the previous commit sees that.
3. **The DUE-CHECKS block and the other tables in this file.** This gate reads register rows only
— lines that begin `| **R-`. The file's other tables are `due_checks_gate.py`'s business.
USAGE
python3 scripts/register_shape_gate.py # the real register
python3 scripts/register_shape_gate.py <file> # any file, for the red-proof
Exit: 0 clean · 1 convicted.
"""
import re
import sys
from pathlib import Path
ROW = re.compile(r'^\| \*\*(R-\d+[a-z]?)\*\* \|') # 2026-09-30: a letter suffix (R-88a, R-88b, R-209a) is a row too — it was skipped, 3 rows unchecked
REG = Path(__file__).resolve().parent.parent / "documentation" / "backlog" / "OPEN-ITEMS.md"
def cells(line):
"""The cells of a markdown table row, as a reader sees them.
A row is `| a | b | c |`. Stripping the outer pipes and splitting on `|` gives the cells; a row
that forgot its trailing pipe yields one fewer, which is exactly RULE 2's symptom, so RULE 1 and
RULE 2 are reported separately rather than collapsed into one confusing message.
"""
t = line.rstrip()
if not t.endswith("|"):
return None
return t.strip("|").split("|")
SEP = re.compile(r'^\|\s*:?-{2,}:?\s*(\|\s*:?-{2,}:?\s*)*\|\s*$')
def check(path):
lines = Path(path).read_text(encoding="utf-8").split("\n")
bad = []
seen = {}
rows = 0
for i, line in enumerate(lines, start=1):
m = ROW.match(line)
if not m:
continue
rows += 1
rid = m.group(1)
# RULE 3 first, and ALWAYS — a row that also breaks another rule is still a row, and
# skipping it here would under-count the ids and report phantom duplicates. (Measured: the
# first draft skipped them and claimed 5 duplicates where there were 2.)
if rid in seen:
bad.append((i, rid, f"RULE 3 — duplicate: {rid} already has a row at line {seen[rid]}"))
else:
seen[rid] = i
# RULE 1 — the row must end with `|`, i.e. it must still HAVE a state cell
if not line.rstrip().endswith("|"):
bad.append((i, rid, "RULE 1 — the row does not end with `|`, so it has no state cell. "
"This is exactly what an eaten state cell looks like, and what "
"R-446, R-458 (2026-09-21) and R-254 (2026-08-08, unnoticed for 45 "
"days) each looked like."))
# RULE 4 — look back over blanks to the previous non-blank line
j = i - 2
blanks = 0
while j >= 0 and lines[j].strip() == "":
blanks += 1
j -= 1
if blanks and j >= 0 and ROW.match(lines[j]):
bad.append((i, rid, f"RULE 4 — {blanks} blank line(s) between this row and "
f"{ROW.match(lines[j]).group(1)} at line {j+1}. A blank line ends "
f"the markdown table."))
return rows, len(seen), bad
def main():
path = sys.argv[1] if len(sys.argv) > 1 else REG
rows, ids, bad = check(path)
print(f"register-shape: {path}")
print(f"register-shape: {rows} register row(s), {ids} distinct R- id(s)")
if rows != ids:
print(f"register-shape: {rows - ids} row(s) are DUPLICATES")
if not bad:
print("register-shape: OK — every row ends with a state cell, every id is unique, "
"and no blank line splits the table")
return 0
print(f"register-shape: CONVICTED — {len(bad)} problem(s)")
for line_no, rid, why in bad:
print(f" line {line_no} {rid}: {why}")
return 1
if __name__ == "__main__":
sys.exit(main())