🤖 spec: close the S2 existence oracle, and record that CI has never run
THE ORACLE. Draft 4's S2 row told a sibling to answer AHEAD rather than NOT_VISIBLE for an item it has no row for at all. That is on main, not in a draft. It makes the two values distinguishable, so a consumer that can name an id learns which ids EXIST — AHEAD for one nobody holds, NOT_VISIBLE for one held privately. Suite gate 3 requires S2's answer to be byte-identical across private, granted, guest-only, link-shared and deleted, precisely so ids cannot be enumerated. A value cut to close a silent failure would have opened an existence leak on the last call. Caller discipline does not save it, and I checked before concluding that: memoria only asks S2 about ids it received on S1, but the S2 row is a contract SIBLINGS implement, answerable to any consumer holding a token, and §3.2's leak list already contemplates a compromised one. A rule that is safe only while every caller behaves is not a property of the answer. Draft 4's argument is kept as a quote because overruling it has a real cost: a sibling whose restore lost a row is now indistinguishable from one enforcing a denial, and only the S4 tombstone and re-announce settle it. AHEAD survives for the shape that does not leak — a revision beyond the log for an item the sibling still admits, which is the partial restore no feed signal can see. The gate fixture is corrected too, and now asserts the INDISTINGUISHABILITY rather than the value: ask about the no-row item and a known-private item in the same call and require equal results, because asserting NOT_VISIBLE alone passes on an implementation that answers it for different reasons. AND THE GATES HAVE NEVER RUN. amadan ci status oficina/memoria answers No
1 file changed,
+56
−12
docs/superpowers/specs/2026-09-03-memoria-design.md+56 −12
diff --git a/docs/superpowers/specs/2026-09-03-memoria-design.md b/docs/superpowers/specs/2026-09-03-memoria-design.md| index 6ee04a1..800bfa0 100644 |
| --- a/docs/superpowers/specs/2026-09-03-memoria-design.md |
| +++ b/docs/superpowers/specs/2026-09-03-memoria-design.md |
| @@ -1053,16 +1053,43 @@ and the re-announce is what reconciles the two. Wholesale `AHEAD` from |
| one sibling is a restore signal and §8.1's third breaker names it as one, |
| rather than as the mis-scoped predicate it is not. |
| -**Why "no row at all" is `AHEAD` and not `NOT_VISIBLE`.** A sibling that |
| -has never heard of an item memoria holds is in the same position as one |
| -whose log stops short of it: memoria holds history the sibling does not. |
| -An ordinary deletion does not arrive this way — it arrives as an `S4` |
| -tombstone on the feed (§6.1), which is a positive statement that the item |
| -is gone. Silence is not that statement. Mapping it to `NOT_VISIBLE` would |
| -put a history gap on the one value that may be silent, which is the |
| -mistake `AHEAD` was cut to fix; mapping it to `UNKNOWN` would report no |
| -answer when the sibling answered. So it is `AHEAD`, and whether the item |
| -is gone for good is settled by the re-announce, not by S2. |
| +**"No row at all" is `NOT_VISIBLE`, and draft 4 had it as `AHEAD`.** |
| +Corrected 2026-09-06 against suite §4.3, which governs. The argument for |
| +`AHEAD` was good and is kept below, because the cost of overruling it is |
| +real and should not be lost: |
| + |
| +> A sibling that has never heard of an item memoria holds is in the same |
| +> position as one whose log stops short of it: memoria holds history the |
| +> sibling does not. An ordinary deletion does not arrive this way — it |
| +> arrives as an `S4` tombstone on the feed, a positive statement that the |
| +> item is gone. Silence is not that statement. Mapping it to |
| +> `NOT_VISIBLE` puts a history gap on the one value that may be silent. |
| + |
| +**What it missed is an oracle.** `NOT_VISIBLE` and `AHEAD` are |
| +distinguishable, so a consumer that can name an id learns which ids |
| +*exist*: `AHEAD` for one nobody holds, `NOT_VISIBLE` for one held |
| +privately. Suite gate 3 requires S2's answer to be byte-identical across |
| +private, granted, guest-only, link-shared-but-not-team **and deleted**, |
| +precisely so ids cannot be enumerated — and this rule would have opened, |
| +on the last call, the enumeration §4.2's indistinguishability and S3's |
| +"404, never 403" were both built to deny. A value cut to close a silent |
| +failure would have opened an existence leak instead. |
| + |
| +**And caller discipline does not save it.** memoria only ever asks S2 |
| +about ids it received on S1, so *memoria* can name no id it was not told |
| +about — but the S2 row is a contract **siblings implement**, answerable to |
| +any consumer holding a token, and §3.2's leak list already contemplates a |
| +compromised one. A rule that is safe only while every caller behaves is |
| +not a property of the answer. |
| + |
| +**So the cost is carried rather than avoided, and it is stated here.** A |
| +sibling whose restore lost a row entirely is now indistinguishable from |
| +one enforcing a denial, and memoria cannot tell them apart from S2 alone. |
| +What settles it is the S4 tombstone and the re-announce — reconciliation |
| +after the fact, not an answer at the point of the question. `AHEAD` |
| +survives for the shape that does not leak: **a revision beyond the log, |
| +for an item the sibling still admits**, which is the partial-restore case |
| +and the one no feed signal can see. |
| **memoria never compares two revisions, and this is what makes `STALE` |
| and `AHEAD` well-defined.** A revision is an opaque token issued by the |
| @@ -3133,8 +3160,14 @@ The gates: |
| memoria holds at 7, (b) holds no row at all for a second item, (c) |
| answers normally for the rest. |
| - - **`AHEAD`, not `NOT_VISIBLE`, for both (a) and (b)** — the no-row |
| - case included, which is the one that has no obvious home. |
| + - **`AHEAD` for (a); `NOT_VISIBLE` for (b).** The no-row case is |
| + `NOT_VISIBLE` and must be byte-identical to a private item's answer |
| + — suite gate 3 — or S2 becomes an id-existence oracle. Draft 4 had |
| + (b) as `AHEAD` and §4.1 records what overruling it costs. **Assert |
| + the indistinguishability, not just the value:** ask about (b) and |
| + about a known-private item in the same call and require the two |
| + results to be equal, because asserting `NOT_VISIBLE` alone passes on |
| + an implementation that answers it for different reasons. |
| - **Nothing is deleted**, and the source is marked for re-announce. |
| - **The empty-page assertion, which is the point of the gate.** Run a |
| query matching all 100 chunks with a page size of 50. The page |
| @@ -3737,6 +3770,17 @@ on 2026-09-06 when the branches merged. |
| as `replace`, and it costs two breaking import-path changes plus a |
| `GOPRIVATE` requirement that fails by silently falling back to a public |
| checksum DB. memoria proposed it and the suite session found the hole.* |
| +- **memoria's gates have never run in CI, and `make ci` is not a merge |
| + gate anywhere.** `amadan ci status oficina/memoria` answers *"No CI |
| + status recorded for this commit"*: the hub runner's repo list does not |
| + include memoria (nor `oficina/suite`, nor calendar). Every gate in §10 |
| + that exists has only ever run because somebody ran it by hand, and |
| + nothing red has ever blocked a merge. That is one rung below the failure |
| + AGENTS.md names — a guard written to pass is at least executed — and it |
| + means the whole §10 apparatus is, as an enforcement mechanism, currently |
| + decorative. **NEEDS PAUL:** add memoria to the runner's `-repo` list. |
| + Found 2026-09-06 by the suite session, which hit the same wall on its own |
| + repo. |
| - **A hand-off cannot include memoria-owned material, and that will read |
| as a bug.** An answer built purely on sibling passages can be saved into |
| Docs; one built on the team's own uploads cannot, because suite §7 makes |