The Morning of 2026-11-10
Dad answered three questions that morning, one at a time, after a first proposal had buried them in prose: the new store's folder lives in Soul Vault's data root on the Mac holding the Pippa role; a batch of several notes is one commit; and the first commit copies the vault byte for byte, leaving his former folders exactly as they are. Then: start the cutover now. Pippa restarts the services. When the probe passes on the real Delta store, Pippa moves the pointer. Moving it back is Dad's hand only.
The cutover log (docs/PILOT-LOG.md) records each step with its evidence. This track walks it.
Step 0: Every Mac Gets the Code First
A pointer move reaches a Mac with its checkouts. That creates an ordering problem with only one safe answer. Imagine the record moving first: a Mac whose Soul Vault code was older than the record would read a pointer naming a backend or a field it did not understand. The rules from track 3 mean it would refuse loudly rather than misbehave, which is better than silence, but it is still not how a cutover should end. So the code goes everywhere first, and the record follows.
The rehearsal surfaced exactly this risk: five of the managed Macs still held pointer generation 1 and part 1's code. They are the Macs whose checkouts are mirrors with no git credentials, so they cannot simply pull; they received the repository by a Delta sync from the workbench instead. In the half hour before the switch (the log's timestamp reads 13:3x KST) every one of the eight managed Macs held the same Soul Vault commit and the current Firelink record, and each one was checked individually: contract version 5, identity loaded and validated, and the same bundle digest on every Mac. Checked Mac by Mac, with soul-vault pointer printing the record as that Mac reads it, not inferred from "the sync finished".
Step 1: A Field Before a Flip
The Delta store needed one piece of data from the record that the old one never had: the name of its tree's folder. So generation 3 added stores.delta.tree = "vault", with the backend unchanged. Until that field existed, the new store answered every call with pointer_schema_error, which the architecture document calls "the correct refusal". Generation 3 was pulled everywhere, and every Mac loaded identity at generation 3, still from the old store.
Splitting the record change in two (add what the new backend needs, then switch the backend) means the dangerous step, the switch, changes exactly one field. If generation 3 had broken anything, the cause could only have been the new field.
Mirrors and Laggards
Two kinds of lag are named in the checklist so they are never silent:
- A Mac that lags behind the move entirely keeps reading its verified copy, labeled
offline_replica, with the cause. - A Mac with old code and the new record refuses by name.
Mom's Mac is a third case: it holds a mirror, not a checkout, so its installer is run from a workbench before and after any move, whenever that Mac is awake, and proves its bootstrap each time. Neither lag is silent, and neither is accepted as a finished cutover.