Commit Graph

126 Commits

Author SHA1 Message Date
Steve Yegge
82dc06eb84 feat(update): add --type flag to bd update command
Allows changing issue type (task/epic/bug/feature/chore) via bd update --type.
Storage layer already supported it, this adds CLI and RPC support.

Fixes GH#522.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-14 17:22:42 -08:00
Charles P. Cross
8af08460a7 Enable daemon RPC support for delete operations to trigger auto-sync, Fix for issue #527 (#528)
Enable daemon RPC support for delete operations to trigger auto-sync.

This PR adds delete operation support to the RPC daemon, ensuring that delete operations emit mutation events and trigger auto-sync like other mutating operations.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2025-12-12 13:19:31 -08:00
Abhinav Gupta
ac8ef9b9e3 test: replace manual os.Chdir with t.Chdir in tests (#457)
Replaces manual working directory save/restore patterns
with Go's built-in `t.Chdir()` helper across 23 test files.

The manual pattern involved calling `os.Getwd()` to save
the original directory, using `defer os.Chdir(origWd)` for
restoration, and manually handling errors during directory
changes. This boilerplate has been replaced with single
`t.Chdir(path)` calls that handle cleanup automatically.

The `t.Chdir()` method automatically restores the working
directory when the test completes, eliminating the need for
manual defer statements and error handling.

Total:
~75 instances replaced (assuming Claude's math is right)

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-04 11:21:43 -08:00
Steve Yegge
a1fba65c67 feat: add --estimate flag to bd create/update commands (GH #443)
The estimated_minutes field existed in the Issue schema but wasn't exposed
via CLI. This adds:

- --estimate / -e flag to bd create (e.g., bd create "Task" --estimate 120)
- --estimate / -e flag to bd update (e.g., bd update bd-xyz --estimate 60)
- EstimatedMinutes field to RPC CreateArgs and UpdateArgs
- Server-side handling in handleCreate and updatesFromArgs
- Validation for non-negative values

The value is specified in minutes and is useful for planning and
prioritization. The vscode-beads extension already has an Estimate column
that can now be populated.

Fixes #443

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-03 15:55:35 -08:00
Steve Yegge
64771a28d2 feat(ready): add --unassigned filter for bd ready
Add -u/--unassigned flag to bd ready command to show only issues
with no assignee. This supports the SCAVENGE protocol where polecats
query the 'Salvage Yard' for unassigned ready work.

Changes:
- Add NoAssignee field to WorkFilter struct
- Update SQLite GetReadyWork to filter by empty/null assignee
- Add --unassigned/-u flag to ready command
- Update RPC protocol and daemon handler
- Add test for NoAssignee filter functionality

Fixes: gt-3rp

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-30 00:38:57 -08:00
Steve Yegge
53342732b5 feat: add --unassigned flag to bd ready command
Adds the ability to filter ready work for issues with no assignee,
which is useful for the SCAVENGE protocol in Gas Town where polecats
need to query the "Salvage Yard" for unclaimed work.

Changes:
- Add Unassigned bool field to types.WorkFilter
- Add --unassigned/-u flag to bd ready command
- Update SQL query in GetReadyWork to filter for NULL/empty assignee
- Add Unassigned field to RPC ReadyArgs for daemon support
- Add tests for the new functionality

Closes: gt-3rp

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-30 00:37:12 -08:00
Steve Yegge
40b07045c7 refactor: deduplicate FindJSONLInDir function (bd-8a5)
Extract shared JSONL file discovery logic to internal/utils/path.go.
Both autoimport and beads packages now use this shared implementation.

Changes:
- Add utils.FindJSONLInDir with common logic
- Update autoimport.go to use utils.FindJSONLInDir
- Update beads.go to delegate to utils.FindJSONLInDir
- Update server_export_import_auto.go to use utils.FindJSONLInDir
- Move FindJSONLInDir test to utils/path_test.go
- Fix pre-existing duplicate countIssuesInJSONLFile in init.go

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 23:07:53 -08:00
Steve Yegge
887c958567 fix(autoimport): prevent export to wrong JSONL file (bd-tqo)
Add FindJSONLInDir helper that correctly prefers issues.jsonl over other
.jsonl files. Previously, glob patterns could return deletions.jsonl or
merge artifacts (beads.base.jsonl, etc.) first alphabetically, causing
issue data to be written to the wrong file.

This fixes the root cause of deletions.jsonl corruption where full issue
objects were written instead of deletion records, leading to all issues
being purged during sync.

Changes:
- Add FindJSONLInDir() in internal/autoimport with proper file selection
- Update AutoImportIfNewer() to use FindJSONLInDir
- Update CheckStaleness() to use FindJSONLInDir
- Update triggerExport() in RPC server to use FindJSONLInDir
- Add comprehensive tests for FindJSONLInDir

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 23:25:32 -08:00
Steve Yegge
18f81051f3 Fix race condition in client socket cleanup (bd-4owj)
- Re-check socket existence after lock check to avoid stale socket state
- If socket is initially missing but daemon lock is held, re-check socket to handle daemon startup race
- Add test TestTryConnectWithTimeout_SocketExistenceRecheck to verify fix

Fixes bd-4owj
2025-11-23 20:58:11 -08:00
Steve Yegge
e3e0a04496 Add configurable export error handling policies (bd-exug)
Implements flexible error handling for export operations with four policies:
- strict: Fail-fast on any error (default for user exports)
- best-effort: Skip errors with warnings (default for auto-exports)
- partial: Retry then skip with manifest tracking
- required-core: Fail on core data, skip enrichments

Key features:
- Per-project configuration via `bd config set export.error_policy`
- Separate policy for auto-exports: `auto_export.error_policy`
- Retry with exponential backoff (configurable attempts/delay)
- Optional export manifests documenting completeness
- Per-issue encoding error handling

This allows users to choose the right trade-off between data integrity
and system availability for their specific project needs.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-23 20:21:51 -08:00
Steve Yegge
9c6b37500c Fix N+1 query pattern in export operations (bd-rcmg)
**Problem**: Export operations called GetLabels() and GetIssueComments()
in a loop for each issue, creating N+1 query pattern. For 100 issues
this created 201 queries instead of 3-5.

**Solution**:
- Added GetCommentsForIssues() batch method to storage interface
- Implemented batch method in SQLite and memory storage backends
- Updated handleExport() and triggerExport() to use batch queries
- Added comprehensive tests for batch operations

**Impact**: Query count reduced from ~201 to ~3-5 for 100 issues.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-23 19:53:44 -08:00
Steve Yegge
bf74160f05 Fix GH#366: Encourage descriptions when creating issues
Addresses GitHub Discussion #366 where users reported Claude Code
creating issues with titles but no descriptions.

Two-pronged solution:

1. Documentation improvements (bd-na8r):
   - Updated AGENTS.md with prominent guidance section
   - Added good/bad examples showing why/what/how to include
   - Updated all bd create examples to include --description
   - Enhanced MCP tool docstring with importance note
   - Updated .github/copilot-instructions.md

2. Code validation (bd-bcrt):
   - Added friendly yellow warning when description is empty
   - Warning skips test issues (title contains "test")
   - Works in both CLI and daemon modes
   - Non-blocking to preserve quick workflows

Evidence from our own projects showed significant empty description
rates:
- ~/src/beads: 110/630 (17.5%)
- ~/wyvern: 8/119 (6.7%)
- ~/src/vc: 3/170 (1.8%)

Fixes bd-0tr0, bd-na8r, bd-bcrt

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-23 14:14:40 -08:00
Steve Yegge
012bed1068 Fix GH#367: bd import defaulting to stdin is confusing
Changes:
1. Add TTY detection to bd import - prevents silent hang when run
   interactively without arguments. Shows helpful usage message instead.
2. Fix misleading error messages - change "Run 'bd import'" to
   "Run 'bd sync --import-only'" or explicit file path throughout.

Technical details:
- Added golang.org/x/term dependency for IsTerminal()
- When stdin is a TTY and no -i flag: show usage and exit
- When stdin is piped: works as before (supports script pipelines)
- Preserved all legitimate stdin uses:
  * python gh2jsonl.py --repo owner/repo | bd import
  * python md2jsonl.py feature.md | bd import
  * git show HEAD:.beads/beads.jsonl | bd import -i /dev/stdin

Updated error messages in:
- cmd/bd/staleness.go - main "out of sync" error
- cmd/bd/sync.go - merge completion suggestions
- internal/rpc/server_export_import_auto.go - daemon warnings

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-23 11:15:34 -08:00
Steve Yegge
3065db261e feat: Add label operations to bd update command
Implements bd-au0.2, completing all P0 tasks in the command standardization epic.

Changes:
- Add --add-label, --remove-label, --set-labels flags to bd update
- Support multiple labels via repeatable flags
- Implement in both daemon and direct modes
- Add comprehensive tests for all label operations

The bd update command now supports:
  bd update <id> --add-label <label>       # Add one or more labels
  bd update <id> --remove-label <label>    # Remove one or more labels
  bd update <id> --set-labels <labels>     # Replace all labels

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-21 22:17:26 -05:00
Steve Yegge
d7f4189e3e feat: Add 'bd count' command for counting and grouping issues
Implements a new 'bd count' command that provides efficient issue counting
with filtering and grouping capabilities.

Features:
- Basic count: Returns total count of issues matching filters
- All filtering options from 'bd list' (status, priority, type, assignee, labels, dates, etc.)
- Grouping via --by-* flags: status, priority, type, assignee, label
- JSON output support for both simple and grouped counts
- Both daemon and direct mode support

Implementation:
- Added OpCount operation and CountArgs to RPC protocol
- Added Count() method to RPC client
- Implemented handleCount() server-side handler with optimized bulk label fetching
- Created cmd/bd/count.go with full CLI implementation

Performance optimization:
- Pre-fetches all labels in a single query when using --by-label to avoid N+1 queries

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-21 19:21:05 -05:00
Steve Yegge
3a0446c431 Fix test compilation errors: add context.Background() to sqlite.New() calls
Updated all test files to pass context.Background() as the first parameter
to sqlite.New() calls to match the updated function signature.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-21 14:57:18 -05:00
Steve Yegge
1168f661d1 fix: Add context.Background() to sqlite.New() calls in test files
Multiple test files were still using the old sqlite.New(path) signature
instead of the new sqlite.New(ctx, path) signature. This was causing
compilation failures in the test suite.

Fixed files:
- internal/importer/importer_test.go
- internal/importer/external_ref_test.go
- internal/importer/timestamp_test.go
- internal/rpc/limits_test.go
- internal/rpc/list_filters_test.go
- internal/rpc/rpc_test.go
- internal/rpc/status_test.go
- internal/syncbranch/syncbranch_test.go
2025-11-21 14:48:41 -05:00
Steve Yegge
82902432f5 test: Tag 16 slow integration tests with build tags
Identified and tagged obviously-slow integration tests with
`//go:build integration` to exclude them from default test runs.

This is step 1 of fixing test performance. The real fix is in
bd-1rh: refactoring tests to use shared DB setup instead of
creating 279 separate databases.

Tagged files:
- cmd/bd: 8 files (CLI tests, git ops, performance benchmarks)
- internal: 8 files (integration tests, E2E tests)

Issues:
- bd-1rh: Main issue tracking test performance
- bd-c49: Audit all tests and create grouping plan (next step)
- bd-y6d: POC refactor of create_test.go

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-21 14:40:22 -05:00
Steve Yegge
57253f93a3 Context propagation with graceful cancellation (bd-rtp, bd-yb8, bd-2o2)
Complete implementation of signal-aware context propagation for graceful
cancellation across all commands and storage operations.

Key changes:

1. Signal-aware contexts (bd-rtp):
   - Added rootCtx/rootCancel in main.go using signal.NotifyContext()
   - Set up in PersistentPreRun, cancelled in PersistentPostRun
   - Daemon uses same pattern in runDaemonLoop()
   - Handles SIGINT/SIGTERM for graceful shutdown

2. Context propagation (bd-yb8):
   - All commands now use rootCtx instead of context.Background()
   - sqlite.New() receives context for cancellable operations
   - Database operations respect context cancellation
   - Storage layer propagates context through all queries

3. Cancellation tests (bd-2o2):
   - Added import_cancellation_test.go with comprehensive tests
   - Added export cancellation test in export_test.go
   - Tests verify database integrity after cancellation
   - All cancellation tests passing

Fixes applied during review:
   - Fixed rootCtx lifecycle (removed premature defer from PersistentPreRun)
   - Fixed test context contamination (reset rootCtx in test cleanup)
   - Fixed export tests missing context setup

Impact:
   - Pressing Ctrl+C during import/export now cancels gracefully
   - No database corruption or hanging transactions
   - Clean shutdown of all operations

Tested:
   - go build ./cmd/bd ✓
   - go test ./cmd/bd -run TestImportCancellation ✓
   - go test ./cmd/bd -run TestExportCommand ✓
   - Manual Ctrl+C testing verified

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-20 21:57:23 -05:00
Steve Yegge
9088988edd Improve staleness check error handling and optimization (bd-n4td, bd-o4qy, bd-c4rq)
This commit implements three related improvements to database staleness checking:

**bd-n4td (P2): Add warning when staleness check errors**
- Added stderr warnings when CheckStaleness fails in ensureDatabaseFresh
- Users now see "Warning: could not check database staleness: <error>"
- Provides visibility into staleness check failures while allowing operations to proceed

**bd-o4qy (P2): Improve CheckStaleness error handling**
- Updated CheckStaleness to distinguish between expected and abnormal conditions:
  * Returns (false, nil) for expected "no data yet" scenarios (missing metadata, missing JSONL)
  * Returns (false, err) for abnormal errors (glob failures, permission errors)
- Updated RPC server (2 locations) to log staleness errors but allow requests to proceed
- Prevents blocking operations due to transient staleness check issues
- Added comprehensive function documentation

**bd-c4rq (P3): Refactor staleness check to avoid function call overhead**
- Moved daemon check from inside ensureDatabaseFresh to all 8 call sites
- Avoids unnecessary function call when running in daemon mode
- Updated: list.go, info.go, status.go, show.go, stale.go, duplicates.go, ready.go, validate.go
- Extracted staleness functions to new staleness.go for better organization

**Code review fixes:**
- Removed dead code in CheckStaleness (unreachable jsonlPath == "" check)
- Removed unused ensureDatabaseFreshQuiet function

**Files changed:**
- New: cmd/bd/staleness.go (extracted staleness checking functions)
- Modified: 8 command files (added daemon check before staleness calls)
- Modified: internal/autoimport/autoimport.go (improved error handling)
- Modified: internal/rpc/server_export_import_auto.go (handle errors gracefully)
2025-11-20 20:45:39 -05:00
Ryan
fb65163692 fix: address critical resource leaks and error handling issues (#327)
* fix: address critical resource leaks and error handling issues

Fixes 5 critical and high-priority issues identified in codebase analysis:

1. bd-vavh: Fix row iterator resource leak in recursive dependency queries
   - Move defer rows.Close() to execute on all code paths
   - Previously leaked connections on scan errors
   - Location: internal/storage/sqlite/sqlite.go:1121-1145

2. bd-qhws: Configure database connection pool limits for daemon mode
   - Set MaxOpenConns to runtime.NumCPU() + 1 for file-based databases
   - Prevents connection exhaustion under concurrent RPC load
   - Only affects daemon mode (long-running server)
   - Location: internal/storage/sqlite/sqlite.go:108-125

3. bd-jo38: Add WaitGroup tracking to FileWatcher goroutines
   - Track goroutines with sync.WaitGroup for graceful shutdown
   - Wait for goroutines to finish before cleanup in Close()
   - Prevents race condition on debouncer access during shutdown
   - Location: cmd/bd/daemon_watcher.go (Start, startPolling, Close)

4. bd-2d5r: Fix silent error handling in RPC response writing
   - writeResponse now returns errors instead of ignoring them
   - Prevents sending partial JSON and client hangs
   - Closes connection on marshal/write errors
   - Location: internal/rpc/server_lifecycle_conn.go:227-246

5. bd-zqmb: Fix goroutine leak in daemon restart
   - Add 10-second timeout to daemon Wait() goroutine
   - Kill process if it doesn't fork within timeout
   - Prevents goroutine accumulation on restart failures
   - Location: cmd/bd/daemons.go:250-268

All changes follow Go best practices and maintain backward compatibility.

* Add feature request for .beads/README.md generation during init

Created bd-m7ge to automatically generate a promotional/documentation
README in the .beads directory when running 'bd init'. This will help
advertise Beads in open source repositories and provide quick reference
documentation for developers using AI coding agents.

The README will include:
- Brief explanation of Beads (AI-native issue tracking)
- Link to steveyegge/beads repository
- Quick reference of essential commands
- Compelling messaging to encourage adoption
2025-11-20 08:13:06 -08:00
Steve Yegge
b9919fe031 Fix: --parent flag now creates parent-child dependency
When using 'bd create --parent <id>', the system now automatically
creates a parent-child dependency linking the child to the parent.
This fixes epic status reporting which was showing zero children.

Fixes #318 (bd-jijf)

Changes:
- cmd/bd/create.go: Add parent-child dependency after issue creation
- internal/rpc/server_issues_epics.go: Add same fix for daemon mode

Tested:
- Created epic with children, verified epic status shows correct count
- Verified closing all children makes epic eligible for closure
- All tests pass

Amp-Thread-ID: https://ampcode.com/threads/T-f1a1aee1-03bd-4e62-a63c-c1d339f8300b
Co-authored-by: Amp <amp@ampcode.com>
2025-11-15 13:20:02 -08:00
David Laing
57b6ea606b fix: add external_ref support to daemon mode RPC (fixes #303) (#304)
Add external_ref field to CreateArgs and UpdateArgs RPC protocol
structs to enable linking issues to external systems (GitHub, Jira,
Shortcut, etc.) when using daemon mode.

Changes:
- Add ExternalRef field to rpc.CreateArgs and rpc.UpdateArgs
- Update bd create/update commands to pass external_ref via RPC
- Update daemon handlers to process external_ref field
- Add integration tests for create and update operations

The --external-ref flag now works correctly in both daemon and direct modes.

Fixes https://github.com/steveyegge/beads/issues/303

Generated with [Claude Code](https://claude.com/claude-code)
via [Happy](https://happy.engineering)

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Happy <yesreply@happy.engineering>
2025-11-13 12:01:27 -08:00
Steve Yegge
98f2e85618 Fix version test error message assertion 2025-11-08 22:57:49 -08:00
Steve Yegge
f027de93b6 Add schema compatibility probe to prevent silent migration failures (bd-ckvw)
- Implement comprehensive schema probe in sqlite.New() that verifies all
  expected tables and columns after migrations
- Add retry logic: if probe fails, retry migrations once
- Return clear fatal error with missing schema elements if probe still fails
- Enhance daemon version gating: refuse RPC if client has newer minor version
- Improve checkVersionMismatch messaging: verify schema before claiming upgrade
- Add schema compatibility check to bd doctor command
- Add comprehensive tests for schema probing

This prevents the silent migration failure bug where:
1. Migrations fail silently
2. Database queries fail with 'no such column' errors
3. Import logic misinterprets as 'not found' and tries INSERT
4. Results in cryptic UNIQUE constraint errors

Fixes #262

Amp-Thread-ID: https://ampcode.com/threads/T-0d7ae2c0-9f12-4f9b-85d1-1291488af150
Co-authored-by: Amp <amp@ampcode.com>
2025-11-08 15:40:19 -08:00
Steve Yegge
f6dbcd1a4f Add test safeguards to prevent production database pollution (bd-2c5a)
- Add failIfProductionDatabase() check in Go test helpers
- Add temp directory verification in RPC test setup
- Create conftest.py with pytest safety checks for Python tests
- Add BEADS_TEST_MODE env var to mark test execution
- Tests now fail fast if they detect production .beads/ usage

This prevents test issues from polluting the production database
like the incident on Nov 7, 2025 where 29+ test issues were created
in .beads/beads.db instead of isolated test databases.

Resolves: bd-2c5a
Amp-Thread-ID: https://ampcode.com/threads/T-635a8807-1120-4122-a0cb-4c21970362ce
Co-authored-by: Amp <amp@ampcode.com>
2025-11-07 21:58:22 -08:00
Steve Yegge
fe705befbe Add RPC diagnostics with BD_RPC_DEBUG env var
- Add BD_RPC_DEBUG=1 for lightweight timing logs to stderr
- Log socket path, socket exists check, dial timing, health check timing
- Improve daemon status message when lock not held
- Helps field triage of connection issues without verbose daemon logs
- Fixes bd-j7e2
2025-11-07 21:29:22 -08:00
Steve Yegge
a236558a7a Add client self-heal for stale daemon.pid
- When socket missing and lock free, automatically remove stale daemon.pid
- Prevents stale artifacts from accumulating after daemon crashes
- Includes comprehensive test coverage
- Fixes bd-1mzt

Amp-Thread-ID: https://ampcode.com/threads/T-3f606a8a-d591-4412-b994-ea790889a04d
Co-authored-by: Amp <amp@ampcode.com>
2025-11-07 21:21:24 -08:00
Steve Yegge
f6bdf7c641 Reduce RPC dial timeout from 2s to 200ms for fast-fail (bd-expt)
- Changed TryConnect default from 2s to 200ms
- Updated fallback timeout in TryConnectWithTimeout
- Complements bd-wgu4 lock probe to eliminate 5s delays
- Fixes GH#243 (5s delay when daemon socket missing)
- Health checks still use longer timeouts via explicit TryConnectWithTimeout calls
2025-11-07 21:12:45 -08:00
Steve Yegge
ba1b856acb Standardize daemon detection with tryDaemonLock probe (bd-wgu4)
- Extract lock checking to internal/lockfile package
- Add lock probe in RPC client before connection attempts
- Update daemon discovery to use lock probe
- Eliminates unnecessary connection attempts when socket missing

Closes bd-wgu4

Amp-Thread-ID: https://ampcode.com/threads/T-3b863f21-3af4-49d3-9214-477d904b80fe
Co-authored-by: Amp <amp@ampcode.com>
2025-11-07 21:02:38 -08:00
vector-sigma
6408ef65f4 Fix #249: Add nil storage checks to prevent RPC daemon crashes (#250)
The daemon RPC server was crashing with a nil pointer dereference when the
global daemon received list, ready, stats, or other storage-dependent RPC
requests. The global daemon is created with nil storage, causing these
operations to panic when they attempted to access storage methods.

This fix adds defensive nil checks at the beginning of all RPC handlers
that require storage access. When storage is unavailable, they now return
a proper JSON error response instead of crashing the daemon.

The error message also informs users that the global daemon is deprecated
and they should use local daemons instead.

Handlers fixed:
- handleCreate, handleUpdate, handleClose
- handleList, handleShow, handleReady, handleStale
- handleResolveID, handleStats, handleEpicStatus
- handleCompact, handleCompactStats
- handleDepAdd (and via handleSimpleStoreOp for all label/dep/comment ops)

Co-authored-by: Test User <test@example.com>
2025-11-07 14:21:14 -08:00
Markus Flür
e7f532db93 Implementing an RPC monitoring solution with a web-ui as implementation example. (#244)
* bd sync: 2025-10-30 12:12:27

* Working on frontend

* bd sync: 2025-11-06 16:55:55

* feat: finish bd monitor human viewer

* Merge conflicts resolved and added tests

* bd sync: 2025-11-06 17:23:41

* bd sync: 2025-11-06 17:34:52

* feat: Add reload button and multiselect status filter to monitor

- Changed status filter from single select to multiselect with 'Open' selected by default
- Added reload button with visual feedback (hover/active states)
- Updated filterIssues() to handle multiple selected statuses
- Added reloadData() function that reloads both stats and issues
- Improved responsive design for mobile devices
- Filter controls now use flexbox layout with better spacing

* fix: Update monitor statistics to show Total, In Progress, Open, Closed

- Replaced 'Ready to Work' stat with 'In Progress' stat
- Reordered stats to show logical progression: Total -> In Progress -> Open -> Closed
- Updated loadStats() to fetch in-progress count from stats API
- Removed unnecessary separate API call for ready count

* fix: Correct API field names in monitor stats JavaScript

The JavaScript was using incorrect field names (stats.total, stats.by_status)
that don't match the actual types.Statistics struct which uses flat fields
with underscores (total_issues, in_progress_issues, etc).

Fixed by updating loadStats() to use correct field names:
- stats.total -> stats.total_issues
- stats.by_status?.['in-progress'] -> stats.in_progress_issues
- stats.by_status?.open -> stats.open_issues
- stats.by_status?.closed -> stats.closed_issues

Fixes beads-9

* bd sync: 2025-11-06 17:51:24

* bd sync: 2025-11-06 17:56:09

* fix: Make monitor require daemon to prevent SQLite locking

Implemented Option 1 from beads-eel: monitor now requires daemon and never
opens direct SQLite connection.

Changes:
- Added 'monitor' to noDbCommands list in main.go to skip normal DB initialization
- Added validateDaemonForMonitor() PreRun function that:
  - Finds database path using beads.FindDatabasePath()
  - Validates daemon is running and healthy
  - Fails gracefully with clear error message if no daemon
  - Only uses RPC connection, never opens SQLite directly

Benefits:
- Eliminates SQLite locking conflicts between monitor and daemon
- Users can now close/update issues via CLI while monitor runs
- Clear error messages guide users to start daemon first

Fixes beads-eel

* bd sync: 2025-11-06 18:03:50

* docs: Add bd daemons restart subcommand documentation

Added documentation for the 'bd daemons restart' subcommand across all documentation files:

- commands/daemons.md: Added full restart subcommand section with synopsis, description, arguments, flags, and examples
- README.md: Added restart examples to daemon management section
- AGENTS.md: Added restart examples with --json flag for agents

The restart command gracefully stops and starts a specific daemon by workspace path or PID,
useful after upgrading bd or when a daemon needs refreshing.

Fixes beads-11

* bd sync: 2025-11-06 18:13:16

* Separated the web ui from the general monitoring functionality

---------

Co-authored-by: Steve Yegge <stevey@sourcegraph.com>
2025-11-07 09:49:12 -08:00
Steve Yegge
95cbcf4fbc Centralize BD_DEBUG logging into internal/debug package
- Created internal/debug package with Enabled(), Logf(), Printf()
- Added comprehensive unit tests for debug package
- Replaced 50+ scattered os.Getenv("BD_DEBUG") checks across 9 files
- Centralized debug logic for easier maintenance and testing
- All tests passing, behavior unchanged

Closes bd-fb95094c.5
2025-11-06 20:14:34 -08:00
Steve Yegge
9520e7a2e2 Extract normalizeLabels to internal/util/strings.go
- Created internal/util/strings.go with NormalizeLabels function
- Added comprehensive tests in internal/util/strings_test.go
- Updated internal/rpc/server_issues_epics.go to use util.NormalizeLabels
- Updated cmd/bd/list.go and cmd/bd/ready.go to use util.NormalizeLabels
- Updated cmd/bd/list_test.go to use util.NormalizeLabels
- Removed duplicate implementations
- All tests pass

Fixes bd-fb95094c.6

Amp-Thread-ID: https://ampcode.com/threads/T-edb3c286-cd60-4231-94cd-edaf75d84a3d
Co-authored-by: Amp <amp@ampcode.com>
2025-11-06 20:00:08 -08:00
Steve Yegge
ac1752d87d Complete cache audit (bd-bc2c6191)
- Created CACHE_AUDIT.md with comprehensive findings
- Confirmed cache was already removed in commit 322ab63
- Fixed stale comment in internal/rpc/server.go
- All tests passing, MCP multi-repo working correctly
- Closed bd-bc2c6191

Amp-Thread-ID: https://ampcode.com/threads/T-c1286278-b1ff-4b8a-b090-2b3a1c38c9dd
Co-authored-by: Amp <amp@ampcode.com>
2025-11-06 19:51:16 -08:00
Steve Yegge
11fa142539 Optimize test suite with testing.Short() guards
- Add Short() guards to slow CLI tests (2-4s each)
- Add Short() guards to slow API/integration tests (3-11s)
- Add Short() guard to hanging daemon discovery test (29s timeout)
- Short test suite now runs in ~6s (down from 5+ minutes)

Run 'go test -short ./...' for fast iteration
Run 'go test ./...' for full coverage

Closes: bd-iov0
2025-11-06 17:31:15 -08:00
Steve Yegge
fc89f15ca0 Add --parent flag support in daemon mode (bd-2e94)
- Added Parent field to CreateArgs RPC protocol
- Updated CLI to pass parent ID to daemon instead of erroring
- Added parent ID handling in RPC server to call GetNextChildID
- Added validation to prevent both --id and --parent flags
- Added comprehensive tests for hierarchical child creation
- Resolves error: '--parent flag not yet supported in daemon mode'

Amp-Thread-ID: https://ampcode.com/threads/T-3e0f76df-4ba6-4b16-bf75-bb7ea6b19541
Co-authored-by: Amp <amp@ampcode.com>
2025-11-05 13:56:25 -08:00
Steve Yegge
510ca17195 test: Add comprehensive RPC list filter parity tests (bd-zkl)
- Test pattern matching filters (title/description/notes contains)
- Test empty/null checks (empty description, no assignee, no labels)
- Test priority range filters (min/max)
- Test date range filters with multiple formats
- Test status normalization ('all' vs unset)
- Test backward compatibility (deprecated --label flag)
- Verify daemon mode (RPC) behaves identically to direct mode
- All tests pass with real daemon instance

Resolves bd-zkl
2025-11-05 00:56:06 -08:00
Steve Yegge
fbe790aa40 feat: Add ancestor_id field and implement epic/child filtering
Amp-Thread-ID: https://ampcode.com/threads/T-22f7d7c5-6f7b-4783-beda-8494360d887a
Co-authored-by: Amp <amp@ampcode.com>
2025-11-05 00:44:41 -08:00
Steve Yegge
cac9ae6647 Add routing integration tests and documentation
- Created routing_integration_test.go with comprehensive routing tests
- Tests cover maintainer/contributor detection, explicit overrides, end-to-end multi-repo
- Added docs/ROUTING.md documenting auto-routing feature
- Closed bd-6u6g, bd-zmi5, bd-nzt4, bd-btsm (routing tests)
- Updated bd-4ms and bd-8hf with progress notes

All routing tests pass. Multi-repo auto-routing is complete.

Amp-Thread-ID: https://ampcode.com/threads/T-2ea8b2ed-ceb7-432e-91f1-1f527b0e7b4d
Co-authored-by: Amp <amp@ampcode.com>
2025-11-04 23:12:42 -08:00
Ben Lovell
b92e79f98e Fix pointer dereferencing in Update RPC handler (#223)
- Dereference Design, AcceptanceCriteria, Notes, and Assignee pointers in updatesFromArgs
- Fixes EOF errors when using --notes, --design, --assignee, or --acceptance-criteria flags
- Enhance TestUpdateIssue to verify all pointer-dereferenced fields are correctly stored
2025-11-04 22:10:56 -08:00
Steve Yegge
eb434dd08c Add template support for issue creation (bd-164b)
- Built-in templates: epic, bug, feature (embedded in binary)
- Custom templates in .beads/templates/ (override built-ins)
- Commands: bd template list/show/create
- Flag: bd create --from-template <name> "Title"
- Template fields: description, type, priority, labels, design, acceptance
- Security: sanitize template names to prevent path traversal
- Flag precedence: explicit flags override template defaults
- Tests: template loading, security, flag precedence
- Docs: commands/template.md and README.md updated

Closes bd-164b

Amp-Thread-ID: https://ampcode.com/threads/T-118fe54f-b112-4f99-a3d9-b7df53fb7284
Co-authored-by: Amp <amp@ampcode.com>
2025-11-03 20:31:11 -08:00
Steve Yegge
3343351d3b Fix epic hierarchy display in bd show command
Amp-Thread-ID: https://ampcode.com/threads/T-43f6c7bf-9d4f-4475-8266-69e0a35a5909
Co-authored-by: Amp <amp@ampcode.com>
2025-11-03 14:24:45 -08:00
Steve Yegge
481649a605 Fix widespread double JSON encoding bug in daemon RPC calls (bd-1048, bd-4ec8)
Multiple CLI commands had a systematic bug where ResolveID responses were
incorrectly converted using string(resp.Data) instead of json.Unmarshal.
Since resp.Data is json.RawMessage (already JSON-encoded), this preserved
the JSON quotes, causing IDs to become "bd-1048" instead of bd-1048.
When re-marshaled for subsequent RPC calls, these became double-quoted
("\"bd-1048\""), causing database lookups to fail.

Bugs fixed:
1. Nil pointer dereference in handleShow - added nil check after GetIssue
2. Double JSON encoding in 12 locations across 4 commands:
   - bd show (3 instances in show.go)
   - bd dep add/remove/tree (5 instances in dep.go)
   - bd label add/remove/list (3 instances in label.go)
   - bd reopen (1 instance in reopen.go)

All instances replaced string(resp.Data) with proper json.Unmarshal.
Removed debug logging added during investigation.

Tested: All affected commands now work correctly with daemon mode.
2025-11-02 22:34:24 -08:00
Steve Yegge
63ff9b93bc Update bd-1048 with investigation findings 2025-11-02 22:12:21 -08:00
Steve Yegge
86c645603e Fix all gosec, misspell, and unparam linter errors
- Add #nosec directives with explanations for all gosec warnings in worktree operations
- Tighten directory permissions from 0755 to 0750 for better security
- Fix misspellings: archaeological -> archeological, cancelled -> canceled
- Remove unused jsonlPath parameter from syncBranchCommitAndPush
- Change branchExists to return bool instead of (bool, error) - error was never used

All changes maintain backward compatibility and improve code quality.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-02 20:06:05 -08:00
Steve Yegge
3b6856904f Fix critical double-release race in importInProgress flag
CRITICAL BUG: The previous fix had a race condition where the
importInProgress flag could be released twice, allowing two goroutines
to think they both hold the lock.

Bug scenario:
1. Goroutine A: acquires lock (CAS true)
2. Goroutine A: manually releases at line 208 for git dirty skip
3. Goroutine B: CAS succeeds, acquires lock
4. Goroutine A: defer runs, releases flag AGAIN (clears B lock)
5. Goroutine C: CAS succeeds - now TWO goroutines have lock

Root cause: Using both manual Store(false) AND defer Store(false)
created a window where the flag could be cleared twice.

Fix: Use a shouldDeferRelease flag to disable the deferred release
when we manually release early. This ensures exactly one release
per acquisition.

Testing: All auto-import tests still passing

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-02 18:16:25 -08:00
Steve Yegge
e8e9e729e5 Fix bd-8931: Prevent daemon corruption from git conflicts
CRITICAL FIX: The daemon could enter a corrupt state when auto-import
was triggered while uncommitted changes existed in .beads/ files. This
caused mysterious EOF errors requiring daemon restarts.

Root Causes Fixed:
1. No git dirty check before auto-import
2. Missing timeout protection (could hang indefinitely)
3. Race condition in importInProgress flag management
4. Improper git status parsing (false positives)
5. Context leak in export goroutine (accessing closed DB)
6. Data loss in triggerExport (missing deps/labels/comments)

Changes:
- Add hasUncommittedBeadsFiles() to check git status before import
  - Properly parses git porcelain format ("XY filename")
  - Ignores untracked files, only checks tracked .jsonl changes
  - 5-second timeout on git command to prevent hangs

- Add 30-second timeout to import operations
  - Prevents daemon from hanging on stuck imports
  - Returns clear error message on timeout

- Fix race condition in importInProgress flag
  - Explicitly release before early returns
  - Prevents other requests seeing incorrect "import in progress"

- Fix context leak in onChanged export goroutine
  - Check daemon shutdown state before export
  - Suppress expected "database closed" errors during shutdown
  - Pass storage/path as parameters to avoid closure issues

- Fix data loss in triggerExport()
  - Populate dependencies, labels, comments (mirrors handleExport)
  - Use atomic file write (temp + rename)
  - Sort issues for consistent output

Impact: Prevents daemon corruption in collaborative workflows where
users frequently pull updates while having local uncommitted changes.

Testing: All auto-import tests passing
- TestDaemonAutoImportAfterGitPull ✓
- TestDaemonAutoImportDataCorruption ✓
- internal/autoimport tests ✓

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-02 18:13:37 -08:00
Steve Yegge
edb9c9e2ab Add panic recovery to RPC handleConnection (bd-1048) 2025-11-02 17:11:52 -08:00
Steve Yegge
1036b0b700 Fix TestMetricsSnapshot/uptime flakiness on Windows
Simplify uptime calculation to always enforce minimum of 1 second,
even if time.Since returns exactly 0 (can happen on Windows with
coarse timing). This makes the test deterministic.
2025-11-02 09:56:42 -08:00