- Add nolint:gosec comments for safe file operations
- G304: File reads from validated/secure paths
- G306/G302: JSONL/error files need 0644 for sharing/debugging
- G204: Subprocess launches with validated arguments
- G104: Deferred file close errors are non-critical
- G115: Safe integer conversions in backoff
- G201: SQL placeholders for IN clause expansion
All warnings are for intentional behavior that is safe in context.
Amp-Thread-ID: https://ampcode.com/threads/T-d78f2780-4709-497f-97b0-035ca8c809e1
Co-authored-by: Amp <amp@ampcode.com>
When daemon detects multiple .db files (after filtering .backup and vc.db),
it now writes detailed error to .beads/daemon-error file before exiting.
The error file is checked and displayed when:
- Daemon discovery fails to connect
- Auto-start fails to yield a running daemon
- User runs 'bd daemons list'
This makes the error immediately visible without requiring users to check
daemon logs.
Changes:
- cmd/bd/daemon.go: Write daemon-error file on multiple .db detection
- internal/daemon/discovery.go: Read and surface daemon-error in DaemonInfo.Error
- cmd/bd/main.go: Display daemon-error when auto-start fails
Amp-Thread-ID: https://ampcode.com/threads/T-1005a8d1-7a5a-4844-ad2d-2b8a6145825f
Co-authored-by: Amp <amp@ampcode.com>
- Changed backup file filtering from checking file extension (.backup) to checking if filename contains '.backup'
- This now properly filters files like 'beads.backup-pre-hash-20251030-171258.db'
- Also exclude vc.db from database detection
- Add strings import to beads.go
- Improve error message to suggest manual removal
Fixes bd-373c
Event-driven daemon is now production-ready after hardening fixes in
commit 349b892. Making it the default for v0.21.0.
Users can still opt back to polling mode with BEADS_DAEMON_MODE=poll
if needed.
Benefits:
- <500ms sync latency (vs 5000ms with polling)
- ~60% less CPU usage
- Instant reactivity to mutations and file changes
- Fallback polling when file watcher unavailable
Amp-Thread-ID: https://ampcode.com/threads/T-a9a67394-37ca-4b79-aa23-c5c011f9c0cd
Co-authored-by: Amp <amp@ampcode.com>
Three critical fixes to make event-driven mode production-ready:
1. Skip redundant imports: Check JSONL mtime vs DB mtime to avoid
self-triggered import loops after export writes JSONL
2. Add server.Stop() in serverErrChan case: Ensures clean RPC
server shutdown on errors
3. Fallback ticker (60s): When file watcher unavailable (e.g., network
filesystems), fall back to periodic polling to detect remote changes
These minimal fixes address Oracle's concerns without over-engineering.
Event-driven mode is now safe for default.
Amp-Thread-ID: https://ampcode.com/threads/T-a9a67394-37ca-4b79-aa23-c5c011f9c0cd
Co-authored-by: Amp <amp@ampcode.com>
Hash-based IDs make collision resolution unnecessary. The flag was
already non-functional (handleCollisions returns error on collision
regardless of flag value).
Removed:
- --resolve-collisions flag from bd import
- ResolveCollisions field from ImportOptions and importer.Options
- All references in daemon, auto-import, and tests
- Updated error messages to reflect hash IDs don't collide
All import tests pass.
Amp-Thread-ID: https://ampcode.com/threads/T-47dfa0cc-bb71-4467-ac86-f0966a7c5d58
Co-authored-by: Amp <amp@ampcode.com>
- Created global daemon registry at ~/.beads/registry.json
- Daemons auto-register on start, unregister on graceful shutdown
- DiscoverDaemons() now uses registry instead of filesystem scan
- Instant daemon discovery (35ms vs indefinite hang)
- Auto-cleanup of stale registry entries
- Full test coverage
Closes bd-07b8c8, bd-acb971c7
- Add mutation events for label/dep/comment operations
- Create separate export-only and import-only functions
- Add dropped events counter with safety net export
- Complete bd-80 mutation channel implementation
Event-driven mode now:
- Emits mutation events for ALL write operations (not just create/update/close)
- Uses createExportFunc() for mutations (export+commit/push only, no pull)
- Uses createAutoImportFunc() for file changes (pull+import only, no export)
- Tracks dropped events and triggers safety export every 60s if any dropped
- Achieves <500ms latency target by avoiding full sync on each trigger
Behind BEADS_DAEMON_MODE=events flag (poll is still default)
- Added CanonicalDatabaseName constant (beads.db) and LegacyDatabaseNames list
- Updated bd init to use canonical name via constant
- Added daemon validation to reject non-canonical database names
- Updated bd migrate to use canonical name constant
- Enhanced FindDatabasePath to warn when using legacy database names
- All database discovery now prefers beads.db with backward compatibility
Closes bd-165
- Added validatePreExport to prevent data loss
- Added checkDuplicateIDs to detect corruption
- Added checkOrphanedDeps to find orphaned dependencies (both sides)
- Added validatePostImport to ensure imports don't lose data
- CRITICAL FIX: Removed post-pull export that clobbered fresh JSONL
- Conservative checks when JSONL is unreadable
- Efficient COUNT(*) SQL path instead of loading all issues
- Comprehensive test coverage including edge cases
Replace the NO-OP importToJSONLWithStore() stub with full implementation:
- Reads and parses JSONL file line by line using bufio.Scanner
- Uses importIssuesCore() with auto-collision resolution enabled
- Integrates with existing import infrastructure
- Fixes PRIMARY root cause of bd-160 multi-clone sync failure
The daemon now properly imports remote changes pulled from git instead
of ignoring them, allowing databases to converge across clones.
Amp-Thread-ID: https://ampcode.com/threads/T-9b92c2dc-e0e2-4d77-b562-136da8c3f64e
Co-authored-by: Amp <amp@ampcode.com>
- Implement bd migrate command with detection, version checking, and cleanup
- Update daemon to suggest bd migrate for version mismatches
- Enhance CLI version warnings to recommend bd migrate
- Add comprehensive tests for migration scenarios
- Document migration workflow in QUICKSTART.md and AGENTS.md
Completes bd-164 and epic bd-159
Amp-Thread-ID: https://ampcode.com/threads/T-34ea4682-8c48-44c2-8421-dc40f867773b
Co-authored-by: Amp <amp@ampcode.com>
- 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>
- Added version validation on daemon startup
- Daemon checks bd_version metadata matches current version
- Clear error messages for version mismatches with 3 resolution options
- Auto-sets missing version metadata for old databases
- Added BEADS_IGNORE_VERSION_MISMATCH=1 override for emergencies
- Tested version mismatch detection, override flag, and missing metadata handling
- Changed bd init to always create beads.db instead of {prefix}.db
- Added migration logic to detect and rename old databases
- Updated findDatabaseInTree to prefer beads.db and warn on multiple .db files
- Daemon now refuses to start if multiple .db files exist (ambiguity error)
- Updated tests to expect beads.db instead of prefix-based naming
- Tested migration, ambiguity detection, and warning messages
- Add OpStatus operation and StatusResponse type to RPC protocol
- Add workspacePath and dbPath fields to Server struct
- Implement handleStatus() handler with daemon metadata
- Track last activity time with atomic.Value
- Add client.Status() method
- Check for exclusive locks via ShouldSkipDatabase()
- Update all test files to use new NewServer signature
- Add comprehensive status endpoint test
Closes bd-148
- Increase flush debounce from 1s to 30s (provides transaction window for batch operations)
- Increase daemon poll from 2s to 5s (reduces commit spam)
- Agents should run 'bd sync' at end of session to force immediate commit
- Prevents creating dozens of commits when making multiple issue changes
- Reduce flush debounce from 5s to 1s (BEADS_FLUSH_DEBOUNCE)
- Reduce daemon poll interval from 10s to 2s
- Makes issue changes sync much faster to JSONL and git
- bd-155: Add pre-import flush in daemon sync cycle to prevent deleted issues from being re-imported
- bd-155: Reduce default daemon polling interval from 5 minutes to 10 seconds
- bd-156: Fix hardcoded 'vc.db' - now properly detects existing .db files in local .beads/ directory
- Set rpc.ServerVersion from Version in daemon startup
- Set rpc.ClientVersion from Version in main.go startup
- Eliminates need to manually update RPC versions
- Both now use 0.0.0 placeholder, overridden at runtime
Amp-Thread-ID: https://ampcode.com/threads/T-03c37f7f-f41e-4b87-8700-d346c21bad30
Co-authored-by: Amp <amp@ampcode.com>
- Added safety check to exportToJSONLWithStore (daemon path)
- Refuses to export 0 issues over non-empty JSONL file
- Added --force flag to override safety check when intentional
- Added test coverage for empty database export protection
- Prevents data loss when daemon has wrong/empty database
Amp-Thread-ID: https://ampcode.com/threads/T-de18e0ad-bd17-46ec-994b-0581e257dcde
Co-authored-by: Amp <amp@ampcode.com>
- Run initial sync in background so daemon becomes responsive immediately
- Skip daemon-running check for forked child process (BD_DAEMON_FOREGROUND=1)
- Fix PID file conflict between acquireDaemonLock and runDaemonLoop
- Daemon now starts reliably even with slow/failing git pulls
Fixes issue where daemon would timeout during auto-start because it was
blocked on git pull in the initial sync cycle. Now the RPC server starts
immediately and sync runs asynchronously.
Amp-Thread-ID: https://ampcode.com/threads/T-57f3c00a-02b4-4878-adba-c7d1649759b4
Co-authored-by: Amp <amp@ampcode.com>
Fixes silent data loss when .beads/ directory removed and daemon auto-starts.
Root cause: checkGitForIssues() hardcoded 'issues.jsonl' but git tracks 'beads.jsonl'
Changes:
- Fix A (bd-131): checkGitForIssues() tries beads.jsonl first, then issues.jsonl
- Fix B (bd-132): Immediate export after import in bd init to prevent daemon race
- Fix C (bd-133): Safety check that fails loudly if import fails
- Fix D (bd-134): Daemon startup auto-import when DB empty but git has issues
- Tests (bd-135): Comprehensive integration test suite
Oracle-recommended improvements:
- Export to exact git-relative path (prevents path drift)
- filepath.ToSlash for Windows git compatibility
- 64MB scanner buffer for large JSONL lines
- Improved safety check messages (only suggest local file if exists)
All tests passing. No regressions.
Amp-Thread-ID: https://ampcode.com/threads/T-0e31dc6a-a0d9-46c6-87b2-cfdebe829a52
Co-authored-by: Amp <amp@ampcode.com>
- Write PID to daemon.pid when acquiring lock for Windows compatibility
- Increase socket cleanup timeout to 5s for Windows
- Windows can't read locked files, so PID file is required fallback
Implements automatic daemon version detection and restart when client
and daemon versions are incompatible. Eliminates need for manual
'bd daemon --stop' after upgrades.
Changes:
- Check daemon version during health check in PersistentPreRun
- Auto-restart mismatched daemon or fall back to direct mode
- Check version when starting daemon, auto-stop old daemon if incompatible
- Robust restart logic: sets working dir, cleans stale sockets, reaps processes
- Uses waitForSocketReadiness helper for reliable startup detection
- Updated AGENTS.md with version management documentation
Closes bd-89
Amp-Thread-ID: https://ampcode.com/threads/T-231a3701-c9c8-49e4-a1b0-e67c94e5c365
Co-authored-by: Amp <amp@ampcode.com>
- Implement robust worktree detection using git-dir vs git-common-dir comparison
- Add prominent warning when daemon mode is active in a worktree
- Warn in 3 places: initial connection, auto-start, and daemon start command
- Show shared database path and clarify BEADS_AUTO_START_DAEMON behavior
- Document limitations and solutions in README.md and AGENTS.md
- Add comprehensive tests for detection and path truncation
Fixes#55
Amp-Thread-ID: https://ampcode.com/threads/T-254eb9e3-1a42-42d7-afdf-b7ca2d2dcb8b
Co-authored-by: Amp <amp@ampcode.com>
- Implemented daemon.lock using flock (Unix) and LockFileEx (Windows)
- Lock acquired before PID file, held for daemon lifetime
- Eliminates race conditions in concurrent daemon starts
- Backward compatible: falls back to PID check for old daemons
- Updated isDaemonRunning() to check lock availability
- All tests pass including new lock and backward compatibility tests
Amp-Thread-ID: https://ampcode.com/threads/T-0e2627f4-03f9-4024-bb4b-21d23d296300
Co-authored-by: Amp <amp@ampcode.com>
Add WaitReady() channel to RPC server that signals when the socket is
listening and ready to accept connections. Previously daemon startup
waited a fixed 2 seconds which could fail if the server took longer.
Changes:
- Add readyChan to Server struct
- Signal ready after listener bind completes
- Update daemon startup to wait on WaitReady() channel
- Increase timeout to 5s with proper signaling
This fixes multi-repo daemon routing test failures where daemon would
start but not be ready to handle requests within the timeout window.
Amp-Thread-ID: https://ampcode.com/threads/T-675a2db5-b1b3-480d-a108-b003d8139d08
Co-authored-by: Amp <amp@ampcode.com>