/** * Backup and restore core module. * * Produces full-`.cleo/` snapshots containing tasks.db, brain.db, config.json * and project-info.json using the safest available method for each file type: * * - SQLite databases: `VACUUM INTO` via the live native handle (see * {@link ../store/sqlite-backup.ts}). This is the ONLY safe way to * snapshot a WAL-mode SQLite database while it is open — raw filesystem * copies can capture torn writes or stale WAL frames. * * - JSON files: atomic tmp-then-rename via {@link atomicWriteSync} so a * partial write can never corrupt the backup target. * * Snapshots are recorded under `.cleo/backups/sqlite/` with a JSON sidecar * (`{backupId}.meta.json`) enumerating which files were captured and how. * Restores read the same sidecars and materialize each file back into the * live `.cleo/` directory. * * This is the backing store for the `cleo backup` and `cleo restore backup` * CLI verbs (see packages/cleo/src/cli/commands/backup.ts and restore.ts). * * ## Canonical backup path (T10315 · ADR-013 §10 · Saga T10281 / Epic T10284) * * Both this module and {@link ../store/sqlite-backup.ts} (the auto session-end * snapshotter) write to the SAME directory: `.cleo/backups/sqlite/`. The two * producers use distinguishable filename schemes that coexist: * * - `vacuumIntoBackupAll` writes `tasks-YYYYMMDD-HHmmss.db` / * `brain-YYYYMMDD-HHmmss.db` (no sidecar). * - `createBackup` writes `.` + `.meta.json`, * where `backupId = -YYYYMMDD-HHmmss` (matching the same local-time * timestamp format). * * The legacy `.cleo/backups/snapshot/` directory is retained as a read-only * fallthrough for one deprecation window — `listSystemBackups` enumerates * both directories and tags legacy entries via `legacy: true`, and * `restoreBackup` searches the legacy directory if no candidate is found in * the canonical directory. A one-time `DeprecationWarning` fires when the * legacy directory is consulted. * * @task T4783 * @task T5158 — extended to use VACUUM INTO for .db files and atomicWrite for JSON * @task T10315 — ratified `.cleo/backups/sqlite/` as the single canonical path * (ADR-013 §10). The previous `.cleo/backups/snapshot/` is now * a deprecated read-only fallthrough for one release. */ /** Internal: reset the once-flag (test seam). */ export declare function _resetLegacyWarningOnce(): void; /** Result shape returned by {@link createBackup}. */ export interface BackupResult { /** Unique backup identifier (timestamped). */ backupId: string; /** Absolute path to the directory containing the snapshot files. */ path: string; /** ISO-8601 timestamp when the backup was created. */ timestamp: string; /** Backup category (`snapshot`, `safety`, `migration`). */ type: string; /** Files that were successfully captured into this backup. */ files: string[]; } /** Result shape returned by {@link restoreBackup}. */ export interface RestoreResult { /** Whether any files were actually restored (false if none matched). */ restored: boolean; /** The backup identifier that was restored. */ backupId: string; /** ISO-8601 timestamp of the original backup. */ timestamp: string; /** File names that were successfully restored back into `.cleo/`. */ filesRestored: string[]; } /** * Create a backup of the canonical CLEO data files. * * Produces safe copies via VACUUM INTO (for SQLite) and atomicWrite * (for JSON) into `.cleo/backups/sqlite/`. Writes a `{backupId}.meta.json` * sidecar describing the snapshot. * * The backup file naming uses the unified `YYYYMMDD-HHmmss` local-time format * (matching `sqlite-backup.ts:formatTimestamp`) so all snapshot files in * `.cleo/backups/sqlite/` share one timestamp convention. The `type` field * (`snapshot` by default) is embedded in the `backupId` to distinguish manual * snapshots from auto-snapshots and from `safety`/`migration` backups. * * Opens both `tasks.db` and `brain.db` through their canonical drizzle * accessors before snapshotting so that the native DB handles are live * when `safeSqliteSnapshot` asks for them. This makes the function * self-contained — callers do not need to pre-open the DBs. * * Async because opening the database engines requires async migration * reconciliation (ADR-012). The CLI dispatch layer awaits this result. * * @task T10315 — write target moved from `.cleo/backups/snapshot/` to * `.cleo/backups/sqlite/` per ADR-013 §10. */ export declare function createBackup(projectRoot: string, opts?: { type?: string; note?: string; /** * Maximum number of backup files to keep per type directory. * Oldest files are rotated out when this cap is exceeded. * Defaults to {@link DEFAULT_MAX_SNAPSHOTS} (10). * * @task T9194 */ maxSnapshots?: number; }): Promise; /** A single backup entry returned by listSystemBackups. */ export interface BackupEntry { /** Unique backup identifier (timestamped). */ backupId: string; /** Backup category (`snapshot`, `safety`, `migration`). */ type: string; /** ISO-8601 timestamp when the backup was created. */ timestamp: string; /** Optional human-readable note attached at creation time. */ note?: string; /** File names captured in this backup. */ files: string[]; /** * `true` when this entry was discovered under the deprecated legacy * `.cleo/backups/snapshot/` directory. Surfaces in the `cleo backup list` * envelope so the operator knows the entry is read-only and will become * unreachable in the release following T10315. * * @task T10315 */ legacy?: boolean; } /** * List all available system backups (`snapshot`, `safety`, `migration`). * * Reads `.meta.json` sidecar files written by {@link createBackup}. Walks * both the canonical `.cleo/backups/sqlite/` directory AND the deprecated * `.cleo/backups/snapshot/` directory (ADR-013 §10 read-side deprecation * window). Entries discovered under the legacy directory are tagged with * `legacy: true` so callers can surface a warning. * * This is a pure read operation — it does not modify any files. A one-time * `DeprecationWarning` is emitted via `process.emitWarning` when the legacy * directory yields ≥1 entry. * * @task T4783 * @task T10315 — added canonical-dir scan + legacy-dir read fallthrough. */ export declare function listSystemBackups(projectRoot: string): BackupEntry[]; /** * Restore a backup into the live `.cleo/` directory. * * This operation overwrites the in-place copies of the files recorded in * the backup's sidecar. SQLite files are restored via a plain `copyFileSync` * because restore runs BEFORE the next CLEO process opens the database — no * WAL is active at that point — so a filesystem copy is safe. Callers must * ensure no CLEO process is concurrently writing to the target database. * * JSON files are restored via `atomicWrite` (tmp-then-rename) so a crash * mid-restore cannot produce a truncated config. * * Search order (T10315 / ADR-013 §10): canonical `.cleo/backups/sqlite/` * first, then legacy `.cleo/backups/{snapshot,safety,migration}/` as a * read-only fallthrough (emits a one-time DeprecationWarning if used). * * @task T10315 */ export declare function restoreBackup(projectRoot: string, params: { backupId: string; force?: boolean; }): RestoreResult; /** Result of restoring an individual file from backup. */ export interface FileRestoreResult { /** Whether the file was actually restored. */ restored: boolean; /** The filename that was restored. */ file: string; /** The backup file path restored from. */ from: string; /** The target path that was written. */ targetPath: string; /** Whether this was a dry-run. */ dryRun?: boolean; } /** * Restore an individual file (tasks.db or config.json) from the most recent backup. * * Moves the backing logic from `backupRestore` in system-engine.ts into core. * Uses `getTaskPath` / `getConfigPath` from `../paths.js` (respects CLEO_DIR). * Imports `listBackups` and `restoreFromBackup` from the store layer. * * @param projectRoot - Absolute path to the project root * @param fileName - File to restore: 'tasks.db' or 'config.json' * @param opts - Optional restore flags * @returns Result of the restore operation * * @task T5329 * @task T1571 */ export declare function fileRestore(projectRoot: string, fileName: string, opts?: { dryRun?: boolean; }): Promise; //# sourceMappingURL=backup.d.ts.map