/** * Operation Journal * * Records destructive operations (sync, migrate, backup, download) before they start. * If the process crashes mid-operation, the journal entry remains on disk. * On next startup, the health check detects incomplete journals and can offer recovery. * * Journal entries are stored as individual JSON files in ~/.pluginator/recovery/journal/. * * @since v2.7.34 */ /** * Journal entry describing an in-progress destructive operation */ export interface JournalEntry { id: string; operation: 'sync' | 'migrate' | 'backup' | 'restore' | 'download' | 'rollback'; startedAt: string; pid: number; affectedPaths: string[]; description: string; metadata?: Record; /** * 'in-progress' while the operation runs; 'failed' once it threw (the * entry is then KEPT on disk for recovery — see {@link journalFail}). * Absent on entries written before Phase 4 — treat as 'in-progress'. */ status?: 'in-progress' | 'failed'; /** When the operation threw (set by {@link journalFail}). */ failedAt?: string; /** Failure message (set by {@link journalFail}). */ error?: string; } /** * Create a journal entry before starting a destructive operation. * Returns the entry ID for later completion/removal. */ export declare function journalStart(operation: JournalEntry['operation'], affectedPaths: string[], description: string, metadata?: Record): Promise; /** * Run an operation wrapped by a journal entry. * * Outcomes: * - `fn` resolves → entry deleted ({@link journalComplete}). * - `fn` throws → entry KEPT on disk, marked failed ({@link journalFail}), * and the error re-thrown. A failed operation may have left partial state * (e.g. sync's disable-then-copy window), so recovery needs the record. * Pre-Phase-4 the entry was deleted in `finally` even on throw — an * exception erased the only trace (June 9 2026 audit, workflows-infra 2.1). * - hard crash inside `fn` → entry survives as written, which is the point. * * All journal calls swallow their own errors — the journal is best-effort * recovery metadata and must not break the underlying operation. * * @since v2.11.15 — replaces 5 hand-rolled copies in workflows/. */ export declare function withJournal(operation: JournalEntry['operation'], affectedPaths: string[], description: string, fn: () => Promise, metadata?: Record): Promise; /** * Mark a journal entry as failed, KEEPING it on disk for recovery. * * Called by {@link withJournal} when the wrapped operation throws. The entry * is rewritten in place with `status: 'failed'`, the failure time, and the * error message, so the startup health check can report exactly what died * and where. Missing/corrupt entries are ignored — the operation's own error * is what matters to the caller. */ export declare function journalFail(id: string, error?: unknown): Promise; /** * Remove a journal entry after an operation completes successfully. */ export declare function journalComplete(id: string): Promise; /** * List all incomplete journal entries (from crashed or failed operations). * Filters out in-progress entries from the current PID (still running, not * crashed) — but failed entries are included regardless of PID: the * operation already threw, so partial state may exist even though the * process is alive. */ export declare function listIncompleteJournals(): JournalEntry[]; /** * Clear all journal entries (used after recovery or manual cleanup) */ export declare function clearJournals(): Promise; //# sourceMappingURL=operation-journal.d.ts.map