Consolidation Lock

Description

The consolidation lock is a file-based mutual exclusion mechanism implemented in src/services/autoDream/consolidationLock.ts that prevents multiple Claude Code processes from running background memory consolidation (the "auto-dream" feature) simultaneously. The lock file is named .consolidate-lock and lives inside the auto-memory directory (keyed to the git root), which ensures it is writable even when the memory path comes from an env/settings override.

The lock file serves dual purposes through a clever encoding. Its mtime (modification timestamp) records when the last successful consolidation occurred -- the readLastConsolidatedAt() function simply stats the file and returns mtimeMs, costing one stat call per turn. Its body contains the PID of the process currently holding the lock. The acquisition protocol in tryAcquireConsolidationLock() implements a compare-and-swap pattern: the acquiring process writes its own PID to the file, then re-reads the file to verify it still sees its own PID. If two processes race to acquire, only the last writer's PID will be present on re-read, so the loser detects the conflict and bails out (if (parseInt(verify.trim(), 10) !== process.pid) return null). A stale-holder guard (HOLDER_STALE_MS = 60 * 60 * 1000, one hour) prevents dead processes from blocking consolidation indefinitely: if the lock's mtime is older than one hour, any process can reclaim it regardless of PID liveness.

The lock integrates into the auto-dream gate chain in autoDream.ts, which checks gates in cheapest-first order: (1) time gate -- hours since lastConsolidatedAt must exceed minHours (default 24), costing one stat; (2) session gate -- transcript count with mtime after lastConsolidatedAt must meet minSessions (default 5); (3) lock acquisition. On successful consolidation, the lock's mtime naturally advances to "now" (from the writeFile during acquire). On failure, rollbackConsolidationLock(priorMtime) rewinds the mtime to its pre-acquire value using utimes() and clears the PID body, so the failed attempt doesn't delay the next trigger. If priorMtime is 0 (no prior lock file existed), rollback unlinks the file entirely.

Key claims

Relations

Sources

src-20260410-consolidation-lock-a: src/services/autoDream/consolidationLock.ts, src/services/autoDream/autoDream.ts