From 9f7f19dd2fd811be0adf7f7e4598d1a2b3c98d1d Mon Sep 17 00:00:00 2001 From: David F Glidden Date: Mon, 31 Aug 2026 09:43:16 +0200 Subject: [PATCH] [HARDENING] PENDING-173: the register-integrity control checks 3 of 16 amendment blocks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit register_findings is narrowed three times without declaring any of them: the header regex and the **Amends:** regex both hard-code REVIEWED-, and the amendment test is startswith("AMENDMENT"). PENDING.md is never passed to it, and ADDENDUM blocks are classified as originals — so an addendum could satisfy the "an un-amended entry exists" test on behalf of a record that was replaced. Not realised today; REVIEWED-56 has both its original and its LOCK ADDENDUM. Demonstrated rather than inferred: appending PENDING-172 AMENDMENT 1 did not move the control's count. Recommends widening the instrument, not normalising the headers — REVIEWED-122 condition 5 already declined rewriting placed records for tidiness. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01Wn9mxsFjHJkzYjuDdrtxwp --- PENDING.md | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/PENDING.md b/PENDING.md index f12bd4b..1db0100 100644 --- a/PENDING.md +++ b/PENDING.md @@ -6630,3 +6630,50 @@ The steward's `stop` succeeded and the transient daemon then exited for want of **Files affected:** unchanged from the parent, plus `~/.claude/jobs/*/state.json` as the read surface for option (e). **Awaiting:** Steward authorization (with the parent). + +--- + +## PENDING-173 — The register-integrity control covers one word of a two-word convention, in one of two registers +**Date:** 2026-08-31 +**Tag:** [HARDENING] +**Summary:** `register_findings` in `scripts/governance-drift-check.py` detects an amendment that replaced the record it amends only for blocks whose header begins with the literal word `AMENDMENT`, and only in `REVIEWED.md`. Thirteen of the sixteen amendment-shaped blocks in this system are outside it, and `ADDENDUM` blocks are counted as *originals* — a path by which the control could satisfy its own test on behalf of a record that was in fact replaced. + +**What the control actually does** (`governance-drift-check.py:217–236, 241`): + +```python +RE_HEAD = re.compile(r"^##\s+REVIEWED-(\d+)\s*[—-]\s*(.*)$", re.M) +RE_AMENDS = re.compile(r"\*\*Amends:\*\*\s*REVIEWED-(\d+)") +... +originals = {n for n, rest in heads if not rest.strip().upper().startswith("AMENDMENT")} +... +reg_findings = register_findings(REVIEWED_MD.read_text(...), ...) # called once, on REVIEWED.md only +``` + +Three independent narrowings, none of them declared: the header regex is `REVIEWED-` only; the `**Amends:**` regex is `REVIEWED-` only; and the amendment test is `startswith("AMENDMENT")`. + +**Measured exposure.** + +| register | AMENDMENT headers | ADDENDUM headers | in-body (`**AMENDMENT`/`**ADDENDUM`) | seen by the control | +|---|---|---|---|---| +| `PENDING.md` | 3 | 7 (131 ×4, 142 ×3) | 2 | **0** | +| `PENDING-archive.md` | 0 | 0 | 0 | 0 | +| `REVIEWED.md` | 3 | 1 (`REVIEWED-56 — LOCK ADDENDUM`) | 0 | **3** | + +⇒ **3 of 16 checked.** This was demonstrated, not inferred: appending `PENDING-172 — AMENDMENT 1` did not move the control's count, which reported `3 amendment(s) checked` before and after. + +**⚠ The latent false-negative, stated as latent.** Because `originals` is *everything not starting with `AMENDMENT`*, an `ADDENDUM` block is counted as an original for its number. If `## REVIEWED-N — AMENDMENT` were ever placed over its parent while a `## REVIEWED-N — …ADDENDUM` existed, the addendum would satisfy the "an un-amended entry exists" test and the control would pass on a record that had been replaced — the exact loss it was built for after REVIEWED-87. **This is not realised today:** the one instance, `REVIEWED-56`, has its genuine original at L505 and its `LOCK ADDENDUM` at L530. The path is real; the instance is not. + +**⚠ The controls encode the case that was already known.** `_GOOD`/`_BAD` use the `AMENDMENT` form only, so all four fixtures pass under a predicate blind to `ADDENDUM` and to `PENDING`. Third instance this month of a positive control satisfied by the very narrowing it should have caught (cf. PENDING-171's `owned_repos`, and PENDING-172's respawn path). + +**⚠ Declared limit of this item's own census.** The first count I took returned **3** amendment blocks in `PENDING.md` by matching one header form, and I reported it before noticing that today's other session had filed three more under `ADDENDUM`. The table above is the corrected census. **The root defect is that the convention has three surface forms and no one chose between them**; a checker cannot be clean against a convention that is not. + +**Options.** +- **(a)** Widen the checker to the convention as it actually is: both words, both registers, both header and in-body forms; make `originals` mean "a block that is neither an amendment nor an addendum" rather than "a block not starting with AMENDMENT". +- **(b)** Normalise the convention to one word and then check it. +- **(c)** Both, (a) first. +- **(d)** Nothing; accept that PENDING amendments are unchecked. + +**Recommendation: (a), and explicitly NOT (b).** Normalising means rewriting headers on records already placed, and **REVIEWED-122 condition 5 declined exactly that on principle** when PENDING-110 (c) proposed backfilling three ruling headers. The rule that follows is worth stating once and keeping: **widen the instrument to the record; never rewrite the record to fit the instrument.** (b) would also destroy the distinction the two words may be carrying — an addendum that *adds* versus an amendment that *alters* — which no one has yet established is meaningless. + +**Files affected:** `scripts/governance-drift-check.py` (`RE_HEAD`, `RE_AMENDS`, `register_findings`, its four controls, and the call site at L241). +**Awaiting:** Steward authorization.