docs(spec): fix what was factually wrong, record what is not yet fixed
The deferred-table trigger sat at 150k chunks while the section it cites derives 90-110k, so it fired after the wake budget was already broken. The corpus box said 30,000 documents x 3 chunks; the benchmark's own corpus averages 11.8, so the ceiling is ~7,600 documents of the kind measured, not 30,000 — and the token count follows from the measured 202-word chunk, so 24M, not 36M. Ingest cost is $0.48, and that figure has now been wrong twice in opposite directions. Gate 10 exercised the retirement §7.4 forbids, so a restore found no blob and the gate passed vacuously — the shape §1.4 warns about, in the gate for the finding §1.3 calls fixed. Gate 15 claimed a network guard asserting no egress; it is a source heuristic, and §3.2 now records that sign-in dials out, so no-egress is not assertable at all. Ten findings are acknowledged in §13 and NOT fixed, including that MEMBER is undefined for guests and the S7 cache's unstated TTL is 30 days by a framework default nobody chose. Recorded rather than carried quietly, because the previous review found two fixes that renamed a problem instead of removing it.
Reviewed-by: Fable Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SiWVaR69Vb2Lzc9wgfit1v
1 file changed,
+69
−11
docs/superpowers/specs/2026-09-03-memoria-design.md+69 −11
diff --git a/docs/superpowers/specs/2026-09-03-memoria-design.md b/docs/superpowers/specs/2026-09-03-memoria-design.md| index d43af30..afbe6b8 100644 |
| --- a/docs/superpowers/specs/2026-09-03-memoria-design.md |
| +++ b/docs/superpowers/specs/2026-09-03-memoria-design.md |
| @@ -334,8 +334,8 @@ per question, so that over months "the frequently-consulted part of the |
| corpus has left in full". That understated it by the corpus. |
| **Embeddings come from a hosted API (§7.2). So with AI on, every chunk of |
| -every document leaves at ingest, on day one.** §8.6 prices it: 36M tokens |
| -for a 30k-document corpus. The frequently-consulted part leaving is the |
| +every document leaves at ingest, on day one.** §8.6 prices it: 24M tokens |
| +for a 90k-chunk corpus. The frequently-consulted part leaving is the |
| *second* leak, not the first. |
| Two consequences the spec carries rather than buries: |
| @@ -866,8 +866,17 @@ unverified — §13.** |
| chunks for memory and 60M tokens for cost, which are inconsistent; both |
| reviewers caught it. |
| -> **30,000 documents × 3 chunks × 400 tokens = 90,000 chunks = 36M |
| -> tokens**, ≈1.6 KB of text per chunk, ≈144 MB of text. |
| +> **90,000 chunks at the measured 202 words / 1325 bytes each** — about |
| +> **24M tokens** and **114 MB of text**. |
| + |
| +**Stated in chunks, because documents vary too much to convert.** Draft 3 |
| +wrote "30,000 documents × 3 chunks"; the benchmark's own corpus averages |
| +**11.8** chunks per document, so this ceiling is roughly **7,600 documents |
| +of the kind measured**, not 30,000. Any figure quoted per-document is |
| +wrong by about 4×. The ceiling is a chunk count and only a chunk count. |
| + |
| +The token figure follows from the measured chunk (202 words ≈ 270 tokens), |
| +not the 400-token target: **24M, not the 36M draft 3 carried into §8.6.** |
| **Vectors.** 512-dim Matryoshka embeddings (OpenAI's `-3` models accept a |
| `dimensions` parameter), stored **int8-quantised**: |
| @@ -1100,12 +1109,15 @@ so** — an empty paragraph is indistinguishable from AI being off. |
| ### 8.6 Cost |
| -On §7.2's single corpus assumption — 30k documents, 90k chunks, **36M |
| -tokens**: |
| +On §7.2's measured corpus — 90k chunks, **24M tokens**: |
| + |
| +**Ingest:** 24M × $0.02/M (`text-embedding-3-small`) = **$0.48 once**; |
| +$3.12 on `-large`. Re-embed only changed chunks. |
| -**Ingest:** 36M × $0.02/M (`text-embedding-3-small`) = **$0.72 once**; |
| -$4.68 on `-large`. Re-embed only changed chunks. Draft 1 said $1.20 and |
| -$7.80, priced against the 60M figure it should not have used. |
| +This has been wrong twice, in opposite directions. Draft 1 priced 60M |
| +tokens against a 90k-chunk corpus; draft 3 corrected to 36M by keeping the |
| +*intended* 400-token chunk; the measured chunk is 202 words. It follows |
| +from §7.2's measurement, and if that measurement moves so does this. |
| **Query:** retrieval is free. The generative layer sends ~8 passages plus |
| instructions — ~5k tokens in, ~500 out. Cheap model ~$0.001–0.003; |
| @@ -1351,8 +1363,54 @@ rows. |
| ## 13. Open |
| -- **§Review pass on draft 3.** Drafts 1 and 2 were reviewed; this one has |
| - not been. |
| +- **§Review pass on draft 4.** Drafts 1–3 have been reviewed, five passes |
| + in total. The items below are draft 3's review, **acknowledged and not |
| + yet fixed** — recorded rather than quietly carried, because the review |
| + before this one found two fixes that renamed a problem instead of |
| + removing it. |
| + |
| + - **`MEMBER` is undefined for a guest.** Sheets §8.2 and Docs §8.2 both |
| + call a guest a member. §4.3 admits on "at least one sibling says |
| + MEMBER", so a person granted one Sheets sheet may be admitted — and |
| + §5.2 step 3 then gives them everything memoria owns. The predicate |
| + S7 asks needs to be "member of this team", not "known to this app". |
| + - **The S7 cache has no stated TTL, and the framework's default is 30 |
| + days.** `rastrillo/auth` sets `DefaultSessionTTL = 30 * 24h` and |
| + memoria overrides nothing, so a person removed from every sibling |
| + reads memoria-owned content for up to a month. The number was never |
| + chosen. It also sits against §6.5's "never to cache its |
| + authorization", which for memoria-owned content is what the cache is. |
| + - **§2 and §4.2 still specify the members table decision 11 rejected**, |
| + word for word from draft 2. A reader of §2 builds it; a reader of |
| + decision 11 does not. |
| + - **§4.1 still says there is "no separate 'is P a member?' question"**, |
| + which §4.3's S7 is. |
| + - **No S2 value covers a sibling that is BEHIND memoria** — restored |
| + from backup, holding revision 5 of an item memoria indexed at 7. |
| + `STALE` is defined as the sibling having moved *past* the revision, so |
| + the natural answer is `NOT_VISIBLE`, which is the one silent value. |
| + The plausible-empty-list failure returns through the restore door. |
| + - **The circuit breaker fires on a routine case.** Under "admit on at |
| + least one sibling", a Docs-only member gets wholesale `NOT_VISIBLE` |
| + from Sheets on every query, which §8.1 calls an anomaly. |
| + - **Derived-artefact provenance is not transitive.** An artefact built |
| + from another artefact partitions as memoria-owned and never reaches |
| + S2 for the first artefact's sibling sources. Two hops launder what |
| + one hop cannot. |
| + - **§8.7's unit compatibility has no test it can run.** Three cells |
| + formatted `General`, one of them in thousands, carry no signal |
| + distinguishing them, so `MIXED_UNITS` cannot fire and the average is |
| + confidently wrong. The spec's own example is "one year in k€". |
| + - **Several draft-3 fixes have no gate**: S3's signature, the keyed |
| + `external_id` (reverting it leaves every test green), §6.5's deadline |
| + and concurrency, the wake warm-up. Gates 2 and 8 name "a threshold" |
| + and "*everything*" without a number, so neither can be written as |
| + stated. |
| + - **`TestNoContentInLogs`'s credential half cannot fail**, because the |
| + test app wires no auth and so never sends a link. |
| + |
| +- **§Review pass on draft 3 itself.** Done: Fable, 22 findings, REQUEST |
| + CHANGES. The blocker it found was mine — see §6.1 on S3. |
| - **BLOCKER, and not mine to close: the source apps must adopt decision |
| 1.** home §2.2, Sheets PRODUCT.md principle 3 and Docs §8.2 each |
| currently forbid content crossing an instance boundary. Paul ruled the |