[FIX] wake-digest: resolve rulings by subject, not by number

sec_pending() suppressed any PENDING-N whose number appeared as a REVIEWED-N,
never checking the ruling was about that item. The two sequences have drifted:
REVIEWED-84 rules on PENDING-87. So PENDING-84 was invisible at wake on the very
morning the steward's pulling thread pointed at it, and closing it later produced
no visible count change because it had never been counted. Found 2026-08-01 at
wake, surfaced not fixed; register row 179.

Resolution now reads the PENDING each ruling names in its header. Rulings that
name none (REVIEWED-78, -81, -82) suppress nothing.

Extracted as ruled_pendings() so it is testable at all -- the logic was buried in
a file-reading routine with no way to exercise it. Five self-tests added,
including the 2026-08-01 bug as a regression control and an empty-input positive
control.

Bounded-change proof against the live files: 18 -> 19 visible. Three items
surfaced that were falsely hidden (PENDING-78, -81, -82); two stopped being shown
that are genuinely ruled (PENDING-87 by REVIEWED-84, PENDING-88 by REVIEWED-85 --
no REVIEWED-87 or -88 exists, so number-matching had never suppressed them).

That proof also caught an overclaim in this fix's own docstring, which asserted
the correction could only ever surface more items and never fewer. It corrects in
both directions. Comment repaired to say what the code does; the false version
would have been a comment promising behaviour the code does not deliver, in a
file whose purpose is to stop governance hiding from the steward.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WuMjg3ipEVa3n8CoSzoyvc
This commit is contained in:
David F Glidden
2026-08-02 11:59:47 +02:00
co-authored by Claude Opus 5
parent 62b92bd425
commit 4dc38e69b9
+39 -2
View File
@@ -132,17 +132,44 @@ def sec_pause():
return newest, span
def ruled_pendings(reviewed_text):
"""
The set of PENDING ids that rulings actually DISPOSE OF.
Resolved by the PENDING each ruling NAMES in its header, never by the REVIEWED
number. Those numbering sequences have drifted apart: REVIEWED-84 rules on
PENDING-87. Matching on the number alone suppressed PENDING-84 from the wake
digest on the very morning the steward's pulling thread pointed at it, and
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.
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.
"""
return set(re.findall(r"^## REVIEWED-\S+\s*—\s*PENDING-(\S+?)\s*—", reviewed_text, re.M))
def sec_pending():
t = read(PENDING)
if t is None:
warn.append("PENDING.md unreadable")
return []
rt = read(REVIEWED) or ""
rev = {m for m in re.findall(r"^## REVIEWED-(\S+)", rt, re.M)}
ruled = ruled_pendings(rt)
items = []
for h, ln in open_items(t):
m = re.match(r"PENDING-(\S+?)\s*—", h)
if m and m.group(1) in rev:
if m and m.group(1) in ruled:
continue
items.append((h, ln, tag_of(t, h)))
if not items:
@@ -452,6 +479,16 @@ def selftest():
chk("tag_of reads a tag",
tag_of("## PENDING-9 — t\n**Date:** d\n**Tag:** [ESCALATE]\n", "PENDING-9 — t") == "[ESCALATE]")
chk("tag_of returns '' when absent", tag_of("## PENDING-9 — t\n", "PENDING-9 — t") == "")
chk("ruled_pendings resolves by the NAMED pending, not the REVIEWED number",
ruled_pendings("## REVIEWED-84 — PENDING-87 — Order attestation") == {"87"})
chk("ruled_pendings does NOT suppress the like-numbered item [the 2026-08-01 bug]",
"84" not in ruled_pendings("## REVIEWED-84 — PENDING-87 — Order attestation"))
chk("ruled_pendings ignores a ruling that names no PENDING",
ruled_pendings("## REVIEWED-82 — Read-only MCP server: eyes on the substrate") == set())
chk("ruled_pendings handles non-numeric families",
ruled_pendings("## REVIEWED-9 — PENDING-S2 — hook-aware deposit") == {"S2"})
chk("ruled_pendings returns empty on empty input [positive control]",
ruled_pendings("") == set())
chk("extract_anchor pulls verbatim",
extract_anchor("noise\n**PULLING THREAD:** do the thing.\n\nmore", "PULLING THREAD")
== "do the thing.")