3159892fab
gates / gates (push) Successful in 27s
- 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
133 lines
6.3 KiB
Python
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())
|