/** * Memory-safe COUNT(*)-only exodus parity — the deficit gate WITHOUT the content * digest (T11837). * * `verifyMigration` is the full parity guard (row counts + content digest + FK + * enum drift), but its content digest streams every row of every table. For the * fleet-flow surface — `cleo exodus seal` (certify an already-migrated install) * and `cleo doctor exodus` (health report) — we only need the DEFICIT gate that * `isDataContinuityOk` actually enforces: per-table `target COUNT(*) >= source * COUNT(*)`. That is a set-based query SQLite answers without materialising a * single row, so it is safe to run against a 1.7 GB-class legacy `brain.db` * (where the digest would be expensive). A SURPLUS (target > source — the live * consolidated DB has moved ahead of the frozen legacy snapshot) is NOT loss and * is tolerated, exactly as in `isDataContinuityOk`. * * This is intentionally a SEPARATE primitive from `verifyMigration` — sealing an * already-migrated install must never re-run the heavy digest that this whole * fleet-hardening epic (T11833) exists to avoid. * * @task T11837 (fleet-flow surface — count-only parity for seal + health) * @epic T11833 (EP-EXODUS-FLEET-HARDENING) * @saga T11242 (SG-DB-SUBSTRATE-V2) */ import type { ExodusScope, LegacyDbDescriptor } from './types.js'; /** Per-table COUNT(*) comparison between a legacy source table and its target. */ export interface CountParityEntry { /** Logical source DB name (`LegacyDbDescriptor.name`). */ readonly sourceDb: string; /** Physical legacy source table name. */ readonly sourceTable: string; /** Consolidated target table name. */ readonly targetTable: string; /** Effective target scope (per-table override included — ADR-090 nexus graph). */ readonly scope: ExodusScope; /** Source row count. */ readonly sourceCount: number; /** Consolidated target row count (0 when the target table is absent). */ readonly targetCount: number; /** `sourceCount - targetCount` when positive (rows MISSING in target); else 0. */ readonly deficit: number; } /** Result of a COUNT(*)-only parity sweep across all source tables. */ export interface CountParityResult { /** `true` when NO data-bearing table has a deficit. */ readonly ok: boolean; /** Every compared table (parity, surplus, and deficit). */ readonly entries: readonly CountParityEntry[]; /** The subset with a genuine deficit (`targetCount < sourceCount`). */ readonly deficits: readonly CountParityEntry[]; /** Count of tables compared. */ readonly checked: number; /** Count of skipped tables (derived/FTS/internal or virtual that cannot be counted). */ readonly skipped: number; } /** * Compute COUNT(*)-only parity for every legacy source table against the * consolidated dual-scope target — the deficit gate, never the heavy digest. * * Opens all DBs read-only. A table whose consolidated counterpart is ABSENT with * source rows is a deficit (`targetCount: 0`). Derived/FTS/internal tables that * map to `skip`, and virtual tables that cannot be counted, are skipped. * * @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`. * @returns A {@link CountParityResult}; `ok === false` when any table has a deficit. * * @task T11837 */ export declare function computeCountParity(sources: readonly LegacyDbDescriptor[], projectDbPath: string, globalDbPath: string): CountParityResult; //# sourceMappingURL=count-parity.d.ts.map