Export deduplication breaks when JSONL and export_hashes table diverge

## Problem

The export deduplication feature (timestamp-only skipping) breaks when the JSONL file and export_hashes table get out of sync, causing exports to skip issues that aren't actually in the file.

## Symptoms

- `bd export` reports "Skipped 128 issue(s) with timestamp-only changes"
- JSONL file only has 38 lines but DB has 149 issues
- export_hashes table has 149 entries
- Auto-import doesn't trigger (hash matches despite missing data)
- Two repos on same commit show different issue counts

## Root Cause

shouldSkipExport() in autoflush.go compares current issue hash with stored export_hashes entry. If they match, it skips export assuming the issue is already in the JSONL.

This assumption fails when:
1. Git operations (pull, reset, checkout) change JSONL without clearing export_hashes
2. Manual JSONL edits or corruption
3. Import operations that modify DB but don't update export_hashes
4. Partial exports that update export_hashes but don't complete

## Impact

- **Critical data loss risk**: Issues appear to be tracked but aren't persisted to git
- Breaks multi-repo sync (root cause of today's debugging session)
- Auto-import fails to detect staleness (hash matches despite missing data)
- Silent data corruption (no error messages, just missing issues)

## Reproduction

1. Have DB with 149 issues, all in export_hashes table
2. Truncate JSONL to 38 lines (simulate git reset or corruption)
3. Run `bd export` - it skips 128 issues
4. JSONL still has only 38 lines but export thinks it succeeded

## Current Workaround

```bash
sqlite3 .beads/beads.db "DELETE FROM export_hashes"
bd export -o .beads/beads.jsonl
```

## Proposed Solutions

**Option 1: Verify JSONL integrity before skipping**
- Count lines in JSONL, compare with export_hashes count
- If mismatch, clear export_hashes and force full export
- Safe but adds I/O overhead

**Option 2: Hash-based JSONL validation**
- Store hash of entire JSONL file in metadata
- Before export, check if JSONL hash matches
- If mismatch, clear export_hashes
- More efficient, detects any JSONL corruption

**Option 3: Disable timestamp-only deduplication**
- Remove the feature entirely
- Always export all issues
- Simplest and safest, but creates larger git commits

**Option 4: Clear export_hashes on git operations**
- Add post-merge hook to clear export_hashes
- Clear on any import operation
- Defensive approach but may over-clear

## Recommended Fix

Combination of Options 2 + 4:
1. Store JSONL file hash in metadata after export
2. Check hash before export, clear export_hashes if mismatch
3. Clear export_hashes on import operations
4. Add `bd validate` check for JSONL/export_hashes sync

## Files Involved

- cmd/bd/autoflush.go (shouldSkipExport)
- cmd/bd/export.go (export with deduplication)
- internal/storage/sqlite/metadata.go (export_hashes table)

## Recovery Session (2025-10-29 21:30)

### What Happened
- Created 14 new hash ID issues (bd-f8b764c9 through bd-f8b764c9.1)
- bd sync appeared to succeed
- Canonical repo (~/src/beads): 162 issues in DB + JSONL ✓
- Secondary repo (fred/beads): Only 145 issues vs 162 in canonical ✗
- Both repos on same git commit but different issue counts!

### Bug Manifestation During Recovery

1. **Initial state**: fred/beads had 145 issues, 145 lines in JSONL, 145 export_hashes entries

2. **After git reset --hard origin/main**:
   - JSONL: 162 lines (from git)
   - DB: 150 issues (auto-import partially worked)
   - Auto-import failed with UNIQUE constraint error

3. **After manual import --resolve-collisions**:
   - DB: 160 issues
   - JSONL: Still 162 lines
   - export_hashes: 159 entries

4. **After bd export**:
   - **JSONL reduced to 17 lines!** ← The bug in action
   - export_hashes: 159 entries (skipped exporting 142 issues)
   - Silent data loss - no error message

5. **After clearing export_hashes and re-export**:
   - JSONL: 159 lines (missing 3 issues still)
   - DB: 159 issues
   - Still diverged from canonical

### The Bug Loop
Once export_hashes and JSONL diverge:
- Export skips issues already in export_hashes
- But those issues aren't actually in JSONL
- This creates corrupt JSONL with missing issues
- Auto-import can't detect the problem (file hash matches what was exported)
- Data is lost with no error messages

### Recovery Solution
Couldn't break the loop with export alone. Had to:
1. Copy .beads/beads.db from canonical repo
2. Clear export_hashes
3. Full re-export
4. Finally converged to 162 issues

### Key Learnings

1. **The bug is worse than we thought**: It can create corrupt exports (17 lines instead of 162!)

2. **Auto-import can't save you**: Once export is corrupt, auto-import just imports the corrupt data

3. **Silent failure**: No warnings, no errors, just missing issues

4. **Git operations trigger it**: git reset, git pull, etc. change JSONL without clearing export_hashes

5. **Import operations populate export_hashes**: Even manual imports update export_hashes, setting up future export failures

### Immediate Action Required

**DISABLE EXPORT DEDUPLICATION NOW**

This feature is fundamentally broken and causes data loss. Should be disabled until properly fixed.

Quick fix options:
- Set environment variable to disable feature
- Comment out shouldSkipExport check
- Always clear export_hashes before export
- Add validation that DB count == JSONL line count before allowing export

### Long-term Fix

Need Option 2 + 4 from proposed solutions:
1. Store JSONL file hash after every successful export
2. Before export, verify JSONL hash matches expected
3. If mismatch, log WARNING and clear export_hashes
4. Clear export_hashes on every import operation
5. Add git post-merge hook to clear export_hashes
6. Add `bd validate` command to detect divergence


Agent 6 Issue 3

Created by agent 6


Agent 6 Issue 33

Created by agent 6


Agent 6 Issue 14

Created by agent 6


Add validation/warning for malformed issue IDs

getNextID silently ignores non-numeric ID suffixes (e.g., bd-foo). CAST returns NULL for invalid strings. Consider detecting and warning about malformed IDs in database. Location: internal/storage/sqlite/sqlite.go:79-82


Agent 3 Batch 12 Issue 1


Base Issue 5


Use -short flag in CI for PR checks

Update CI configuration to use -short flag for PR checks, run full tests nightly.

The slow tests already support testing.Short() and will be skipped.

Expected savings: ~20 seconds for PR checks (fast tests only)

Implementation:
- Update .github/workflows/ci.yml to add -short flag for PR tests
- Create/update nightly workflow for full test runs
- Update README/docs about test strategy

File: .github/workflows/ci.yml:30


Agent 1 Issue 49

Created by agent 1


Agent 5 Issue 96

Created by agent 5


Agent 5 New Issue 25


Agent 2 Issue 0


Agent 6 Issue 31


Agent 5 Issue 56


Agent 6 Issue 78

Created by agent 6


Agent 1 Issue 24


Agent 1 Issue 60

Created by agent 1


Agent 3 Batch 16 Issue 1


Agent 1 Issue 42

Created by agent 1


Agent 7 Issue 73

Created by agent 7


Help agents understand version changes with bd info --whats-new

**Problem** (from GH Discussion #239 by @maphew):
Weekly major versions mean agents need to adapt workflows, but currently there's no efficient way to communicate "what changed that affects you."

**Proposed solutions:**

1. **bd info --whats-new** - Show agent-actionable changes since last version
   ```
   Since v0.20.1:
   • Hash IDs eliminate collisions - remove ID coordination workarounds
   • Event-driven daemon (opt-in) - add BEADS_DAEMON_MODE=events
   • Merge driver auto-configured - conflicts rarer
   ```

2. **Version-aware bd onboard** - Detect version changes and show diff of agent-relevant changes

3. **AGENTS.md top section** - "🆕 Recent Changes (Last 3 Versions)" with workflow impacts

**Why agents need this:**
- Raw CHANGELOG is token-heavy and buried in release details
- Full bd onboard re-run wasteful if only 2-3 things changed
- Currently requires user to manually explain updates

**Related:** https://github.com/steveyegge/beads/discussions/239


Agent 3 Issue 30

Created by agent 3


Agent 6 Issue 56

Created by agent 6


Final validation test


Agent 7 Issue 24

Created by agent 7


Agent 4 Issue 3

Created by agent 4


Update AGENTS.md with event-driven mode

Document BEADS_DAEMON_MODE env var. Explain opt-in during Phase 1. Add troubleshooting for watcher failures.


Agent 3 Issue 79

Created by agent 3


Agent 5 Issue 0


Agent 4 Issue 26


Agent 9 Issue 60


Agent 3 Issue 84

Created by agent 3


Agent 4 Issue 4

Created by agent 4


Agent 0 Batch 46 Issue 2


Vendor beads-merge Go code into internal/merge/

Copy beads-merge source code from @neongreen's repo into bd codebase.

**Tasks**:
- Create `internal/merge/` package
- Copy merge algorithm code
- Add attribution header to all files
- Update imports to use bd's internal types
- Add LICENSE/ATTRIBUTION file crediting @neongreen
- Keep original algorithm intact

**Source**: https://github.com/neongreen/mono/tree/main/beads-merge


Agent 8 Issue 85


Agent 4 Issue 63

Created by agent 4


Agent 6 Issue 43


Add tests for Comments API (AddIssueComment, GetIssueComments)

Comments API currently has 0% coverage. Need tests for:
- AddIssueComment - adding comments to issues
- GetIssueComments - retrieving comments
- Comment ordering and pagination
- Edge cases (non-existent issues, empty comments)


Add 'new' as alias for 'create' command


Agent 6 Issue 87

Created by agent 6


Agent 5 Issue 3


Agent 3 Issue 54


Agent 7 Issue 60


Agent 1 Batch 44 Issue 2


Agent 5 Issue 64

Created by agent 5


Agent 1 Issue 81


Agent 0 Issue 95

Created by agent 0


Agent 4 Issue 50

Created by agent 4


Agent 0 Issue 96


Agent 4 Issue 48

Created by agent 4


Use in-memory filesystem for test git operations

Use tmpfs/ramdisk for git operations in tests to reduce I/O overhead.

Options:
1. Mount /tmp as tmpfs in CI (GitHub Actions supports this)
2. Use Go's testing.TB.TempDir() which may already use tmpfs on some systems
3. Explicitly create ramdisk for tests on macOS

Expected savings: 20-30% reduction in git operation time


Agent 4 Issue 28

Created by agent 4


Agent 4 Issue 50


Agent 4 Issue 27

Created by agent 4


Agent 0 Issue 70

Created by agent 0


CleanupStaleInstances() never called in production - orphaned claims accumulate

The CleanupStaleInstances() method exists in storage layer but is never called in production code. This means dead executors leave orphaned claims that block work forever. Example: vc-106 claimed by executor that died 2 hours ago, still shows in_progress with execution_state record. Need to: 1) Add periodic cleanup to executor main loop (every 5 min?), 2) Make cleanup also release claimed issues (delete execution_state AND reset status to open), 3) Add comment explaining why released.


Agent 0 Issue 34

Created by agent 0


Agent 2 Issue 59

Created by agent 2


Deletions not propagated across multi-workspace sync

## Problem

When working with multiple beads workspaces (clones) sharing the same git remote, deleted issues keep coming back.

## Reproduction

1. Clone A deletes issue `bd-xyz` via `bd delete bd-xyz --force`
2. Clone A daemon syncs and pushes to GitHub
3. Clone B still has `bd-xyz` in its database
4. Clone B daemon exports and pushes its JSONL
5. Clone A pulls and imports → `bd-xyz` comes back!

## Root Cause

**No deletion tracking mechanism.** The system has no way to distinguish between:
- "Issue doesn't exist in JSONL because it was deleted"
- "Issue doesn't exist in JSONL because the export is stale"

Import treats missing issues as "not in this export" rather than "explicitly deleted."

## Solution Options

1. **Tombstone records** - Keep deleted issues in JSONL with `"status":"deleted"` or `"deleted_at"` field
2. **Deletion log** - Separate `.beads/deletions.jsonl` file tracking all deleted IDs
3. **Three-way merge** - Import compares: DB state, old JSONL, new JSONL
4. **Manual conflict resolution** - Detect resurrection and prompt user

## Related

- Similar to resurrection logic for orphaned children (bd-cc4f)
- beads-merge tool handles this better with 3-way merge


Implement "bd daemons logs" subcommand

Add command to view daemon logs for a specific workspace. Requires daemon logging to file (may need separate issue for log infrastructure).


Agent 6 Issue 8

Created by agent 6


Agent 7 Issue 68


Agent 0 Issue 76


Agent 1 Batch 12 Issue 1


Agent 6 Issue 65

Created by agent 6


Daemon crash recovery: panic handler + socket cleanup

Improve daemon cleanup on unexpected exit:
1. Add top-level recover() in runDaemonLoop to capture panics
2. Write daemon-error file with stack trace on panic
3. Prefer return over os.Exit where possible (so defers run)
4. In stopDaemon forced-kill path, also remove stale socket if present

This ensures better diagnostics and cleaner state after crashes.


Add 'bd comments' command to view and manage issue comments

Add support for commenting on issues with a new 'bd comments' command.

Commands:
- bd comments <issue-id>                    # List all comments on an issue
- bd comments add <issue-id> "text"         # Add a comment
- bd comments add <issue-id> -f file.txt    # Add comment from file
- bd comments <issue-id> --json             # JSON output for agents

Use cases:
- Track discussion/decisions on issues
- Add context without cluttering description
- Record why work was paused/resumed
- Multi-person collaboration notes
- Agent can leave progress updates

Implementation:
- Add comments table to schema (id, issue_id, author, text, timestamp)
- Store in JSONL as nested array in issue objects
- Show chronologically with timestamps
- Include in 'bd show' output (collapsed by default?)

Questions:
- Should comments be editable/deletable?
- Include author field (env var or git config)?
- Threading/replies to comments?


Agent 8 Issue 81


Agent 1 Batch 38 Issue 1


Agent 4 New Issue 25


Agent 7 Issue 91


Agent 7 Issue 81


Benchmark Helper Functions

Extend existing benchmark helpers in internal/storage/sqlite/bench_helpers_test.go (or create if organizing separately).

Existing helper (in compact_bench_test.go):
- setupBenchDB(tb) - Creates temp SQLite database with basic config
  * Used by compact and cycle benchmarks
  * Returns (*SQLiteStorage, cleanup func())

New helpers to add:
- setupLargeBenchDB(b *testing.B) storage.Storage
  * Creates 10K issue database using LargeSQLite fixture
  * Returns configured storage instance

- setupXLargeBenchDB(b *testing.B) storage.Storage
  * Creates 20K issue database using XLargeSQLite fixture
  * Returns configured storage instance

Implementation options:
1. Add to existing compact_bench_test.go (co-located with setupBenchDB)
2. Create new bench_helpers_test.go for organization

Both approaches:
- Build tag: //go:build bench
- Uses fixture generator from internal/testutil/fixtures
- Follows existing setupBenchDB() pattern
- Handles database cleanup

These helpers reduce duplication across new benchmark functions and provide consistent large-scale database setup.


Agent 7 Issue 97

Created by agent 7


Agent 4 Issue 96


Agent 3 Batch 13 Issue 1


Agent 0 Issue 75


Agent 5 Issue 93


Agent 3 Batch 33 Issue 2


Agent 1 Batch 45 Issue 2


Agent 7 Issue 1


Agent 2 Issue 68

Created by agent 2


Performance Testing Framework

Add comprehensive performance testing for beads focusing on optimization guidance and validating 10K+ database scale. Uses standard Go tooling, follows existing patterns, minimal complexity.

Components:
- Benchmark suite for critical operations at 10K-20K scale
- Fixture generator for realistic test data (epic hierarchies, cross-links)
- User diagnostics via bd doctor --perf
- Always-on profiling integration

Goals:
- Identify bottlenecks for optimization work
- Validate performance at 10K+ issue scale
- Enable users to collect diagnostics for bug reports
- Support both SQLite and JSONL import paths


Implement bd migrate command

Add bd migrate command to move issues between repos with filtering. Should support: filtering by status/priority/labels, dry-run mode, preserving dependencies, handling source_repo field updates.


Agent 3 Issue 97

Created by agent 3


Publish official devcontainer configuration

Devcontainer configuration implemented. Manual testing required in actual devcontainer environment (Codespaces or VSCode Remote Containers). All code changes complete, tests pass, linting clean.


Agent 7 Issue 42


Add tests for helper functions (GetDirtyIssueHash, GetAllDependencyRecords, export hashes)

Several utility functions have 0% coverage:
- GetDirtyIssueHash (dirty.go)
- GetAllDependencyRecords (dependencies.go)
- GetExportHash, SetExportHash, ClearAllExportHashes (hash.go)

These are lower priority but should have basic coverage.


Benchmark git traffic reduction

Automated benchmark comparing git operations with/without Agent Mail.

Acceptance Criteria:
- Script that processes 50 issues
- Counts git operations (pull, commit, push)
- Generates comparison report
- Verifies ≥70% reduction
- Fails if regression detected

File: tests/benchmarks/git_traffic.py

Output: Without Agent Mail: 450 git operations, With Agent Mail: 135 git operations, Reduction: 70%

Implemented automated benchmark script with following features:
- Processes configurable number of issues (default 50)
- Compares git operations in two modes: git-only vs Agent Mail
- Generates detailed comparison report with statistics
- Exit code reflects pass/fail based on 70% reduction target
- Results: 98.5% reduction (200 ops → 3 ops) for 50 issues

Files created:
- tests/benchmarks/git_traffic.py (main benchmark script)
- tests/benchmarks/README.md (documentation)
- tests/benchmarks/git_traffic_50_issues.md (sample results)

The benchmark vastly exceeds the 70% target, showing 98.5% reduction.


Add migration scripts for GitHub Issues

Create scripts to import from GitHub Issues API or exported JSON


Agent 1 Issue 52


Agent 3 Batch 34 Issue 1


Agent 4 Issue 36

Created by agent 4


Agent 5 Issue 11

Created by agent 5


Add mutation channel to internal/rpc/server.go

Add mutationChan chan MutationEvent to Server struct. Emit events on CreateIssue, UpdateIssue, DeleteIssue, AddComment. Non-blocking send with default case for full channel.


Agent 2 Issue 72


Agent 6 Issue 49

Created by agent 6


Add Claude setup tip with dynamic priority

Add a predefined tip that suggests running `bd setup claude` when Claude Code is detected but not configured. This tip should have higher priority (shown more frequently) until the setup is complete.


Agent 2 Batch 19 Issue 1


Agent 2 Issue 66


Agent 0 Batch 44 Issue 1


Fix multi-round convergence for N-way collisions

## Problem

N-way collision resolution is working (IDs get remapped correctly), but clones don't fully converge after a single final pull. Each clone is missing some issues that other clones have.

From TestFiveCloneCollision results:
- Clone A has: A, B
- Clone B has: A, B
- Clone C has: A, B, C
- Clone D has: A, B, C, D
- Clone E has: A, B, C, E

**Expected**: All clones should have A, B, C, D, E after final pull.

## Root Cause

The current sync workflow does:
1. Each clone syncs in order (resolving collisions locally)
2. Final pull to get all changes

But the final pull itself may need import with collision resolution, which creates new commits. These new commits aren't propagated to other clones, so they remain incomplete.

## Proposed Solution

**Option 1: Multi-round final sync**
- After final pull, do additional sync rounds until all clones converge
- Check convergence by comparing issue counts or content hashes
- Maximum N rounds for N clones

**Option 2: Iterative pull-import-push**
- Each clone: pull → import with --resolve-collisions → push
- Repeat until no new changes
- Guaranteed convergence but may create commit spam

**Option 3: Fix auto-import to be truly idempotent**
- Ensure importing same JSONL multiple times produces no new commits
- May require smarter content-based deduplication

## Acceptance Criteria

- TestFiveCloneCollision passes without t.Skip
- All N clones have all N issues after convergence
- Convergence happens in bounded rounds (≤ N)
- No data loss or duplication
- Works for arbitrary N (tested with 5, 10 clones)

## Impact

This is the final blocker for bd-cbed9619 epic completion.


Agent 5 Issue 38

Created by agent 5


Agent 2 Issue 24

Created by agent 2


Agent 6 Issue 62


Agent 7 Issue 8


Agent 3 Batch 10 Issue 2


Agent 2 Issue 60


Agent 0 Batch 25 Issue 2


Agent 6 Issue 72

Created by agent 6


Agent 1 Issue 76


Create npm package structure for bd-wasm

Set up npm package for distribution:
- Create package.json with bd-wasm name
- Bundle bd.wasm + wasm_exec.js
- Create CLI wrapper (bin/bd) that invokes WASM
- Add installation scripts if needed
- Configure package for Claude Code Web sandbox compatibility


Agent 2 Batch 28 Issue 1


Agent 7 Issue 30


Agent 8 Issue 61


Agent 0 Issue 43


Agent 4 Issue 2

Created by agent 4


Agent 2 Batch 9 Issue 2


Agent 0 Issue 69


Agent 2 Batch 44 Issue 1


Agent 2 Issue 29

Created by agent 2


Agent 6 Issue 36


Agent 0 Issue 1


Agent 0 Batch 10 Issue 1


Add comprehensive tests for show.go commands (show, update, edit, close)

Need to add tests for cmd/bd/show.go which contains show, update, edit, and close commands.

**Challenge**: The existing test patterns use rootCmd.SetArgs() and rootCmd.Execute(), but the global `store` variable needs to match what the commands use. Initial attempt created tests that failed with "no issue found" because the test's store instance wasn't the same as the command's store.

**Files to test**:
- show.go (contains showCmd, updateCmd, editCmd, closeCmd)

**Coverage needed**:
- show command (single issue, multiple issues, JSON output, with dependencies, with labels, with compaction)
- update command (status, priority, title, assignee, description, multiple fields, multiple issues)
- edit command (requires $EDITOR, may need mocking)
- close command (single issue, multiple issues, with reason, JSON output)

**Test approach**:
1. Study working test patterns in init_test.go, list_test.go, etc.
2. Ensure BEADS_NO_DAEMON=1 is set
3. Properly initialize database with bd init
4. Use the command's global store, not a separate instance
5. May need to reset global state between tests

**Success criteria**:
- All test functions pass
- Coverage for show.go increases significantly
- Tests follow existing patterns in cmd/bd/*_test.go


Agent 5 Issue 95


Latency test 1


Add 'bd comment' as alias for 'bd comments add'

The command 'bd comments add' is verbose and unintuitive. Add 'bd comment' as a shorter alias that works the same way.

## Rationale
- More natural: 'bd comment <issue-id> <text>' reads better than 'bd comments add <issue-id> <text>'
- Matches user expectations: users naturally try 'bd comment' first
- Follows convention: other commands like 'bd create', 'bd show', 'bd close' are verbs

## Implementation
Could be implemented as:
1. A new command that wraps bd comments add
2. An alias registered in cobra
3. Keep 'bd comments add' for backwards compatibility

## Examples
```bash
bd comment bd-1234 'This is a comment'
bd comment bd-1234 'Multi-line comment' --body 'Additional details here'
```


Agent 3 New Issue 30


Agent 7 Issue 76

Created by agent 7


Agent 6 Issue 90

Created by agent 6


Agent 4 Issue 40


Write plugin documentation

Create comprehensive documentation for the plugin.

Contents:
- Installation instructions
- Available commands
- MCP tools reference
- Configuration options
- Examples and workflows
- Troubleshooting guide


Agent 1 Issue 30

Created by agent 1


Agent 1 Batch 49 Issue 1


Consider implementing pre-commit hooks for Storage interface changes

The documentation (INTERFACE_CHANGES.md) suggests adding pre-commit hooks that automatically check for Storage interface changes and verify all mocks are updated. This would prevent similar issues in the future where interface changes break mock implementations.

Discovered during execution of vc-228 (dogfooding run #14/15).


Agent 7 Issue 93

Created by agent 7


Debug MCP Agent Mail tool execution errors

**EXTERNAL WORK**: Debug the standalone MCP Agent Mail server (separate from beads integration).

The Agent Mail server runs as an independent service at ~/src/mcp_agent_mail. This is NOT beads code - it's a separate GitHub project we're evaluating for optional coordination features.

Current Issue:
- MCP API endpoint returns errors when calling ensure_project tool
- Error: "Server encountered an unexpected error while executing tool"
- Core HTTP server works, web UI functional, but tool wrapper layer fails

Server Details:
- Location: ~/src/mcp_agent_mail (separate repo)
- Repository: https://github.com/Dicklesworthstone/mcp_agent_mail
- Runs on: http://127.0.0.1:8765
- Bearer token: In .env file

Investigation Steps:
1. Check tool execution logs for full stack trace
2. Verify Git storage initialization at ~/.mcp_agent_mail_git_mailbox_repo
3. Review database setup (storage.sqlite3)
4. Test with simpler MCP tools if available
5. Compare with working test cases in tests/

Why This Matters:
- Blocks [deleted:bd-6hji] (testing file reservations)
- Need working MCP API to validate Agent Mail benefits
- Proof of concept for lightweight beads integration later

Note: The actual beads integration (bd-wfmw) will be lightweight HTTP client code only.


Agent 9 Issue 96


Agent 8 Issue 14


Add tests for daemon vs non-daemon parity in list filters

After bd-o43 RPC integration, we need tests to verify daemon mode behaves identically to direct mode for all new filter flags.

Test coverage needed:
- Pattern matching: --title-contains, --desc-contains, --notes-contains
- Date ranges: all 6 date filter flags (created/updated/closed after/before)
- Empty/null checks: --empty-description, --no-assignee, --no-labels
- Priority ranges: --priority-min, --priority-max
- Status normalization: --status all vs no status flag
- Date parsing: YYYY-MM-DD, RFC3339, and error cases
- Backward compat: deprecated --label flag still works

Oracle review findings (bd-o43):
- Date parsing should support multiple formats
- Status 'all' should be treated as unset
- NoLabels field was missing from RPC protocol
- Error messages should be clear and actionable

Test approach:
- Create RPC integration tests in internal/rpc/server_issues_epics_test.go
- Compare daemon client.List() vs direct store.SearchIssues() for same filters
- Verify error messages match between modes
- Test with real daemon instance, not just unit tests


Agent 5 Issue 53

Created by agent 5


Add richer query capabilities to bd list

Current bd list filters are limited to basic field matching (status, priority, type, assignee, label). This forces users to resort to piping through jq for common queries.

Missing query capabilities:
- Pattern matching: --title-contains, --desc-contains
- Date ranges: --created-after, --updated-before, --closed-after
- Empty/null checks: --empty-description, --no-assignee, --no-labels
- Numeric ranges: --priority-min, --priority-max
- Complex boolean logic: --and, --or operators
- Full-text search: --search across all text fields
- Negation: --not-status, --exclude-label

Example use cases:
- Find issues with empty descriptions
- Find stale issues not updated in 30 days
- Find high-priority bugs with no assignee
- Search for keyword across title/description/notes

Implementation approach:
- Add query builder pattern to storage layer
- Support --query DSL for complex queries
- Keep simple flags for common cases
- Add --json output for programmatic use

## Progress Update

**Completed:**
- ✅ Extended IssueFilter struct with new fields (pattern matching, date ranges, empty/null checks, priority ranges)
- ✅ Updated SQLite SearchIssues implementation
- ✅ Added CLI flags to list.go
- ✅ Added parseTimeFlag helper
- ✅ Comprehensive tests added - all passing

**Remaining:**
- ⚠ RPC layer needs updating (internal/rpc/protocol.go ListArgs)
- ⚠ Daemon handler needs to forward new filters
- ⚠ End-to-end testing with daemon mode
- 📝 Documentation updates

**Files Modified:**
- internal/types/types.go
- internal/storage/sqlite/sqlite.go
- cmd/bd/list.go
- cmd/bd/list_test.go

**Next Steps:**
1. Update RPC protocol
2. Update daemon handler
3. Test with daemon mode
4. Update docs


Agent 8 Issue 91


Agent 1 Issue 88

Created by agent 1


Agent 7 Issue 31


Agent 3 Issue 8

Created by agent 3


releaseIssueWithError() deletes execution_state but leaves status as in_progress

When an executor hits an error and releases an issue via releaseIssueWithError(), it deletes the execution_state but leaves the issue status as in_progress. This means the issue drops out of ready work but has no active executor. Expected: releasing should reset status to open so the issue becomes available again. Current code in conversation.go just calls ReleaseIssue() which only deletes execution_state.


Agent 0 Issue 15

Created by agent 0


Agent 4 Issue 64

Created by agent 4


Agent 6 Issue 57

Created by agent 6


Agent 1 Issue 22

Created by agent 1


Agent 0 Issue 96

Created by agent 0


Handle unchecked errors (errcheck - 683 issues)

683 unchecked error returns, mostly in tests (Close, Rollback, RemoveAll). Many already excluded in config but still showing up.

Fixed all errcheck warnings in production code:
- Enabled errcheck linter (was disabled)
- Set tests: false in .golangci.yml to focus on production code
- Fixed 27 total errors in production code using Oracle guidance:
  * Database patterns: defer func() { _ = rows.Close() }() and defer func() { _ = tx.Rollback() }()
  * Best-effort closers: _ = store.Close(), _ = client.Close()
  * Proper error handling for file writes, fmt.Scanln(), os.Remove()
- All tests pass
- Only 2 "unused" linter warnings remain (not errcheck)


Agent 1 New Issue 20


Agent 8 Issue 15


Agent 6 Issue 10

Created by agent 6


Agent 1 Issue 83

Created by agent 1


Agent 2 Batch 17 Issue 1


Agent 3 Issue 20


Agent 6 Issue 24


Agent 2 Issue 11


Agent 1 Issue 23

Created by agent 1


Remove Cache Configuration Docs

Remove documentation of deprecated cache env vars


Agent 7 Issue 22


Agent 0 Issue 67


Agent 1 Issue 37


bd validate - Comprehensive health check

Run all validation checks in one command.

Checks:
- Duplicates
- Orphaned dependencies
- Test pollution
- Git conflicts

Supports --fix-all for auto-repair.

Depends on bd-cbed9619.1, bd-0dcea000, bd-31aab707, bd-9826b69a.

Files: cmd/bd/validate.go (new)


Agent 1 Batch 7 Issue 2


Agent 0 Issue 36

Created by agent 0


Agent 5 Issue 43

Created by agent 5


Agent 4 Issue 28


Agent 4 Issue 37


Agent 2 Batch 23 Issue 2


Agent 1 Issue 86


Agent 1 Issue 9


Agent 7 Issue 80


Agent 4 Issue 0


Agent 2 Batch 30 Issue 2


Agent 5 Issue 97


Version test issue


Agent 4 Issue 63


Agent 3 Issue 46

Created by agent 3


bd find-duplicates - AI-powered duplicate detection

Find semantically duplicate issues.

Approaches:
1. Mechanical: Exact title/description matching
2. Embeddings: Cosine similarity (cheap, scalable)
3. AI: LLM-based semantic comparison (expensive, accurate)

Uses embeddings by default for >100 issues.

Files: cmd/bd/find_duplicates.go (new)


Improve integration test coverage for stateful features


Agent 5 Issue 45


Agent 9 Issue 87


Agent 3 Issue 69

Created by agent 3


Agent 9 Issue 25


Agent 8 Issue 37


Agent 2 Batch 35 Issue 1


Agent 1 Issue 41


Clean up MCP integration for daemon reliability

Ensure MCP server properly handles daemon lifecycle, connection failures, and recovery scenarios.


Agent 4 Issue 78

Created by agent 4


Agent 6 Issue 19


Agent 1 Batch 36 Issue 1


Agent 0 Batch 18 Issue 2


Agent 0 Batch 11 Issue 1


Agent 2 Issue 7


Optimize test suite performance - cut runtime by 50%+

## Problem
Test suite takes ~20.8 seconds, with 95% of time spent in just 2 tests:
- TestHashIDs_MultiCloneConverge: 11.08s (53%)
- TestHashIDs_IdenticalContentDedup: 8.78s (42%)

Both tests in beads_hash_multiclone_test.go perform extensive Git operations (bare repos, multiple clones, sync rounds).

## Goal
Cut total test time by at least 50% (to ~10 seconds or less).

## Analysis
Tests already have some optimizations:
- --shared --depth=1 --no-tags for fast cloning
- Disabled hooks, gc, fsync
- Support -short flag

## Impact
- Faster development feedback loop
- Reduced CI costs and time
- Better developer experience


Agent 0 Issue 12

Created by agent 0


Add composite index on dependencies(depends_on_id, type)

The hierarchical blocking query does:
JOIN dependencies d ON d.depends_on_id = bt.issue_id
WHERE d.type = 'parent-child'

Currently we only have idx_dependencies_depends_on (line 41 in schema.go), which covers depends_on_id but not the type filter.

**Impact:**
- Query has to scan ALL dependencies for a given depends_on_id, then filter by type
- With 10k+ issues and many dependencies, this could cause slowdowns
- The blocker propagation happens recursively, amplifying the cost

**Solution:**
Add composite index: CREATE INDEX idx_dependencies_depends_on_type ON dependencies(depends_on_id, type)

**Testing:**
Run EXPLAIN QUERY PLAN on GetReadyWork query before/after to verify index usage.


Agent 3 Issue 18


Agent 2 Issue 23


Agent 2 Batch 12 Issue 2


Agent 3 Issue 60

Created by agent 3


Agent 6 Issue 59

Created by agent 6


bd-hv01: Non-atomic snapshot operations can cause data loss

## Problem
In sync.go:146-155 and daemon_sync.go:502-505, snapshot capture failures are logged as warnings but sync continues:

```go
if err := exportToJSONL(ctx, jsonlPath); err != nil { ... }
if err := captureLeftSnapshot(jsonlPath); err != nil {
    fmt.Fprintf(os.Stderr, "Warning: failed to capture snapshot...")
}
```

If export succeeds but snapshot capture fails, the merge uses stale snapshot data, potentially deleting wrong issues.

## Impact
- Critical data integrity issue
- Could delete issues incorrectly during multi-workspace sync

## Fix
Make snapshot capture mandatory:
```go
if err := captureLeftSnapshot(jsonlPath); err != nil {
    return fmt.Errorf("failed to capture snapshot (required for deletion tracking): %w", err)
}
```

## Files Affected
- cmd/bd/sync.go:146-155
- cmd/bd/daemon_sync.go:502-505


Agent 3 Batch 33 Issue 1


Agent 2 Issue 79


Agent 8 Issue 16


Agent 7 Issue 95


Agent 6 Issue 34


Agent 9 Issue 83


Agent 3 Issue 7


bd doctor should check for multiple DBs, multiple JSONLs, daemon health


Agent 9 Issue 15


Optimize CLI test suite - eliminate redundant git init calls

Current: Each of 13 CLI tests calls git init (31s total). Solution: Use single test binary built once in init(), skip git operations where possible, or use mock filesystem.


Add batch deletion command for issues

Support deleting multiple issues efficiently instead of one at a time.

**Use Cases:**
- Cleaning up duplicate/spam issues (e.g., bd-83 to bd-93 watchdog spam)
- Removing test-only issues after feature removal
- Bulk cleanup of obsolete/spurious bugs
- Renumbering prep: delete ranges before compaction

**Proposed Syntax Options:**

**Option 1: Multiple IDs as arguments**
```bash
bd delete vc-1 vc-2 vc-3 --force
bd delete vc-{1..20} --force  # Shell expansion
```

**Option 2: Read from file (RECOMMENDED)**
```bash
bd delete --from-file deletions.txt --force --dry-run  # Preview
bd delete --from-file deletions.txt --force            # Execute
# File format: one issue ID per line
```

**Option 3: Query-based deletion**
```bash
bd delete --where "priority=3 AND type=chore" --force
bd delete --label test-only --force
bd delete --prefix bd- --status open --force
```

**Must-Have Features:**

1. **Dry-run mode**: `--dry-run` to preview what would be deleted
   - Show issue IDs, titles, dependency counts
   - Warn about issues with dependents

2. **Dependency handling**:
   - `--cascade`: Delete dependents recursively
   - `--force`: Delete even if dependents exist (orphans them)
   - Default: Fail if any issue has dependents

3. **Summary output**:
   ```
   Deleted 162 issues
   Removed 347 dependencies
   Removed 89 labels
   Orphaned 5 issues (use --cascade to delete)
   ```

4. **Transaction safety**: All-or-nothing for file/query input
   - Either all deletions succeed or none do
   - Rollback on error

**Nice-to-Have Features:**

1. **Interactive confirmation** for large batches (>10 issues)
   ```
   About to delete 162 issues. Continue? [y/N]
   (Use --force to skip confirmation)
   ```

2. **Progress indicator** for large batches (>50 deletions)
   ```
   Deleting issues... [####------] 42/162 (26%)
   ```

3. **Undo support**:
   ```bash
   bd undelete --last-batch  # Restore from snapshots
   bd undelete bd-83        # Restore single issue
   ```

**Implementation Notes:**

- Leverage existing `DeleteIssue()` in storage layer
- Wrap in transaction for atomicity
- Consider adding `DeleteIssues(ctx, []string)` for efficiency
- May need to query dependents before deletion
- File format should support comments (#) and blank lines
- JSON output mode should list all deleted IDs

**Example Workflow:**
```bash
# Identify issues to delete
bd list --label test-only --json | jq -r '.[].id' > /tmp/delete.txt

# Preview deletion
bd delete --from-file /tmp/delete.txt --dry-run

# Execute with cascade
bd delete --from-file /tmp/delete.txt --cascade --force

# Verify
bd stats
```

**Security Considerations:**
- Require explicit `--force` flag to prevent accidents
- Warn when deleting issues with dependencies
- Log deletions to audit trail
- Consider requiring confirmation for >100 deletions even with --force

**Requested by:** Another agent during cleanup of bd-83 to bd-93 watchdog spam

Fixed critical issues found in code review:
1. Dry-run mode now properly uses dryRun parameter instead of deleting data
2. Text references are pre-collected before deletion so they update correctly
3. Added orphan deduplication to prevent duplicate IDs
4. Added rows.Err() checks in all row iteration loops
5. Updated defer to ignore rollback error per Go best practices


Agent 3 Batch 5 Issue 1


Migration and onboarding for multi-repo

Create migration tools, wizards, and documentation to help users adopt multi-repo workflow, with special focus on OSS contributor onboarding and team adoption scenarios.


Agent 1 Issue 31


Agent 7 Issue 73


Agent 3 Issue 44

Created by agent 3


Agent 7 Issue 69


Agent 7 Issue 88


Document Claude Code for Web SessionStart hook

Create documentation for using bd in Claude Code for Web:

## Documentation locations
- README.md - Add Claude Code for Web section
- Create docs/CLAUDE_CODE_WEB.md with detailed instructions

## SessionStart hook example
```json
{
  "sessionStart": {
    "script": "npm install -g @beads/bd && bd init --quiet --prefix bd || true"
  }
}
```

## Documentation should cover
- How to configure SessionStart hook in .claude/settings.json
- Verification: Check bd is installed (bd --version)
- Basic workflow in Claude Code for Web
- Troubleshooting common issues
- Note about network restrictions and why npm approach works

## Examples
- Creating issues in web sandbox
- Syncing with git in web environment
- Using MCP server (if applicable)


Agent 1 Issue 76

Created by agent 1


Agent 4 Issue 5


Multi-clone collision resolution testing and documentation

Epic to track improvements to multi-clone collision resolution based on ultrathinking analysis of-3d844c58 and [deleted:bd-71107098].

Current state:
- 2-clone collision resolution is SOUND and working correctly
- Hash-based deterministic collision resolution works
- Test fails due to timestamp comparison, not actual logic issues

Work needed:
1. Fix TestTwoCloneCollision to compare content not timestamps
2. Add TestThreeCloneCollision for regression protection
3. Document 3-clone ID non-determinism as known behavior


Agent 5 Issue 61

Created by agent 5


Agent 7 Issue 17

Created by agent 7


DetectCycles SQL query has bug preventing cycle detection

The DetectCycles function's SQL query has a bug in the LIKE filter that prevents it from detecting cycles.

Current code (line 571):
```sql
AND p.path NOT LIKE '%' || d.depends_on_id || '→%'
```

This prevents ANY revisit to nodes, including returning to the start node to complete a cycle.

Fix:
```sql
AND (d.depends_on_id = p.start_id OR p.path NOT LIKE '%' || d.depends_on_id || '→%')
```

This allows revisiting the start node (to detect the cycle) while still preventing intermediate node revisits.

Impact: Currently DetectCycles cannot detect any cycles, but this hasn't been noticed because AddDependency prevents cycles from being created. The function would only matter if cycles were manually inserted into the database.


Agent 0 Issue 8


Agent 1 Issue 93

Created by agent 1


Updated by agent 5


Agent 5 Issue 58

Created by agent 5


Agent 4 New Issue 10


Agent 4 Issue 20


Agent 0 Issue 79


Agent 7 Issue 59

Created by agent 7


Agent 5 Issue 15

Created by agent 5


Agent 1 Issue 29


Add Agent Mail to QUICKSTART.md

Mention Agent Mail as optional advanced feature in quickstart guide.

File: docs/QUICKSTART.md


Agent 6 Issue 18

Created by agent 6


Agent 9 Issue 88


Agent 1 Batch 45 Issue 1


Remove unreachable utility functions

Several small utility functions are unreachable:

Files to clean:
1. `internal/storage/sqlite/hash.go` - `computeIssueContentHash` (line 17)
   - Check if entire file can be deleted if only contains this function

2. `internal/config/config.go` - `FileUsed` (line 151)
   - Delete unused config helper

3. `cmd/bd/git_sync_test.go` - `verifyIssueOpen` (line 300)
   - Delete dead test helper

4. `internal/compact/haiku.go` - `HaikuClient.SummarizeTier2` (line 81)
   - Tier 2 summarization not implemented
   - Options: implement feature OR delete method

Impact: Removes 50-100 LOC depending on decisions


Agent 0 Issue 64

Created by agent 0


Extract daemon config functions to daemon_config.go


Agent 0 Issue 55


Agent 0 Issue 64


Agent 3 Issue 26

Created by agent 3


Update daemon commit logic for separate branch

Modify daemon to use worktree for commits when sync.branch configured.

Tasks:
- Update internal/daemon/server_export_import_auto.go
- Detect sync.branch configuration
- Ensure worktree exists before commit
- Sync JSONL to worktree
- Commit in worktree context
- Push to configured branch
- Fallback to current behavior if sync.branch not set
- Handle git errors (network, permissions, conflicts)

Estimated effort: 3-4 days


Clarify exclusive lock protocol compatibility with multi-repo

The contributor-workflow-analysis.md proposes per-repo file locking (Decision #7) using flock on JSONL files. However, VC (a downstream library consumer) uses an exclusive lock protocol (vc-195, requires Beads v0.17.3+) that allows bd daemon and VC executor to coexist.

Need to clarify:
- Does the proposed per-repo file locking work with VC's existing exclusive lock protocol?
- Do library consumers like VC need to adapt their locking logic?
- Can multiple repos be locked atomically for cross-repo operations?

Context: contributor-workflow-analysis.md lines 662-681


Agent 2 Issue 80

Created by agent 2


Agent 6 Issue 57


Add version compatibility checks for daemon RPC protocol

Client (bd CLI) and daemon may be different versions after upgrade. This causes:
- Missing features (newer CLI, older daemon)
- Protocol mismatches (older CLI, newer daemon)
- Silent failures or confusing errors
- No guidance to restart daemon

Location: internal/rpc/protocol.go, internal/rpc/client.go


Add daemon health check endpoint and probes

Auto-start only checks socket existence, not daemon responsiveness. Daemon can be running but unresponsive (deadlock, hung DB). Users work in degraded direct mode without knowing why.

Need health check RPC operation that:
- Tests DB connectivity (1s timeout)
- Returns uptime, status, metrics
- Used by auto-start before connecting
- Enables monitoring/alerting

Location: internal/rpc/server.go, cmd/bd/main.go:100-108


Agent 6 Issue 52

Created by agent 6


Agent 6 Issue 88

Created by agent 6


Agent 0 Issue 42

Created by agent 0


Agent 0 Issue 3


Implement content-hash based collision resolution for deterministic convergence

The current collision resolution uses creation timestamps to decide which issue to keep vs. remap. This is non-deterministic when two clones create issues at nearly the same time.

Root cause of bd-71107098:
- Clone A creates test-1="Issue from clone A" at T0
- Clone B creates test-1="Issue from clone B" at T0+30ms
- Clone B syncs first, remaps Clone A's to test-2
- Clone A syncs second, sees collision, remaps Clone B's to test-2
- Result: titles are swapped between clones

Solution:
- Use content-based hashing (title + description + priority + type)
- Deterministic winner: always keep issue with lower hash
- Same collision on different clones produces same result (idempotent)

Implementation:
- Modify ScoreCollisions in internal/storage/sqlite/collision.go
- Replace timestamp-based scoring with content hash comparison
- Ensure hash function is stable across platforms

Rename detection successfully implemented and tested!

**What was implemented:**
1. Content-hash based rename detection in DetectCollisions
2. When importing JSONL, if an issue has different ID but same content as DB issue, treat as rename
3. Delete old ID and accept new ID from JSONL
4. Added post-import re-export in sync command to flush rename changes
5. Added post-import commit to capture rename changes

**Test results:**
TestTwoCloneCollision now shows full convergence:
- Clone A: test-2="Issue from clone A", test-1="Issue from clone B"
- Clone B: test-1="Issue from clone B", test-2="Issue from clone A"

Both clones have **identical content** (titles match IDs correctly). Only timestamps differ (expected).

**What remains:**
- Test still expects exact JSON match including timestamps
- Could normalize timestamp comparison, but content convergence is the critical success metric
- The two-clone collision workflow now works without data corruption!


Agent 4 Issue 74

Created by agent 4


Agent 0 Issue 16


Agent 9 Issue 18


Agent 2 Issue 35

Created by agent 2


Agent 6 Issue 21


Implement git worktree management

Create git worktree lifecycle management for separate beads branch.

Tasks:
- Create internal/git/worktree.go
- Implement CreateBeadsWorktree(branch, path)
- Implement RemoveBeadsWorktree(path)
- Implement CheckWorktreeHealth(path)
- Configure sparse checkout (only .beads/)
- Implement SyncJSONLToWorktree()
- Handle worktree errors gracefully
- Auto-cleanup on config change

Estimated effort: 3-4 days


Agent 2 Issue 62

Created by agent 2


Agent 0 Batch 36 Issue 1


Agent 6 Issue 27


Test Issue


Agent 5 Issue 88


Agent 0 Issue 80


Test issue 1


Agent 4 Issue 31


Agent 0 Issue 81

Created by agent 0


Override test

## Overview

[Describe the high-level goal and scope of this epic]

## Success Criteria

- [ ] Criteria 1
- [ ] Criteria 2
- [ ] Criteria 3

## Background

[Provide context and motivation]

## Scope

**In Scope:**
- Item 1
- Item 2

**Out of Scope:**
- Item 1
- Item 2


Agent 2 Issue 59


Test parent issue


Agent 1 Issue 79


Agent 8 Issue 57


Agent 1 Issue 53


Agent 8 Issue 40


Improve session management

Current session management is basic. Need to improve with better expiration handling.


BG's issue to reopen


Agent 5 Issue 71

Created by agent 5


Agent 1 New Issue 0


Implement clone-scoped ID allocation to prevent N-way collisions

## Problem
Current ID allocation uses per-clone atomic counters (issue_counters table) that sync based on local database state. In N-way collision scenarios:
- Clone B sees {test-1} locally, allocates test-2
- Clone D sees {test-1, test-2, test-3} locally, allocates test-4
- When same content gets assigned test-2 and test-4, convergence fails

Root cause: Each clone independently allocates IDs without global coordination, leading to overlapping assignments for the same content.

## Solution
Add clone UUID to ID allocation to make every ID globally unique:

**Current format:** `test-1`, `test-2`, `test-3`
**New format:** `test-1-a7b3`, `test-2-a7b3`, `test-3-c4d9`

Where suffix is first 4 chars of clone UUID.

## Implementation

### 1. Add clone_identity table
```sql
CREATE TABLE clone_identity (
    clone_uuid TEXT PRIMARY KEY,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
```

### 2. Modify getNextIDForPrefix()
```go
func (s *SQLiteStorage) getNextIDForPrefix(ctx context.Context, prefix string) (string, error) {
    cloneUUID := s.getOrCreateCloneUUID(ctx)
    shortUUID := cloneUUID[:4]

    nextNum := s.getNextCounterForPrefix(ctx, prefix)
    return fmt.Sprintf("%s-%d-%s", prefix, nextNum, shortUUID), nil
}
```

### 3. Update ID parsing logic
All places that parse IDs (utils.ExtractIssueNumber, etc.) need to handle new format.

### 4. Migration strategy
- Existing IDs remain unchanged (no suffix)
- New IDs get clone suffix automatically
- Display layer can hide suffix in UI: `bd-cb64c226.3-a7b3` → `#42`

## Benefits
- **Zero collision risk**: Same content in different clones gets different IDs
- **Maintains readability**: Still sequential numbering within clone
- **No coordination needed**: Works offline, no central authority
- **Scales to 100+ clones**: 4-char hex = 65,536 unique clones

## Concerns
- ID format change may break existing integrations
- Need migration path for existing databases
- Display logic needs update to hide/show suffixes appropriately

## Success Criteria
- 10+ clone collision test passes without failures
- Existing issues continue to work (backward compatibility)
- Documentation updated with new ID format
- Migration guide for v1.x → v2.x

## Timeline
Medium-term (v1.1-v1.2), 2-3 weeks implementation

## References
- Related to bd-e6d71828 (immediate fix)
- See beads_nway_test.go for failing N-way tests


Testing event-driven mode!


Agent 2 Issue 6


Agent 0 Batch 43 Issue 1


Agent 1 Issue 85


Agent 2 Issue 38

Created by agent 2


Create cmd/bd/daemon_debouncer.go (~60 LOC)

Implement Debouncer to batch rapid events into single action. Default 500ms, configurable via BEADS_DEBOUNCE_MS. Thread-safe with mutex.


Agent 3 Batch 8 Issue 2


Agent 5 Issue 48

Created by agent 5


Agent 2 Batch 45 Issue 1


Agent 6 Issue 28


Document protected branch workflow

Create comprehensive documentation for protected branch workflow.

Tasks:
- Add "Protected Branch Workflow" section to AGENTS.md
- Create docs/PROTECTED_BRANCHES.md guide
- Update README.md quick start
- Add examples to examples/protected-branch/
- Update bd init --help documentation
- Add troubleshooting guide
- Add migration guide for existing users
- Record demo video (optional)

Estimated effort: 2-3 days

Completed protected branch workflow documentation. Created comprehensive guide (docs/PROTECTED_BRANCHES.md), updated AGENTS.md with workflow section, added feature to README.md, and created working example (examples/protected-branch/). All commands verified working (bd init --branch, bd sync --status, bd sync --merge, bd config get/set sync.branch).


Critical bug


Fix mypy errors in beads-mcp

Running `mypy .` in `integrations/beads-mcp` reports 287 errors. These should be addressed to improve type safety and code quality.


Agent 1 Issue 36

Created by agent 1


Agent 5 Issue 14


Agent 3 Batch 37 Issue 1


Agent 0 Issue 69

Created by agent 0


Agent 2 Batch 46 Issue 2


Agent 2 Issue 54

Created by agent 2


Agent 0 Issue 61

Created by agent 0


Agent 0 Issue 13


Feature with design

This is a description


Agent 5 Issue 85


Agent 1 Issue 18

Created by agent 1


Agent 7 Issue 45


Test issue with explicit ID


Agent 8 Issue 24


Agent 1 Issue 34

Created by agent 1


Hash-based IDs with aliasing system

Replace sequential auto-increment IDs (bd-1c63eb84, bd-9063acda) with content-hash based IDs (bd-af78e9a2) plus human-friendly aliases (#1, #2).

## Motivation
Current sequential IDs cause collision problems when multiple clones work offline:
- Non-deterministic convergence in N-way scenarios (bd-cbed9619.1, bd-e6d71828)
- Complex collision resolution logic (~2,100 LOC)
- UNIQUE constraint violations during import
- Requires coordination between workers

Hash-based IDs eliminate collisions entirely while aliases preserve human readability.

## Benefits
- ✅ Collision-free distributed ID generation
- ✅ Eliminates ~2,100 LOC of collision handling code
- ✅ Better git merge behavior (different IDs = different JSONL lines)
- ✅ True offline-first workflows
- ✅ Simpler auto-import (no remapping needed)
- ✅ Enables parallel CI/CD workers without coordination

## Design
- Canonical ID: bd-af78e9a2 (8-char SHA256 prefix of title+desc+timestamp+creator)
- Alias: #42 (auto-increment per workspace, mutable, display-only)
- CLI accepts both: bd show bd-af78e9a2 OR bd show #42
- JSONL stores hash IDs only (aliases reconstructed on import)
- Alias conflicts resolved via content-hash ordering (deterministic)

## Breaking Change
This is a v2.0 feature requiring migration. Provide bd migrate --hash-ids tool.

## Timeline
~9 weeks (Phase 1: Hash IDs 4w, Phase 2: Aliases 3w, Phase 3: Testing 2w)

## Dependencies
Should complete after bd-7c5915ae (cleanup validation) and before bd-710a4916 (CRDT).


Agent 1 Issue 35

Created by agent 1


Agent 2 Issue 25

Created by agent 2


Agent 4 Issue 52

Created by agent 4


Agent 1 Issue 25

Created by agent 1


Agent 6 Issue 38

Created by agent 6


Agent 2 Issue 52

Created by agent 2


Add label display to bd show and bd list output

Include labels in issue display:
- bd show <issue> should show labels
- bd list should show labels (compact format)
- JSON output should include labels array

Currently labels exist in DB but aren't shown in CLI output.


Agent 4 Issue 71

Created by agent 4


Agent 4 Issue 51

Created by agent 4


Fix SQL timestamp scanning error on macOS (GH-88)

User reported 'Scan error on column index 11, name created_at: unsupported Scan, storing driver.Value type string into type *time.Time' on macOS 13.5.

Root cause: modernc.org/sqlite driver doesn't recognize mattn-style DSN parameters like _journal_mode=WAL and _foreign_keys=ON. When these are present, it ignores _time_format=sqlite on some platforms, causing DATETIME columns to be returned as strings instead of time.Time.

Fix: Use modernc's native _pragma syntax for all options:
- Changed _journal_mode=WAL to _pragma=journal_mode(WAL)
- Changed _foreign_keys=ON to _pragma=foreign_keys(ON)

This ensures _time_format=sqlite is properly recognized and DATETIME columns are automatically parsed to time.Time.


Agent 2 Issue 94

Created by agent 2


Agent 3 Issue 82


Agent 3 Batch 26 Issue 1


Agent 6 Issue 26


Agent 3 Batch 39 Issue 1


Agent 2 Issue 28

Created by agent 2


Agent 9 Issue 68


Agent 3 Issue 73

Created by agent 3


Agent 6 Issue 68


Agent 6 Issue 25


Agent 1 Issue 96

Created by agent 1


Agent 2 Issue 31


Agent 1 Issue 68


Create architecture decision record (ADR)

Document why we chose Agent Mail, alternatives considered, and tradeoffs.

Acceptance Criteria:
- Problem statement (git traffic, no locks)
- Alternatives considered (custom RPC, Redis, etc.)
- Why Agent Mail fits Beads
- Integration principles (optional, graceful degradation)
- Future considerations

File: docs/adr/002-agent-mail-integration.md


Invert control for compact: provide tools for agent-driven compaction

Currently compact requires Anthropic API key because bd calls the AI directly. This is backwards - we should provide tools (like all other bd commands) that let an AI agent perform the compaction. The agent decides what to keep/merge, not bd. Related to GH #243 complaint about API key requirement.


Agent 8 Issue 23


Agent 2 Batch 15 Issue 2


Agent 5 Issue 16


Agent 7 Issue 36


Agent 2 Issue 44


bd uses wrong default prefix when database filename indicates different prefix

When creating issues without explicit --id flag, bd defaults to 'bd-' prefix even when the database filename and existing issues use a different prefix (e.g., 'wy-').


Agent 4 Issue 70

Created by agent 4


Agent 0 Issue 5

Created by agent 0


Agent 0 Issue 23


Agent 4 Issue 34

Created by agent 4


Agent 9 Issue 22


Test plugin installation and functionality

Verify the plugin works end-to-end.

Test cases:
- Fresh installation via /plugin command
- All slash commands work correctly
- MCP server tools are accessible
- Configuration options work
- Documentation is accurate
- Works in both terminal and VS Code


Investigate vector/semantic search for issue discovery

From GH issue #2 RFC discussion: Evaluate if vector/semantic search over issues would provide value for beads.

**Use case:** Find semantically related issues (e.g., 'login broken' finds 'authentication failure', 'session expired').

**Questions to answer:**
1. What workflows would this enable that we can't do now?
2. Is dataset size (typically 50-200 issues) large enough to benefit?
3. Do structured features (deps, tags, types) already provide better relationships?
4. What's the maintenance cost (embeddings, storage, recomputation)?

**Alternatives to consider:**
- Improve 'bd list' filtering with regex/boolean queries
- Add 'bd related <id>' showing deps + mentions + same tags
- Export to JSON and pipe to external AI tools

**Decision:** Only implement if clear use case emerges. Don't add complexity for theoretical benefits.

**Context:** Part of evaluating Turso RFC ideas (GH #2). Vector search was proposed but unclear if needed for typical beads usage.


Agent 4 Issue 89

Created by agent 4


Split test suites: fast vs. integration

Reorganize tests into separate packages/files for fast unit tests vs slow integration tests.

Benefits:
- Clear separation of concerns
- Easier to run just fast tests during development
- Can parallelize CI jobs better

Files to organize:
- beads_hash_multiclone_test.go (slow integration tests)
- beads_integration_test.go (medium-speed integration tests)
- Other test files (fast unit tests)


Add import metrics for external_ref matching statistics

Add observability for external_ref matching behavior during imports to help debug and optimize import operations.

Metrics to track:
- Number of issues matched by external_ref
- Number of issues matched by ID
- Number of issues matched by content hash
- Number of external_ref updates vs creates
- Average import time with vs without external_ref

Output format:
- Add to ImportResult struct
- Include in import command output
- Consider structured logging

Use cases:
- Debugging slow imports
- Understanding match distribution
- Optimizing import performance

Related: bd-1022


Agent 3 Issue 43

Created by agent 3


Agent 3 Batch 0 Issue 2


Agent 3 Batch 9 Issue 2


Agent 9 Issue 47


Agent 6 Issue 45


Agent 2 Issue 52


Agent 1 Batch 22 Issue 1


Agent 9 Issue 80


Split monolithic sqlite.go into focused files

internal/storage/sqlite/sqlite.go is 1050 lines containing initialization, 20+ CRUD methods, query building, and schema management.

Split into:
- store.go: Store struct & initialization (150 lines)
- bead_queries.go: Bead CRUD (300 lines)
- work_queries.go: Work queries (200 lines)
- stats_queries.go: Statistics (150 lines)
- schema.go: Schema & migrations (150 lines)
- helpers.go: Common utilities (100 lines)

Impact: Impossible to understand at a glance; hard to find specific functionality; high cognitive load

Effort: 6-8 hours


Agent 2 Issue 95


Agent 3 Batch 31 Issue 1


bd delete bulk operations fight with auto-import/daemon causing data resurrection

When bulk deleting issues (e.g., 244 closed issues older than 24h), the process fights with auto-import and daemon infrastructure:

**Expected behavior:**
- Delete 244 issues from 468-issue database
- Export to JSONL (224 lines)
- Commit and push
- Result: 224 issues

**Actual behavior:**
- Delete 244 issues
- Import runs (from stale git JSONL with 468 issues)
- Resurrects deleted issues back into database
- Export writes 356 lines (not 224)
- Math: 468 - 244 = 224, but got 356 (132 issues resurrected)

**Root cause:**
Auto-import keeps re-importing from git during the delete operation, before the new JSONL is committed. The workflow is:
1. Delete from DB
2. Auto-import runs (reads old JSONL from git with deleted issues still present)
3. Issues come back
4. Export writes partially-deleted state

**Solution options:**
1. Add `--no-auto-import` flag to bulk delete operations
2. Atomic delete-export-commit operation that suppresses imports
3. Dedicated `bd prune` command that handles this correctly
4. Lock file to prevent auto-import during bulk mutations

**Impact:**
- Bulk cleanup operations don't work reliably
- Makes it nearly impossible to prune old closed issues
- Confusing UX (delete 244, but only 112 actually removed)

**FIXED**: Auto-import now skips during delete operations to prevent resurrection.

**Root cause confirmed**: Auto-import was running in PersistentPreRun before delete executed, causing it to re-import stale JSONL from git and resurrect deleted issues.

**Solution implemented**:
1. Added delete to skip list in main.go PersistentPreRun (alongside import and sync --dry-run)
2. Delete operations now complete atomically without auto-import interference
3. Added comprehensive test (TestBulkDeleteNoResurrection) to prevent regression

**Test verification**:
- Creates 20 issues, deletes 10
- Verifies no resurrection after delete
- Confirms JSONL has correct count (10 remaining)
- All existing tests still pass


Agent 3 Issue 77


Agent 7 Issue 85


Agent 0 Issue 31


Agent 0 Batch 0 Issue 2


Agent 6 Issue 32


Test npm package installation locally

Verify npm package works before publishing:

## Local testing
- Run npm pack in npm/ directory
- Install tarball globally: npm install -g beads-bd-0.21.5.tgz
- Test basic commands:
  - bd --version
  - bd init --quiet --prefix test
  - bd create "Test issue" -p 1 --json
  - bd list --json
  - bd sync

## Test environments
- macOS (darwin-arm64 and darwin-amd64)
- Linux (ubuntu docker container for linux-amd64)
- Windows (optional, if available)

## Validation
- Binary downloads during postinstall
- All bd commands work identically to native
- No permission issues
- Proper error messages on failure


Direct mode test2


Agent 8 Issue 72


Agent 4 Issue 81

Created by agent 4


Agent 9 Issue 94


Agent 3 Issue 19

Created by agent 3


Agent 2 New Issue 10


Wire config to import pipeline

Connect import.orphan_handling config to importer.go and sqlite validation functions. Pass mode flag through call chain. Implement all four modes (strict/resurrect/skip/allow) with proper error messages and logging.


Add unit tests for import ordering

Test topological sort: import [child, parent] should succeed, import [parent.1.2, parent, parent.1] should sort correctly. Verify depth-based batching works. Test max depth limits.


Agent 6 Issue 32

Created by agent 6


Agent 8 Issue 49


Test all core bd commands in WASM for feature parity

Comprehensive testing of bd-wasm against native bd:
- Test all CRUD operations (create, update, show, close)
- Test dependency management (dep add, dep tree)
- Test sync operations (sync, import, export)
- Verify JSONL output matches native bd
- Run existing Go test suite in WASM if possible
- Benchmark performance (should be within 2x of native)


Agent 7 Issue 23

Created by agent 7


Agent 4 Issue 96

Created by agent 4


Delete collision resolution code

Remove ~2,100 LOC of ID collision detection and resolution code (no longer needed with hash IDs).

## Files to Delete Entirely
```
internal/storage/sqlite/collision.go              (~800 LOC)
internal/storage/sqlite/collision_test.go         (~300 LOC)
cmd/bd/autoimport_collision_test.go               (~400 LOC)
```

## Code to Remove from Existing Files

### internal/importer/importer.go
Remove:
- `DetectCollisions()` calls
- `ScoreCollisions()` logic
- `RemapCollisions()` calls
- `handleRename()` function
- All collision-related error handling

Keep:
- Basic import logic
- Exact match detection (idempotent import)

### beads_twoclone_test.go
Remove:
- `TestTwoCloneCollision` (bd-71107098)
- `TestThreeCloneCollision` (bd-cbed9619)
- `TestFiveCloneCollision` (bd-a40f374f)
- All N-way collision tests

### cmd/bd/import.go
Remove:
- `--resolve-collisions` flag
- `--dry-run` collision preview
- Collision reporting

## Issues Closed by This Change
- bd-71107098: Add test for symmetric collision
--89: Content-hash collision resolution
- bd-cbed9619: N-way collision resolution epic
- bd-cbed9619.5: Add ScoreCollisions (already done but now unnecessary)
- bd-cbed9619.4: Make DetectCollisions read-only
- bd-cbed9619.3: ResolveNWayCollisions function
- bd-cbed9619.2: Multi-round import convergence
- bd-cbed9619.1: Multi-round convergence for N-way collisions
- bd-e6d71828: Transaction + retry logic for collisions
- bd-70419816: Test case for symmetric collision

## Verification Steps
1. `grep -r "collision" --include="*.go"` → should only find alias conflicts
2. `go test ./...` → all tests pass
3. `go build ./cmd/bd` → clean build
4. Check LOC reduction: `git diff --stat`

## Expected Metrics
- **Files deleted**: 3
- **LOC removed**: ~2,100
- **Test coverage**: Should increase (less untested code)
- **Binary size**: Slightly smaller

## Caution
Do NOT delete:
- Alias conflict resolution (new code in bd-f8b764c9.6)
- Duplicate detection (bd-581b80b3, bd-149) - different from ID collisions
- Merge conflict resolution (bd-7e7ddffa.1, bd-5f483051) - git conflicts, not ID collisions

## Files to Modify
- internal/importer/importer.go (remove collision handling)
- cmd/bd/import.go (remove --resolve-collisions flag)
- beads_twoclone_test.go (remove collision tests)
- Delete: internal/storage/sqlite/collision.go
- Delete: internal/storage/sqlite/collision_test.go
- Delete: cmd/bd/autoimport_collision_test.go

## Testing
- Ensure all remaining tests pass
- Manual test: create issue on two clones, sync → no collisions
- Verify error if somehow hash collision occurs (extremely unlikely)


Agent 6 Issue 82

Created by agent 6


Agent 2 Batch 38 Issue 2


Agent 3 Batch 36 Issue 1


AI-supervised database migrations for safer schema evolution

## Problem

Database migrations can lose user data through edge cases that are hard to anticipate (e.g., GH #201 where bd migrate failed to set issue_prefix, or bd-d355a07d false positive data loss warnings). Since beads is designed to be run by AI agents, we should leverage AI to make migrations safer.

## Current State

Migrations run blindly with:
- No pre-flight validation
- No data integrity verification
- No rollback on failure
- Limited post-migration testing

Recent issues:
- GH #201: Migration didn't set issue_prefix config, breaking commands
- bd-d355a07d: False positive "data loss" warnings on collision resolution
- Users reported migration data loss (fixed but broader problem remains)

## Proposal: AI-Supervised Migration Framework

Use AI to supervise migrations through structured verification:

### 1. Pre-Migration Analysis
- AI reads migration code and current schema
- Identifies potential data loss scenarios
- Generates validation queries to verify assumptions
- Creates snapshot queries for before/after comparison

### 2. Migration Execution
- Take database backup/snapshot
- Run validation queries (pre-state)
- Execute migration in transaction
- Run validation queries (post-state)

### 3. Post-Migration Verification
- AI compares pre/post snapshots
- Verifies data integrity invariants
- Checks for unexpected data loss
- Validates config completeness (like issue_prefix)

### 4. Rollback on Anomalies
- If AI detects data loss, rollback transaction
- Present human-readable error report
- Suggest fix before retrying

## Example Flow

```
$ bd migrate

→ Analyzing migration plan...
→ AI identified 3 potential data loss scenarios
→ Generating validation queries...
→ Creating pre-migration snapshot...
→ Running migration in transaction...
→ Verifying post-migration state...
✓ All 247 issues accounted for
✓ Config table complete (issue_prefix: "mcp")
✓ Dependencies intact (342 relationships verified)
→ Migration successful!
```

If something goes wrong:
```
$ bd migrate

→ Analyzing migration plan...
→ AI identified issue: Missing issue_prefix config after migration
→ Recommendation: Add prefix detection step
→ Aborting migration - database unchanged
```

## Implementation Ideas

### A. Migration Validator Tool
Create `bd migrate --validate` that:
- Simulates migration on copy of database
- Uses AI to verify data integrity
- Reports potential issues before real migration

### B. Migration Test Generator
AI generates test cases for migrations:
- Edge cases (empty DB, large DB, missing config)
- Data integrity checks
- Regression tests

### C. Migration Invariants
Define invariants that AI checks:
- Issue count should not decrease (unless collision resolution)
- All required config keys present
- Foreign key relationships intact
- No orphaned dependencies

### D. Self-Healing Migrations
AI detects incomplete migrations and suggests fixes:
- Missing config values (like GH #201)
- Orphaned data
- Index inconsistencies

## Benefits

1. **Catch edge cases**: AI explores scenarios humans miss
2. **Self-documenting**: AI explains what migration does
3. **Agent-friendly**: Agents can run migrations confidently
4. **Fewer rollbacks**: Detect issues before committing
5. **Better testing**: AI generates comprehensive test suites

## Open Questions

1. Which AI model? (Fast: Haiku, Thorough: Sonnet/GPT-4)
2. How to balance safety vs migration speed?
3. Should AI validation be required or optional?
4. How to handle offline scenarios (no API access)?
5. What invariants should always be checked?

## Related Work

- bd-b245: Migration registry (makes migrations introspectable)
- GH #201: issue_prefix migration bug (motivating example)
- bd-d355a07d: False positive data loss warnings

## Progress

### ✅ Phase 1: Migration Invariants (COMPLETED)

**Implemented:**
- Created internal/storage/sqlite/migration_invariants.go with 3 invariants
- Updated RunMigrations() to verify invariants after migrations
- All tests pass ✓

### ✅ Phase 2: Inspection Tools (COMPLETED & PUSHED)

**Commit:** 1abe4e7 - "Add migration inspection tools for AI agents (bd-627d Phase 2)"

**Implemented:**
1. ✅ bd migrate --inspect --json - Shows migration plan
2. ✅ bd info --schema --json - Returns schema details
3. ✅ Migration warnings system
4. ✅ Documentation updated in AGENTS.md
5. ✅ All tests pass

### ✅ Phase 3: MCP Tools (COMPLETED & PUSHED)

**Commit:** 2493693 - "Add MCP tools for migration inspection (bd-627d Phase 3)"

**Implemented:**
1. ✅ inspect_migration(workspace_root) tool in beads-mcp
2. ✅ get_schema_info(workspace_root) tool in beads-mcp
3. ✅ Abstract methods in BdClientBase
4. ✅ CLI client implementations
5. ✅ All tests pass

**All phases complete!** Migration inspection fully integrated into MCP server.


Agent 1 Issue 55

Created by agent 1


Agent 3 Issue 19


Agent 0 Issue 13

Created by agent 0


Agent 6 Issue 98

Created by agent 6


Agent 4 Issue 51


Agent 2 New Issue 15


Agent 3 Issue 39


Standardize daemon detection: use tryDaemonLock probe before RPC

Before attempting RPC connection, call tryDaemonLock() to check if lock is held:
- If lock NOT held: skip RPC attempt (no daemon running)
- If lock IS held: proceed with RPC + short timeout

This is extremely cheap and eliminates unnecessary connection attempts.

Apply across all client entry points that probe for daemon.


bd validate - Comprehensive health check

Run all validation checks in one command.

Checks:
- Duplicates
- Orphaned dependencies
- Test pollution
- Git conflicts

Supports --fix-all for auto-repair.

Depends on bd-cbed9619.1, bd-0dcea000, bd-31aab707, bd-9826b69a.

Files: cmd/bd/validate.go (new)


Agent 5 Issue 91

Created by agent 5


Agent 1 Issue 86

Created by agent 1


Agent 2 Issue 34

Created by agent 2


Add resource limits to daemon (connections, cache, memory)

Daemon has no resource limits. Under heavy load or attack, it could:
- Accept unlimited connections
- Cache unlimited databases
- Use unbounded memory
- Exhaust file descriptors

Need limits for:
- Max concurrent RPC connections (default: 100)
- Max storage cache size (default: 50)
- Request timeout enforcement (default: 30s)
- Memory pressure detection

Location: internal/rpc/server.go


Agent 6 Issue 55


Agent 0 Issue 79

Created by agent 0


CRDT-based architecture for guaranteed convergence (v2.0)

## Vision
Redesign beads around Conflict-Free Replicated Data Types (CRDTs) to provide mathematical guarantees for N-way collision resolution at arbitrary scale.

## Current Limitations
- Content-hash based collision resolution fails at 5+ clones
- Non-deterministic convergence in multi-round scenarios
- UNIQUE constraint violations during rename operations
- No formal proof of convergence properties

## CRDT Benefits
- Provably convergent (Strong Eventual Consistency)
- Commutative/Associative/Idempotent operations
- No coordination required between clones
- Scales to 100+ concurrent workers
- Well-understood mathematical foundations

## Proposed Architecture

### 1. UUID-Based IDs
Replace sequential IDs with UUIDs:
- Current: bd-1c63eb84, bd-9063acda, bd-4d80b7b1
- CRDT: bd-a1b2c3d4-e5f6-7890-abcd-ef1234567890
- Human aliases maintained separately: #42 maps to UUID

### 2. Last-Write-Wins (LWW) Elements
Each field becomes an LWW register:
- title: (timestamp, clone_id, value)
- status: (timestamp, clone_id, value)
- Deterministic conflict resolution via Lamport timestamp + clone_id tiebreaker

### 3. Operation Log
Track all operations as CRDT ops:
- CREATE(uuid, timestamp, clone_id, fields)
- UPDATE(uuid, field, timestamp, clone_id, value)
- DELETE(uuid, timestamp, clone_id) - tombstone, not hard delete

### 4. Sync as Merge
Syncing becomes merging two CRDT states:
- No merge conflicts possible
- Deterministic merge function
- Guaranteed convergence

## Implementation Phases

### Phase 1: Research & Design (4 weeks)
- Study existing CRDT implementations (Automerge, Yjs, Loro)
- Design schema for CRDT-based issue tracking
- Prototype LWW-based Issue CRDT
- Benchmark performance vs current system

### Phase 2: Parallel Implementation (6 weeks)
- Implement CRDT storage layer alongside SQLite
- Build conversion tools: SQLite ↔ CRDT
- Maintain backward compatibility with v1.x format
- Migration path for existing databases

### Phase 3: Testing & Validation (4 weeks)
- Formal verification of convergence properties
- Stress testing with 100+ clone scenario
- Performance profiling and optimization
- Documentation and examples

### Phase 4: Migration & Rollout (4 weeks)
- Release v2.0-beta with CRDT backend
- Gradual migration from v1.x
- Monitoring and bug fixes
- Final v2.0 release

## Risks & Mitigations

**Risk 1: Performance overhead**
- Mitigation: Benchmark early, optimize hot paths
- CRDTs can be slower than append-only logs
- May need compaction strategy

**Risk 2: Storage bloat**
- Mitigation: Implement operation log compaction
- Tombstone garbage collection for deleted issues
- Periodic snapshots to reduce log size

**Risk 3: Breaking changes**
- Mitigation: Maintain v1.x compatibility layer
- Gradual migration tools
- Dual-mode operation during transition

**Risk 4: Complexity**
- Mitigation: Use battle-tested CRDT libraries
- Comprehensive documentation
- Clear migration guide

## Success Criteria
- 100-clone collision test passes without failures
- Formal proof of convergence properties
- Performance within 2x of current system
- Zero manual conflict resolution required
- Backward compatible with v1.x databases

## Timeline
18-20 weeks total (4-5 months)

## References
- Automerge: https://automerge.org
- Yjs: https://docs.yjs.dev
- Loro: https://loro.dev
- CRDT theory: Shapiro et al, A comprehensive study of CRDTs
- Related issues: bd-0dcea000, bd-4d7fca8a, bd-6221bdcd


Agent 3 Issue 88


Add depth-based batch creation in upsertIssues

Replace single batch creation with depth-level batching (max depth 3). Create issues at depth 0, then 1, then 2, then 3. Prevents parent validation errors when importing hierarchical issues in same batch. File: internal/importer/importer.go:534-546


Agent 1 Issue 0


Agent 4 Issue 38


Update Metrics and Health Endpoints

Remove cache-related metrics from health/metrics endpoints


Agent 6 Issue 16


Agent 8 Issue 31


Agent 0 Issue 6

Created by agent 0


Agent 6 Issue 63

Created by agent 6


Rapid 4


Document label best practices and use cases

Create documentation covering:
- When to use labels vs structured fields
- Common label sets (coding agents, open source, product dev, SRE)
- Naming conventions (kebab-case, specificity, present tense)
- Anti-patterns (too many labels, overlapping, personal labels)
- Label lifecycle management

Content from LABELS.md analysis document.


Agent 5 Issue 12


Add migration registry and simplify New()

Create migrations.go with Migration type and registry. Change New() to: openDB -> initSchema -> RunMigrations(db). This removes 8+ separate migrate functions from New().


Agent 3 New Issue 45


Phase 3: Implement daemon command with SQLite ownership

Create 'bd daemon' command that starts the RPC server and owns the SQLite database.

Implementation:
- Add cmd/bd/daemon.go with start/stop/status subcommands
- Daemon holds exclusive SQLite connection
- Integrates git sync loop (batch exports every 5 seconds)
- PID file management for daemon lifecycle
- Logging for daemon operations

Socket location: .beads/bd.sock per repository


Agent 2 Batch 34 Issue 2


Agent 4 Issue 27


Agent 2 Batch 35 Issue 2


Agent 1 Issue 65

Created by agent 1


Reach 1.0 release milestone

Stabilize API, finalize documentation, comprehensive testing


Extract daemon lifecycle functions to daemon_lifecycle.go


Agent 7 Issue 71


Agent 3 Batch 31 Issue 2


Agent 1 Issue 69


Agent 3 Issue 47


Agent 9 Issue 99


Agent 8 Issue 99


Agent 0 Issue 11


Refactor AGENTS.md to use external references

Suggestion to use external references (e.g., "ALWAYS REFER TO ./beads/prompt.md") instead of including all instructions directly within AGENTS.md.
Reasons:
1. Agents can follow external references.
2. Prevents context pollution/stuffing in AGENTS.md as more tools append instructions.


Fix daemon exiting after 5s on macOS due to PID 1 parent monitoring

GitHub issue #278 reports that the daemon exits after <=5 seconds on macOS because it incorrectly treats PID 1 (launchd) as a dead parent.

When the daemon detaches on macOS, it gets reparented to PID 1 (launchd), which is the init process. The checkParentProcessAlive function was incorrectly treating PID 1 as a sign that the parent died.

Fixed by changing the logic to treat PID 1 as a valid parent for detached daemons.


Agent 1 Issue 8

Created by agent 1


Fix TestMigrateHashIDs test failure

Test failure in cmd/bd/migrate_hash_ids_test.go:100 - New ID bd-09970281 for bd-1 is not a hash ID. This test is validating the hash ID migration but the generated ID doesn't match the expected format.


Add alias field to database schema

Extend database schema to support human-friendly aliases alongside hash IDs.

## Database Changes

### 1. Add alias column to issues table
```sql
ALTER TABLE issues ADD COLUMN alias INTEGER UNIQUE;
CREATE INDEX idx_issues_alias ON issues(alias);
```

### 2. Add alias counter table
```sql
CREATE TABLE alias_counter (
    id INTEGER PRIMARY KEY CHECK (id = 1),
    next_alias INTEGER NOT NULL DEFAULT 1
);
INSERT INTO alias_counter (id, next_alias) VALUES (1, 1);
```

### 3. Add alias conflict tracking (for multi-clone scenarios)
```sql
CREATE TABLE alias_history (
    issue_id TEXT NOT NULL,
    alias INTEGER NOT NULL,
    assigned_at TIMESTAMP NOT NULL,
    workspace_id TEXT NOT NULL,
    PRIMARY KEY (issue_id, alias)
);
```

## API Changes

### CreateIssue
- Generate hash ID
- Assign next available alias
- Store both in database

### ResolveAliasConflicts (new function)
- Detect conflicting alias assignments after import
- Apply resolution strategy (content-hash ordering)
- Reassign losers to next available aliases

## Migration Path
```bash
bd migrate --add-aliases  # Adds columns, assigns aliases to existing issues
```

## Files to Modify
- internal/storage/sqlite/schema.go
- internal/storage/sqlite/sqlite.go (CreateIssue, GetIssue)
- internal/storage/sqlite/aliases.go (new file for alias logic)
- internal/storage/sqlite/migrations.go

## Testing
- Test alias auto-assignment on create
- Test alias uniqueness constraint
- Test alias lookup performance
- Test alias conflict resolution


Agent 2 Batch 13 Issue 2


Agent 5 Issue 98

Created by agent 5


Agent 3 Issue 57

Created by agent 3


Update documentation for collision resolution

Update README.md with collision resolution section. Update CLAUDE.md with new workflow. Document --resolve-collisions and --dry-run flags. Add example scenarios showing branch merge workflows.


Agent 3 New Issue 15


Agent 4 Issue 73

Created by agent 4


Agent 2 Batch 6 Issue 2


Agent 2 Batch 49 Issue 2


Test basic bd commands in WASM (init, create, list)

Compile and verify basic bd functionality works in WASM:
- Test bd init --quiet
- Test bd create with simple issue
- Test bd list --json output
- Verify SQLite database creation and queries work
- Document any runtime issues or workarounds needed


Agent 4 Issue 13


Agent 3 Issue 76


Agent 9 Issue 50


Agent 4 Issue 87


Agent 2 Batch 40 Issue 1


Agent 0 Issue 41

Created by agent 0


Agent 0 Issue 68

Created by agent 0


Configure database connection pool limits for daemon mode

Database connection pool not configured for file-based databases when running in daemon mode.

Location: internal/storage/sqlite/sqlite.go:108-116

Problem:
- Daemon is a long-running server handling concurrent RPC requests
- Multiple CLI commands hit same daemon simultaneously
- Go default: unlimited connections (MaxOpenConns=0)
- SQLite IMMEDIATE transactions serialize on write lock
- Can have 100+ goroutines blocked waiting, each holding connection
- Results in connection exhaustion and 'database is locked' errors

Current code only limits in-memory DBs:
if isInMemory {
    db.SetMaxOpenConns(1)
    db.SetMaxIdleConns(1)
}
// File DBs: UNLIMITED connections!

Fix:
if !isInMemory {
    maxConns := runtime.NumCPU() + 1  // 1 writer + N readers
    db.SetMaxOpenConns(maxConns)
    db.SetMaxIdleConns(2)
    db.SetConnMaxLifetime(0)
}

Impact: 'database is locked' errors under concurrent load in daemon mode

Note: NOT an issue for direct CLI usage (each process isolated). Only affects daemon mode where multiple CLI commands share one database pool.

Effort: 1 hour


Test: N-clone scenario with hash IDs (no collisions)

Comprehensive test to verify hash IDs eliminate collision problems.

## Test: TestHashIDsNClones

### Purpose
Verify that N clones can work offline and sync without ID collisions using hash IDs.

### Test Scenario
```
Setup:
- 1 bare remote repo
- 5 clones (A, B, C, D, E)

Offline Work:
- Each clone creates 10 issues with different titles
- No coordination, no network access
- Total: 50 unique issues

Sync:
- Clones sync in random order
- Each pull/import other clones' issues

Expected Result:
- All 5 clones converge to 50 issues
- Zero ID collisions
- Zero remapping needed
- Alias conflicts resolved deterministically
```

### Implementation
File: cmd/bd/beads_hashid_test.go (new)

```go
func TestHashIDsFiveClones(t *testing.T) {
    tmpDir := t.TempDir()
    remoteDir := setupBareRepo(t, tmpDir)

    // Setup 5 clones
    clones := make(map[string]string)
    for _, name := range []string{"A", "B", "C", "D", "E"} {
        clones[name] = setupClone(t, tmpDir, remoteDir, name)
    }

    // Each clone creates 10 issues offline
    for name, dir := range clones {
        for i := 0; i < 10; i++ {
            createIssue(t, dir, fmt.Sprintf("%s-issue-%d", name, i))
        }
        // No sync yet!
    }

    // Sync in random order
    syncOrder := []string{"C", "A", "E", "B", "D"}
    for _, name := range syncOrder {
        syncClone(t, clones[name], name)
    }

    // Final convergence round
    for _, name := range []string{"A", "B", "C", "D", "E"} {
        finalPull(t, clones[name], name)
    }

    // Verify all clones have all 50 issues
    for name, dir := range clones {
        issues := getIssues(t, dir)
        if len(issues) != 50 {
            t.Errorf("Clone %s: expected 50 issues, got %d", name, len(issues))
        }

        // Verify all issue IDs are hash-based
        for _, issue := range issues {
            if !strings.HasPrefix(issue.ID, "bd-") || len(issue.ID) != 11 {
                t.Errorf("Invalid hash ID: %s", issue.ID)
            }
        }
    }

    // Verify no collision resolution occurred
    // (This would be in logs if it happened)

    t.Log("✓ All 5 clones converged to 50 issues with zero collisions")
}
```

### Edge Case Tests

#### Test: Hash Collision Detection (Artificial)
```go
func TestHashCollisionDetection(t *testing.T) {
    // Artificially inject collision by mocking hash function
    // Verify system detects and handles it
}
```

#### Test: Alias Conflicts Resolved Deterministically
```go
func TestAliasConflictsNClones(t *testing.T) {
    // Two clones assign same alias to different issues
    // Verify deterministic resolution (content-hash ordering)
    // Verify all clones converge to same alias assignments
}
```

#### Test: Mixed Sequential and Hash IDs (Should Fail)
```go
func TestMixedIDsRejected(t *testing.T) {
    // Try to import JSONL with sequential IDs into hash-ID database
    // Verify error or warning
}
```

### Performance Test

#### Benchmark: Hash ID Generation
```go
func BenchmarkHashIDGeneration(b *testing.B) {
    for i := 0; i < b.N; i++ {
        GenerateHashID("title", "description", time.Now(), "workspace-id")
    }
}

// Expected: < 1μs per generation
```

#### Benchmark: N-Clone Convergence Time
```go
func BenchmarkNCloneConvergence(b *testing.B) {
    for _, n := range []int{3, 5, 10, 20} {
        b.Run(fmt.Sprintf("N=%d", n), func(b *testing.B) {
            // Measure total convergence time
        })
    }
}

// Expected: Linear scaling O(N)
```

### Acceptance Criteria
- TestHashIDsFiveClones passes reliably (10/10 runs)
- Zero ID collisions in any scenario
- All clones converge in single round (not multi-round like old system)
- Alias conflicts resolved deterministically
- Performance benchmarks meet targets (<1μs hash gen)

## Files to Create
- cmd/bd/beads_hashid_test.go

## Comparison to Old System
This test replaces:
- TestTwoCloneCollision (bd-71107098) - no longer needed
- TestThreeCloneCollision (bd-cbed9619) - no longer needed
- TestFiveCloneCollision (bd-a40f374f) - no longer needed

Old system required complex collision resolution and multi-round convergence.
New system: single-round convergence with zero collisions.


Agent 9 Issue 59


Agent 5 Issue 14

Created by agent 5


Agent 1 Issue 3

Created by agent 1


Agent 5 Issue 8

Created by agent 5


Add test case for symmetric collision (both clones create same ID simultaneously)

TestTwoCloneCollision demonstrates the problem, but we need a simpler unit test for the collision resolver itself.

Test should verify:
- Two issues with same ID, different content
- Content hash determines winner deterministically
- Result is same regardless of which clone imports first
- No title swapping occurs

This can be a simpler test than the full integration test.


WASM integration testing

Comprehensive testing of WASM build. Child of epic bd-44d0.

## Tasks
- [ ] Unit tests for WASM module
- [ ] Integration tests with real JSONL files
- [ ] Test all bd commands for parity
- [ ] Performance benchmarks
- [ ] Test in actual Claude Code Web sandbox
- [ ] Document any limitations

## Test Coverage Target
- >90% of bd CLI commands work identically


Agent 2 Batch 0 Issue 2


Agent 9 Issue 38


Agent 4 Issue 25

Created by agent 4


Document versioning and release strategy

Create comprehensive versioning strategy for beads ecosystem.

Components to document:
1. bd CLI (Go binary) - main version number
2. Plugin (Claude Code) - tracks CLI version
3. MCP server (Python) - bundled with plugin
4. Release workflow - how to sync all three

Decisions to make:
- Should plugin.json auto-update from bd CLI version?
- Should we have a VERSION file at repo root?
- How to handle breaking changes across components?
- What's the update notification strategy?

References:
- plugin.json engines field now requires bd >=0.9.0
- /bd-version command added for checking compatibility
- PLUGIN.md now documents update workflow


Agent 5 Issue 74


Refactor duplicate flush logic in PersistentPostRun

PersistentPostRun contains a complete copy of the flush logic instead of calling flushToJSONL(). This violates DRY principle and makes maintenance harder. Refactor to use flushToJSONL() with a force parameter to bypass isDirty check, or extract shared logic into a helper function. Located in cmd/bd/main.go:104-138.


Add rule-based compaction (e.g., compact children of closed epics)

Support semantic compaction rules beyond just time-based, such as:
- Compact all children of closed epics
- Compact by priority level (e.g., all P3/P4 closed issues)
- Compact by label (e.g., all issues labeled 'archive')
- Compact by type (e.g., all closed chores)

This would allow smarter database size management based on semantic meaning rather than just age.


Agent 9 Issue 16


Add daemon telemetry and metrics

Track and report daemon metrics: request count, latency, cache hits/misses, error rates.


Agent 4 New Issue 5


Test child direct


Agent 7 Issue 12

Created by agent 7


Batch test 5


Agent 1 Issue 78


Agent 3 Issue 29

Created by agent 3


Agent 7 Issue 14

Created by agent 7


Agent 0 Issue 22

Created by agent 0


Issue in repo1

This should go to repo1 database


Agent 5 Issue 15


Agent 3 Issue 98


Agent 0 Issue 74


Agent 1 Batch 26 Issue 1


Agent 0 Batch 26 Issue 2


Agent 1 Issue 71


Migration tool for existing users

Ensure smooth migration for existing users to separate branch workflow.

Tasks:
- Add bd migrate --separate-branch command
- Detect existing repos, migrate cleanly
- Preserve git history
- Add rollback mechanism
- Test migration on beads' own repo (dogfooding)
- Communication plan (GitHub discussion, docs)
- Version compatibility checks

Estimated effort: 2-3 days


Remove obsolete renumber.go command (hash IDs eliminated need)


Agent 7 Issue 68

Created by agent 7


Agent 1 Issue 94

Created by agent 1


Add content-addressable identity to Issue type

## Overview
Phase 1: Add content hashing to enable global identification of issues regardless of their assigned IDs.

## Current Problem
The system identifies issues only by ID (e.g., test-1, test-2). When multiple clones create the same ID with different content, there's no way to identify that these are semantically different issues without comparing all fields.

## Solution
Add a ContentHash field to the Issue type that represents the canonical content fingerprint.

## Implementation Tasks

### 1. Add ContentHash field to Issue type
File: internal/types/types.go
```go
type Issue struct {
    ID          string
    ContentHash string  // SHA256 of canonical content
    // ... existing fields
}
```

### 2. Add content hash computation method
Use existing hashIssueContent from collision.go:186 as foundation:
```go
func (i *Issue) ComputeContentHash() string {
    return hashIssueContent(i)
}
```

### 3. Compute hash at creation time
- Modify CreateIssue to compute and store ContentHash
- Modify CreateIssues (batch) to compute hashes

### 4. Compute hash at import time
- Modify ImportIssues to compute ContentHash for all incoming issues
- Store hash in database

### 5. Add database column
- Add migration to add content_hash column to issues table
- Update SELECT/INSERT statements to include content_hash
- Index on content_hash for fast lookups

### 6. Populate existing issues
- Add migration step to compute ContentHash for all existing issues
- Use hashIssueContent function

## Acceptance Criteria
- Issue type has ContentHash field
- Hash is computed automatically at creation time
- Hash is computed for imported issues
- Database stores content_hash column
- All existing issues have non-empty ContentHash
- Hash is deterministic (same content → same hash)
- Hash excludes ID, timestamps (only semantic content)

## Files to Modify
- internal/types/types.go
- internal/storage/sqlite/sqlite.go (schema, CreateIssue, CreateIssues)
- internal/storage/sqlite/migrations.go (new migration)
- internal/importer/importer.go (compute hash during import)
- cmd/bd/create.go (compute hash at creation)

## Testing
- Unit test: same content produces same hash
- Unit test: different content produces different hash
- Unit test: hash excludes ID and timestamps
- Integration test: hash persists in database
- Migration test: existing issues get hashes populated


Agent 0 Issue 32

Created by agent 0


Blocking issue


Agent 3 Batch 30 Issue 2


Agent 3 Issue 17


Agent 0 Issue 12


Agent 4 Issue 57

Created by agent 4


Agent 3 Batch 47 Issue 2


Extract normalizeLabels to shared utility package

The `normalizeLabels` function appears in multiple locations with identical implementation. Extract to a shared utility package.

Current locations:
- `internal/rpc/server.go:37` (53 lines) - full implementation
- `cmd/bd/list.go:50-52` - uses the server version (needs to use new shared version)

Function purpose:
- Trims whitespace from labels
- Removes empty strings
- Deduplicates labels
- Preserves order

Target structure:
```
internal/util/
├── strings.go         # String utilities
    └── NormalizeLabels([]string) []string
```

Impact: DRY principle, single source of truth, easier to test


Agent 1 Issue 6

Created by agent 1


Agent 0 Batch 24 Issue 2


Agent 5 Issue 90

Created by agent 5


Agent 0 Issue 24

Created by agent 0


Agent 3 Issue 81

Created by agent 3


Agent 2 Issue 18

Created by agent 2


Agent 4 Issue 47

Created by agent 4


Agent 4 Issue 46

Created by agent 4


Agent 5 Issue 18

Created by agent 5


Agent 9 Issue 41


Implement `bd setup cursor` for Cursor IDE integration

Create a `bd setup cursor` command that integrates Beads workflow into Cursor IDE via .cursorrules file. Unlike Claude Code (which has hooks), Cursor uses a static rules file to provide context to its AI.


Latency test


Agent 7 Issue 67


Test parent issue


Agent 2 Issue 8

Created by agent 2


Rapid 1


Agent 8 Issue 60


Add 'bd repos' command for multi-repo aggregation

When using daemon in multi-repo mode, users need commands to view/manage work across all active repositories.

Add 'bd repos' subcommand with:

1. bd repos list
   - Show all repositories daemon has cached
   - Display: path, prefix, issue count, last activity
   - Example output:
     ~/src/project1  [p1-]   45 issues  (active)
     ~/src/project2  [p2-]   12 issues  (2m ago)

2. bd repos ready --all
   - Aggregate ready work across all repos
   - Group by repo or show combined list
   - Support priority/assignee filters

3. bd repos stats
   - Combined statistics across all repos
   - Total issues, breakdown by status/priority
   - Per-repo breakdown

4. bd repos clear-cache
   - Close all cached storage connections
   - Useful for freeing resources

Implementation notes:
- Requires daemon to track active storage instances
- May need RPC protocol additions for multi-repo queries
- Should gracefully handle repos that no longer exist

Depends on: Global daemon flag (makes this more useful)

Context: This provides the UX layer on top of existing multi-repo support. The daemon can already serve multiple repos - this makes it easy to work with them.


Agent 0 Issue 29

Created by agent 0


Fix race condition in TestSocketCleanup

Race condition detected in internal/rpc/rpc_test.go:195 in TestSocketCleanup. This is causing CI test failures.

The race appears to be between goroutines accessing shared state during server startup/shutdown in the socket cleanup test.

Location: internal/rpc/rpc_test.go:195
Test output shows DATA RACE between goroutines 83 and 85.


Agent 5 Issue 21

Created by agent 5


Agent 0 Batch 13 Issue 1


Agent 1 Issue 5


Extract daemon logger functions to daemon_logger.go


Create WASM build infrastructure (Makefile, scripts)

Set up build tooling for WASM compilation:
- Add GOOS=js GOARCH=wasm build target
- Copy wasm_exec.js from Go distribution
- Create wrapper script for Node.js execution
- Add build task to Makefile or build script


Agent 1 Batch 47 Issue 2


Agent 3 Batch 5 Issue 2


Agent 4 Issue 42


Agent 5 Issue 41

Created by agent 5


Agent 7 Issue 32


Agent 4 Issue 99

Created by agent 4


bd ready doesn't show epics/tasks ready to close when all children complete

The 'bd ready' command doesn't show epics that have all children complete as ready work. Example: vc-30 (epic) blocks 4 children - 3 are closed, 1 is in_progress. The epic itself should be reviewable/closable but doesn't show in ready work. Similarly, vc-61 (epic, in_progress) depends on vc-48 (closed) but doesn't show as ready. Expected: epics with all dependencies satisfied should show as ready to review/close. Actual: 'bd ready' returns 'no ready work' even though multiple epics are completable.


Add WebSocket support

## Feature Request

[Describe the desired feature]

## Motivation

[Why is this feature needed? What problem does it solve?]

## Use Cases

1. **Use Case 1**: [description]
2. **Use Case 2**: [description]

## Proposed Solution

[High-level approach to implementing this feature]

## Alternatives Considered

- **Alternative 1**: [description and why not chosen]
- **Alternative 2**: [description and why not chosen]


Agent 8 Issue 89


Add bd init --contributor wizard

Interactive wizard for OSS contributor setup. Guides user through: fork workflow setup, separate planning repo configuration, auto-detection of fork relationships, examples of common OSS workflows.


Agent 1 Issue 2


Agent 6 Issue 99


Agent 0 Issue 25


Document shared memory test isolation pattern in test_helpers.go

Tests were failing because :memory: creates a shared database across all tests. The fix is to use "file::memory:?mode=memory&cache=private" for test isolation.

Should document this pattern in test_helpers.go and potentially update newTestStore to use private memory by default.


Agent 2 Issue 99


Agent 2 Issue 94


Add --strict flag for dependency import failures

Currently dependency import errors are warnings (logged to stderr, execution continues). Missing targets or cycles may indicate JSONL corruption. Add --strict flag to fail on any dependency errors for data integrity validation. Location: cmd/bd/import.go:159-164


Agent 6 Issue 67


Agent 1 Issue 75

Created by agent 1


Add tests for daemon config module


Agent 7 Issue 87

Created by agent 7


Agent 9 Issue 7


Agent 2 Issue 55


Agent 0 Issue 47

Created by agent 0


Agent 1 Issue 10


Agent 8 Issue 3


Agent 1 Batch 43 Issue 1


Agent 6 Issue 41

Created by agent 6


Agent 0 Batch 41 Issue 1


Agent 8 Issue 4


Agent 3 Issue 0

Created by agent 3


Agent 3 Issue 61


Agent 2 Batch 13 Issue 1


Agent 3 Issue 66


Agent 5 Issue 60


Agent 2 Batch 20 Issue 2


Agent 0 Issue 23

Created by agent 0


Agent 6 Issue 75

Created by agent 6