- Add --label flag for AND filtering (must have ALL labels)
- Add --label-any flag for OR filtering (must have AT LEAST ONE label)
- Add normalizeLabels() helper to trim, dedupe, and clean inputs
- Fix RPC title filtering parity bug (forward via Query field)
- Add comprehensive tests for label filtering including combined AND+OR
- Update documentation in README and CHANGELOG
- Improve flag help text to clarify combined semantics
Closes bd-161
- Populate labels in bd list human-readable output (direct mode)
- Populate labels in bd list JSON output (direct and daemon modes)
- Populate labels in daemon RPC handlers (handleList, handleShow)
- handleShow now returns full IssueDetails with labels/deps/dependents
- Labels displayed with 'Labels: [label1, label2]' format
Closes bd-164
Amp-Thread-ID: https://ampcode.com/threads/T-30cd607d-c509-4a8c-9cac-c2aea2ad75c6
Co-authored-by: Amp <amp@ampcode.com>
- Tests for daemon/client version checking
- Covers all compatibility scenarios (major/minor/patch versions)
- Tests legacy client support (empty version)
- Tests health check version reporting
- Tests ping/health bypass version checks
- All 13 test cases pass
Closes bd-160
Amp-Thread-ID: https://ampcode.com/threads/T-30cd607d-c509-4a8c-9cac-c2aea2ad75c6
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>
Fixes bd-160
The race was between Start() writing s.listener and Stop() reading it.
Now all listener access is protected by the server mutex:
- Start() stores listener under lock after creation
- Accept loop reads listener under RLock
- Stop() closes listener under lock
All RPC tests now pass with -race flag.
Implemented bd-150: Improve daemon fallback visibility and user feedback
- Added DaemonStatus struct to track connection state
- Enhanced BD_DEBUG logging with detailed diagnostics and timing
- Added BD_VERBOSE mode with actionable warnings when falling back
- Implemented health checks before using daemon
- Clear fallback reasons: connect_failed, health_failed, auto_start_disabled, auto_start_failed, flag_no_daemon
- Updated documentation
Implemented bd-151: Add version compatibility checks for daemon RPC protocol
- Added ClientVersion field to RPC Request struct
- Client sends version (0.9.10) in all requests
- Server validates version compatibility using semver:
- Major version must match
- Daemon >= client for backward compatibility
- Clear error messages with directional hints (upgrade daemon vs upgrade client)
- Added ClientVersion and Compatible fields to HealthResponse
- Implemented 'bd version --daemon' command to check compatibility
- Fixed batch operations to propagate ClientVersion for proper checks
- Updated documentation with version compatibility section
Code review improvements:
- Propagate ClientVersion in batch sub-requests
- Directional error messages based on which side is older
- Made ServerVersion a var for future unification
Amp-Thread-ID: https://ampcode.com/threads/T-b5fe36b8-c065-44a9-a55b-582573671609
Co-authored-by: Amp <amp@ampcode.com>
Improvements based on oracle code review:
- Move socket cleanup AFTER lock acquisition (prevents unlinking live sockets)
- Add PID liveness check before removing stale socket
- Add stale lock detection with retry mechanism
- Tighten directory permissions to 0700 for security
- Improve socket readiness probing with shorter timeouts
- Make removeOldSocket() ignore ENOENT errors
Fixes race condition where socket could be removed during daemon startup window,
potentially orphaning a running daemon process.
Amp-Thread-ID: https://ampcode.com/threads/T-63542c60-b5b9-4a34-9f22-415d9d7e8223
Co-authored-by: Amp <amp@ampcode.com>
- Add OpHealth RPC operation to protocol
- Implement handleHealth() with DB ping and 1s timeout
- Returns status (healthy/degraded/unhealthy), uptime, cache metrics
- Update TryConnect() to use health check instead of ping
- Add 'bd daemon --health' CLI command with JSON output
- Track cache hits/misses for metrics
- Unhealthy daemon triggers automatic fallback to direct mode
- Health check completes in <2 seconds
Amp-Thread-ID: https://ampcode.com/threads/T-1a4889f3-77cf-433a-a704-e1c383929f48
Co-authored-by: Amp <amp@ampcode.com>
- bd-159: Global daemon now runs in routing mode without opening DB
- bd-158: Set socket permissions to 0600 for security
- bd-160: Reject --auto-commit/--auto-push with --global
- bd-157: Verified stale socket cleanup (already working)
- bd-56: Closed as won't-do (cycle prevention is better)
- bd-73: Multi-repo support complete
- Added per-request storage routing in daemon server
- Server now supports Cwd field in requests for database discovery
- Tree-walking to find .beads/*.db from any working directory
- Storage caching for performance across requests
- Created Python daemon client (bd_daemon_client.py)
- RPC over Unix socket communication
- Implements full BdClientBase interface
- Auto-discovery of daemon socket from working directory
- Refactored bd_client.py with abstract interface
- BdClientBase abstract class for common interface
- BdCliClient for CLI-based operations (renamed from BdClient)
- create_bd_client() factory with daemon/CLI fallback
- Backwards-compatible BdClient alias
Next: Update MCP server to use daemon client when available