| index 1e97590..e399f77 100644 |
| --- a/docs/superpowers/specs/2026-09-03-memoria-design.md |
| +++ b/docs/superpowers/specs/2026-09-03-memoria-design.md |
| @@ -32,7 +32,7 @@ draft they reviewed; all drafts were written by Opus. |
| | 3, §8.4 and decisions 13–14 | Fable | REQUEST CHANGES — 5 MAJOR, 4 MINOR, 1 NIT. All applied. It found §8.4's central argument resting on a misreading of §6.5 and §4.1; §1.8 records what it changed | |
| | 3, gate 17 + live-key verification | Fable | REQUEST CHANGES — 3 MAJOR, 4 MINOR, 3 NIT. All applied. **It mutation-tested gate 17 itself** and found five idioms the gate blessed, including one that served a declared path outside the session gate; §1.9 records what it changed | |
| | 3, suite doctrine adoption (A.4) | Fable | **REQUEST CHANGES — 1 BLOCKER, 9 MAJOR, 3 MINOR, 1 NIT.** All applied. The blocker: §4.1 adopted a custody intersection that was not the doctrine's, could not fail, and left the leak it claimed to close. §1.10 records what it changed | |
| -| slice 1's S2 client, gate 27, gate 21, the merge | — **not yet reviewed** | Owed before this branch merges | |
| +| slice 1's S2 client, gate 33, gate 21, the merge | — **not yet reviewed** | Owed before this branch merges | |
| |
| §1.2 records what the draft-1 reviews changed, §1.3 what the draft-2 |
| review changed, §1.4 what the review of the built code changed, §1.5 what |
| @@ -98,7 +98,7 @@ embedding is a plaintext cell in a costume — §3.1. |
| | 7 | **Every SIBLING call is a pull. memoria exposes no sibling-facing surface.** Its ingest endpoint serves external connectors only, which are memoria-owned content, not a sibling push. | An outbox per sibling; and draft 1's §9, which specified the push surface this decision forbids | Fable contract pass; corrected after review | |
| | 8 | **Provenance or deletion, at `(id, revision)` granularity.** A derived artefact whose provenance stops resolving *or whose source changed* is deleted or regenerated. memoria never fine-tunes. | Draft 1's id-level rule, which left "the Q3 target is X" standing after the source said Y | Fable ingestion pass; corrected after review | |
| | 10 | **memoria never does arithmetic. A number comes from a cell, or from Sheets' engine via S6.** S6 takes an enumerated function over cell refs — never expression text — so memoria is never a formula author. | memoria computing and showing its working (a second calculator, arrived at one `mean` at a time); writing a formula into a scratch sheet (a write, forbidden by §6.4) | Paul asked for numeric questions, 2026-09-03; shape ruled by Fable and GPT Sol independently, converging | |
| -| 11 | ~~**Admission is derived from the siblings.**~~ **SUPERSEDED 2026-09-05 by suite ruling 4** — the home owns identity, the team and the membership roster; instances pull it (suite call 8) and memoria admits from that roster in suite shape, from the owners list in lone shape. S7 is retired. The old rule was right that memoria holds no members table of its own and wrong about where the answer comes from, and it made a guest a member: "at least one sibling says MEMBER" has no value for someone on no roster. §4.3. **The owners carve-out survives the supersession and is still stated rather than discovered:** the platform-configured owners list the app refuses to start without bypasses the roster entirely. It admits operators, is fixed at provisioning, does not grow, and carries a revocation tail §4.3 measures — the 15-minute figure is false for owners. Under ruling 4 that is no longer an exception to S7 but the whole of lone-shape admission, and in suite shape it sits beside the roster rather than inside it. | Draft 2's own members table, which left a person removed everywhere else still able to read memoria-owned content; and, for the carve-out, leaving it implicit in §2 and §4.3, where drafts 3 and 4 left it and where it read as a contradiction rather than a carve-out | after the draft-2 review, 2026-09-03; carve-out recorded explicitly 2026-09-04; superseded 2026-09-05 | |
| +| 11 | ~~**Admission is derived from the siblings.**~~ **SUPERSEDED 2026-09-05 by suite ruling 4** — the home owns identity, the team and the membership roster; instances pull it (suite call 8) and memoria admits from that roster in suite shape, from the owners list in lone shape. S7 is retired. The old rule was right that memoria holds no members table of its own and wrong about where the answer comes from, and it made a guest a member: "at least one sibling says MEMBER" has no value for someone on no roster. §4.3. **The owners carve-out survives the supersession and is still stated rather than discovered:** the platform-configured owners list the app refuses to start without bypasses the roster entirely. It admits operators, is fixed at provisioning, does not grow, and carries a revocation tail nothing measures: the 15-minute figure it used to cite was S7's cache, which no longer exists, and the roster's TTL does not apply to a list the roster never contained. **An owner's removal is a redeploy, and that is the honest statement of the tail.** Under ruling 4 that is no longer an exception to S7 but the whole of lone-shape admission, and in suite shape it sits beside the roster rather than inside it. | Draft 2's own members table, which left a person removed everywhere else still able to read memoria-owned content; and, for the carve-out, leaving it implicit in §2 and §4.3, where drafts 3 and 4 left it and where it read as a contradiction rather than a carve-out | after the draft-2 review, 2026-09-03; carve-out recorded explicitly 2026-09-04; superseded 2026-09-05 | |
| | 12 | **Name: `memoria`.** House convention is plain Spanish office nouns. A *memoria* is both a memory and, in Spanish office usage, a written record. | `archivo`; `cerebro`; `base`; anything English | Paul, 2026-09-03 | |
| | 13 | **The provider is TensorX, and memoria supports exactly one.** A team owner's choice is on or off, not which — a configurable base URL would let an owner reinstate a proxy while the answer still printed "one named provider". Chosen for EU jurisdiction and open weights, criteria decision 4 did not state, at a known cost in id-pinning and frontier quality (§8.3). | OpenRouter (a proxy: two parties see content); OpenAI direct (better id-pinning, worse jurisdiction and cost) | Paul, 2026-09-04, both halves — *"we go with exactly one for now: TensorX. If we want to swap that later we can."* Swapping the *generation* provider is a code change and a review, not a setting; swapping the *embedding* provider is that plus a full corpus re-embed unless the new host serves the same open weights (§8.3, §13) | |
| | 14 | **memoria is a search page, not a chat.** One GET search form, `?q=`, one query in and one page out, with `/documents/{id}` as the only other passage surface. This follows from decision 5, not from decision 3 — §8.4's invariant is what decision 3 requires, and a conversational surface could satisfy it. | A chat UI with citations; a threaded follow-up. Deferred to §12, not forbidden — the invariant forbids the leak, this row chooses the shape | Spec author, 2026-09-04, answering a question Paul asked; **confirmed by Paul 2026-09-05**, parking the conversational surface in §12 rather than forbidding it | |
| @@ -398,7 +398,7 @@ id that can move under a team without the team changing it cannot be |
| printed on an answer — is right, and generalises `openrouter/auto`'s |
| disqualification properly. Then it selected `moonshotai/kimi-k3` and |
| `z-ai/glm-5.3-flash`, neither datestamped, both plausibly aliases over |
| -dated checkpoints. The fix is a datestamped id where one exists, gate 24's |
| +dated checkpoints. The fix is a datestamped id where one exists, gate 30's |
| canary where none does, and §13 recording that the vendor's id-immutability |
| policy is unread. The draft had even quoted the one datestamped id in the |
| catalogue as evidence — and it was the model it did not pick. |
| @@ -416,7 +416,7 @@ similarity is scale-invariant: against a true cosine, skipping the |
| renormalise changes no ranking, and the gate stays green forever. The spec |
| had never said whether search computes cosine or a raw dot product. It now |
| says dot product — which is what §7.3's flop count always assumed — and |
| -gate 22 asserts unit norm deterministically instead of inferring it from |
| +gate 28 asserts unit norm deterministically instead of inferring it from |
| quality. This is the fourth gate in this project to have been written in a |
| shape that could not go red, and the first caught before it was built. |
| |
| @@ -456,7 +456,7 @@ chat; it now sits in §3.2's leak list where it applies to everything. |
| **re-speaking**: no passage crosses a request, in a response or in a model |
| prompt, without §4.1 in the request that carries it. That is decision 3 |
| applied to rendering, it is what §8.5 already said about the model, and |
| -gate 26 asserts it against the prompt builder. Carrying query *text* |
| +gate 32 asserts it against the prompt builder. Carrying query *text* |
| forward breaks nothing. |
| |
| **And the shape is a choice, so it is recorded as one.** Decision 14 rests |
| @@ -645,10 +645,13 @@ getting an answer grounded in the team's own documents is the gap. |
| **What it never does.** |
| |
| - **Never decides who may read sibling content.** It asks (§4.1). |
| -- **Never holds a team roster.** Admission is relayed from the siblings, |
| - and refused when none of them will vouch (§4.3). The |
| - platform-configured owners list is not one, for the reasons above, and |
| - is decision 11's one exception. |
| +- **Never *authors* a roster**, which is the claim that survives ruling 4. |
| + It holds the home's, as a pulled copy refreshed by epoch (§4.3), and it |
| + reconciles none of it and writes none of it. In lone shape there is no |
| + roster at all and admission is the owners list. *This bullet said |
| + "never holds a team roster. Admission is relayed from the siblings" until |
| + 2026-09-06, four lines below the paragraph describing the pulled copy — |
| + and §4.3 by then asked no sibling anything.* |
| - **Never writes to a sibling**, and exposes no sibling-facing surface. |
| - **Never acts as a person.** It holds no signing key; every assertion's |
| `aud` binds to "app + instance host" (home §5.3). |
| @@ -966,15 +969,28 @@ shape above is the contract's four, because that is what the module |
| carries and ruling 7 says an app cites the contract rather than restating |
| it. |
| |
| -**That is not agreement, and it should not be minuted as agreement.** What |
| -happened is that the suite session was asked about the source-behind case |
| -by this branch, which had not read draft 4, and answered `UNKNOWN` without |
| -memoria's argument in front of it. §1.10's lesson, one repository over: |
| -the sections you did not open are where it goes wrong. Raised with the |
| -suite as a proposed contract change; until it lands, memoria maps the case |
| -to `UNKNOWN` and **loses the distinction between "the sibling answered, |
| -and is behind" and "the sibling did not answer"** — which is precisely the |
| -collapse `AHEAD` was cut to prevent. §13 carries it. |
| +**That is not agreement, and it should not be minuted as agreement.** |
| + |
| +Record the doctrine's reasoning as the doctrine records it: suite §4.3 |
| +attributes the `UNKNOWN` ruling to *its own GPT-6 review, finding 11* — |
| +never `VISIBLE`, because that authorises a revision nobody can vouch for; |
| +never `NOT_VISIBLE`, because that is the silent value — and its trigger was |
| +**draft 3's open §13 item**, not a question from this branch. It weighed |
| +two of draft 4's three wrong homes. What it did not weigh is the third: |
| +that `UNKNOWN` reports no answer when the app of record answered, precisely |
| +about its own log. |
| + |
| +*An earlier version of this paragraph said the suite "was asked by this |
| +branch, which had not read draft 4, and answered without memoria's argument |
| +in front of it". That is wrong twice — it credits this branch with the |
| +question and the doctrine with none of the reasoning — and it is the more |
| +embarrassing way to be wrong, because it makes another repository's |
| +careful work look like an accident of mine.* |
| + |
| +Until the contract change lands, memoria maps the case to `UNKNOWN` and |
| +**loses the distinction between "the sibling answered, and is behind" and |
| +"the sibling did not answer"** — which is the collapse `AHEAD` was cut to |
| +prevent. §13 carries it. |
| |
| **The sibling intersects its own answer with custody, and memoria depends |
| on that** (suite §4.3, and the S2 row of suite §6): |
| @@ -1221,7 +1237,6 @@ does not have. The test is two facts and nothing else: |
| ruling 4 is the home's roster in suite shape and the owners list |
| in lone shape. A statement about the *team*, not about this |
| document; and |
| - statement about the *team* and not about this document; and |
| 2. **the document is present in memoria and not deleted.** |
| |
| So memoria-owned content is team-wide by construction. Anything a |
| @@ -1332,14 +1347,19 @@ the sibling only knows its own. A roster held by the home answers *member |
| of this team* and nothing else, which is the property draft 4 was reaching |
| for and could not get from S7. |
| |
| -**Slice 0 has no siblings, so it has no S7**, and the spec should say so |
| -rather than leave a reader to infer a table. Until the first sibling is |
| -connected the only people admitted are the platform-configured owners the |
| -app refuses to start without. That list admits operators, it is not a |
| -roster, and **it does not grow**: when the first sibling connects, |
| -everyone who is not an owner comes from `S7`. Extending the owners list |
| -one person at a time would be the members table decision 11 rejected, |
| -arriving under another name. |
| +**Slice 0 has no home and no siblings, so admission is the owners list |
| +and nothing else**, and the spec should say so rather than leave a reader |
| +to infer a table. Until a home exists, the only people admitted are the |
| +platform-configured owners the app refuses to start without. That list |
| +admits operators, it is not a roster, and **it does not grow**: when a home |
| +exists, everyone who is not an owner comes from the pulled roster (suite |
| +call 8). Extending the owners list one person at a time would be the |
| +members table decision 11 rejected, arriving under another name. |
| + |
| +*This paragraph said "slice 0 has no S7" and "everyone who is not an owner |
| +comes from S7" until 2026-09-06 — inside the section that retires S7, |
| +reintroduced by the merge from a branch written before ruling 4. §1.10's |
| +rule is to grep the retired thing by name; this is what it catches.* |
| |
| No guests, no anonymous link viewers — and after this section, no guest |
| of a *sibling* either. Admission is not authorization: an admitted person |
| @@ -2191,7 +2211,7 @@ is exactly the shape the rule is about, in this vendor's own inventory |
| (`v4-pro-0813`, `v4-flash-0731`, `r1-0528`) and one Qwen |
| (`qwen3-235b-a22b-2507`). Every Kimi, GLM and MiniMax id is a bare name — |
| `kimi-k3` exists, but no `kimi-k3-<date>` does. So pinning Kimi would make |
| -gate 24's canary load-bearing, and pinning DeepSeek does not. |
| +gate 30's canary load-bearing, and pinning DeepSeek does not. |
| |
| **Both tiers are therefore DeepSeek:** `model.cheap` is |
| `deepseek/deepseek-v4-flash-0731` and `model.frontier` is |
| @@ -2208,7 +2228,7 @@ keeps. |
| **The concentration gets a stated response, not just a note.** Both tiers |
| are now one lab as well as one host, so a DeepSeek withdrawal moves both at |
| once. Name the fallback now — `qwen/qwen3-235b-a22b-2507` for the frontier |
| -tier, `z-ai/glm-5.3-flash` for the cheap one with gate 24 carrying it — so |
| +tier, `z-ai/glm-5.3-flash` for the cheap one with gate 30 carrying it — so |
| a withdrawal is a config change through §Review on a normal day rather than |
| a research task on a bad one. |
| |