Commit c5b5a95
authored
Make the local v1→v2 gate ledger-stamped and journal-corruption-proof (#982)
The desktop sidecar crashed at boot (2026-06-11, every launch) on a real
~/.executor/data.db: full v1-final schema but an EMPTY __drizzle_migrations
journal. The legacy-replay prefix check read '0 applied' as a valid prefix
of the bundled chain and replayed migration 0000 over the existing tables,
dying on 'table blob already exists'. Detection by data shape on every
boot meant there was no way out.
Three layers, in order of defense:
- Schema-marker gate: the legacy replay exists only so readV1Snapshot can
query plugin_storage (created by legacy 0011). If plugin_storage already
exists the schema is sufficient — the journal is never consulted. This
alone fixes the observed crash.
- Tolerant replay: when the journal is missing/empty/foreign AND the
schema is genuinely mid-chain, re-execute the frozen legacy chain
statement-by-statement skipping 'already exists / duplicate column /
no such ...' errors (the chain's data statements are idempotent by
construction: INSERT OR IGNORE / OR REPLACE, conditional UPDATEs).
Replaces the old 'read the schema as-is' fallback, which just crashed
later in readV1Snapshot.
- Ledger stamp: the v1 gate is now the first entry in the boot
data-migration registry (2026-06-11-local-v1-to-v2). After one
successful pass the stamp short-circuits the gate before any schema
probing — the stamp row, not data shape, is the source of truth, so
v1-looking residue can never re-trigger a migration.
Coverage (all against real libSQL databases built by the real frozen
legacy chain):
- v1-v2-ledger.test.ts: 8-state matrix — the exact crash state, wiped
journal mid-chain (tolerant replay proves 0011's backfill runs for
real), healthy v1-final, pre-v1-final replay, fresh, stamped-residue,
downgrade/re-upgrade, pre-ledger v2 stamping order.
- v1-v2-boot-drive.test.ts: full-stack boot drives (gate -> fumadb DDL ->
ledger -> createExecutor) with real work after every boot: addSpec, a
connection, live HTTP tool invocations; reboot loops asserting no-op
convergence and exactly one backup; the real 16MB Cloudflare spec
(2800+ ops) added on a crash-state-migrated database and re-listed
after reboot.
Also verified directly against a copy of the actual crashed
~/.executor/data.db: migrates (1 integration carried), stamps, second
boot no-ops, 407ms total.1 parent b92dba6 commit c5b5a95
4 files changed
Lines changed: 909 additions & 23 deletions
File tree
- apps/local/src/db
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
8 | | - | |
| 8 | + | |
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
| |||
14 | 14 | | |
15 | 15 | | |
16 | 16 | | |
| 17 | + | |
17 | 18 | | |
18 | 19 | | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
19 | 26 | | |
20 | 27 | | |
21 | 28 | | |
| |||
0 commit comments