/** * Legacy-backup walker for `cleo doctor legacy-backups`. * * Enumerates every `*-pre-cleo.db.bak`, `brain.db.PRE-DUP-FIX-*`, * `*.pre-untrack-*`, and overflow `.cleo/backups/sqlite/*.db` artefact * across: * * - `/.cleo/quarantine/` (NEVER auto-pruned) * - `/.cleo/backups/` (snapshot rotation overflow only) * - `/.cleo/backups/sqlite/` (per-DB rotation overflow) * - `/.cleo/backups/safety/` (T5158 pre-untrack siblings) * - `/` (global tier legacy DBs) * - `/nexus/` (nested-nexus legacy DBs) * * Each match is classified by `LegacyBackupOriginHint` and given a * retention recommendation (`keep` / `compress` / `delete`) based on the * 30-day soft + 90-day hard retention windows documented in ADR-013 §9. * * Two modes are exposed: * * - {@link scanLegacyBackups} — read-only walk; populates `entries`. * - {@link pruneLegacyBackups} — same walk + actually deletes * `delete`-recommended files (dry-run by default). * * Path resolution honours the project root + `@cleocode/paths` * `getCleoHome()`. Every disk op is wrapped in a defensive try/catch so * a single permission error never breaks the survey. * * @task T10309 * @epic T10282 * @saga T10281 * @see ADR-013 §9 — Legacy backup retention policy */ import type { LegacyBackupEntry, LegacyBackupOriginHint, LegacyBackupRecommendation, LegacyBackupScanResult } from '@cleocode/contracts'; /** * Default soft retention window. Files younger than this are * unconditionally classified `keep` regardless of any other heuristic. */ export declare const DEFAULT_SOFT_RETENTION_DAYS = 30; /** * Default hard retention window. Files older than this and outside the * quarantine tree are classified `delete`. */ export declare const DEFAULT_HARD_RETENTION_DAYS = 90; /** * Configurable retention thresholds + override hook for clock-skew * deterministic tests. * * @task T10309 */ export interface LegacyBackupScanOptions { /** Soft retention window in days (default {@link DEFAULT_SOFT_RETENTION_DAYS}). */ softRetentionDays?: number; /** Hard retention window in days (default {@link DEFAULT_HARD_RETENTION_DAYS}). */ hardRetentionDays?: number; /** * Wall-clock reference used by the walker for age computation. Test * fixtures pin this so the recommendation is independent of the * machine clock. Defaults to `Date.now()` at call time. */ nowMs?: number; } /** * Prune-mode options. Always implies dry-run unless the caller passes * `dryRun: false`. * * @task T10309 */ export interface LegacyBackupPruneOptions extends LegacyBackupScanOptions { /** * When `false`, the walker physically removes every artefact whose * recommendation is `delete`. DEFAULTS to `true` (dry-run) so a bare * `--prune` invocation can never destroy data. */ dryRun?: boolean; } /** * Predicate: does this filename match one of the legacy backup * patterns the walker is responsible for? * * @param name - Plain filename (no directory). * @returns `true` when the file is a legacy backup candidate. */ export declare function isLegacyBackupFilename(name: string): boolean; /** * Infer the origin hint for a legacy backup file from its absolute path * and basename. * * @param absolutePath - Absolute path to the candidate file. * @returns The most specific {@link LegacyBackupOriginHint} we can * confidently assign without opening the file. */ export declare function classifyLegacyBackup(absolutePath: string): LegacyBackupOriginHint; /** * Compute the retention recommendation for a legacy backup. * * Decision table: * * | Condition | Recommendation | * |--------------------------------------|----------------| * | `originHint === 'quarantine-*'` | `keep` | * | `ageDays <= softRetentionDays` | `keep` | * | `ageDays >= hardRetentionDays` | `delete` | * | `softRetentionDays < age < hard...` | `compress` | * * Quarantine and brain-malformed origins are ALWAYS kept — operators * may need them for forensic incident analysis. * * @param entry - Partial entry with `ageDays` and `originHint` already * resolved. * @param softRetentionDays - Soft retention threshold. * @param hardRetentionDays - Hard retention threshold. * @returns Tuple of recommendation + human-readable reason. */ export declare function recommendForBackup(entry: Pick, softRetentionDays: number, hardRetentionDays: number): { recommendation: LegacyBackupRecommendation; reason: string; }; /** * Source paths the walker visits, in canonical order. Excludes the * worktree mirror under `/.cleo/worktrees.json` (sentinel * file, not a directory) and the `.git/` tree. * * @param projectRoot - Absolute project root. * @param cleoHome - Absolute CLEO home (`getCleoHome()`). * @returns Ordered array of directories to walk. */ export declare function legacyBackupSearchRoots(projectRoot: string, cleoHome: string): string[]; /** * Read-only legacy-backup walker. * * Enumerates every artefact under {@link legacyBackupSearchRoots} that * matches {@link isLegacyBackupFilename}, classifies each by origin, * and assigns a retention recommendation. The result is sorted by path * ascending and exposes the configured thresholds back to the caller. * * @param projectRoot - Absolute path to the project root. * @param options - Optional retention thresholds + clock override. * @returns A {@link LegacyBackupScanResult} with `prune: false` and * empty `pruned`/`kept` arrays. * * @task T10309 */ export declare function scanLegacyBackups(projectRoot: string, options?: LegacyBackupScanOptions): LegacyBackupScanResult; /** * Prune-mode wrapper around {@link scanLegacyBackups}. * * Walks the same roots and, when `options.dryRun === false`, removes * every artefact whose `recommendation === 'delete'`. Quarantine * artefacts are NEVER touched — the `recommendForBackup` decision * table already filters them out. * * @param projectRoot - Absolute path to the project root. * @param options - Retention thresholds + dry-run toggle. `dryRun` * defaults to `true` so the verb is safe under all calling * conditions. * @returns A {@link LegacyBackupScanResult} with `prune: true` and * `pruned`/`kept`/`errors` populated. * * @task T10309 */ export declare function pruneLegacyBackups(projectRoot: string, options?: LegacyBackupPruneOptions): LegacyBackupScanResult; //# sourceMappingURL=legacy-backups.d.ts.map