/** * Reusable CORE migration-parity primitive — `verifyMigration()`. * * This is the durable guard (T11551 · DHQ-045) that prevents the exodus * dual-DB consolidation from silently losing rows. It is intentionally generic: * given a set of legacy source DBs and the consolidated target DB paths, it * returns a typed {@link VerifyMigrationResult} covering FOUR failure classes: * * 1. **Per-table row-count parity** — every data-bearing source table's * consolidated counterpart MUST NOT have FEWER rows than the source (a * DEFICIT = data loss → failure). A SURPLUS (target > source — e.g. * `nexus_audit_log` gaining the migration's own audit writes during the * migrating open) is NOT loss and is tolerated with a WARN (T11577). The * per-table `countMatch` field stays a strict `source === target` * diagnostic; only a deficit contributes a failure. * 2. **`PRAGMA foreign_key_check`** — genuine referential orphans on the * consolidated target surface as failures (not copy-order artifacts). * 3. **Content checksum** — an ordered canonical-JSON SHA-256 digest over the * sorted intersection of source/target columns catches content drift even * when counts match. * 4. **Enum/type-drift report** — source values outside the target column's * CHECK enum. This is the EXACT class that `INSERT OR IGNORE` used to drop * silently (the root cause of the ~805K-row exodus loss). * * ## Relationship to `runExodusVerify` * * `runExodusVerify` ({@link ./verify.ts}) is the exodus-specific entry point. * It now DELEGATES the row-count + checksum parity to this primitive (DRY — * T11551 AC2) and additionally surfaces the FK + enum-drift checks this module * adds. The digest, name-mapping, and rowid-safe ordering logic that the exodus * campaign hardened (T11531/32/33) live here as the single implementation. * * ## False-pass guard (T11531, preserved) * * When `ok === false`, `error` is ALWAYS populated with a human-readable * failure summary so a caller that only checks `result.error` cannot mistake a * silent loss for success. * * @task T11551 (DHQ-045 — exodus zero-loss durable guard) * @epic T10878 * @saga T11242 */ import type { VerifyMigrationResult } from '@cleocode/contracts'; import type { LegacyDbDescriptor } from './types.js'; /** * Verify that a source→target SQLite migration preserved every row, referential * integrity, content, and enum validity. * * Opens all source DBs and the consolidated target DBs **read-only**, then for * each legacy source table: * * 1. Resolves the consolidated target name via {@link resolveConsolidatedTableName}. * 2. Compares row counts (parity gate). * 3. Computes a column-intersection content digest on both sides. * 4. Records any enum/type drift (source values outside the target CHECK enum). * * After all tables, it runs `PRAGMA foreign_key_check` on each distinct target * DB and folds the orphan rows into the result. * * @param sources - Legacy source descriptors (from `buildExodusPlan()`). * @param projectDbPath - Absolute path to the consolidated project `cleo.db`. * @param globalDbPath - Absolute path to the consolidated global `cleo.db`. * @param onProgress - Optional progress callback. * * @returns A {@link VerifyMigrationResult}. `ok === false` (with `error` * populated) on any count mismatch, content mismatch, FK orphan, or enum * drift. * * @task T11551 (DHQ-045 — exodus zero-loss durable guard · AC1) */ export declare function verifyMigration(sources: LegacyDbDescriptor[], projectDbPath: string, globalDbPath: string, onProgress?: (msg: string) => void): VerifyMigrationResult; //# sourceMappingURL=verify-migration.d.ts.map