[FIX] The closure rule reads three header forms the register writes, and declines a fourth

ruled_pendings() intended to detect "the PENDING ids that rulings actually DISPOSE
OF" and matched exactly one header form. The register writes four. Censused over 132
placed rulings: 80 em-dash single, 3 parenthetical, 1 plus-joined, 1 slash-joined,
47 naming no PENDING at all. Eight items were counted open while ruled — four of
them by the three most recent rulings — which is how the queue reported 64 when 56
was defensible. [FIX] against existing specification: the code failed its own stated
intent, and no ruling widens it.

Also read: closure declared on an item's own **Awaiting:** line. Two items were
counted open with their own bodies saying otherwise (PENDING-82 "CLOSED 2026-08-08",
the STATE-CLAIM marker "DISCHARGED 2026-08-26"), because the rule read headers only.

THE SLASH-JOINED FORM IS DECLINED, AND THAT IS THE LOAD-BEARING PART. Its sole
instance is REVIEWED-116 — PENDING-131/132/133/134, a design gate on a package
rather than a disposition of four items, and PENDING-133's body still reads
"Awaiting: Steward authorization". Reading it would have falsely closed a live item.
Closure detection HIDES items, so an unrecognised form never yields the permissive
answer (REVIEWED-132 condition 1). unreadable_ruling_headers() reports the decline so
the gap is visible rather than looking like a clean pass.

The same reasoning set the body-closure anchor. A bare \bCLOSED\b search of item
bodies matches 20 items, including PENDING-95, -108 and -109 — all live, all merely
discussing closure. Anchored to the Awaiting line it matches exactly the two closed.

Controls are paired throughout: every form that is read has a negative twin holding
the form that must not be. 99 controls pass. Verified end-to-end against the live
register, not by selftest alone: 64 -> 56, and PENDING-133 still visible.

PENDING.md is NOT touched. Widening the instrument to the record is authorized;
normalising the record to fit the instrument is not (REVIEWED-132 §6).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X3L79vgAnt1x2kxvf23Qt7
This commit is contained in:
David F Glidden
2026-09-05 11:10:43 +02:00
co-authored by Claude Opus 5
parent 8031db0e26
commit 9d152f1d48
+91 -5
View File
@@ -74,12 +74,37 @@ def item_spans(text):
for k, (h, s) in enumerate(heads)]
# An item is also closed by its OWN body saying so, on the `**Awaiting:**` line.
# ANCHORED deliberately, and the anchor is the whole point: closure detection HIDES
# items, so an unrecognised form must never yield the permissive answer (REVIEWED-132
# condition 1). Measured 2026-09-04 against the live register: this anchored form finds
# exactly the two items closed in their own body (PENDING-82 "CLOSED 2026-08-08", the
# STATE-CLAIM marker "DISCHARGED 2026-08-26") and nothing else, while a bare \bCLOSED\b
# search of item bodies matches TWENTY — including PENDING-95, -108 and -109, all live,
# all of which merely discuss closure. The negative control below holds that line.
AWAITING_CLOSED_RE = re.compile(
r"^\*\*Awaiting:\*\*.*?\b(?:CLOSED|DISCHARGED|WITHDRAWN)\b", re.M)
def open_items(text):
"""-> [(header, line_no)] for every item lacking closure evidence. Closure
evidence = a REVIEWED-N (resolved by the caller) or CLOSED/COMPLETED in the
header."""
return [(h, s) for h, s, _e in item_spans(text)
if "CLOSED" not in h and not h.startswith("COMPLETED")]
evidence = a REVIEWED-N (resolved by the caller), CLOSED/COMPLETED in the
header, or an `**Awaiting:**` line declaring the item closed.
The third form was added 2026-09-04. Two items were being counted open with
their own bodies saying otherwise, because this read the header only."""
lines = text.split("\n")
out = []
for h, s, e in item_spans(text):
if "CLOSED" in h or h.startswith("COMPLETED"):
continue
# header sits at 0-based s-1; body ends before the NEXT header at 0-based e-1,
# and that exclusion matters — otherwise a following header carrying CLOSED
# would close the item above it.
if AWAITING_CLOSED_RE.search("\n".join(lines[s:e - 1])):
continue
out.append((h, s))
return out
def tag_of(text, header):
@@ -445,8 +470,38 @@ def ruled_pendings(reviewed_text):
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.
⚠ WIDENED 2026-09-04, and the widening is deliberately PARTIAL. The single
em-dash form below was the only one recognised, while the register writes four.
Censused over 132 placed rulings: 80 em-dash single, 3 parenthetical, 1
plus-joined, 1 slash-joined, 47 naming no PENDING at all. The parenthetical and
plus-joined forms are now read — they cost eight items their closure, four of them
ruled by the three most recent rulings, which is how a queue reported 64 while 56
was defensible.
THE SLASH-JOINED FORM IS NOT READ, AND THAT IS A DECISION RATHER THAN AN OMISSION.
Its sole instance is `REVIEWED-116 — PENDING-131/132/133/134 —`, a DESIGN-GATE on a
package, and PENDING-133's own body still reads `Awaiting: Steward authorization`.
Reading it as disposition would falsely close a live item, which is the direction
this function must never guess in. It is reported instead — see
`unreadable_ruling_headers`, which exists so the gap is visible rather than silent.
"""
return set(re.findall(r"^## REVIEWED-\S+\s*—\s*PENDING-(\S+?)\s*—", reviewed_text, re.M))
ids = set(re.findall(r"^## REVIEWED-\S+\s*—\s*PENDING-(\S+?)\s*—", reviewed_text, re.M))
# REVIEWED-N (PENDING-M) — : the form of the three most recent rulings.
ids |= set(re.findall(r"^## REVIEWED-\S+\s*\(PENDING-([^)\s]+)\)\s*—", reviewed_text, re.M))
# REVIEWED-N — PENDING-A + PENDING-B — : an explicitly joint ruling disposes of both.
for joint in re.findall(r"^## REVIEWED-\S+\s*—\s*((?:PENDING-\d+\s*\+\s*)+PENDING-\d+)\s*—",
reviewed_text, re.M):
ids |= set(re.findall(r"PENDING-(\d+)", joint))
return ids
def unreadable_ruling_headers(reviewed_text):
"""-> [header] for rulings that name PENDING ids in a form `ruled_pendings` will
not treat as closure. Honest degradation: the closure rule declines to guess, and
this is how the declining becomes visible instead of looking like a clean pass."""
return [h for h in re.findall(r"^## (REVIEWED-.*)$", reviewed_text, re.M)
if re.search(r"PENDING-\d+(?:/\d+)+", h)]
def sec_pending():
@@ -1028,6 +1083,37 @@ def selftest():
len(open_items("## PENDING-S2 — x\n## PENDING — ICP-19")) == 2)
chk("open_items excludes CLOSED / COMPLETED",
open_items("## PENDING-1 — x (CLOSED)\n## COMPLETED — y") == [])
# --- closure-rule widening, 2026-09-04. Every control below is paired: the form is
# read, AND the form that must NOT be read stays open. Closure hides items, so the
# negative halves are the load-bearing ones.
_AWT_CLOSED = "## PENDING-2 — x\n**Awaiting:** ~~steward~~ → **INSTALLED. CLOSED 2026-08-08.**"
chk("open_items honours closure declared on the Awaiting line",
open_items(_AWT_CLOSED) == [])
chk("open_items honours DISCHARGED on the Awaiting line",
open_items("## PENDING-2 — x\n**Awaiting:** nothing — **DISCHARGED 2026-08-26**") == [])
chk("CLOSED elsewhere in the body does NOT close an item "
"[negative control — bare word-match would close 20, three of them live]",
[h for h, _ in open_items("## PENDING-2 — x\nthis waits until PENDING-9 is CLOSED\n"
"**Awaiting:** steward authorization")] == ["PENDING-2 — x"])
chk("a following header's CLOSED does not close the item above it [span boundary]",
[h for h, _ in open_items("## PENDING-2 — x\nbody\n## PENDING-3 — y (CLOSED)")]
== ["PENDING-2 — x"])
chk("ruled_pendings reads the em-dash form",
"12" in ruled_pendings("## REVIEWED-9 — PENDING-12 — t"))
chk("ruled_pendings reads the PARENTHETICAL form [3 rulings; cost 4 items closure]",
"137" in ruled_pendings("## REVIEWED-133 (PENDING-137) — t"))
chk("ruled_pendings reads a PLUS-JOINED joint ruling, BOTH ids",
{"157", "158"} <= ruled_pendings("## REVIEWED-127 — PENDING-157 + PENDING-158 — t"))
chk("ruled_pendings does NOT read the slash-joined design-gate form "
"[negative control — PENDING-133 is live and must stay visible]",
not ({"131", "132", "133", "134"} & ruled_pendings(
"## REVIEWED-116 — PENDING-131/132/133/134 — design gate")))
chk("a ruling header naming no PENDING suppresses nothing [FALSE-OPEN class, kept]",
ruled_pendings("## REVIEWED-128 — The rejection log against §9") == set())
chk("unreadable_ruling_headers surfaces the form the closure rule declines",
len(unreadable_ruling_headers("## REVIEWED-116 — PENDING-131/132/133/134 — x")) == 1)
chk("unreadable_ruling_headers is silent on forms that ARE read [negative control]",
unreadable_ruling_headers("## REVIEWED-133 (PENDING-137) — t") == [])
chk("open_items returns empty on empty input", open_items("") == [])
FENCED = "## PENDING-9 — real\nbody\n```markdown\n## REVIEWED-9 — a draft\n```\ntail"
chk("open_items ignores a header inside a fenced block [drafting-habit trigger]",