- Add comprehensive godoc to CreateIssues with usage examples
- Add batch operations section to EXTENDING.md with performance comparison
- Add performance feature to README.md
- Include when to use CreateIssue vs CreateIssues guidance
- Document counter sync requirement after explicit IDs
Amp-Thread-ID: https://ampcode.com/threads/T-59fc78c3-a7f2-4c33-b074-2fa840c97c87
Co-authored-by: Amp <amp@ampcode.com>
The skipUpdate flag should only apply to existing DB issues, not to
duplicates within the import batch. Batch duplicates always use
last-one-wins semantics.
- Replace CreateIssue loop with single CreateIssues batch call
- Add in-memory de-duplication for duplicate IDs (last one wins)
- 5-15x faster for bulk imports
- All tests pass
- Add CreateIssues method to Storage interface
- Implement SQLiteStorage.CreateIssues with atomic ID range reservation
- Single transaction for N issues (5-10x speedup expected)
- Set timestamps before validation to match CreateIssue behavior
- All tests passing
- Test add/remove labels
- Test multiple labels and duplicates
- Test label persistence across updates
- Test event creation for label operations
- Test labels with different issue types
- All 10 test cases passing
Enhance Graphviz dot output with status-based fill colors:
- open: white background (default)
- in_progress: light yellow background
- blocked: light coral background
- closed: light gray background with dimmed text
Node labels show: ID, type, priority, title, and status.
Priority is visible in the label (e.g., [bug P0]) but not color-coded
to keep the visualization clean and focused on status.
Add flexible --format flag to 'bd list' command supporting:
- Built-in presets: 'digraph' (basic 'from to' format) and 'dot' (Graphviz)
- Custom Go templates for dependency output
- Template variables: IssueID, DependsOnID, Type, Issue, Dependency
This enables graph analysis with tools like golang.org/x/tools/cmd/digraph while allowing users to customize output format for their specific needs.
Examples:
bd list --format=digraph | digraph nodes
bd list --format=dot | dot -Tsvg -o deps.svg
bd list --format='{{.IssueID}} -> {{.DependsOnID}} [{{.Type}}]'
- Add closed_at field to Issue type with JSON marshaling
- Implement closed_at timestamp in SQLite storage layer
- Update import/export to handle closed_at field
- Add comprehensive tests for closed_at functionality
- Maintain backward compatibility with existing databases
Amp-Thread-ID: https://ampcode.com/threads/T-f3a7799b-f91e-4432-a690-aae0aed364b3
Co-authored-by: Amp <amp@ampcode.com>
- Added design documents (ULTRATHINK_BD222.md, ULTRATHINK_BD224.md)
- Created bd-224 epic with 6 child issues for status/closed_at invariant fix
- Created bd-222 epic with 7 child issues for batching API
- Set up dependencies: bd-224 blocks bd-222 (must fix invariant first)
- Dependencies enable max parallelism while ensuring correct order
Code review and fixes:
- Increased scanner buffer to 2MB for large JSON lines
- Added line numbers and snippets to parse error messages
- Made non-SQLite fallback conservative (skip import to prevent data loss)
- Improved collision warnings (concise, show first 10 IDs)
- Removed unused autoImportWithoutCollisionDetection function
Status/closed_at invariant enforcement:
- Auto-import now enforces invariant on all creates/updates
- Fixed CreateIssue to respect closed_at field (was ignoring it)
- Closed issues without closed_at get timestamp set automatically
Integration tests:
- TestAutoImportWithCollision: verifies local changes preserved
- TestAutoImportNoCollision: happy path with new issues
- TestAutoImportClosedAtInvariant: enforces invariant
Closes bd-226, bd-230, bd-231
Ran: UPDATE issues SET closed_at = updated_at WHERE status = 'closed' AND closed_at IS NULL
Result: 0 remaining inconsistencies (verified)
Database now ready for CHECK constraint migration
Findings:
- 86/93 closed issues (92%) are missing closed_at timestamps
- All inconsistencies are historical (old issues bd-1 through bd-93)
- No cases of non-closed issues with timestamps
Recommendation: Set closed_at = updated_at for affected issues
Next: Apply cleanup SQL and add constraint
Fixes#42 and #44
- Remove BEADS_ACTOR and BEADS_WORKING_DIR from plugin.json env
(Claude Code only supports ${CLAUDE_PLUGIN_ROOT} expansion)
- Move commands from .claude-plugin/commands/ to commands/ at root
- Rename command files to remove redundant bd- prefix
This fixes MCP server crashes with literal ${PWD} directory errors
and makes slash commands discoverable in Claude Code.
Amp-Thread-ID: https://ampcode.com/threads/T-69426d6c-25ea-4333-8955-5b624001c8c6
Co-authored-by: Amp <amp@ampcode.com>
Add an apps.default output to the Nix flake that enables running bd
directly with 'nix run .' without needing to use the full package path.
The apps output references the built bd binary from packages.default,
allowing users to easily run the tool with: nix run . -- <command>
Tested with 'nix run . -- version' which correctly executes bd.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add flake.nix with computed vendorHash for Go dependencies. The flake
supports all major platforms (x86_64/aarch64 Linux and macOS) and
builds the bd binary from cmd/bd.
Removed unnecessary postInstall section as buildGoModule already names
the binary correctly from subPackages.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
perf: Use self input instead of ./. for faster Nix evaluation
Replace src = ./. with src = self in flake.nix to reduce unnecessary
file copying during evaluation. This eliminates the Nix warning about
evaluation performance.
1. Fix `test_default_beads_path_auto_detection`
- Changed beads_path to use `Field(default_factory=_default_beads_path)` so the default is evaluated at instance
creation time, not class definition time
- Updated test to mock both `shutil.which` and `os.access`
2. Fix `test_init_creates_beads_directory`
- Fixed test to pass `working_dir=temp_dir` to `BdClient` instead of using `os.chdir()`
- The `_get_working_dir()` method checks `PWD` env var first, which isn't updated by `os.chdir()`
3. Fix minor linting errors reported by `ruff` tool
4. Update `beads` version to `0.9.6` in `uv.lock` file
MCP Server test coverage is now excellent, at 92% overall maintaining our high-standards of production level quality.
```
Name Stmts Miss Cover
------------------------------------------------
src/beads_mcp/__init__.py 1 0 100%
src/beads_mcp/__main__.py 3 3 0%
src/beads_mcp/bd_client.py 214 14 93%
src/beads_mcp/config.py 51 2 96%
src/beads_mcp/models.py 92 1 99%
src/beads_mcp/server.py 58 16 72%
src/beads_mcp/tools.py 59 0 100%
------------------------------------------------
TOTAL 478 36 92%
```
Fixed UNIQUE constraint errors when creating multiple issues in parallel.
Root cause: The previous two-step approach used INSERT OR IGNORE to
pre-initialize counters, followed by an UPSERT to increment. Multiple
concurrent transactions could all execute the INSERT OR IGNORE with the
same initial value, causing them to generate duplicate IDs.
Solution: Replaced with a single atomic UPSERT that:
1. Initializes counter from MAX(existing IDs) if needed
2. Updates counter to MAX(current, max existing) + 1 on conflict
3. Returns the final incremented value
This ensures counters are correctly initialized from existing issues
(fixing lazy init tests) while preventing race conditions through the
BEGIN IMMEDIATE transaction serialization.
Tested with 10 parallel processes - all succeeded with unique IDs.
Also added comprehensive profiling test suite for import performance
investigation (bd-199).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Recovery investigation complete. Key findings documented in bd-229 notes.
No need for separate recovery doc - issue tracker has the details.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Auto-import collision detection fix (bd-228) is deployed and needs field testing.
Banner alerts users that the critical bug is fixed but testing is ongoing.
Links to LOST_ISSUES_RECOVERY.md for transparency about recovered data.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Successfully recovered 3 valuable issues from 22 total lost during auto-import bug:
- bd-222 → bd-232: Batching API feature request
- bd-223 → bd-233: Early context check optimization
- bd-221 context preserved in bd-89 notes
19 test fixtures identified but not recovered (no production value).
Auto-import collision detection fix (bd-228) prevents future data loss.
See LOST_ISSUES_RECOVERY.md for full investigation details.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
CRITICAL FIX: Auto-import was silently overwriting local changes without any
collision detection or warning. This caused data loss in multi-developer workflows.
Changes:
- Auto-import now uses sqlite.DetectCollisions() before importing
- Colliding issues are skipped (preserves local changes)
- Warning printed with list of skipped issues and resolution instructions
- Added autoImportWithoutCollisionDetection() fallback for non-SQLite backends
- All tests pass
Impact:
- Local changes are now preserved during git pull
- Users are informed when collisions occur
- Can manually resolve with 'bd import --resolve-collisions'
- No more silent data corruption
Also:
- Removed critical warning banner from README
- Created bd-229 for data recovery investigation
- Closed bd-228 as fixed
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
CRITICAL: Auto-import silently overwrites local changes without collision detection.
Changes:
- Added prominent warning banner at top of README
- Documents data corruption risk for multi-developer workflows
- Provides --no-auto-import workaround
- References bd-228 for tracking and updates
This affects anyone using bd with multiple developers or agent swarms.
Local updates/closes can be silently reverted by auto-import after git pull.
Also includes:
- ULTRATHINK_BD224.md analysis document (bd-224, bd-225)
- Updated issues.jsonl with bd-224, bd-225, bd-226, bd-227, bd-228
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Deleted stale beads.db (last modified Oct 14, 20KB)
- bd.db is the active database (2MB, 208 issues)
- Filed bd-199 to investigate import timeout with 208 issues
- Import should handle 100k+ issues, currently times out at 208
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Created bd-198: Add label management commands to CLI
- Add bd label add/remove/list subcommands
- Extend bd list with --label filter
- Enable organizing issues into streams/categories
- Support parallel workflow coordination
Closes mistakenly created GitHub issue #39 (should use beads itself).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Use IMMEDIATE transactions with dedicated connections to fix race condition
where multiple processes creating issues concurrently caused "UNIQUE constraint
failed: issues.id" errors.
Key changes:
- Use BEGIN IMMEDIATE to acquire RESERVED lock early
- Use dedicated connection (sql.Conn) for transaction to ensure all operations
happen on same connection
- Increase busy_timeout from 10s to 30s for better parallel write handling
- Use context.Background() for ROLLBACK to ensure cleanup even if ctx cancelled
Added regression test TestParallelIssueCreation that creates 20 issues in
parallel and verifies no ID collisions occur.
Fixes#6🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Fixes#34
Problem: Users with Go 1.18 were unable to install beads because go.mod
specifies 'go 1.23.0', which older Go toolchains cannot parse. The error
"invalid go version '1.23.0': must match format 1.23" occurs because
Go versions before 1.21 don't support the three-part version format.
Root cause: Our dependencies (especially modernc.org/sqlite) require Go 1.23,
which forces go.mod to use the 1.23.0 format. This is correct for our actual
requirements, but was incorrectly documented as requiring only Go 1.21.
Solution:
1. Updated install.sh to check for Go 1.23+ and show clear error messages
if an older version is detected
2. Updated README.md to correctly state "requires Go 1.23+" instead of 1.21+
3. go.mod already correctly specifies go 1.23.0 (no changes needed there)
The version check in install.sh now:
- Parses the Go version from 'go version' output
- Compares major.minor version numbers
- Fails fast with helpful upgrade instructions if Go < 1.23
This prevents confusing build errors and guides users to upgrade Go before
attempting installation.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>