Spike note: the fork's pathname entry points enumerated by reading every call (Part B's task list), grouped by the directory each must take
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
1 file changed,
+12
−0
docs/superpowers/specs/2026-10-03-replicator-pinned-roots-spikes.md+12 −0
CI passed — run details
diff --git a/docs/superpowers/specs/2026-10-03-replicator-pinned-roots-spikes.md b/docs/superpowers/specs/2026-10-03-replicator-pinned-roots-spikes.md| index 48a70767e..d6b9ce836 100644 |
| --- a/docs/superpowers/specs/2026-10-03-replicator-pinned-roots-spikes.md |
| +++ b/docs/superpowers/specs/2026-10-03-replicator-pinned-roots-spikes.md |
| @@ -24,3 +24,15 @@ Plan step 0's second spike is code, kept in tree at `internal/ops/admissionmodel |
| - **Mutants, in a tree copy**, each killed by a named test or a schedule: no construction backfill (reach); the pending set not counted (the commit-after-discovery tests); no recheck after commit (the same test, and a hazard at seed 264); the replay dropping counted settlements (hazard); the replay closing at the discovery instant (liveness and the latch tests); a settlement writing no interval (hazard); recovery ignoring the fence (the fence test); helper death without transport-lost (an uncertainty open at quiescence); the lower bound ignoring the clean look (the lower-bound test; the 30000-schedule sweep alone did not find it, which is why that sequence is a named test); the lower bound ignoring the earliest unsettled admission (liveness, because the model's proof then reached too far); unrecorded synthesised for a registered worker (the guard test); recovery skipping unclosed fleets (an uncertainty open at quiescence); acknowledgement not root-first and reach ignoring successors (reach). An epoch check made redundant by the stale state is the one equivalent mutant, noted in the model. |
| - **What the model does not cover**, by construction: the ledger's commit latency on a box's disk under the replicator's request rate (the spike's other half, which needs a box), Part C2's owner scope beyond the owner-scoped holds the model writes, and process kills inside a transaction (the model's transactions are atomic by fiat; the ledger's are SQLite's). |
| +## The fork's pathname entry points (read 2026-10-03 08:25, every call, not a sample) |
| + |
| +Part B's first task is to move every pathname operation of `third_party/litestream` beneath a retained directory. This is the list, by `grep` over every non-test file for `os.*`, `filepath.Walk` and `sql.Open`, each call read in its function and assigned the directory it must take. `vfs.go` is build-tagged `vfs` and is not compiled into the platform; `server.go` (a control socket) is not used by the platform. |
| + |
| +**The tenant's data directory (`SetDataDir`, Part B item 1):** `db.go:987` `os.Stat(db.path)` and `:996` `os.Stat(filepath.Dir(db.path))` in `init` (the identity checks the design replaces with the accepted facts and the retained directory); `:1004` `sql.Open("sqlite", dsn)` in `init` (the connection: the descriptor-rooted VFS's DSN); `:1014` `os.Open(db.path)` in `init` (`db.f`, the long-lived descriptor: `OpenRegular` against the accepted facts); `:698` `os.Stat(db.Path())` in `EnsureExists`; `:1242` `os.Stat(db.path)` in `syncLocked`; the WAL by path in `walFileSize` `:1386`, `:1404`, `:1540`, `detectFullCheckpoint` `:1690`, `sync` `:1866`, `snapshotReader` `:2410` (all `openat(dirfd, "<name>-wal")` with `O_NOFOLLOW|O_NONBLOCK` and a regular-file `fstat`); `litestream.go:139` `readWALHeader` and `:153` `readWALFileAt` (called with `db.WALPath()`; take the directory and the name). |
| + |
| +**The platform's shadow-state directory (`SetMetaDir`, Part B item 1):** `db.go:705` `os.MkdirAll(dir)` in `EnsureExists` (the directory is created by the agent and handed over; the fork creates nothing above it); `:488` `os.RemoveAll(db.LTXDir())` in `ResetLocalState` and `:1445` in `checkDatabaseBehindReplica` (an `unlinkat` walk beneath the descriptor); `:519` `openLocalLTXFile`, `:526` remove, `:537` `os.ReadDir(db.LTXLevelDir(0))` in `MaxLTX`, `:583` in `Pos`, `:1116` in `verifyHeadersMatch`, `:1523` in `verifyWithExecutor`, `:1465`–`:1486` (temp file, rename) in `checkDatabaseBehindReplica`, `:1936`–`:2027` (temp LTX, rename) in `sync`, `:2676` and `:2739`, `:2797` in the retention passes; `litestream.go:170`–`:179` `removeTmpFiles` (`filepath.Walk` over the meta root: becomes a listing-and-`unlinkat` walk on `Dir`s); `replica.go:186` `os.Open(filename)` in `uploadLTXFile` (an LTX file: the meta directory). The design's lineage record and migration marker live here too, with the five-step write the design states. |
| + |
| +**Restore-side, not the agent's streaming path:** `replica.go:561`–`:738` `Restore` and `follow`, `:1011`–`:1095` `RestoreV3`, `:1158` `downloadSnapshotV3`, `:1216` `applyWALSegmentsV3`, `:1248` `checkpointV3` and `:1264` `checkIntegrity` (`sql.Open` by path on the restore output), `:1289`–`:1290`, `:1651`–`:1690` `WriteTXIDFile` (the one place that syncs a parent after a rename) and `ReadTXIDFile`. These act on an output path the caller chooses; whether the platform's restore door uses them is a question for the console, not the fleet, and Part B does not change them. The design's restore statement (D:63) is about the fork's verification on the next sync, not these. |
| + |
| +So Part B's fork task has twenty-three call sites to move (eleven data-directory, twelve meta-directory, counting the two `litestream.go` readers once each) and the one `sql.Open` to give the VFS's DSN; the restore side is seventeen sites left as they are, named so nothing is sampled. |
| + |