/** * Rebuild an unconvergeable legacy `drizzle-tasks` table family inside a * consolidated `cleo.db`. * * ## The failure (T12346) * * Post-E6 the project store is `cleo.db`, and the tasks domain still replays * the legacy `drizzle-tasks` lineage on it. That lineage creates the BARE table * family (`tasks`, `sessions`, `architecture_decisions`, `attachments`, …), * which is dead for task reads and writes (those use the prefixed * `tasks_tasks` family), apart from a few tables older builds still write * (`attachments` and `attachment_refs` are frozen by the T12535 docs collapse: * the runtime uses `docs_attachments` / `docs_attachment_refs`). * On a fresh project the lineage runs from scratch on empty tables. * * Some projects instead carry a `cleo.db` that began life as a copy of their * pre-consolidation `tasks.db` (claude-todo: every bare table row-identical to * `tasks.db`). Its journal was written by the old created_at HIGH-WATER * migrator, which treated every migration older than the newest applied one as * done — so 40 lineage migrations were never executed, and their tables and * columns never existed. Drizzle 1.x selects pending migrations BY NAME, so it * replays those gaps against a schema they were never written for: * * - `t033` rebuilds `architecture_decisions` with a self-FK, and a reference * that was ALREADY dangling fails the copy (`FOREIGN KEY constraint failed`); * - with that out of the way, `t033` rebuilds `tasks` without `assignee`, which a * later migration then SELECTs (`no such column: assignee`); * - stamping the gaps as applied (the high-water reading) instead leaves the * later migrations reaching for tables the gaps create (`no such table: * attachments`). * * No replay order converges, and every command in the project dies at open. * * ## The repair * * The lineage objects are rebuilt exactly as a fresh project gets them: * * 1. `VACUUM INTO` a full snapshot of the database (the bare rows are preserved * there byte-for-byte; the repair refuses to proceed without it); * 2. in ONE transaction, drop every table, view, trigger and index the lineage * creates — never an object any sibling lineage (consolidated schema, brain, * nexus, …) also creates — and delete only the lineage's journal rows; * 3. in the same transaction, execute the whole lineage in order, journaling each * migration as drizzle does. * * Any failure rolls the transaction back, leaving the database byte-identical * to before, and the caller rethrows the original migration error. The * prefixed tables, which hold the project's live data, are never touched. * * @module * @task T12346 */ import type { DatabaseSync } from 'node:sqlite'; /** Outcome of {@link rebuildLegacyTasksLineage}. */ export interface LegacyTasksLineageRebuild { /** Full pre-repair snapshot of the database (holds every dropped row). */ readonly snapshotPath: string; /** Lineage objects that existed and were dropped, by name. */ readonly dropped: readonly string[]; /** Lineage migrations executed afresh. */ readonly migrationsApplied: number; /** * Per dropped table: rows in the snapshot and rows in the recreated table * after the verified copy-back (never fewer; more only where the fresh * lineage seeded rows the snapshot lacked). */ readonly carriedForward: readonly { table: string; snapshotRows: number; restored: number; }[]; } /** * Rebuild the `drizzle-tasks` table family of a consolidated `cleo.db` from * scratch, after snapshotting the whole database. Atomic: on any failure the * transaction is rolled back and the error is rethrown. * * @param nativeDb - Connection on the consolidated `cleo.db`; must not be mid-transaction. * @param dbPath - Absolute path of that database (the snapshot goes beside it). * @param migrationsFolder - The `drizzle-tasks` migrations folder. * @param siblingFolders - Every other lineage sharing this database; objects * they create are never dropped. * @returns What was snapshotted, dropped and applied. * @throws When the snapshot cannot be written, or when the rebuild fails (rolled back). * @task T12346 */ export declare function rebuildLegacyTasksLineage(nativeDb: DatabaseSync, dbPath: string, migrationsFolder: string, siblingFolders: readonly string[]): LegacyTasksLineageRebuild; //# sourceMappingURL=legacy-tasks-lineage.d.ts.map