Implement stricter daemon lock file validation (bd-161)

- Add JSON format to daemon.lock with database path, version, PID, and timestamp
- Validate database path on client connection (fail if mismatch)
- Backward compatible with old plain-PID lock files
- Add comprehensive tests for JSON format and validation
- Update all lock acquisition callsites to pass database path

Amp-Thread-ID: https://ampcode.com/threads/T-137e6a9c-b690-4ade-9bec-13fcd7d0e4ed
Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
Steve Yegge
2025-10-26 18:37:17 -07:00
parent 50623f8be1
commit 7549bd86bc
5 changed files with 212 additions and 43 deletions

View File

@@ -269,18 +269,30 @@ var rootCmd = &cobra.Command{
daemonStatus.Detail = fmt.Sprintf("version mismatch (daemon: %s, client: %s) and restart failed",
health.Version, Version)
} else {
// Daemon is healthy and compatible - use it
daemonClient = client
daemonStatus.Mode = cmdDaemon
daemonStatus.Connected = true
daemonStatus.Degraded = false
daemonStatus.Health = health.Status
if os.Getenv("BD_DEBUG") != "" {
fmt.Fprintf(os.Stderr, "Debug: connected to daemon at %s (health: %s)\n", socketPath, health.Status)
// Daemon is healthy and compatible - validate database path
beadsDir := filepath.Dir(dbPath)
if err := validateDaemonLock(beadsDir, dbPath); err != nil {
_ = client.Close()
daemonStatus.FallbackReason = FallbackHealthFailed
daemonStatus.Detail = fmt.Sprintf("daemon lock validation failed: %v", err)
if os.Getenv("BD_DEBUG") != "" {
fmt.Fprintf(os.Stderr, "Debug: daemon lock validation failed: %v\n", err)
}
// Fall through to direct mode
} else {
// Daemon is healthy, compatible, and validated - use it
daemonClient = client
daemonStatus.Mode = cmdDaemon
daemonStatus.Connected = true
daemonStatus.Degraded = false
daemonStatus.Health = health.Status
if os.Getenv("BD_DEBUG") != "" {
fmt.Fprintf(os.Stderr, "Debug: connected to daemon at %s (health: %s)\n", socketPath, health.Status)
}
// Warn if using daemon with git worktrees
warnWorktreeDaemon(dbPath)
return // Skip direct storage initialization
}
// Warn if using daemon with git worktrees
warnWorktreeDaemon(dbPath)
return // Skip direct storage initialization
}
} else {
// Health check failed or daemon unhealthy