diff --git a/PENDING.md b/PENDING.md index d7ca355..f80df1e 100644 --- a/PENDING.md +++ b/PENDING.md @@ -3258,3 +3258,26 @@ The third is the sharpest: **both halves are in the same document**, so this is **Awaiting:** Steward authorization on the standing rule. The arrears above are already paid. --- +## PENDING-142 — ADDENDUM 3: jurist ruling received; docstring corrected under it; and the drift-check's subject is one file +**Date:** 2026-08-17 +**Tag:** [HARDENING] +**Summary:** The jurist has design-gated the parent item. Recorded here pending steward placement in `~/REVIEWED.md` — the executor does not write that file. + +**Jurist ruling (2026-08-17), as received:** +- **(d) as the frame, with (a) and (b) inside it** — as recommended. Reasoning given: (d) is the only option that makes the tool report its own limit rather than guess, **and Class A is unfixable by (a) or (b)** — those two items can never be closed by any ruling, so `UNDETERMINED` is the only honest value for them. +- **CONDITION on (b):** the enumeration of closing verbs **must default to NOT CLOSED on any verb it does not recognize**, or it reproduces the gate-on-the-class trap. *(This is the ladder's "gate on the class, not the instances" applied to the remedy — the trap that produced the parent defect.)* +- **The docstring is to be ruled on separately and corrected without waiting for the mechanism**, since it is a false claim regardless of which option wins. +- ⚠ The jurist identifies **"the acceptance check may not be a count" as the load-bearing sentence of the parent item, not the option list.** Recorded so that a later implementer does not read the options as the substance. +- The jurist verified PENDING-142's body and REVIEWED-78's Notes **directly against the substrate rather than accepting the executor's report of them.** Both confirmed verbatim. Noted because it is the condition under which this ruling has any independent value — REVIEWED-116 pt 7's limit, closed by access. + +**EXECUTED under the docstring half** (`[FIX]`, this session): `ruled_pendings`'s docstring no longer asserts that REVIEWED-78/-81/-82 are *"like-numbered rulings … concerning other matters"* that had *"falsely hidden"* three items. It now records the opposite, which is what the substrate says: they are the authorized rulings on those items, like-numbered **on purpose**, per REVIEWED-78's own quoted Notes — so surfacing them was a **regression, not a repair**, and they have read open since 2026-07-28. The superseded wording is retained in the note rather than overwritten. + +**NEW FINDING, arising from the jurist's observation and verified: the instrument that reports drift is not itself instrumented.** `governance-drift-check.py`'s subject is exactly one file — `~/CLAUDE.md` (`CLAUDE_MD = HOME / "dotfiles" / "CLAUDE.md"`); nothing else is read for substrate-contradicted claims. But the scripts *implementing* the governance checks are dense with substrate claims of their own — docstrings citing measurements, provenance comments naming commits and rulings, inline notes asserting what a check does and does not establish. **None of it is checked by anything.** One confirmed instance today: `ruled_pendings`'s docstring carried a false claim about three live governance items for weeks and was found by a jurist relay, not by an instrument. That is the same class the drift-check was built for, one layer in, where the drift-check cannot see. +- **Not asserted:** how many other such claims exist. A census of factual claims in `scripts/` has not been run and its cost is unknown; the claim here is that the coverage gap is real and has one confirmed occupant, not that the population is large. +- **Options:** (i) extend the drift-check's subject to the scripts' docstrings — hard, prose claims are not machine-checkable in general; (ii) require any docstring making a *checkable* substrate claim to carry the check beside it, as the selftest already does for behaviour; (iii) accept the gap and record it, so a clean drift-check is never read as "no false claims in governance tooling." +- **Recommendation: (iii) now, (ii) as practice.** (i) is the trap this whole item is about — building a cleverer parser to infer truth from prose that was never constrained to carry it. ⚠ And whatever is done, the drift-check's clean line should say what it does **not** cover; today it reads as a verdict on governance state and is a verdict on one file. + +**Steward decisions outstanding on this item:** the option ruling (jurist recommends (d)+(a)+(b) with the not-recognized-defaults-to-open condition); whether the drift-check-coverage finding stays folded here or is split into its own item; and **PENDING-121, which its own ruling holds open and the tool has hidden since REVIEWED-110** — the design-gate class is 3 items (121, 124, 128), of which only 121 is asserted; 124 and 128 remain flagged undetermined, not claimed. +**Awaiting:** Steward. The jurist ruling above needs placement in `~/REVIEWED.md` by the steward's hand. + +--- diff --git a/scripts/wake-digest.py b/scripts/wake-digest.py index b0fc658..361fceb 100755 --- a/scripts/wake-digest.py +++ b/scripts/wake-digest.py @@ -367,18 +367,39 @@ def ruled_pendings(reviewed_text): closing that item later produced no visible change because it had never been counted. Measured at the time: 9 suppressed, 8 correctly, 1 falsely. - A ruling whose header names no PENDING (REVIEWED-78, -81, -82 …) suppresses - nothing. + A ruling whose header names no PENDING suppresses nothing — which is the rule's + correct behaviour in general and its FALSE-OPEN class in particular. See below. The correction runs in BOTH directions, and an earlier draft of this docstring claimed otherwise — that it could only ever surface more, never fewer. That was an overclaim, caught by the change proof rather than by reading. Measured against - the live files at the time of the fix: 3 items surfaced that had been falsely - hidden (PENDING-78, -81, -82 — like-numbered rulings exist, concerning other - matters), and 2 stopped being shown that were genuinely ruled (PENDING-87 by - REVIEWED-84, PENDING-88 by REVIEWED-85 — no REVIEWED-87 or -88 exists, so the - number-match had never suppressed them). Net 18 → 19 visible. Number-matching - was wrong in both directions; only subject-matching is right in either. + the live files at the time of the fix: 3 items surfaced (PENDING-78, -81, -82), + and 2 stopped being shown that were genuinely ruled (PENDING-87 by REVIEWED-84, + PENDING-88 by REVIEWED-85 — no REVIEWED-87 or -88 exists, so the number-match had + never suppressed them). Net 18 → 19 visible. + + ⚠ CORRECTED 2026-08-17 (PENDING-142; jurist-ruled to correct independently of the + mechanism). This docstring previously described those 3 as *"falsely hidden"* by + "like-numbered rulings … concerning other matters." **Both halves are false, and + the substrate says so in its own words.** REVIEWED-78/-81/-82 are the AUTHORIZED + rulings ON PENDING-78/-81/-82 — same date (2026-07-28), same titles verbatim, and + REVIEWED-81 names "PENDING-81" twice in its body. They are like-numbered ON + PURPOSE: REVIEWED-78's own Notes state it was filed as a separate entry + *"for a mechanical reason: the closure rule in `wake-digest.py` matches a PENDING + item to `REVIEWED-`, so a cross-numbered closure stated only in prose + would leave PENDING-78 listed as open at every wake."* + + So the number→subject fix broke the three entries that had been deliberately + authored to satisfy the rule it replaced, and then recorded their compliance as + coincidence. Surfacing them was a REGRESSION, not a repair; they have read open + since 2026-07-28. The change proof could not see it because it measured a COUNT + (18 → 19) while the claim was about each item's disposition — and the counts stay + equal: removing 3 false-opens and restoring 3 false-closeds both leave 29. + + Number-matching was wrong in both directions. Subject-matching is right in + neither until it matches on the SUBJECT — the title or the decision — rather than + on the presence of an id token in a header. Remedy is PENDING-142, unbuilt; this + note exists so the code does not keep asserting the opposite while it waits. """ return set(re.findall(r"^## REVIEWED-\S+\s*—\s*PENDING-(\S+?)\s*—", reviewed_text, re.M))