diff --git a/docs/cultcache-publication-cut.md b/docs/cultcache-publication-cut.md index 7143127a..51953101 100644 --- a/docs/cultcache-publication-cut.md +++ b/docs/cultcache-publication-cut.md @@ -1,7 +1,21 @@ # CultCache publication: the cache owns "published once", and order stays data -Status: cut map, Imagination pass 1, 2026-09-29. It is not committed yet. Self -commits it to `main` as `docs/cultcache-publication-cut.md`. The ends are the +Status, 2026-09-30: Cuts 1-2 landed on `main` at `2a1b8a8`, from `hands/cultcache-pub-c1c2` at `5fb3fca`. +Soul verdict: merge. Suites green: Caching 323, Networking 295, Mesh 262. Cut 3 is in Hands on +`hands/cultcache-pub-c3`, with Soul's Cuts 1-2 follow-ups folded in: +- F4: pin `Held`'s publish-on-throw guard. This is needed before Cut 4 relies on sequence density; Stryker could + not mutate `Held` (CS0165). +- F3: pin observer removal on unsubscribe. +- F1: the "getters run once" claim is false for conditional commits on variant stores. + +Recorded: +- F2, the Q-P2 hazard. A rethrown observer exception makes a committed write look cancelled or refused. The + only live typed catch around a cache write is AetheriaEve `Aetheria.State.Daemon/Program.cs:3722`. It needs a + fail-fast handler, and no production code installs one. +- F5: subscribe and unsubscribe cost O(n). +- F6: writes after `Dispose` are dropped silently. + +Map written by Imagination pass 1, 2026-09-29. The ends are the operator ruling of 2026-09-30: every committed cache change reaches subscribers exactly once. This document owns the means. diff --git a/docs/document-variants-cut.md b/docs/document-variants-cut.md index 923c1735..a23fe4ea 100644 --- a/docs/document-variants-cut.md +++ b/docs/document-variants-cut.md @@ -339,6 +339,23 @@ Soul held it. Fixes are in Hands: - **C2b precondition (Soul F7).** Whether a pre-id element keeps its load-time id depends on the write path. C2b must refuse an override that targets a record whose ids exist only in memory, or mint on open. +**C2a Soul pass 2 (`e85b201b`), 2026-09-30: hold.** The tripwire only works against unreleased readers. +Every published release (`cultlib-unity-v1.0.60`, `caching-unity-v1.4.0`, `cultcache-ts-v0.14.0`, +`cultcache-py-v0.3.0`) predates C0. The 1.0.60 C# reader loads a v3 store, and its next write is v1 with the ids +stripped (probe). Other findings: +- F2: the same element object twice in one list commits, then the store refuses to load. +- F3: CultMesh single-file writes bypass the marker. +- F4: TS `pushAll` writes the header without reading it first. + +**C2a rulings, 2026-09-30 (operator):** +- **Rollout order closes the released-reader hole.** Ship a CultLib release that refuses v3, move every C# + reader of a store onto it, then let a C2a writer touch that store. There is no format change for this. + This supersedes the claim above that old readers are tripwired: that claim holds only for post-C0 readers. +- **Mark by content.** A store is written as v3 (v5 for directory stores) only when a record actually holds an + element id. An existing v3 header on disk stays. +- Fix batch 3 in Hands: F2, marking by content in every runtime, F3 routed through the cache's header + decision and load checks, F4. + **Operator rulings, 2026-09-30:** - **Duplicate unique-index values do not load** ("Duplicate indices should not load"). This covers plain records too, so R6-for-indexes becomes one general rule: