import type { AdapterBackupResult } from '@adhd/sox-store-adapter'; export interface MigrateOpenSchemaOptions { /** TEST-ONLY. Never set this from production code or the CLI (`tools/graph-store-migrate-open-schema.mjs` * has no flag that can reach this option). When true, the post-commit re-verification step (§3 step 8) * is told the just-recomputed edge count is wrong regardless of what it actually is, forcing the * restore-from-backup path to execute for real. This is the only way to prove AC-3 (rollback) without * engineering a genuine torn write. */ __test_forcePostCommitMismatch?: boolean; /** * (Task #16, finding 4) Every run of this migration leaves a * `.pre-open-schema-migration-.bak` sibling on disk — pre-fix, * NOTHING ever deleted it, on success or on a handled rollback alike * (verified: neither the success return path nor `MigrationRolledBackError`'s * throw path touched `backupPath` after using it). Since this is an * operator-invoked, rarely-run migration (not a scheduled job), unbounded * growth is slow but real over repeated re-runs against the same store * (retries, re-tests, multiple environments sharing a `dbPath` basename * pattern). Bounds it to the `keepBackups` most recent backups for this * `dbPath`, pruned AFTER the run's own outcome is fully resolved so a * prune can never race the very backup a rollback/error path is reporting * as evidence. Default 3, matching this repo's other retention idiom * (ADR-0014 D2.2's count floor). Set to `Infinity` to disable pruning * entirely (never negative or zero-and-below without explicit intent — * `pruneOldMigrationBackups` treats non-finite/negative as "keep all"). */ keepBackups?: number; } export interface StoreSnapshot { nodeCount: number; edgeCount: number; /** rel -> count, live edges only. */ perRelation: Record; /** sha256 over an ordered, stable projection of `node` — see `captureSnapshot`. */ nodeChecksum: string; /** sha256 over an ordered, stable projection of `edge` — see `captureSnapshot`. */ edgeChecksum: string; } export type MigrateOpenSchemaResult = { status: 'migrated'; backupPath: string; before: StoreSnapshot; after: StoreSnapshot; }; export declare class MigrationPreflightError extends Error { constructor(message: string); } /** Turso-formatted file — refuse. See SPEC-PKT-61.md Decision D-3. */ export declare class UnsupportedBackendError extends Error { constructor(dbPath: string, cause?: unknown); } /** Exclusive lock unobtainable — another connection currently holds the store open. */ export declare class StoreOpenElsewhereError extends Error { constructor(dbPath: string, opts?: { cause?: unknown; }); } /** `backupTo()`'s `integrityReport` wasn't `'verified'`. Nothing was mutated. */ export declare class BackupNotVerifiedError extends Error { readonly backupResult: AdapterBackupResult; constructor(backupResult: AdapterBackupResult); } /** In-transaction pre-commit mismatch — SQL ROLLBACK already ran; the working file is untouched. */ export declare class MigrationVerificationError extends Error { readonly detail?: unknown | undefined; constructor(message: string, detail?: unknown | undefined); } /** Post-commit mismatch; the file-level restore ran and was itself verified. */ export declare class MigrationRolledBackError extends Error { readonly detail: { mismatch: unknown; backupPath: string; restoredSnapshot: StoreSnapshot; }; constructor(detail: { mismatch: unknown; backupPath: string; restoredSnapshot: StoreSnapshot; }); } /** The restore itself didn't reproduce the backup's counts — unrecoverable, never silently swallowed. */ export declare class MigrationRestoreFailedError extends Error { readonly detail: { backupPath: string; restoredSnapshot: StoreSnapshot; }; constructor(detail: { backupPath: string; restoredSnapshot: StoreSnapshot; }); } /** * Converts a raw `ETursoNativeStore` (thrown synchronously by `SqliteAdapterImpl`'s * constructor, per BL-329) into the typed `UnsupportedBackendError` this module surfaces to * callers. Returns `null` for anything else, so the caller can fall through to re-throwing * the original error unconverted. * * Exported and independently testable (AC-6) without needing a live Turso engine — pass a * real `ETursoNativeStore` instance directly. */ export declare function toUnsupportedBackendRefusal(err: unknown): UnsupportedBackendError | null; /** * Enforce a bounded retention policy on `.pre-open-schema-migration-*.bak` * siblings: keep the `keepBackups` most recent, delete the rest. * * Pre-fix, NOTHING ever called this — every invocation of `migrateToOpenSchema` * left its backup on disk permanently, on both the success path and the * `MigrationRolledBackError` path (both used `backupPath` and then simply * returned/threw without cleanup). This is an operator-invoked, rarely-run * migration, so the accumulation is slow, but it is exactly the "no * reclamation path" class the rest of this task addresses — a `--confirm` * CLI run against a shared fixture/dev store, repeated across retries or CI * runs, silently grows an unbounded set of full-store `.bak` copies. * * Deliberately never called from the `MigrationRestoreFailedError` path * (`migrateToOpenSchema` step 8's unrecoverable branch): that error's whole * point is "do not trust anything here, a human must look," and its own * message explicitly promises the backup is "still on disk at the path * above" — pruning there would break that promise on the one path where it * matters most. * * Exported and independently testable without running a real migration — * seed matching filenames directly. */ export declare function pruneOldMigrationBackups(dbPath: string, keepBackups?: number, log?: (...args: unknown[]) => void): string[]; export declare function migrateToOpenSchema(dbPath: string, opts?: MigrateOpenSchemaOptions): Promise; //# sourceMappingURL=open-schema-migration.d.ts.map