|
| 1 | +-- 2026072303_layer_worktree_scope |
| 2 | +-- |
| 3 | +-- plan-20260714 Part C W1 (§C.4.1.1): scope the layer overlay registry per |
| 4 | +-- worktree. `layer` gains `worktree_id` with UNIQUE(worktree_id, name) and |
| 5 | +-- `layer_path` gains `worktree_id` with UNIQUE(worktree_id, path) — the same |
| 6 | +-- layer name and the same materialized destination may exist independently |
| 7 | +-- in different worktrees. |
| 8 | +-- |
| 9 | +-- Legacy-row rule (§C.4.1.1): layer registration/ownership is NOT rebuildable |
| 10 | +-- advisory state — clearing it would make materialized overlay files |
| 11 | +-- committable (breaking never-enters-commit), and guessing an owner is |
| 12 | +-- forbidden. Legacy global rows are adopted to the MAIN scope ('') ONLY when |
| 13 | +-- the guard below proves no linked worktree exists (no linked HEAD row in |
| 14 | +-- `reference`): layer mutations have been main-only since the W0 transition |
| 15 | +-- guard, so absent linked worktrees the rows can only belong to main. If |
| 16 | +-- linked worktrees coexist with legacy rows, this migration FAILS CLOSED — |
| 17 | +-- run `libra layer unapply` / `libra layer remove <name>` from the owning |
| 18 | +-- worktree on the previous binary (or main), then upgrade. |
| 19 | + |
| 20 | +-- Defensive: guarantee the legacy shapes exist so the rebuild below is |
| 21 | +-- well-defined even on a database that somehow skipped 2026070501. |
| 22 | +CREATE TABLE IF NOT EXISTS `layer` ( |
| 23 | + `id` INTEGER PRIMARY KEY AUTOINCREMENT, |
| 24 | + `name` TEXT NOT NULL UNIQUE, |
| 25 | + `source` TEXT NOT NULL, |
| 26 | + `priority` INTEGER NOT NULL DEFAULT 0, |
| 27 | + `enabled` INTEGER NOT NULL DEFAULT 1, |
| 28 | + `created_at` TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP, |
| 29 | + `updated_at` TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP |
| 30 | +); |
| 31 | +CREATE TABLE IF NOT EXISTS `layer_path` ( |
| 32 | + `id` INTEGER PRIMARY KEY AUTOINCREMENT, |
| 33 | + `layer_name` TEXT NOT NULL, |
| 34 | + `path` TEXT NOT NULL UNIQUE, |
| 35 | + `content_hash` TEXT NOT NULL, |
| 36 | + `materialized_at` TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP |
| 37 | +); |
| 38 | + |
| 39 | +-- Fail-closed guard: legacy global layer rows + linked worktree evidence |
| 40 | +-- (a linked HEAD row) is ambiguous ownership — refuse the whole migration |
| 41 | +-- (CHECK violation rolls back this transaction, including the version claim). |
| 42 | +CREATE TABLE `layer__legacy_rows_need_explicit_adopt_2026072303` ( |
| 43 | + `blocked` INTEGER NOT NULL CHECK (`blocked` = 0) |
| 44 | +); |
| 45 | +INSERT INTO `layer__legacy_rows_need_explicit_adopt_2026072303` (`blocked`) |
| 46 | +SELECT CASE |
| 47 | + WHEN ((SELECT COUNT(*) FROM `layer`) + (SELECT COUNT(*) FROM `layer_path`)) > 0 |
| 48 | + AND EXISTS (SELECT 1 FROM `reference` |
| 49 | + WHERE `worktree_id` IS NOT NULL AND `worktree_id` <> '') |
| 50 | + THEN 1 ELSE 0 END; |
| 51 | +DROP TABLE `layer__legacy_rows_need_explicit_adopt_2026072303`; |
| 52 | + |
| 53 | +ALTER TABLE `layer` RENAME TO `layer__old_2026072303`; |
| 54 | +CREATE TABLE `layer` ( |
| 55 | + `id` INTEGER PRIMARY KEY AUTOINCREMENT, |
| 56 | + `worktree_id` TEXT NOT NULL DEFAULT '', |
| 57 | + `name` TEXT NOT NULL, |
| 58 | + `source` TEXT NOT NULL, |
| 59 | + `priority` INTEGER NOT NULL DEFAULT 0, |
| 60 | + `enabled` INTEGER NOT NULL DEFAULT 1, |
| 61 | + `created_at` TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP, |
| 62 | + `updated_at` TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP, |
| 63 | + UNIQUE(`worktree_id`, `name`) |
| 64 | +); |
| 65 | +INSERT INTO `layer` |
| 66 | + (`id`, `worktree_id`, `name`, `source`, `priority`, `enabled`, |
| 67 | + `created_at`, `updated_at`) |
| 68 | +SELECT `id`, '', `name`, `source`, `priority`, `enabled`, |
| 69 | + `created_at`, `updated_at` |
| 70 | +FROM `layer__old_2026072303`; |
| 71 | +DROP TABLE `layer__old_2026072303`; |
| 72 | + |
| 73 | +ALTER TABLE `layer_path` RENAME TO `layer_path__old_2026072303`; |
| 74 | +CREATE TABLE `layer_path` ( |
| 75 | + `id` INTEGER PRIMARY KEY AUTOINCREMENT, |
| 76 | + `worktree_id` TEXT NOT NULL DEFAULT '', |
| 77 | + `layer_name` TEXT NOT NULL, |
| 78 | + `path` TEXT NOT NULL, |
| 79 | + `content_hash` TEXT NOT NULL, |
| 80 | + `materialized_at` TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP, |
| 81 | + UNIQUE(`worktree_id`, `path`) |
| 82 | +); |
| 83 | +INSERT INTO `layer_path` |
| 84 | + (`id`, `worktree_id`, `layer_name`, `path`, `content_hash`, |
| 85 | + `materialized_at`) |
| 86 | +SELECT `id`, '', `layer_name`, `path`, `content_hash`, `materialized_at` |
| 87 | +FROM `layer_path__old_2026072303`; |
| 88 | +DROP TABLE `layer_path__old_2026072303`; |
0 commit comments