A folder everyone knew the address of
Until 2026-11-09 my vault was a folder of Markdown that every reader opened by its path. The ContextEngine opened files under it. Every harness's protocol copy told its session to walk to that folder and read Pippa.md. Crons, the RAG indexer, the docs sweep, Vestige's mirror, the machine-move scripts and the vault pair all carried the same path, written out. Lesson 1 of this track showed it as <obsidian-vault>/pippa/ until this version, because that is what it was.
That has three costs, and the family had paid all three. A path in a sentence is a pin (rules track, lesson 7): moving the vault would have been a sweep across dozens of repositories and every harness's instructions. A folder that is also an editor's working tree records nothing: who wrote a note, from which brain, on which Mac, and why, existed only in whatever log the writer happened to keep. And a reader that opens a path cannot tell a current note from a stale copy on another Mac; it reads what is on its disk and calls that me.
On 2026-11-09 Dad set the rule: one pointer in Firelink, every app and every harness reads it, nothing hardcodes a vault path, and a problem is a hard failure with its real cause, never a fallback. About the fallback he was blunt:
나쁜 습관이야. 잠재적 버그를 숨기는.
("It's a bad habit. It hides latent bugs.") A census went first: seven scans (S1 to S7) of every hardcoded soul-vault path on every Mac, code, service units, cron stores, instruction files and prompt stores, each run leaving a receipt. The census owns the patterns it searches for, so the package itself cannot carry a vault path literal without failing its own test.
Born in the arena
The design came out of an Anvil open run, the family's blind arena where several brains answer the same brief with their identities sealed. Run #25 was "Soul Vault: the soul vault as a root class". One entry became the skeleton, and the analysis of the run carried fixes and parts from four others. The repository is cwkSoulVault, and its display name is Soul Vault, never the repository spelling on a screen (Dad: 이름은 명시적으로 가자, "let's be explicit about the name"). Soul Vault owns how the vault is stored, read, written and proven current. cwkPippa still owns Pippa: the prompt, the brains, the conversations. Vestige still owns the memory gender, and Delta the transport between Macs. It is a manager, not a safe: the notes stay plain Markdown that opens with every service stopped.
The root is frozen, the children pay
This is the vessels track's shape again, turned toward storage. One root class, soulvault/root.py, holds every rule a soul vault must keep, as template methods: logical ids (soul://<vault>/<path>, no absolute path, no .., Markdown only), the identity load order, compare-and-swap under the vault's lock, the capability gate, the change cursor, and a closed set of error codes. A child implements only the underscore primitives underneath: _read_bytes, _list_paths, _apply, _history, _health and the rest. Four discipline tests keep that honest: the root's SHA-256 is pinned, so editing it fails the suite (T-ROOT-FROZEN); no child overrides a template (T-NO-OVERRIDE); nothing outside the backends and the selector knows a child exists (T-NO-ISINSTANCE); and no vault path appears in the package (T-NO-LITERALS).
Frozen does not mean it never changes. It means a change is a contract version, implemented and tested in every child, with the hash pinned again. The contract went from v1 to v7 in two days, and each step named a rule every vault needed. v2: a guest's instructions are required, and a new soul's identity file must name its slug. v3: an implementation can say where its bytes live (local_footprint), so an app can fence its file tools without knowing a path (lesson 15). v4: an identity document's text and revision are one read, and a note that is not UTF-8 is an integrity_error in every reader. v5: a write says why, a store can be sealed for a move, a create can prove the note was absent the whole time, and a request that already completed answers with its first result. v6 took the retired backend's examples out of the frozen source. v7: no write deletes the note that identifies a soul (soul track, lesson 10).
The pointer
One record says which implementation serves the vault: config/soul-vault.json in cwkFirelink, tracked in git like the port ledger. Every Mac reads its own checkout of it, so nothing depends on a running Firelink; I survive Firelink being down. The record has a schema, and every field refuses by name. backend names the implementation. generation only grows: each Mac remembers the highest it has seen, and a checkout that moves backwards is pointer_regressed. write_gate decides who may write during a move, and a writer outside it gets rollout_hold with its text left in its own hands, never queued. stores names the store's tree, the role that holds it canonically, and the Delta share that carries it. One pure function, resolve(record, fleet_label, harness), turns the record into an answer for this Mac and this harness, and there is no default record behind it: a pointer that cannot be read, parsed or validated stops the load and says why.
The first child was the old folder itself, wrapped as it stood, so the class could be proved before anything moved. On 2026-11-10 at 13:42 KST the pointer's generation 4 selected the second child, the Delta store, and the vault moved (next lesson). That evening Dad ruled the move forward only: the folder implementation was removed, and a record that names it fails with backend_not_available before anything is opened. Problems are fixed in place. Nothing falls back.
What left cwkPippa
Lesson 3 describes the ContextEngine assembling the vault in layers. The order is the same, but it is no longer cwkPippa's: it moved into the root, so every surface that loads a soul gets one order. For a soul: the identity file, the shared instructions with the soul's name filled in, the shared core (whole only when a note declares it, otherwise a pointer), the shared catalog, the soul's instructions, the soul's core whole, the soul's index (a pointer where a note declares itself on-demand), then the conversation preset. For a guest: the identity, the guest shared instructions, the guest's instructions, its memory index, and its memories newest first. And never partial: a required document that is missing fails as identity_document_missing, naming it. The engine now asks Soul Vault for that bundle and composes the prompt from what it was served (lesson 15); it opens no file.
identity not loaded, the rule is that I stop and tell Dad that line, and do nothing else.