/** * Detect pre-dual-scope store files left on disk under their old LIVE names. * * ## The failure this exists to stop (T12095) * * Before the E6 dual-scope migration (ADR-068), a project's task database was * `.cleo/tasks.db`. Afterwards it is `.cleo/cleo.db`, and task rows live in * PREFIXED tables (`tasks_tasks`, `tasks_sessions`, …) rather than bare `tasks`. * The migration does not delete the old file, so a migrated project has * * .cleo/cleo.db 60 MB modified today ← the real store * .cleo/tasks.db 408 KB modified in June ← superseded, still named * as though it were live * * Three separate things then point an agent at the wrong file: * * 1. The old name is the one every doc, ADR-013 §9 note and `cleo restore * backup --file tasks.db` invocation still says out loud. * 2. Snapshots are written as `.cleo/backups/sqlite/tasks-.db` even though * they are snapshots of `cleo.db`. So the superseded 408 KB file sits beside * 58 MB files bearing its own name — which reads unmistakably as truncation. * 3. `cleo.db` ALSO contains a bare, empty `tasks` table next to the populated * `tasks_tasks`. Any direct SQL probe finds the empty decoy. * * Measured on 2026-08-09: an agent in a healthy project with 1,123 tasks looped * on "the current tasks.db is 417KB which is much smaller than the backups * (58MB) — maybe it was rotated/rebuilt", then began theorising that the real * store might be `llmtxt.db`. Nothing was wrong with the data. The layout * manufactured a corruption signal, and the agent believed it over the CLI. * * This check names the file, proves which store is authoritative by counting * rows in both, and says what to do — so the question is answered in one call * instead of becoming an investigation. * * @task T12095 * @see ADR-068 — dual-scope DB chokepoint */ /** * A store file that has been superseded by `cleo.db` but still exists under the * name that used to mean "the live database". */ export interface SupersededStoreEntry { /** Absolute path of the superseded file. */ readonly path: string; /** Bare filename, e.g. `tasks.db`. */ readonly name: string; /** Size in bytes. */ readonly sizeBytes: number; /** Last modification time, ISO 8601. */ readonly modifiedAt: string; /** * Rows found in the superseded file's own task table, if it has one. * `null` when the file has no such table or could not be read. A 0-byte * file yields `0`, never `null` — an empty file holds zero rows by * definition (T12099). */ readonly rowsInSuperseded: number | null; /** Rows found in the LIVE store's prefixed table. */ readonly rowsInLive: number | null; /** * True when the live store demonstrably holds the data and this file does * not — i.e. it is safe to archive. False keeps the entry but withholds the * recommendation, because "delete the other database" must never be advised * on a guess. */ readonly safeToArchive: boolean; /** Human-readable justification, suitable for printing verbatim. */ readonly reason: string; } /** Result of {@link scanSupersededStores}. */ export interface SupersededStoreScanResult { /** Absolute project root that was scanned. */ readonly projectRoot: string; /** Absolute path of the live dual-scope store. */ readonly liveStorePath: string; /** Whether the live store exists — when false, nothing is superseded. */ readonly liveStoreExists: boolean; /** Superseded files found, newest-modified first. */ readonly entries: readonly SupersededStoreEntry[]; } /** The dual-scope store filename (ADR-068). */ export declare const LIVE_STORE_FILENAME = "cleo.db"; /** * Scan a project for store files superseded by `cleo.db`. * * Read-only — deletes nothing and opens nothing for write. The caller decides * what to do with the recommendation. * * @param projectRoot - absolute path to the project root. * @returns the survey; `entries` is empty for a project that never migrated or * that has already been tidied. * * @example * ```ts * const scan = scanSupersededStores('/mnt/projects/PepsVida'); * for (const e of scan.entries) console.log(e.name, e.reason); * // tasks.db superseded by cleo.db: 0 rows here vs 1123 in cleo.db#tasks_tasks … * ``` * * @task T12095 */ export declare function scanSupersededStores(projectRoot: string): SupersededStoreScanResult; //# sourceMappingURL=superseded-store.d.ts.map