Harden fusion.db against recurring corruption

Root cause: node:sqlite SIGSEGVs inside pager_write leave the B-tree
malformed in a way that still opens but fails integrity checks; large
operational-log tables widen the write window where the crash strikes.

- backup: verify every copy with PRAGMA quick_check, quarantine corrupt
  copies as *.corrupt, and never rotate out the last verified-good backup
- db: add Database.recoverIfCorrupt() startup guard (wired into
  TaskStore.init, disk-backed only, opt out via FUSION_DISABLE_DB_AUTORECOVER)
  that rebuilds a malformed db via sqlite3 .recover, preserving the corrupt
  original; also fixes the latent `.recover main` invalid-option bug that made
  recoverDatabase() always fail
- db: drop lost_and_found* scratch tables on init; add pruneOperationalLogs()
- settings: add operationalLogRetentionDays (default 30, 0 = off) and prune
  activityLog/agentLogEntries/runAuditEvents/agentHeartbeats during maintenance
- dashboard: expose retention in Settings -> Backups -> Database Maintenance

Tests: backup 59/59, db 135/135 (incl. real corrupt->recover->reopen),
self-healing cleanup/corruption 10/10, settings 77/77, SettingsModal 460/460.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsxdsm
2026-06-01 21:55:10 -07:00
parent e561290174
commit f9e551317f
10 changed files with 713 additions and 16 deletions

View File

@@ -6106,6 +6106,31 @@ export function SettingsModal({
)}
</div>
<h4 className="settings-section-heading settings-section-heading--spaced">Database Maintenance</h4>
<div className="form-group">
<label htmlFor="operationalLogRetentionDays">Operational log retention</label>
<select
id="operationalLogRetentionDays"
className="select"
value={form.operationalLogRetentionDays ?? 0}
onChange={(e) =>
setForm((f) => ({ ...f, operationalLogRetentionDays: Number(e.target.value) || 0 }))
}
>
<option value={0}>Off</option>
<option value={30}>30 days</option>
<option value={60}>60 days</option>
<option value={90}>90 days</option>
<option value={180}>180 days</option>
<option value={365}>365 days</option>
</select>
<small>
Prune append-only operational logs (activity log, agent logs, run audit, heartbeats) older than this
many days during periodic maintenance. Keeps the database from growing without bound — large databases
are slower to checkpoint and more prone to corruption. Default: 30 days.
</small>
</div>
<h4 className="settings-section-heading">Memory Backups</h4>
<div className="form-group">
<label htmlFor="memoryBackupEnabled" className="checkbox-label">