Commit Graph

381 Commits

Author SHA1 Message Date
Steve Yegge
d5239eeef9 Refactor: Extract duplicated validation logic to internal/validation
Extracted repeated priority and ID validation patterns from CLI commands
into reusable functions in internal/validation/bead.go.

Changes:
- Added ValidatePriority(): Combines parsing and error handling
- Added ValidateIDFormat(): Validates ID format and extracts prefix
- Added ValidatePrefix(): Validates prefix matching with database config
- Updated create.go and show.go to use new validation functions
- Simplified force flag logic to always call ValidatePrefix()
- Added comprehensive tests for all validation functions
- Added TODO comment for daemon mode validation enhancement

Results:
- Reduced code duplication by ~20 lines
- Centralized validation logic for easier maintenance
- Consistent error messages across all commands
- All tests passing

Fixes bd-g5p7

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-20 20:39:23 -05:00
Steve Yegge
614ba8ab20 Add cache invalidation for blocked_issues_cache
Ensures cache stays synchronized with dependency and status changes
by calling invalidateBlockedCache() at all mutation points (bd-5qim).

Cache invalidation points:
- AddDependency: when type is 'blocks' or 'parent-child'
- RemoveDependency: when removed dep was 'blocks' or 'parent-child'
- UpdateIssue: when status field changes
- CloseIssue: always (closed issues don't block)

The invalidation strategy is full cache rebuild on any change,
which is fast enough (<1ms for 10K issues) and keeps the logic simple.

Only 'blocks' and 'parent-child' dependency types affect blocking,
so 'relates-to' and other types skip invalidation.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-20 19:29:30 -05:00
Steve Yegge
ed23f8f4fe Optimize GetReadyWork to use blocked_issues_cache
Replaces expensive recursive CTE query with simple cache lookup,
achieving 96% performance improvement on 10K databases (bd-5qim).

Performance results:
- Before: ~752ms (recursive CTE on every call)
- After: ~29ms (cache lookup + filters)
- Target: <50ms ✓

The query now uses a simple NOT EXISTS check against the
blocked_issues_cache table instead of computing the full
blocked issue tree on every call.

Cache is maintained by invalidateBlockedCache() called on
dependency and status changes (added in next commit).

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-20 19:29:30 -05:00
Steve Yegge
62c1f42d9f Add blocked_issues_cache table for GetReadyWork optimization
Introduces a materialized cache table to store blocked issue IDs,
replacing the expensive recursive CTE computation that was causing
~752ms query times on 10K databases (bd-5qim).

The cache is maintained via invalidation on dependency and status
changes, reducing GetReadyWork from O(n²) recursive traversal to
O(1) cache lookup.

Technical details:
- New blocked_issues_cache table with single issue_id column
- ON DELETE CASCADE ensures automatic cleanup
- Migration populates cache using existing recursive CTE logic
- rebuildBlockedCache() fully rebuilds cache on invalidation
- execer interface allows both *sql.DB and *sql.Tx usage

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-20 19:29:30 -05:00
Steve Yegge
0470105fee Merge branch 'main' of https://github.com/steveyegge/beads
# Conflicts:
#	.beads/issues.jsonl
2025-11-20 19:19:28 -05:00
Steve Yegge
3b2cac4d8f Centralize error handling patterns in storage layer (bd-bwk2)
Created internal/storage/sqlite/errors.go with:
- Sentinel errors: ErrNotFound, ErrInvalidID, ErrConflict, ErrCycle
- wrapDBError helpers that auto-convert sql.ErrNoRows to ErrNotFound
- Type-safe error checking with errors.Is() compatibility

Updated error handling across storage layer:
- dirty.go: Added context to error returns, converted sql.ErrNoRows checks
- util.go: Updated withTx to use wrapDBError
- batch_ops.go: Added context wrapping to batch operations
- dependencies.go: Wrapped errors from markIssuesDirtyTx calls
- ids.go: Added error wrapping for ID validation

Also restored sqlite.go that was accidentally deleted in previous commit.

All tests pass. Provides consistent error wrapping with operation context
for better debugging.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-20 19:17:57 -05:00
Steve Yegge
06b6f864b8 Merge remote-tracking branch 'origin/main'
Amp-Thread-ID: https://ampcode.com/threads/T-c8d369a3-32f0-42a0-96d1-fd589e89bd6b
Co-authored-by: Amp <amp@ampcode.com>
2025-11-20 19:12:06 -05:00
Steve Yegge
bbfedb060a Refactor: extract duplicated validation and flag logic (bd-g5p7)
- Created internal/validation package for centralized validation logic
- Created cmd/bd/flags.go for shared flag registration
- Updated create and update commands to use shared logic
- Added support for 'P1' style priority to update command
- Added tests for validation logic

Amp-Thread-ID: https://ampcode.com/threads/T-c8d369a3-32f0-42a0-96d1-fd589e89bd6b
Co-authored-by: Amp <amp@ampcode.com>
2025-11-20 19:11:27 -05:00
Steve Yegge
1736f9f12d bd sync: 2025-11-20 18:58:07 2025-11-20 19:10:37 -05:00
Steve Yegge
631c9236e7 Resolve merge conflict in beads.jsonl
Amp-Thread-ID: https://ampcode.com/threads/T-fc47ce9d-88a4-4bcd-b9cb-79327d98dee7
Co-authored-by: Amp <amp@ampcode.com>
2025-11-20 19:08:23 -05:00
Steve Yegge
8e05847d31 Fix TestRoutingIntegration and improve DetectUserRole robustness
Amp-Thread-ID: https://ampcode.com/threads/T-fc47ce9d-88a4-4bcd-b9cb-79327d98dee7
Co-authored-by: Amp <amp@ampcode.com>
2025-11-20 19:04:42 -05:00
Steve Yegge
6a25f5eaa6 fix: resolve remaining hyphenated ID issues in memory store and doctor 2025-11-20 19:01:30 -05:00
Steve Yegge
7b865eb541 Remove legacy issues.jsonl and update defaults to beads.jsonl
Amp-Thread-ID: https://ampcode.com/threads/T-ae11b392-24b5-4060-b431-606dd81c1763
Co-authored-by: Amp <amp@ampcode.com>
2025-11-20 19:00:36 -05:00
Steve Yegge
345766badc Fix FK constraint failures in AddComment and ApplyCompaction (bd-5arw)
Amp-Thread-ID: https://ampcode.com/threads/T-4358e6e4-28ea-4ed7-ba3f-3da39072e169
Co-authored-by: Amp <amp@ampcode.com>
2025-11-20 18:55:10 -05:00
Steve Yegge
7665ff0763 Merge branch 'fix-issue-325' into main
Amp-Thread-ID: https://ampcode.com/threads/T-aa765a68-5cc4-465b-a2f6-aa008933c11e
Co-authored-by: Amp <amp@ampcode.com>
2025-11-20 14:20:45 -05:00
Steve Yegge
09666b4219 Fix FOREIGN KEY constraint failed when operating on non-existent issues
Fixes #325

- Fix CloseIssue to check rows affected before inserting event
- Fix RemoveLabel to check rows affected before inserting event
- Fix UpdateIssueID to check rows affected before inserting event
- Prevent orphan events and confusing error messages

Amp-Thread-ID: https://ampcode.com/threads/T-aa765a68-5cc4-465b-a2f6-aa008933c11e
Co-authored-by: Amp <amp@ampcode.com>
2025-11-20 12:35:26 -05:00
Steve Yegge
20ffe60316 Merge origin/main 2025-11-20 12:27:47 -05:00
Steve Yegge
78a893d17d Merge pull request #337 from cpdata/fix-resolve-partial-id
Fix: Restore JSON unmarshaling in ResolveID for fixing failed bd show/update/close operations
2025-11-20 09:15:08 -08: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
Charles P. Cross
4432af0aa4 fix: improve ResolvePartialID / ResolveID handling for bd show (issue #336)
- Add fast path for exact ID matches in ResolvePartialID
- Properly unmarshal ResolveID RPC responses used by `bd show`

Summary:
--------
Fixes regression introduced after v0.23.1 where `bd show <issue_id>`,
`bd update <issue_id>`, and `bd close <issue_id>` commands failed with
"operation failed: issue not found" errors even when the issue existed
in the database.

Root Cause:
-----------
The daemon's ResolveID RPC handler (handleResolveID in
internal/rpc/server_issues_epics.go) returns a JSON-encoded string
containing the resolved issue ID. For example, when resolving "ao-izl",
the RPC response contains the JSON string: "ao-izl" (with quotes).

After v0.23.1, the show/update/close commands in cmd/bd/show.go were
changed to use string(resp.Data) to extract the resolved ID, which
treats the raw bytes as a string without decoding the JSON. This caused
the resolved ID to literally be "ao-izl" (including the quotes),
which then failed to match the actual issue ID ao-izl (without quotes)
when passed to subsequent Show/Update/Close RPC calls.

In v0.23.1 (commit 77dcf55), the code correctly unmarshaled the JSON:
  var resolvedID string
  if err := json.Unmarshal(resp.Data, &resolvedID); err != nil {
      // handle error
  }

This unmarshal step was removed in later commits, causing the regression.

Fix:
----
Restored the JSON unmarshaling step in three places in cmd/bd/show.go:
1. showCmd - line 37-42
2. updateCmd - line 400-405
3. closeCmd - line 723-728

Each now properly decodes the JSON string response before using the
resolved ID in subsequent RPC calls.

Testing:
--------
- Verified `bd show <issue-id-with-prefix>` works correctly in both daemon and direct modes
- Tested with newly created issues to ensure the fix works for all IDs
- All Go tests pass (go test ./... -short)
- Confirmed behavior matches v0.23.1 working binary

The fix ensures that issue ID resolution works correctly regardless of
whether the ID prefix matches the configured issue_prefix.
2025-11-19 05:54:28 -05:00
Codex Agent
4cd26c8e5a Fix Windows concurrent issue creation 2025-11-17 10:41:05 -07:00
Codex Agent
bf9b2c83fb Annotate gosec-safe file accesses 2025-11-17 10:12:46 -07:00
Codex Agent
7b63b5a30b Fix CI regressions and stabilize tests 2025-11-17 10:06:35 -07:00
Steve Yegge
934ae04fa0 Fix gh-316: Prefer exact ID matches over prefix matches
The ID disambiguation logic treated 'offlinebrew-3d0' as ambiguous when
child IDs like 'offlinebrew-3d0.1' existed. Now the system:

1. Checks for exact full ID matches first (issue.ID == input)
2. Checks for exact hash matches (handling cross-prefix scenarios)
3. Only falls back to substring matching if no exact match is found

Added test cases verifying:
- 'offlinebrew-3d0' matches exactly, not ambiguously with children
- '3d0' without prefix still resolves to exact match

Amp-Thread-ID: https://ampcode.com/threads/T-5358ea57-e9ea-49e9-aedf-7044ebf8b52a
Co-authored-by: Amp <amp@ampcode.com>
2025-11-15 14:07:38 -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
Ryan
690c73fc31 Performance Improvements (#319)
* feat: add performance testing framework foundation

Implements foundation for comprehensive performance testing and user
diagnostics for beads databases at 10K-20K scale.

Components added:
- Fixture generator (internal/testutil/fixtures/) for realistic test data
  * LargeSQLite/XLargeSQLite: 10K/20K issues with epic hierarchies
  * LargeFromJSONL/XLargeFromJSONL: test JSONL import path
  * Realistic cross-linked dependencies, labels, assignees
  * Reproducible with seeded RNG

- User diagnostics (bd doctor --perf) for field performance data
  * Collects platform info (OS, arch, Go/SQLite versions)
  * Measures key operation timings (ready, list, show, search)
  * Generates CPU profiles for bug reports
  * Clean separation in cmd/bd/doctor/perf.go

Test data characteristics:
- 10% epics, 30% features, 60% tasks
- 4-level hierarchies (Epic → Feature → Task → Subtask)
- 20% cross-epic blocking dependencies
- Realistic status/priority/label distributions

Supports bd-l954 (Performance Testing Framework epic)
Closes bd-6ed8, bd-q59i

* perf: optimize GetReadyWork with compound index (20x speedup)

Add compound index on dependencies(depends_on_id, type, issue_id) to
eliminate performance bottleneck in GetReadyWork recursive CTE query.

Performance improvements (10K issue database):
- GetReadyWork: 752ms → 36.6ms (20.5x faster)
- Target: <50ms ✓ ACHIEVED
- 20K database: ~1500ms → 79.4ms (19x faster)

Benchmark infrastructure enhancements:
- Add dataset caching in /tmp/beads-bench-cache/ to avoid regenerating
  10K-20K issues on every benchmark run (first run: ~2min, subsequent: <5s)
- Add progress logging during fixture generation (shows 10%, 20%... completion)
- Add database size logging (17.5 MB for 10K, 35.1 MB for 20K)
- Document rationale for only benchmarking large datasets (>10K issues)
- Add CPU/trace profiling with --profile flag for performance debugging

Schema changes:
- internal/storage/sqlite/schema.go: Add idx_dependencies_depends_on_type_issue

New files:
- internal/storage/sqlite/bench_helpers_test.go: Reusable benchmark setup with caching
- internal/storage/sqlite/sqlite_bench_test.go: Comprehensive benchmarks for critical operations
- Makefile: Convenient benchmark execution (make bench-quick, make bench)

Related:
- Resolves bd-5qim (optimize GetReadyWork performance)
- Builds on bd-6ed8 (fixture generator), bd-q59i (bd doctor --perf)

* perf: add WASM compilation cache to eliminate cold-start overhead

Configure wazero compilation cache for ncruces/go-sqlite3 to avoid
~220ms JIT compilation on every process start.

Cache configuration:
- Location: ~/.cache/beads/wasm/ (platform-specific via os.UserCacheDir)
- Automatic version management: wazero keys entries by its version
- Fallback: in-memory cache if directory creation fails
- No cleanup needed: old versions are harmless (~5-10MB each)

Performance impact:
- First run: ~220ms (populate cache)
- Subsequent runs: ~20ms (load from cache)
- Savings: ~200ms per cold start

Cache invalidation:
- Automatic when wazero version changes (upgrades use new cache dir)
- Manual cleanup: rm -rf ~/.cache/beads/wasm/ (safe to delete anytime)

This complements daemon mode:
- Daemon mode: eliminates startup cost by keeping process alive
- WASM cache: reduces startup cost for one-off commands or daemon restarts

Changes:
- internal/storage/sqlite/sqlite.go: Add init() with cache setup

* refactor: improve maintainability of performance testing code

Extract common patterns and eliminate duplication across benchmarks, fixture generation, and performance diagnostics. Replace magic numbers with explicit configuration to improve readability and make it easier to tune test parameters.

* docs: clarify profiling behavior and add missing documentation

Add explanatory comments for profiling setup to clarify why --profile
forces direct mode (captures actual database operations instead of RPC
overhead) and document the stopCPUProfile function's role in flushing
profile data to disk. Also fix gosec G104 linter warning by explicitly
ignoring Close() error during cleanup.

* fix: prevent bench-quick from running indefinitely

Added //go:build bench tags and skipped timeout-prone benchmarks to
prevent make bench-quick from running for hours.

Changes:
- Add //go:build bench tag to cycle_bench_test.go and compact_bench_test.go
- Skip Dense graph benchmarks (documented to timeout >120s)
- Fix compact benchmark prefix: bd- → bd (validation expects prefix without trailing dash)

Before: make bench-quick ran for 3.5+ hours (12,699s) before manual interrupt
After: make bench-quick completes in ~25 seconds

The Dense graph benchmarks are known to timeout and represent rare edge
cases that don't need optimization for typical workflows.
2025-11-15 12:46:13 -08:00
Steve Yegge
944ed1033d Fix bd-yvlc: in-memory database deadlock in migrations
- Force single connection for all in-memory databases (including file::memory:)
- Close rows before executing statements in external_ref migration
- Prevents connection pool deadlock with MaxOpenConns(1)
- Fixes test failures in syncbranch_test.go
2025-11-15 12:42: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
Ryan
f7e80dd80c feat: add context optimization features for AI agents (#297)
* feat: add bd prime and setup commands for AI agent integration

This commit consolidates context optimization features for AI agents:

## New Commands

**bd prime** - AI-optimized workflow context injection
- Outputs ~1-2k tokens of workflow context
- Context-aware: adapts to MCP vs CLI mode
- MCP mode: minimal reminders (~500 tokens)
- CLI mode: full command reference (~1-2k tokens)
- Warns against TodoWrite tool and markdown TODOs
- Designed for SessionStart/PreCompact hooks

**bd setup claude** - Claude Code integration installer
- Installs hooks via JSON configuration (not file scripts)
- Supports --project for project-only installation
- Supports --check to verify installation
- Supports --remove to uninstall hooks
- Idempotent (safe to run multiple times)
- Merges with existing settings

**bd setup cursor** - Cursor IDE integration installer
- Creates .cursor/rules/beads.mdc with workflow rules
- Simplified implementation (just overwrites file)

## bd doctor Enhancements

- New: CheckClaude() verifies Claude Code integration
- Detects plugin, MCP server, and hooks installation
- Provides actionable fix suggestions
- Extracted legacy pattern detection to doctor/legacy.go
- Detects JSONL-only mode and warns about legacy issues.jsonl

## Core Improvements

- FindBeadsDir() utility for cross-platform .beads/ discovery
- Works in JSONL-only mode (no database required)
- Sorted noDbCommands alphabetically (one per line for easy diffs)

## Testing

- Unit tests for setup command hook manipulation
- Tests for idempotency, adding/removing hooks
- All tests passing

## Documentation

- cmd/bd/doctor/claude.md - Documents why beads doesn't use Claude Skills
- commands/prime.md - Slash command for bd prime
- Fixed G304 gosec warnings with nosec comments

## Token Efficiency

The bd prime approach reduces AI context usage dramatically:
- MCP mode: ~500 tokens (vs ~10.5k for full MCP tool scan)
- CLI mode: ~1-2k tokens
- 80-99% reduction in standing context overhead

* fix: resolve linting errors in setup utils and remove obsolete test

- Add error check for tmpFile.Close() in setup/utils.go to fix golangci-lint G104
- Remove TestCheckMultipleJSONLFiles test that referenced deleted checkMultipleJSONLFiles function

Fixes golangci-lint errcheck violations introduced in the bd prime/setup feature.
2025-11-12 10:48:36 -08:00
Steve Yegge
8be792a460 Fix external_ref migration failure on old databases
The schema initialization was trying to create an index on the external_ref
column before the migration that adds the column runs. This caused 'no such
column: external_ref' errors when opening very old databases (pre-0.17.5).

Solution: Move the index creation into the migration that adds the column.

Fixes #284

Amp-Thread-ID: https://ampcode.com/threads/T-2744d5a7-168f-4ef6-bcab-926db846de20
Co-authored-by: Amp <amp@ampcode.com>
2025-11-10 10:50:39 -08:00
Steve Yegge
83472aca3d bd sync: 2025-11-09 14:53:59 2025-11-09 14:53:59 -08:00
Steve Yegge
98f2e85618 Fix version test error message assertion 2025-11-08 22:57:49 -08:00
Steve Yegge
734579b1a2 Remove version field from metadata.json
- Removes noisy version mismatch warnings on every bd upgrade
- Version field in metadata.json was redundant with daemon version checking via RPC
- Daemon version mismatches still detected via HealthResponse
- Removes checkVersionMismatch() function and related test file
- Updates .beads/.gitignore to properly ignore merge artifacts

Amp-Thread-ID: https://ampcode.com/threads/T-7ba8aff2-97a0-4d0c-9008-e858bdfadd61
Co-authored-by: Amp <amp@ampcode.com>
2025-11-08 18:16:39 -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
773aa736e4 Document external_ref in content hash behavior (bd-9f4a)
- Added comprehensive code comments in collision.go explaining external_ref inclusion
- Documented content hash behavior in HASH_ID_DESIGN.md with examples
- Enhanced test documentation in collision_test.go
- Closes bd-9f4a, bd-df11, bd-537e

Amp-Thread-ID: https://ampcode.com/threads/T-47525168-d51c-4f56-b598-18402e5ea389
Co-authored-by: Amp <amp@ampcode.com>
2025-11-08 02:22:15 -08:00
Steve Yegge
a140436db8 test: improve internal/daemon test coverage to 60%
Adds fast unit tests for previously uncovered functions in the daemon package:

- checkDaemonErrorFile: tests reading daemon error files
- StopDaemon: tests error handling for non-running daemons
- KillAllDaemons: tests empty lists and non-alive daemons
- FindDaemonByWorkspace: tests not found case
- discoverDaemon: tests missing socket scenario
- CleanupStaleSockets: tests edge cases (already removed, alive daemon)
- Registry: tests corrupted file handling and unregistering non-existent entries

Coverage improved from 22.5% to 60.0% with only fast tests (<1s runtime).
All new tests work in -short mode and don't start actual daemons.

Fixes bd-3f80d9e0

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-08 01:20:03 -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
Steve Yegge
3191c9c3da Remove vc.db exclusion from FindDatabasePath filter
Only filter out backup files, allow vc.db to be a valid database

Amp-Thread-ID: https://ampcode.com/threads/T-8600ed89-42af-4785-b5dc-01ad37f1451d
Co-authored-by: Amp <amp@ampcode.com>
2025-11-07 14:55:01 -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
ca5e32e5f2 Remove commented-out code
Cleaned up old bd-160 export hash tracking code that was disabled.
Removed unnecessary test comments.

Amp-Thread-ID: https://ampcode.com/threads/T-de38a626-a425-414f-92d8-102bc1519c8b
Co-authored-by: Amp <amp@ampcode.com>
2025-11-06 20:15:34 -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
b655b29ad9 Extract SQLite migrations into separate files (bd-fb95094c.7)
- Created migrations/ subdirectory with 14 individual migration files
- Reduced migrations.go from 680 to 98 lines (orchestration only)
- Updated test imports to use migrations package
- Updated MULTI_REPO_HYDRATION.md documentation
- All tests passing
2025-11-06 20:06:45 -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
a7ec8a2eaa Remove unused internal/daemonrunner/ package (~1,500 LOC)
Removed old global daemon infrastructure that was replaced by per-workspace
daemon architecture. Package had no imports and all functions were unreachable.

Closes bd-irq6
2025-11-06 19:35:43 -08:00