[HARDENING] PENDING-174 (severed) + [FIX] PENDING-175, per the jurist ruling
174 is REVIEWED-131 draft §5's severed leg: the memory layer is date-keyed and written whole, so a day with two sessions keeps one record. Distinguished from PENDING-104 explicitly — this loss does not require concurrency, since two sequential sessions lose the same thing and a lock would not help. Realised today: MEMORY.md's Active Session records one session's day. 175 is REVIEWED-132 draft §7, routed here. The code corrects the jurist's own account and shrinks the defect: t_item's predicate matches both blocks; the return is inside the loop. ### amendments sit inside the parent span and are unaffected; ## amendments become siblings the parent id truncates before. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wn9mxsFjHJkzYjuDdrtxwp
This commit is contained in:
co-authored by
Claude Opus 5
parent
201d809b07
commit
bec3882ab1
+56
@@ -6707,3 +6707,59 @@ Three independent narrowings, none of them declared: the header regex is `REVIEW
|
||||
|
||||
**Files affected:** unchanged from the parent.
|
||||
**Awaiting:** Steward authorization (with the parent).
|
||||
|
||||
---
|
||||
|
||||
## PENDING-174 — The memory protocol has no merge semantics for a day with more than one session
|
||||
**Date:** 2026-08-31
|
||||
**Tag:** [HARDENING]
|
||||
**Severed from:** PENDING-172, on the jurist ruling of 2026-08-31 (REVIEWED-131 draft §5) — *"a live `[HARDENING]` ask embedded in an `[ESCALATE]` item … filed as its own item and not disposed of here."* The shape PENDING-146 names in PENDING-131 ADDENDUM 2.
|
||||
**Summary:** Every durable surface of the memory layer is keyed by date and written whole: `session-ledger-YYYY-MM-DD.md`, one `session-YYYY-MM-DD-*.md`, and one **Active Session** block in `MEMORY.md` under demote-on-promote. Two sessions in one day do not merge; the second to write becomes the record of the day and the first leaves no trace it was there.
|
||||
|
||||
**⚠ THIS IS NOT PENDING-104's DEFECT, AND THE DISTINCTION IS THE ITEM.** PENDING-104 and its ADDENDUM 2 (filed 2026-08-31 by the unattended session) are about **concurrency** — two live writers, no lock, no lease, nothing detecting the overlap. **This item's loss does not require concurrency.** Two sessions run strictly one after the other, hours apart, with no overlap and no collision, produce exactly the same outcome: the second `/wrap-up` promotes its own Active Session block and demotes the first, and the day has one record where two sessions happened. A lock would not help. Sequencing is not a mitigation because sequencing is the failure.
|
||||
|
||||
**Realised today, and measurable now.** Two sessions ran on 2026-08-31. `MEMORY.md`'s Active Session block, as it stands, records the 270-candidate classification pass and says nothing of the unattended-executor incident, PENDING-172, PENDING-173, the jurist ruling, or that two stray background sessions were found and stopped. That is not an error by its author — it wrapped correctly, by the protocol, with no way to know the other session's content. **The protocol produced a true record of one session and a silent record of the day.**
|
||||
|
||||
**⚠ The one surface that did NOT collide, and why that is not reassurance.** `session-ledger-2026-08-31.md` survives intact at 54 lines with both sessions' day in the same directory — **only because the other session never invoked `/symmetria`.** Had it done so, the date-keyed path is identical and one ledger would have been written over the other. The absence of the collision is a fact about which skills were invoked, not about the design.
|
||||
|
||||
**Options.**
|
||||
- **(i)** Key the per-session surfaces by session id as well as date (`session-ledger-YYYY-MM-DD-<short-id>.md`), and let the day be a directory rather than a file.
|
||||
- **(ii)** Make `/wrap-up` read-before-write on the Active Session block and **append** a second session's block rather than promote-and-demote, so a multi-session day reads as one.
|
||||
- **(iii)** Detect only: `/wrap-up` refuses to promote when another `session-YYYY-MM-DD-*.md` already exists for today that this session did not write, and asks.
|
||||
- **(iv)** Nothing; accept that a day is a single record.
|
||||
|
||||
**Recommendation: (iii) first, then (ii).** (iii) is small, needs no schema change, and converts a silent overwrite into a question — which is the whole difference between this defect and its absence. (ii) is the real repair but changes what `MEMORY.md`'s Active Session *is*, and that block is read at every wake by every party; it should not be reshaped in the same act that discovers the problem. ⚠ (i) is deliberately not recommended first: it multiplies the files the wake must read, and the wake's budget is already a live constraint (`MEMORY.md` is at 23.9 KB against a stated ceiling).
|
||||
|
||||
**⚠ What this item does not establish.** How often two sessions occur in one day. The executor cannot observe it — the same limit PENDING-104 ADDENDUM 2 declares about its own option space. Today is one instance, and it arose from PENDING-172's mechanism rather than from the steward choosing to run two.
|
||||
|
||||
**Files affected:** `~/.claude/skills/wrap-up/SKILL.md`, `~/.claude/skills/symmetria/SKILL.md` (§4 ledger path), `MEMORY.md`'s Active Session convention.
|
||||
**Awaiting:** Steward authorization.
|
||||
|
||||
---
|
||||
|
||||
## PENDING-175 — `governance_item` returns the first block under an id and gives no sign that others exist
|
||||
**Date:** 2026-08-31
|
||||
**Tag:** [FIX]
|
||||
**Raised by:** the jurist, first-hand, while ruling PENDING-172 on 2026-08-31 — REVIEWED-132 draft §7, which routes it here as a separate item.
|
||||
**Summary:** `t_item` in `scripts/governance-mcp.py` iterates `item_spans` and **returns inside the loop on the first header matching the id**. When two `## ` blocks share an id — a parent and its amendment — only the parent is returned, with nothing in the output indicating a sibling exists.
|
||||
|
||||
**⚠ THE JURIST'S CHARACTERISATION IS CORRECTED BY THE CODE, AND THE CORRECTION MAKES IT SMALLER.** The ruling reads *"the id alone does not reach it."* The id **does** reach it. `governance-mcp.py:200` —
|
||||
|
||||
```python
|
||||
for head, start, end in wd.item_spans(text):
|
||||
if head == ident or head.startswith(ident + " "):
|
||||
return (...)
|
||||
```
|
||||
|
||||
`PENDING-172 — AMENDMENT 1: …` satisfies `head.startswith("PENDING-172 ")` exactly as the parent does. The predicate matches both blocks; the `return` is inside the loop, so the second is never reached. This is an early return, not a matching failure — a smaller defect with a smaller fix, and it should be recorded as what it is.
|
||||
|
||||
**Why it bit here and not before.** `item_spans` treats **any `## ` header** as an item and `### ` as body (`l.startswith("## ")` is False for `### `). So the register's two amendment placements behave oppositely: a `###` amendment sits **inside** its parent's span and is returned with it, while a `##` amendment becomes a **separate item** that a parent-id lookup silently truncates before. PENDING-172 AMENDMENT 1 was filed as `##`, following the PENDING-133 and PENDING-162 precedent; PENDING-164 AMENDMENT 2, filed the same day, used `###` and would have been returned intact. **Neither placement is wrong under any stated rule, and that is PENDING-173 ADDENDUM 1's finding arriving at a fourth instrument.**
|
||||
|
||||
**The consequence is not hypothetical.** The jurist reports it nearly ruled on PENDING-172's Recommendation, which AMENDMENT 1 corrects as **wrong**. The retrieval tool built to give the jurist verbatim access returned a verbatim half.
|
||||
|
||||
**Recommendation.** Collect every matching span and return all of them, with a leading count (`3 blocks under PENDING-172 — parent, AMENDMENT 1, …`) and each block's line number. A single-block result then means one block exists, rather than meaning nothing about how many do. Add a control with a two-block id — PENDING-172 is now a permanent fixture for it — asserting both blocks are returned; ⚠ the control must assert **both**, since a one-block assertion passes on the current behaviour.
|
||||
|
||||
**⚠ Not established.** Whether the same early-return shape exists elsewhere in `governance-mcp.py` or in `wake-digest.py`'s consumers. Not audited here; a first-match return over a multi-match predicate is a class, and this item found one instance of it.
|
||||
|
||||
**Files affected:** `scripts/governance-mcp.py` (`t_item`, its controls).
|
||||
**Awaiting:** Steward authorization.
|
||||
|
||||
Reference in New Issue
Block a user