[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:
co-authored by
Claude Opus 5
parent
8031db0e26
commit
9d152f1d48
+91
-5
@@ -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]",
|
||||
|
||||
Reference in New Issue
Block a user