feat: add SelfHealingManager for unattended multi-day operation
Adds four self-healing subsystems to enable the engine to recover from common failure modes without human intervention: - Auto-unpause: clears rate-limit-triggered globalPause with escalating backoff (5 min → 60 min cap), resets on sustained recovery - Stuck kill budget: caps task stuck-kill retries (default 3) to prevent infinite stuck→todo→stuck loops - Periodic maintenance (every 15 min): git worktree prune, orphan cleanup, SQLite WAL checkpoint - Worktree cap enforcement: removes oldest idle worktrees when count exceeds 2× maxWorktrees New settings: autoUnpauseEnabled, autoUnpauseBaseDelayMs, autoUnpauseMaxDelayMs, maxStuckKills, maintenanceIntervalMs. New task field: stuckKillCount (schema v8 migration). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -59,7 +59,7 @@ export function fromJson<T>(json: string | null | undefined): T | undefined {
|
||||
|
||||
// ── Schema Definition ────────────────────────────────────────────────
|
||||
|
||||
const SCHEMA_VERSION = 7;
|
||||
const SCHEMA_VERSION = 8;
|
||||
|
||||
function normalizeTaskComments(
|
||||
steeringComments: SteeringComment[] | undefined,
|
||||
@@ -418,8 +418,14 @@ export class Database {
|
||||
});
|
||||
}
|
||||
|
||||
if (version < 8) {
|
||||
this.applyMigration(8, () => {
|
||||
this.addColumnIfMissing("tasks", "stuckKillCount", "INTEGER DEFAULT 0");
|
||||
});
|
||||
}
|
||||
|
||||
// Future migrations go here:
|
||||
// if (version < 8) { this.applyMigration(8, () => { ... }); }
|
||||
// if (version < 9) { this.applyMigration(9, () => { ... }); }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -486,6 +492,15 @@ export class Database {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a WAL checkpoint to truncate the WAL file and reclaim disk space.
|
||||
* Safe to call periodically. Returns checkpoint stats.
|
||||
*/
|
||||
walCheckpoint(): { busy: number; log: number; checkpointed: number } {
|
||||
const row = this.db.prepare("PRAGMA wal_checkpoint(TRUNCATE)").get() as any;
|
||||
return { busy: row?.busy ?? 0, log: row?.log ?? 0, checkpointed: row?.checkpointed ?? 0 };
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the database connection.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user