The daemon-restart data bug: what broke, why, the fix on the table, and the one decision engineering, SRE, and leadership need to co-sign this week.
On June 14, a routine daemon restart under a stale namespace let 41 projects' SQLite files resolve against a cwd-relative fallback instead of the daemon's actual data root.
The only question left this sprint is which fix we ship — a patch, or a guardrail.
Fix the 9 known openDatabase(projectRoot) calls to pass the resolved data root explicitly. Ships in two days — but the next engineer who adds a call site can reintroduce the same escape.
Delete the cwd-relative default from openDatabase itself, so a missing data root fails loudly at startup instead of silently writing elsewhere. One migration, closes the whole bug class.
A per-site patch depends on every future engineer remembering the rule. Removing the fallback makes the rule impossible to violate — the daemon simply refuses to start with an unresolved data root.
# apps/daemon/src/db.ts — before vs after function openDatabase(projectRoot?) { const root = projectRoot ?? cwd-relative default // silent escape return sqlite.open(root) } # after: fallback deleted, root is required function openDatabase(root = RUNTIME_DATA_DIR) { if (!root) throw "missing data root — refuse to start" return sqlite.open(root) }
Recurrences targeted across next 2 restart drills
MTTR for data-path incidents once the CI guardrail lands (14m → 70s)
Legacy fallback call sites remaining after the migration
Restart-drill pass rate, CI guardrail catches on PRs, and support tickets tagged "missing project."
Platform infra and SRE co-sign the guardrail PR; engineering leadership signs off on the quarterly restart-drill cadence.
One irreversible step: merge the fallback removal plus the CI check before the next namespace migration ships.
Cross-functional agreement closes this retro: Platform, SRE, and Leadership all back the guardrail, not just the patch.