From cb8cab58a84af7e95a9c8e63ce8d5c91f0199ce3 Mon Sep 17 00:00:00 2001 From: David F Glidden Date: Mon, 31 Aug 2026 11:49:02 +0200 Subject: [PATCH] [FIX] REVIEWED-132: widen the register-integrity control to the record MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Option (a) on conditions 1-4. The check read only REVIEWED.md, only `##`, and only headers starting with the literal word AMENDMENT. It now reads all three registers at `##` and `###`, recognises ADDENDUM, and computes `originals` across registers because a parent may be archived while its amendment stays open. Condition 1's default is inverted: a header is an ORIGINAL only if it carries an identifier and no marker. Compound headers are excluded from originals, not admitted to them, so an ADDENDUM can no longer satisfy "an un-amended entry exists" on behalf of a record that was replaced. Condition 3 did its job on my own code. Enumerating rather than counting returned 89 against the item's 82; the surplus was six prose titles — "Citation amendment (#2)", "Dream amendment" — matched by an upper-cased containment test and struck off `originals`, which is the mirror of the bug being fixed and would have raised false "the record was replaced" findings. Markers are now uppercase standalone tokens, with controls in both directions. The enumeration then agrees with the item's method at 82; the remaining +1 against the filed table is this session's own later filing, reported rather than reconciled away. ⚠ The widening is the floor, not the fix: 48 of the blocks carry no item number and are reported NOT ESTABLISHED, never passed. The prospective-convention question belongs to PENDING-146 and is deliberately not decided here (cond. 5). Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01Wn9mxsFjHJkzYjuDdrtxwp --- scripts/governance-drift-check.py | 180 ++++++++++++++++++++++++------ 1 file changed, 145 insertions(+), 35 deletions(-) diff --git a/scripts/governance-drift-check.py b/scripts/governance-drift-check.py index 33c8e48..5447545 100755 --- a/scripts/governance-drift-check.py +++ b/scripts/governance-drift-check.py @@ -213,48 +213,137 @@ control("doctrine-id citing surface is reachable", # Detection only, like every check here: REVIEWED.md is [ESCALATE], the # steward's hand (Constitutional Constraint #1). REVIEWED_MD = HOME / "dotfiles" / "REVIEWED.md" +PENDING_MD = HOME / "dotfiles" / "PENDING.md" +PENDING_ARCHIVE_MD = HOME / "dotfiles" / "PENDING-archive.md" -RE_HEAD = re.compile(r"^##\s+REVIEWED-(\d+)\s*[—-]\s*(.*)$", re.M) -RE_AMENDS = re.compile(r"\*\*Amends:\*\*\s*REVIEWED-(\d+)") +# WIDENED 2026-08-31 under REVIEWED-132 (PENDING-173 + ADDENDUM 1). The check was +# narrowed three times without declaring any of them: the header regex and the +# **Amends:** regex both hard-coded REVIEWED-, and the amendment test was +# startswith("AMENDMENT"). It saw 3 of the 81 amendment-shaped blocks in the +# registers, and — worse — an ADDENDUM was classified as an ORIGINAL, so it could +# have satisfied its own "an un-amended entry exists" test on behalf of a record +# that had been replaced. +# +# ⚠ WIDENING IS THE FLOOR, NOT THE FIX. 48 of the 81 blocks carry NO item number +# (`### AMENDMENT 1 — 2026-08-08`) and are attributable only by which header sits +# above them. No id-keyed reader can check those; they are reported NOT ESTABLISHED, +# never passed. The prospective-convention question is PENDING-146's, deliberately +# not decided here (REVIEWED-132 condition 5). +MARKERS = ("AMENDMENT", "ADDENDUM") +RE_MARKER_TOKEN = re.compile(r"\b(?:AMENDMENT|ADDENDUM)\b") +RE_HEAD_LINE = re.compile(r"^#{2,3}\s+(.*)$", re.M) +RE_ID = re.compile(r"^((?:PENDING|REVIEWED|COMPLETED)\S*)\s*[—–-]\s*(.*)$") +RE_INBODY = re.compile(r"^\*\*(?:AMENDMENT|ADDENDUM)\b.*$", re.M) +RE_AMENDS = re.compile(r"\*\*Amends:\*\*\s*((?:PENDING|REVIEWED|COMPLETED)-\S+?)[\s,.(]") + +# Every form the controls below actually exercise. A form found in the record and +# absent from this set is reported NOT ESTABLISHED rather than silently passed +# (REVIEWED-132 condition 2) — the check may not certify what it has never been shown. +FORMS_COVERED = {"id+marker", "id-only", "bare-marker", "in-body", "compound"} -def register_findings(text: str, label: str) -> list[str]: - """Every amendment must sit ALONGSIDE the record it amends, never replace it.""" - out: list[str] = [] - heads = RE_HEAD.findall(text) - originals = {n for n, rest in heads - if not rest.strip().upper().startswith("AMENDMENT")} - for n, rest in heads: - if rest.strip().upper().startswith("AMENDMENT") and n not in originals: - out.append(f"{label}: '## REVIEWED-{n} — AMENDMENT' exists with no " - f"un-amended REVIEWED-{n} entry — the amendment replaced " - f"the record it amends") - for n in sorted(set(RE_AMENDS.findall(text))): - if n not in originals: - out.append(f"{label}: a block declares '**Amends:** REVIEWED-{n}' but " - f"no REVIEWED-{n} entry exists in the file") - return out +def _classify(head: str): + """-> (form, ident|None, title). One place decides what a header is.""" + m = RE_ID.match(head.strip()) + if not m: + up = head.strip().upper() + return ("bare-marker" if any(up.startswith(k) for k in MARKERS) else "prose"), None, head + ident, rest = m.group(1), m.group(2) + s = rest.strip() + if any(s.startswith(k) for k in MARKERS): + return "id+marker", ident, rest + if RE_MARKER_TOKEN.search(s): + # A marker somewhere other than the start — "BUILD RECORD + AMENDMENT 1 result". + # Condition 1: NOT admitted to originals. Excluded, and made visible. + return "compound", ident, rest + # ⚠ CASE IS LOAD-BEARING, found 2026-08-31 by the enumeration REVIEWED-132 cond. 3 + # requires. An earlier draft upper-cased the title first, so prose titles — "Citation + # amendment (#2)", "Dream amendment", "PENDING-46 addendum (2026-07-03)" — matched and + # were struck from `originals`. That is the mirror of the bug this widening repairs: + # it would raise FALSE "the record was replaced" findings about six real originals. + # Markers in this register are uppercase standalone tokens; a lower-case mention in a + # title is a title. + return "id-only", ident, rest -reg_findings: list[str] = [] -if REVIEWED_MD.exists(): - reg_findings = register_findings(REVIEWED_MD.read_text(errors="replace"), - "REVIEWED.md") +def register_scan(texts: dict) -> tuple: + """-> (findings, unattributable, forms_seen). -# Controls. The third is the one that matters and is the lesson of the day: -# a check that has never fired on a known-bad input is unestablished, so the -# instrument is run against a synthetic reproduction of the actual failure. + `originals` is computed across ALL registers, because a parent may have been + archived while its amendment stays open; the old per-file rule would have + called that a replacement. A header is an original ONLY if it carries an + identifier and no marker anywhere — everything else is excluded (condition 1), + which is the opposite default from the version this replaces. + """ + parsed, forms = {}, {} + for label, text in texts.items(): + rows = [_classify(h) for h in RE_HEAD_LINE.findall(text)] + rows += [("in-body", None, ln.strip()) for ln in RE_INBODY.findall(text)] + parsed[label] = rows + for form, _i, _r in rows: + if form != "prose": + forms.setdefault(form, set()).add(label) + originals = {i for rows in parsed.values() for f, i, _ in rows + if f == "id-only" and i} + findings, unattributable = [], [] + for label, rows in parsed.items(): + for form, ident, title in rows: + if form == "id+marker" and ident not in originals: + findings.append(f"{label}: '{ident} — {title[:48]}' exists with no " + f"un-amended {ident} entry — the amendment replaced " + f"the record it amends") + elif form in ("bare-marker", "in-body"): + unattributable.append((label, form, title[:72])) + for ident in sorted(set(RE_AMENDS.findall(text := texts[label]))): + if ident not in originals: + findings.append(f"{label}: a block declares '**Amends:** {ident}' but " + f"no un-amended {ident} entry exists in any register") + return findings, unattributable, forms + + +_TEXTS = {p.name: p.read_text(errors="replace") + for p in (REVIEWED_MD, PENDING_MD, PENDING_ARCHIVE_MD) if p.exists()} +reg_findings, reg_unattrib, reg_forms = ([], [], {}) if not _TEXTS else register_scan(_TEXTS) +reg_uncovered = sorted(set(reg_forms) - FORMS_COVERED - {"prose"}) + +# Controls. Drawn from the census, not from the author's memory of the convention +# (REVIEWED-132 condition 2): ADDENDUM headers, ### depth, in-body forms and +# PENDING-side instances are all exercised, because all four are in the record. _GOOD = ("## REVIEWED-87 — PENDING-99 — original\n**Date:** 2026-08-05\n\n" "## REVIEGH\n\n## REVIEWED-87 — AMENDMENT 2026-08-07\n" "**Amends:** REVIEWED-87 (x).\n") _BAD = ("## REVIEWED-87 — AMENDMENT 2026-08-07\n" "**Amends:** REVIEWED-87 (x).\n") -control("register parser finds REVIEWED headings", len(RE_HEAD.findall(_GOOD)) == 2) -control("register check passes a correctly JOINED amendment", - not register_findings(_GOOD, "t")) +_ADDENDUM_BAD = "## PENDING-142 — ADDENDUM 1: the selftest encodes the defect\n" +_ADDENDUM_OK = ("## PENDING-142 — the parent\n\n" + "### PENDING-142 — ADDENDUM 1: joined, at ### depth\n") +_BARE = "## PENDING-9 — parent\n\n### AMENDMENT 1 — 2026-08-08, no item number\n" + +_f_good, _u_good, _ = register_scan({"t": _GOOD}) +_f_bad, _, _ = register_scan({"t": _BAD}) +_f_add, _, _ = register_scan({"t": _ADDENDUM_BAD}) +_f_addok, _, _ = register_scan({"t": _ADDENDUM_OK}) +_f_bare, _u_bare, _ = register_scan({"t": _BARE}) + +control("register check passes a correctly JOINED amendment", not _f_good) control("register check DETECTS an amendment that replaced its record " - "[reproduces the 2026-08-07 loss]", - len(register_findings(_BAD, "t")) == 2) + "[reproduces the 2026-08-07 loss]", len(_f_bad) == 2) +control("register check DETECTS a replacing ADDENDUM [the word the old test could " + "not see; it classified this as an ORIGINAL and passed]", len(_f_add) == 1) +control("register check passes a JOINED ### addendum [must-not-flag: ### depth is " + "the register's own placement form]", not _f_addok) +control("an unnumbered '### AMENDMENT 1' is NOT ESTABLISHED, never passed", + any(f == "bare-marker" for _l, f, _t in _u_bare) and not _f_bare) +_PROSE = "## PENDING-60 — Citation amendment (#2): specify the CTS-URN model\n" +_f_prose, _, _fm_prose = register_scan({"t": _PROSE}) +control("a lower-case 'amendment' in a TITLE stays an ORIGINAL [must-not-flag: the " + "mirror bug — it would strike six real originals off the list]", + "id-only" in _fm_prose and not _f_prose) +control("an UPPER-CASE marker mid-title is still excluded from originals [must-detect]", + "compound" in register_scan( + {"t": "## PENDING-164 — BUILD RECORD + AMENDMENT 1 result\n"})[2]) +control("PENDING-side registers are actually read", "PENDING.md" in _TEXTS) +control("every form present in the record is covered by a control", not reg_uncovered) control("register file is reachable", REVIEWED_MD.exists()) @@ -779,11 +868,32 @@ if reg_findings: print(f" {f}") print("\n An amendment must sit alongside the record it amends, never replace it.") print(" Correction requires [ESCALATE] — REVIEWED.md is the steward's hand.") -elif REVIEWED_MD.exists(): - n_am = sum(1 for _, r in RE_HEAD.findall(REVIEWED_MD.read_text(errors="replace")) - if r.strip().upper().startswith("AMENDMENT")) - print(f"✓ register integrity: every amendment link resolves " - f"({n_am} amendment(s) checked)") +elif _TEXTS: + # REVIEWED-132 condition 3: ENUMERATE, do not count. The old line reported a + # bare number and that number never moved when a matching block was appended. + _checked = {} + for _lab, _txt in _TEXTS.items(): + _rows = [_classify(h) for h in RE_HEAD_LINE.findall(_txt)] + _rows += [("in-body", None, "") for _ in RE_INBODY.findall(_txt)] + for _f, _i, _r in _rows: + if _f != "prose" and _f != "id-only": + _checked.setdefault(_lab, {}).setdefault(_f, 0) + _checked[_lab][_f] += 1 + _tot = sum(sum(d.values()) for d in _checked.values()) + _att = sum(c for d in _checked.values() for f, c in d.items() + if f in ("id+marker", "compound")) + print(f"✓ register integrity: {_att} attributable amendment block(s) checked, " + f"all resolve — of {_tot} amendment-shaped block(s) across " + f"{len(_TEXTS)} register(s)") + for _lab in sorted(_checked): + print(" " + _lab + ": " + ", ".join(f"{f}={c}" for f, c in sorted(_checked[_lab].items()))) + if reg_unattrib: + print(f" ⚠ {len(reg_unattrib)} block(s) NOT ESTABLISHED — they carry no item " + f"identifier, so no id-keyed reader can say what they amend. Counted, " + f"never passed. The convention question is PENDING-146's.") + if reg_uncovered: + print(f" ⚠ NOT ESTABLISHED — form(s) present in the record with no control: " + f"{', '.join(reg_uncovered)}") # Built-without-a-ruling. THREE-VALUED (REVIEWED-106): clean / findings / cannot-assess. if not build_assessable: