Hardens shared-budget cross-process locking (follow-up to 0.4.6), validated by a /code-review pass that empirically tested crash modes.
Changed
budget.record()fails loud on a corrupt/unreadable budget file. It previously fell back to writing stale local state over the committed total (silent spend loss → overspend risk); it now throwsBudgetUnavailableError, per PRD §13. Only fires on genuine corruption — a missing file is re-seeded before the lock, andinit()keeps its rebuild-from-audit recovery. Migration: a corrupt file now propagates out ofgate.record()/gate.run(); wrap them to degrade rather than halt.proper-lockfilestale10s → 20s for the budget file — shrinks the lock-steal window that could put two writers in the sub-millisecond critical section and silently lose an update. The ~2.25s retry budget stays well understale, so a waiter on a live holder always errors before it would steal. Fail-safe under a SIGKILLed-mid-lock holder (halts rather than overspends).
Tests
Suite 106 → 107 (corrupt-file fail-loud), green on ubuntu/macos/windows × Node 20/22. Also folds in 0.4.6's flaky concurrent-budget test fix.
Full notes in CHANGELOG.