diff --git a/.beads/beads.jsonl b/.beads/beads.jsonl index 2bd9618b..65fa4247 100644 --- a/.beads/beads.jsonl +++ b/.beads/beads.jsonl @@ -22,14 +22,14 @@ {"id":"bd-0fvq","content_hash":"6fb6e394efe3010fd5d9213669417e5f6376017de4187988d5a6fd0d36c80b40","title":"bd doctor should recommend bd prime migration for existing repos","description":"bd doctor should detect old beads integration patterns and recommend migrating to bd prime approach.\n\n## Current behavior\n- bd doctor checks if Claude hooks are installed globally\n- Doesn't check project-level integration (AGENTS.md, CLAUDE.md)\n- Doesn't recommend migration for repos using old patterns\n\n## Desired behavior\nbd doctor should detect and suggest:\n\n1. **Old slash command pattern detected**\n - Check for /beads:* references in AGENTS.md, CLAUDE.md\n - Suggest: These slash commands are deprecated, use bd prime hooks instead\n \n2. **No agent documentation**\n - Check if AGENTS.md or CLAUDE.md exists\n - Suggest: Run 'bd onboard' or 'bd setup claude' to document workflow\n \n3. **Old MCP-only pattern**\n - Check for instructions to use MCP tools but no bd prime hooks\n - Suggest: Add bd prime hooks for better token efficiency\n\n4. **Migration path**\n - Show: 'Run bd setup claude to add SessionStart/PreCompact hooks'\n - Show: 'Update AGENTS.md to reference bd prime instead of slash commands'\n\n## Example output\n\n⚠ Warning: Old beads integration detected in CLAUDE.md\n Found: /beads:* slash command references (deprecated)\n Recommend: Migrate to bd prime hooks for better token efficiency\n Fix: Run 'bd setup claude' and update CLAUDE.md\n\nπŸ’‘ Tip: bd prime + hooks reduces token usage by 80-99% vs slash commands\n MCP mode: ~50 tokens vs ~10.5k for full MCP scan\n CLI mode: ~1-2k tokens with automatic context recovery\n\n## Benefits\n- Helps existing repos adopt new best practices\n- Clear migration path for users\n- Better token efficiency messaging","status":"open","priority":2,"issue_type":"feature","created_at":"2025-11-12T03:20:25.567748-08:00","updated_at":"2025-11-12T03:20:25.567748-08:00","source_repo":"."} {"id":"bd-0kz8","content_hash":"b641c9c097cdeaa44b090d632eac2f89d89a5c3579f0ea58c8b02320b0fa49f7","title":"Fix default .beads/.gitignore to ignore merge artifacts (GH #274)","description":"Updated the default .gitignore template created by `bd init` to properly ignore merge artifacts and fix overly broad patterns.\n\nChanges:\n- Added `*.db?*` pattern for database files with query strings\n- Added explicit patterns for merge artifacts: beads.{base,left,right}.{jsonl,meta.json}\n- Changed `!*.jsonl` to `!issues.jsonl` to avoid including merge artifact JSONL files\n\nThis fixes GitHub issue #274 reported by rscorer.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-09T11:23:25.595551-08:00","updated_at":"2025-11-09T11:23:28.780095-08:00","closed_at":"2025-11-09T11:23:28.780095-08:00","source_repo":"."} {"id":"bd-0qeg","content_hash":"50f35dcc442b133e766668f3201f5e4820a66dd05cfac1c5d30595d11806f98e","title":"Fix bd doctor hash ID detection for short all-numeric hashes","description":"bd doctor incorrectly flags hash-based IDs as sequential when they are short (3-4 chars) and all-numeric (e.g., pf-158).\n\nRoot cause: isHashID() in cmd/bd/migrate_hash_ids.go:328-358 uses faulty heuristic:\n- For IDs \u003c 5 chars, only returns true if contains letters\n- But base36 hash IDs can be 3+ chars and all-numeric (MinLength: 3)\n- Example: pf-158 is valid hash ID but flagged as sequential\n\nFix: Check multiple IDs (10-20 samples) instead of single-ID pattern matching:\n- Sample IDs across database \n- Check majority pattern (sequential vs hash format)\n- Sequential: 1-4 digits (bd-1, bd-2...)\n- Hash: 3-8 chars base36 (pf-158, pf-3s9...)\n\nImpact: False positive warnings in bd doctor output","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-16T13:45:20.733761-08:00","updated_at":"2025-11-16T14:27:48.143485-08:00","closed_at":"2025-11-16T14:27:48.143485-08:00","source_repo":"."} -{"id":"bd-0tr0","content_hash":"6bcdf8cba6934e0d8b703a2c5a35297db3bf31c83513d78cdd633c05a737973d","title":"Claude Code frequently creates issues with empty descriptions","description":"## Problem\n\nUsers report that Claude Code creates beads issues with titles but no descriptions when asked to analyze code and create issues. Discussion #366 on GitHub highlights this.\n\n## Evidence\n\nAnalysis of our own projects shows significant rates of empty descriptions:\n- ~/src/beads: 110 empty / 630 total (17.5%)\n- ~/wyvern: 8 empty / 119 total (6.7%)\n- ~/src/vc: 3 empty / 170 total (1.8%)\n\nExamples of real issues with no description:\n- [deleted:bd-5qim]: Optimize GetReadyWork performance\n- bd-ge7/vc-7kln: Improve test coverage (appears in multiple projects)\n- Package-specific test coverage tasks (bd-m0w, bd-4h3, bd-t3b, bd-e92)\n- Wyvern testing tasks (wy-3hx, wy-qc9, wy-66)\n\nMany date from Nov 20-21, suggesting batch creation operations.\n\n## Impact\n\n- Issues lack context for future work\n- Harder to prioritize without understanding scope\n- Need manual follow-up to add details\n- Poor workflow experience for users\n\n## Related\n\n- GitHub Discussion #366: https://github.com/steveyegge/beads/discussions/366","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-11-23T13:59:45.931488-08:00","updated_at":"2025-11-23T21:11:04.522351-08:00","closed_at":"2025-11-23T21:11:04.522351-08:00","source_repo":"."} +{"id":"bd-0tr0","content_hash":"a432fe36e27a4a2fd9b825368aa57dcfb6e76c2cacdd8a9313a54755dd7e8bbf","title":"Claude Code frequently creates issues with empty descriptions","description":"## Problem\n\nUsers report that Claude Code creates beads issues with titles but no descriptions when asked to analyze code and create issues. Discussion #366 on GitHub highlights this.\n\n## Evidence\n\nAnalysis of our own projects shows significant rates of empty descriptions:\n- ~/src/beads: 110 empty / 630 total (17.5%)\n- ~/wyvern: 8 empty / 119 total (6.7%)\n- ~/src/vc: 3 empty / 170 total (1.8%)\n\nExamples of real issues with no description:\n- [deleted:bd-5qim]: Optimize GetReadyWork performance\n- bd-ge7/vc-7kln: Improve test coverage (appears in multiple projects)\n- Package-specific test coverage tasks (bd-m0w, bd-4h3, bd-t3b, bd-e92)\n- Wyvern testing tasks (wy-3hx, wy-qc9, wy-66)\n\nMany date from Nov 20-21, suggesting batch creation operations.\n\n## Impact\n\n- Issues lack context for future work\n- Harder to prioritize without understanding scope\n- Need manual follow-up to add details\n- Poor workflow experience for users\n\n## Related\n\n- GitHub Discussion #366: https://github.com/steveyegge/beads/discussions/366","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-11-23T13:59:45.931488-08:00","updated_at":"2025-11-23T21:11:04.522351-08:00","closed_at":"2025-11-23T21:11:04.522351-08:00","source_repo":"."} {"id":"bd-0vfe","content_hash":"e142bd97d91f70e50e8fea0681d8cdcffb17f17fdbd4c106d56607e243005d21","title":"Blocked issue","description":"","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-07T19:07:17.105974-08:00","updated_at":"2025-11-07T22:07:17.342098-08:00","closed_at":"2025-11-07T21:55:09.425545-08:00","source_repo":"."} {"id":"bd-1022","content_hash":"0b712a337844711597d2dd950d27d4c032a3b746a27f44326d62db740f5944e9","title":"Use external_ref as primary matching key for import updates","description":"Enable re-syncing from external systems (Jira, GitHub, Linear) by using external_ref as the primary matching key during imports. Currently imports treat any content change as a collision, making it impossible to sync updates from external systems without creating duplicates.\n\nSee GH #142 for detailed proposal and implementation plan.\n\nKey changes needed:\n1. Add findByExternalRef() query function\n2. Update DetectCollisions() to match by external_ref first\n3. Update import_shared.go to update existing issues when external_ref matches\n4. Add index on external_ref for performance\n5. Preserve local issues (no external_ref) from being overwritten\n\nThis enables hybrid workflows: import external backlog, break down with local tasks, re-sync anytime.","notes":"## Code Review Complete βœ…\n\n**Overall Assessment**: EXCELLENT - Production ready\n\n### Implementation Quality\n- βœ“ Clean architecture with proper interface extension\n- βœ“ Dual backend support (SQLite + Memory)\n- βœ“ Smart matching priority: external_ref β†’ ID β†’ content hash\n- βœ“ O(1) lookups with database index\n- βœ“ Timestamp-based conflict resolution\n- βœ“ Comprehensive test coverage (11 test cases)\n\n### Follow-up Issues Filed\nHigh Priority (P2):\n- bd-897a: Add UNIQUE constraint on external_ref column\n- bd-7315: Add validation for duplicate external_ref in batch imports\n\nMedium Priority (P3):\n- bd-f9a1: Add index usage verification test\n- bd-3f6a: Add concurrent import race condition tests\n\nLow Priority (P4):\n- bd-e166: Improve timestamp comparison readability\n- bd-9e23: Optimize Memory backend with index\n- bd-537e: Add external_ref change tracking\n- bd-df11: Add import metrics\n- bd-9f4a: Document external_ref in content hash\n\n### Key Features\nβœ… External systems (Jira, GitHub, Linear) can re-sync without duplicates\nβœ… Hybrid workflows: import external backlog, add local tasks, re-sync anytime\nβœ… Local issues protected from being overwritten\nβœ… Timestamp checking ensures only newer updates applied\nβœ… Performance optimized with database index\n\n**Confidence Level**: 95% - Ship it! πŸš€","status":"closed","priority":0,"issue_type":"feature","created_at":"2025-11-02T14:55:56.355813-08:00","updated_at":"2025-11-02T15:34:56.634126-08:00","closed_at":"2025-11-02T15:27:44.810375-08:00","source_repo":"."} {"id":"bd-1048","content_hash":"1a889d79a98f8c0919f99094736ee7c856c6d8a2ee062a0add49ce2c06c40174","title":"Daemon crashes silently on RPC query after startup","description":"The daemon fails to handle 'show' RPC commands when:\n1) JSONL is newer than database (needs import)\n2) git pull fails due to uncommitted changes\n\nSymptoms:\n- Daemon appears to run (ps shows process)\n- 'bd list' and other commands work fine \n- 'bd show \u003cid\u003e' returns \"failed to read response: EOF\"\n- No panic or error logged in daemon.log\n\nRoot cause likely: auto-import deadlock or state corruption when import is blocked by git conflicts.\n\nWorkaround: \n- Restart daemon after syncing git state (commit/push changes)\n- OR use --no-daemon flag for all commands\n\nThe panic recovery added in server_lifecycle_conn.go:183 didn't catch any panics, confirming this isn't a panic-based crash.","notes":"Root cause found and fixed: Two bugs - (1) nil pointer check missing in handleShow causing panic, (2) double JSON encoding in show.go ID resolution. Both fixed. bd show now works with daemon.","status":"closed","priority":0,"issue_type":"bug","created_at":"2025-11-02T17:05:03.658333-08:00","updated_at":"2025-11-03T12:08:12.947672-08:00","closed_at":"2025-11-03T12:08:12.947676-08:00","source_repo":"."} {"id":"bd-11e0","content_hash":"2f0b0a8d0f918cf665e378a1c817c591fc5efc284b65034e73b58b65d58d5674","title":"Database import silently fails when daemon version != CLI version","description":"","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-10-31T21:08:09.096749-07:00","updated_at":"2025-11-01T19:29:35.267817-07:00","closed_at":"2025-11-01T19:29:35.267817-07:00","source_repo":"."} {"id":"bd-1231","content_hash":"94139e31b3a3e58086ea77a916173a6f0c372a66a21925af0b9385de2f387c2f","title":"CI failing on all 3/4 test jobs despite individual tests passing","description":"CI has been broken for a day+ with mysterious test failures. Issue #173 on GitHub tracks this.\n\n## Current Status\n- **Lint job**: βœ… PASSING\n- **Test (Linux)**: ❌ FAILING (exit code 1)\n- **Test (Windows)**: ❌ FAILING (exit code 1)\n- **Test Nix Flake**: ❌ FAILING (exit code 1)\n\n## Key Observations\nAll three failing jobs show identical pattern:\n- Individual test output shows PASS for every test\n- Final result: `FAIL github.com/steveyegge/beads/cmd/bd`\n- Exit code 1 despite no visible test failures\n- Last visible test output before failure: \"No Reason Issue\" test (TestCloseCommand/close_without_reason)\n\n## Investigation So Far\n1. All tests appear to pass when examined individually\n2. Likely causes:\n - Race detector finding data races during test cleanup (`-race` flag)\n - Panic/error occurring after main tests complete\n - Test harness issue not reporting actual failure\n - Possible regression from PR #203 (dependency_type changes)\n\n## Recent CI Runs\n- Run 19015040655 (latest): 3/4 failing\n- Multiple recent commits tried to fix Windows/lint issues\n- Agent on rrnewton/beads fork attempting fixes (2/4 passing there)\n\n## Next Steps\n1. Run tests locally with `-race -v` to see full output\n2. Check for unreported test failures or panics\n3. Examine test cleanup/teardown code\n4. Review recent changes around close command tests\n5. Consider if race detector is too sensitive or catching real issues","notes":"## Progress Update\n\n### βœ… Fixed (commits 09bd4d3, 21a29bc)\n1. **Daemon auto-import** - Always recompute content_hash in importer to avoid stale hashes\n2. **TestScripts failures** - Added bd binary to PATH for shell subprocess tests\n3. **Test infrastructure** - Added .gitignore to test repos, fixed last_import_time metadata\n\n### βœ… CI Status (Run 19015638968)\n- **Test (Linux)**: βœ… SUCCESS - All tests passing\n- **Test (Windows)**: ❌ FAILURE - Pre-existing Windows test failures\n- **Test Nix Flake**: ❌ FAILURE - Build fails with same test errors\n- **Lint**: ❌ FAILURE - Pre-existing issue in migrate.go:647\n\n### ❌ Remaining Issues (not related to original bd-1231)\n\n**Windows failures:**\n- TestFindDatabasePathEnvVar\n- TestHashIDs_MultiCloneConverge \n- TestHashIDs_IdenticalContentDedup\n- TestDatabaseReinitialization (5 subtests)\n- TestFindBeadsDir_NotFound\n- TestMetricsSnapshot/uptime\n\n**Lint failure:**\n- cmd/bd/migrate.go:647:37: cleanupWALFiles - result 0 (error) is always nil (unparam)\n\n**Nix failure:**\n- Build fails during test phase with same test errors\n\n### Next Steps\n1. Investigate Windows-specific test failures\n2. Fix linting issue in migrate.go\n3. Debug Nix build test failures","status":"closed","priority":0,"issue_type":"bug","created_at":"2025-11-02T08:42:16.142128-08:00","updated_at":"2025-11-02T12:32:00.15834-08:00","closed_at":"2025-11-02T12:32:00.158346-08:00","external_ref":"https://github.com/steveyegge/beads/issues/173","source_repo":"."} {"id":"bd-12c2","content_hash":"77aa473abba394b850dfbaf1b5c4841aae3523238b21a82038ec0e8b39283677","title":"Add comprehensive tests for show.go commands (show, update, edit, close)","description":"Need to add tests for cmd/bd/show.go which contains show, update, edit, and close commands.\n\n**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.\n\n**Files to test**:\n- show.go (contains showCmd, updateCmd, editCmd, closeCmd)\n\n**Coverage needed**:\n- show command (single issue, multiple issues, JSON output, with dependencies, with labels, with compaction)\n- update command (status, priority, title, assignee, description, multiple fields, multiple issues)\n- edit command (requires $EDITOR, may need mocking)\n- close command (single issue, multiple issues, with reason, JSON output)\n\n**Test approach**:\n1. Study working test patterns in init_test.go, list_test.go, etc.\n2. Ensure BEADS_NO_DAEMON=1 is set\n3. Properly initialize database with bd init\n4. Use the command's global store, not a separate instance\n5. May need to reset global state between tests\n\n**Success criteria**: \n- All test functions pass\n- Coverage for show.go increases significantly\n- Tests follow existing patterns in cmd/bd/*_test.go","status":"closed","priority":0,"issue_type":"task","created_at":"2025-10-31T20:08:40.545173-07:00","updated_at":"2025-10-31T20:19:22.411066-07:00","closed_at":"2025-10-31T20:19:22.411066-07:00","source_repo":"."} -{"id":"bd-13gm","content_hash":"eaccb72612df62d1f88be6a265de906d071917ff03df8b1eb781060577ad8eb2","title":"Add explicit cache validation tests for blocked_issues_cache","description":"The blocked_issues_cache optimization works correctly but lacks explicit tests that verify cache invalidation behavior.\n\n## What to test\n\n1. **Cache invalidation on dependency add**\n - Add a blocking dependency\n - Verify blocked issue appears in cache\n \n2. **Cache invalidation on dependency remove**\n - Remove a blocking dependency\n - Verify blocked issue removed from cache\n \n3. **Cache invalidation on status change**\n - Close a blocker issue\n - Verify dependent issue removed from cache\n - Reopen blocker\n - Verify dependent issue added back to cache\n\n4. **Cache consistency across operations**\n - Multiple dependency changes in sequence\n - Verify cache stays consistent with actual blocking state\n\n5. **Parent-child transitive blocking**\n - Create epic with child tasks\n - Add blocking dependency to epic\n - Verify all children appear in cache\n\n## Implementation\n\nAdd tests to internal/storage/sqlite/blocked_cache_test.go (new file) with direct cache queries:\n\n```go\nfunc TestBlockedCacheInvalidation(t *testing.T) {\n // Verify cache updates correctly on dependency changes\n}\n\nfunc TestBlockedCacheConsistency(t *testing.T) {\n // Verify cache matches actual blocking state\n}\n```\n\n## Why this matters\n\n- Current tests verify behavior but not implementation\n- Explicit cache tests catch cache-specific bugs\n- Makes cache correctness visible in test output\n- Easier debugging if cache gets out of sync\n\n## Related\n\n- [deleted:[deleted:bd-5qim]]: GetReadyWork performance optimization (implemented cache)\n- internal/storage/sqlite/blocked_cache.go\n- internal/storage/sqlite/ready_test.go (behavior tests)","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-23T20:06:55.736412-08:00","updated_at":"2025-11-23T21:31:18.599098-08:00","source_repo":".","dependencies":[{"issue_id":"bd-13gm","depends_on_id":"bd-5qim","type":"discovered-from","created_at":"2025-11-23T20:07:39.271399-08:00","created_by":"daemon"}]} +{"id":"bd-13gm","content_hash":"eaccb72612df62d1f88be6a265de906d071917ff03df8b1eb781060577ad8eb2","title":"Add explicit cache validation tests for blocked_issues_cache","description":"The blocked_issues_cache optimization works correctly but lacks explicit tests that verify cache invalidation behavior.\n\n## What to test\n\n1. **Cache invalidation on dependency add**\n - Add a blocking dependency\n - Verify blocked issue appears in cache\n \n2. **Cache invalidation on dependency remove**\n - Remove a blocking dependency\n - Verify blocked issue removed from cache\n \n3. **Cache invalidation on status change**\n - Close a blocker issue\n - Verify dependent issue removed from cache\n - Reopen blocker\n - Verify dependent issue added back to cache\n\n4. **Cache consistency across operations**\n - Multiple dependency changes in sequence\n - Verify cache stays consistent with actual blocking state\n\n5. **Parent-child transitive blocking**\n - Create epic with child tasks\n - Add blocking dependency to epic\n - Verify all children appear in cache\n\n## Implementation\n\nAdd tests to internal/storage/sqlite/blocked_cache_test.go (new file) with direct cache queries:\n\n```go\nfunc TestBlockedCacheInvalidation(t *testing.T) {\n // Verify cache updates correctly on dependency changes\n}\n\nfunc TestBlockedCacheConsistency(t *testing.T) {\n // Verify cache matches actual blocking state\n}\n```\n\n## Why this matters\n\n- Current tests verify behavior but not implementation\n- Explicit cache tests catch cache-specific bugs\n- Makes cache correctness visible in test output\n- Easier debugging if cache gets out of sync\n\n## Related\n\n- [deleted:[deleted:bd-5qim]]: GetReadyWork performance optimization (implemented cache)\n- internal/storage/sqlite/blocked_cache.go\n- internal/storage/sqlite/ready_test.go (behavior tests)","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-23T20:06:55.736412-08:00","updated_at":"2025-11-23T21:25:52.048095-08:00","source_repo":".","dependencies":[{"issue_id":"bd-13gm","depends_on_id":"bd-5qim","type":"discovered-from","created_at":"2025-11-23T20:07:39.271399-08:00","created_by":"daemon"}]} {"id":"bd-1445","content_hash":"b3272105f48a2b0f11d2cf669d3e7e5c93a5e6c491cbabddf16872966618de0a","title":"Create shared insert/event/dirty helpers","description":"Create issues.go (insertIssue/insertIssues), events.go (recordCreatedEvent/recordCreatedEvents), dirty.go (markDirty/markDirtyBatch). Refactor single and bulk create paths to use these.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-01T11:41:14.882142-07:00","updated_at":"2025-11-02T15:28:11.99706-08:00","closed_at":"2025-11-02T15:28:11.997063-08:00","source_repo":"."} {"id":"bd-149","content_hash":"4865a0eaf982fedd744f824f990037f40763be2a133e4c3bb4e28971f8372428","title":"Auth tokens expire too quickly","description":"## Summary\n\n[Brief description of the bug]\n\n## Steps to Reproduce\n\n1. Step 1\n2. Step 2\n3. Step 3\n\n## Expected Behavior\n\n[What should happen]\n\n## Actual Behavior\n\n[What actually happens]\n\n## Environment\n\n- OS: [e.g., macOS 15.7.1]\n- Version: [e.g., bd 0.20.1]\n- Additional context: [any relevant details]\n\n## Additional Context\n\n[Screenshots, logs, or other relevant information]\n","design":"## Root Cause Analysis\n\n[Describe the underlying cause once identified]\n\n## Proposed Fix\n\n[Outline the solution approach]\n\n## Impact Assessment\n\n- Affected features: [list]\n- Breaking changes: [yes/no and details]\n- Migration needed: [yes/no and details]\n","acceptance_criteria":"- [ ] Bug no longer reproduces with original steps\n- [ ] Regression tests added\n- [ ] Related edge cases tested\n- [ ] Documentation updated if behavior changed\n","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-03T19:54:10.671488-08:00","updated_at":"2025-11-05T00:25:06.427601-08:00","closed_at":"2025-11-05T00:25:06.427601-08:00","source_repo":".","labels":["bug"]} {"id":"bd-164b","content_hash":"5cddac4d59502d1a6b3999f2dd85e1719389c8f9ea15f3515a62d52049d03645","title":"Add template support for issue creation","description":"Support creating issues from predefined templates to streamline common workflows like epics, bug reports, or feature proposals.\n\nExample usage:\n bd create --from-template epic \"Phase 3 Features\"\n bd create --from-template bug \"Login failure\"\n bd template list\n bd template create epic\n\nTemplates should include:\n- Pre-filled description structure\n- Suggested priority and type\n- Common labels\n- Design/acceptance criteria sections\n\nImplementation notes:\n- Store templates in .beads/templates/ directory\n- Support YAML or JSON format\n- Ship with built-in templates (epic, bug, feature)\n- Allow custom project-specific templates","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-11-03T18:10:18.985902-08:00","updated_at":"2025-11-03T19:56:41.287303-08:00","closed_at":"2025-11-03T19:56:41.287303-08:00","source_repo":"."} @@ -49,19 +49,19 @@ {"id":"bd-1f4086c5.1","content_hash":"ba5173c61613a29786641ba06a93427de87bed65ce39dbc3c3ddd2b6900f827e","title":"Integration test: mutation to export latency","description":"Measure time from bd create to JSONL update. Verify \u003c500ms latency. Test with multiple rapid mutations to verify batching.","notes":"Test added to daemon_test.go as TestMutationToExportLatency().\n\nCurrently skipped with note that it should be enabled once bd-146 (event-driven daemon) is fully implemented and enabled by default.\n\nThe test structure is complete:\n1. Sets up test environment with fast debounce (500ms)\n2. SingleMutationLatency: measures latency from mutation to JSONL update\n3. RapidMutationBatching: verifies multiple mutations batch into single export\n\nOnce event-driven mode is default, remove the t.Skip() line and the test will validate \u003c500ms latency.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-29T20:49:49.103759-07:00","updated_at":"2025-10-30T17:12:58.195867-07:00","closed_at":"2025-10-29T14:19:19.808139-07:00","source_repo":".","dependencies":[{"issue_id":"bd-1f4086c5.1","depends_on_id":"bd-1f4086c5","type":"parent-child","created_at":"2025-10-29T20:49:49.107244-07:00","created_by":"import-remap"}]} {"id":"bd-1f64","content_hash":"80f404d7c0f06c7f4bc6d52ac02c1a002a95ac7cb60c6485b2ceed5e013dad75","title":"Add comprehensive tests for config.yaml issue-prefix migration","description":"The GH #209 config.yaml migration lacks test coverage:\n\nMissing tests:\n- config.SetIssuePrefix() edge cases (empty file, comments, malformed YAML)\n- config.GetIssuePrefix() with various config states\n- MigrateConfigToYAML() automatic migration logic\n- bd init writing to config.yaml instead of DB\n- bd migrate DBβ†’config.yaml migration path\n\nTest scenarios needed:\n1. SetIssuePrefix with empty config.yaml\n2. SetIssuePrefix with existing config.yaml (preserves other settings)\n3. SetIssuePrefix with commented issue-prefix line\n4. SetIssuePrefix atomic write (temp file cleanup)\n5. GetIssuePrefix fallback behavior\n6. MigrateConfigToYAML when config.yaml missing prefix but DB has it\n7. MigrateConfigToYAML when both missing (detect from issues)\n8. MigrateConfigToYAML when config.yaml already has prefix (no-op)\n9. Integration test: fresh bd init writes to config.yaml only\n10. Integration test: upgrade from v0.21 DB migrates to config.yaml\n\nPriority 1 because this is a user-facing migration affecting all users upgrading to v0.22.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-03T22:33:43.08753-08:00","updated_at":"2025-11-03T22:46:16.306565-08:00","closed_at":"2025-11-03T22:46:16.306565-08:00","source_repo":"."} {"id":"bd-1fkr","content_hash":"ad8fd9d0254ef9f4ff430253234569af0a606b5d813ee98995dc5a6a2cbf897b","title":"bd-hv01: Storage backend extensibility broken by type assertion","description":"Problem: deletion_tracking.go:69-82 uses type assertion for DeleteIssue which breaks if someone adds a new storage backend.\n\nFix: Check capability before starting merge or add DeleteIssue to Storage interface.\n\nFiles: cmd/bd/deletion_tracking.go:69-82, internal/storage/storage.go","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-06T18:16:20.770662-08:00","updated_at":"2025-11-06T18:55:08.666253-08:00","closed_at":"2025-11-06T18:55:08.666253-08:00","source_repo":".","dependencies":[{"issue_id":"bd-1fkr","depends_on_id":"bd-rbxi","type":"parent-child","created_at":"2025-11-06T18:19:14.925961-08:00","created_by":"daemon"}]} -{"id":"bd-1h8","content_hash":"9c7421a5fa7f7bba3811bb45c5a2dcab78d0b156734ec2dada60b3bd4693fc7e","title":"Fix compact --analyze/--apply error messages to clarify direct mode requirement","description":"**Problem:**\nWhen users run `bd compact --analyze` with daemon running, they get:\n```\nError: compact requires SQLite storage\n```\n\nThis is misleading because they ARE using SQLite (via daemon), but the command needs DIRECT SQLite access.\n\n**Current behavior:**\n- Error message suggests they don't have SQLite\n- No hint about using --no-daemon flag\n- Related to issue #349 item #1\n\n**Proposed fix:**\n1. Update error messages in cmd/bd/compact.go lines 106-114 (analyze) and 121-137 (apply)\n2. Add explicit hint: \"Use --no-daemon flag to bypass daemon\"\n3. Change SQLite check error from \"requires SQLite storage\" to \"failed to open database in direct mode\"\n\n**Files to modify:**\n- cmd/bd/compact.go (lines ~106-137)\n\n**Testing:**\n- Run with daemon: `bd compact --analyze` should show clear error + hint\n- Run with --no-daemon: `bd compact --analyze --no-daemon` should work\n- Verify error message is actionable","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-20T20:47:45.606924-05:00","updated_at":"2025-11-23T14:14:13.329268-08:00","closed_at":"2025-11-20T20:59:13.406952-05:00","source_repo":".","labels":["bug","documentation","ux"],"comments":[{"id":16,"issue_id":"bd-1h8","author":"stevey","text":"Addresses GitHub issue #349 item 1: https://github.com/steveyegge/beads/issues/349\n\nUser reported misleading error when running 'bd compact --analyze' with daemon active. Error says 'requires SQLite storage' but user IS using SQLite via daemon - the real issue is that --analyze mode needs DIRECT database access.","created_at":"2025-11-21T02:23:27Z"}]} +{"id":"bd-1h8","content_hash":"9c7421a5fa7f7bba3811bb45c5a2dcab78d0b156734ec2dada60b3bd4693fc7e","title":"Fix compact --analyze/--apply error messages to clarify direct mode requirement","description":"**Problem:**\nWhen users run `bd compact --analyze` with daemon running, they get:\n```\nError: compact requires SQLite storage\n```\n\nThis is misleading because they ARE using SQLite (via daemon), but the command needs DIRECT SQLite access.\n\n**Current behavior:**\n- Error message suggests they don't have SQLite\n- No hint about using --no-daemon flag\n- Related to issue #349 item #1\n\n**Proposed fix:**\n1. Update error messages in cmd/bd/compact.go lines 106-114 (analyze) and 121-137 (apply)\n2. Add explicit hint: \"Use --no-daemon flag to bypass daemon\"\n3. Change SQLite check error from \"requires SQLite storage\" to \"failed to open database in direct mode\"\n\n**Files to modify:**\n- cmd/bd/compact.go (lines ~106-137)\n\n**Testing:**\n- Run with daemon: `bd compact --analyze` should show clear error + hint\n- Run with --no-daemon: `bd compact --analyze --no-daemon` should work\n- Verify error message is actionable","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-20T20:47:45.606924-05:00","updated_at":"2025-11-23T14:14:13.329268-08:00","closed_at":"2025-11-20T20:59:13.406952-05:00","source_repo":".","labels":["bug","documentation","ux"]} {"id":"bd-1hxf","content_hash":"609579b48faaa40c437e8380ac7dec2021ccdb08eca252f4f6380a0edf0a656b","title":"Fix Windows test failure: TestFindAllDatabases returns nil","description":"On Windows, TestFindAllDatabases fails with 'expected non-nil slice'.\n\nTest failure: beads_test.go:63: expected non-nil slice\n\nThe FindAllDatabases() function is returning nil instead of an empty slice on Windows. Need to investigate why the function returns nil and ensure it always returns a non-nil slice (even if empty).","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-11-23T20:16:33.018645-08:00","updated_at":"2025-11-23T21:16:32.849196-08:00","closed_at":"2025-11-23T21:11:57.05394-08:00","source_repo":"."} {"id":"bd-1ls","content_hash":"af79708476d560abaac3cbe9c537bcf43c2100dcb1d676954ea604486f75d199","title":"Override test","description":"## Overview\n\n[Describe the high-level goal and scope of this epic]\n\n## Success Criteria\n\n- [ ] Criteria 1\n- [ ] Criteria 2\n- [ ] Criteria 3\n\n## Background\n\n[Provide context and motivation]\n\n## Scope\n\n**In Scope:**\n- Item 1\n- Item 2\n\n**Out of Scope:**\n- Item 1\n- Item 2\n","design":"## Architecture\n\n[Describe the overall architecture and approach]\n\n## Components\n\n- Component 1: [description]\n- Component 2: [description]\n\n## Dependencies\n\n[List external dependencies or constraints]\n","acceptance_criteria":"- [ ] All child issues are completed\n- [ ] Integration tests pass\n- [ ] Documentation is updated\n- [ ] Code review completed\n","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-03T20:15:10.01471-08:00","updated_at":"2025-11-03T22:07:10.946574-08:00","closed_at":"2025-11-03T22:07:10.946574-08:00","source_repo":".","labels":["epic"]} {"id":"bd-1mzt","content_hash":"3dffe5c0934f51c6fa526a952a975e808665d80e7c69dffbe910aabc87d32a7b","title":"Client self-heal: remove stale pid when lock free + socket missing","description":"When client detects:\n- Socket is missing AND\n- tryDaemonLock shows lock NOT held\n\nThen automatically:\n1. Remove stale daemon.pid file\n2. Optionally auto-start daemon (behind BEADS_AUTO_START_DAEMON=1 env var)\n\nThis prevents stale artifacts from accumulating after daemon crashes.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-07T16:42:12.75205-08:00","updated_at":"2025-11-07T22:07:17.342845-08:00","closed_at":"2025-11-07T21:21:15.317562-08:00","source_repo":".","dependencies":[{"issue_id":"bd-1mzt","depends_on_id":"bd-ndyz","type":"discovered-from","created_at":"2025-11-07T16:42:12.753099-08:00","created_by":"daemon"}]} {"id":"bd-1pj6","content_hash":"de1c1195b29d9a70c88b5f2b05ca1c3497469d1802f9c0be415d5a44b0575deb","title":"Proposal: Custom status states via config","description":"Proposal to add 'custom status states' via `bd config`.\nUsers could define an optional issue status enum (e.g., awaiting_review, review_in_progress) in the config.\nThis would enable multi-step pipelines to process issues where each step correlates to a specific status.\n\nExamples:\n- awaiting_verification\n- awaiting_docs\n- awaiting_testing\n","status":"open","priority":3,"issue_type":"feature","created_at":"2025-11-20T18:55:48.670499-05:00","updated_at":"2025-11-20T18:55:48.670499-05:00","source_repo":"."} -{"id":"bd-1rh","content_hash":"2bf7c47993db5a35d15a724213910e231f5ea746893801427a422c68945949fa","title":"cmd/bd test suite is absurdly slow - 279 tests taking 8+ minutes","description":"# Problem\n\nThe cmd/bd test suite is painfully slow:\n- **279 tests** in cmd/bd alone\n- Full suite takes **8+ minutes** to run\n- Even with the 16 slowest integration tests now tagged with `integration` build tag, the remaining tests still take forever\n\nThis makes the development loop unusable. We can't wait 8+ minutes every time we want to run tests.\n\n# Root Cause Analysis\n\n## 1. Sheer Volume\n279 tests is too many for a single package. Even at 0.1s per test, that's 28 seconds minimum just for cmd/bd.\n\n## 2. Each Test Creates Full Database + Temp Directories\nEvery test does heavy setup:\n- Creates temp directory (`t.TempDir()` or `os.MkdirTemp`)\n- Initializes SQLite database\n- Sets up git repo in many cases\n- Creates full storage layer\n\nExample from the tests:\n```go\nfunc setupCLITestDB(t *testing.T) string {\n tmpDir := createTempDirWithCleanup(t)\n runBDInProcess(t, tmpDir, \"init\", \"--prefix\", \"test\", \"--quiet\")\n return tmpDir\n}\n```\n\nThis happens 279 times!\n\n## 3. Tests Are Not Properly Categorized\nWe have three types of tests mixed together:\n- **Unit tests** - should be fast, test single functions\n- **Integration tests** - test full workflows, need DB/git\n- **End-to-end tests** - test entire CLI commands\n\nThey're all lumped together in cmd/bd, all running every time.\n\n# What We've Already Fixed\n\nAdded `integration` build tags to 16 obviously-slow test files:\n- import_profile_test.go (performance benchmarking tests)\n- export_mtime_test.go (tests with time.Sleep calls)\n- cli_fast_test.go (full CLI integration tests)\n- delete_test.go, import_uncommitted_test.go, sync_local_only_test.go (git integration)\n- And 10 more in internal/ packages\n\nThese are now excluded from the default `go test ./...` run.\n\n# Proposed Solutions\n\n## Option 1: Shared Test Fixtures (Quick Win)\nCreate a shared test database that multiple tests can use:\n```go\nvar testDB *sqlite.SQLiteStorage\nvar testDBOnce sync.Once\n\nfunc getSharedTestDB(t *testing.T) storage.Storage {\n testDBOnce.Do(func() {\n // Create one DB for all tests\n })\n return testDB\n}\n```\n\n**Pros**: Easy to implement, immediate speedup\n**Cons**: Tests become less isolated, harder to debug failures\n\n## Option 2: Table-Driven Tests (Medium Win)\nCollapse similar tests into table-driven tests:\n```go\nfunc TestCreate(t *testing.T) {\n tests := []struct{\n name string\n args []string\n want string\n }{\n {\"basic issue\", []string{\"create\", \"Test\"}, \"created\"},\n {\"with description\", []string{\"create\", \"Test\", \"-d\", \"desc\"}, \"created\"},\n // ... 50 more cases\n }\n \n db := setupOnce(t) // Setup once, not 50 times\n for _, tt := range tests {\n t.Run(tt.name, func(t *testing.T) {\n // test using shared db\n })\n }\n}\n```\n\n**Pros**: Dramatically reduces setup overhead, tests run in parallel\n**Cons**: Requires refactoring, tests share more state\n\n## Option 3: Split cmd/bd Tests Into Packages (Big Win)\nMove tests into focused packages:\n- `cmd/bd/internal/clitests` - CLI integration tests (mark with integration tag)\n- `cmd/bd/internal/unittests` - Fast unit tests\n- Keep only essential tests in cmd/bd\n\n**Pros**: Clean separation, easy to run just fast tests\n**Cons**: Requires significant refactoring\n\n## Option 4: Parallel Execution (Quick Win)\nAdd `t.Parallel()` to independent tests:\n```go\nfunc TestSomething(t *testing.T) {\n t.Parallel() // Run this test concurrently with others\n // ...\n}\n```\n\n**Pros**: Easy to add, can cut time in half on multi-core machines\n**Cons**: Doesn't reduce actual test work, just parallelizes it\n\n## Option 5: In-Memory Databases (Medium Win)\nUse `:memory:` SQLite databases instead of file-based:\n```go\nstore, err := sqlite.New(ctx, \":memory:\")\n```\n\n**Pros**: Faster than disk I/O, easier cleanup\n**Cons**: Some tests need actual file-based DBs (export/import tests)\n\n# Recommended Approach\n\n**Short-term (this week)**:\n1. Add `t.Parallel()` to all independent tests in cmd/bd\n2. Use `:memory:` databases where possible\n3. Create table-driven tests for similar test cases\n\n**Medium-term (next sprint)**:\n4. Split cmd/bd tests into focused packages\n5. Mark more integration tests appropriately\n\n**Long-term (backlog)**:\n6. Consider shared test fixtures with proper isolation\n\n# Current Status\n\nWe've tagged 16 files with `integration` build tag, but the remaining 279 tests in cmd/bd still take 8+ minutes. This issue tracks fixing the cmd/bd test performance specifically.\n\n# Target\n\nGet `go test ./...` (without `-short` or `-tags=integration`) down to **under 30 seconds**.\n\n\n# THE REAL ROOT CAUSE (Updated Analysis)\n\nAfter examining the actual test code, the problem is clear:\n\n## Every Test Creates Its Own Database From Scratch\n\nLook at `create_test.go`:\n```go\nfunc TestCreate_BasicIssue(t *testing.T) {\n tmpDir := t.TempDir() // ← Creates temp dir\n testDB := filepath.Join(tmpDir, \".beads\", \"beads.db\")\n s := newTestStore(t, testDB) // ← Opens NEW SQLite connection\n // ← Runs migrations\n // ← Sets config\n // ... actual test (3 lines)\n}\n\nfunc TestCreate_WithDescription(t *testing.T) {\n tmpDir := t.TempDir() // ← Creates ANOTHER temp dir\n testDB := filepath.Join(tmpDir, \".beads\", \"beads.db\")\n s := newTestStore(t, testDB) // ← Opens ANOTHER SQLite connection\n // ... actual test (3 lines)\n}\n```\n\n**This happens 279 times!**\n\n## These Tests Don't Need Isolation!\n\nMost tests are just checking:\n- \"Can I create an issue with a title?\"\n- \"Can I create an issue with a description?\"\n- \"Can I add labels?\"\n\nThey don't conflict with each other. They could all share ONE database!\n\n## The Fix: Test Suites with Shared Setup\n\nInstead of:\n```go\nfunc TestCreate_BasicIssue(t *testing.T) {\n s := newTestStore(t, t.TempDir()+\"/db\") // ← Expensive!\n // test\n}\n\nfunc TestCreate_WithDesc(t *testing.T) {\n s := newTestStore(t, t.TempDir()+\"/db\") // ← Expensive!\n // test\n}\n```\n\nDo this:\n```go\nfunc TestCreate(t *testing.T) {\n // ONE setup for all subtests\n s := newTestStore(t, t.TempDir()+\"/db\")\n \n t.Run(\"basic_issue\", func(t *testing.T) {\n t.Parallel() // Can run concurrently - tests don't conflict\n // test using shared `s`\n })\n \n t.Run(\"with_description\", func(t *testing.T) {\n t.Parallel()\n // test using shared `s`\n })\n \n // ... 50 more subtests, all using same DB\n}\n```\n\n**Result**: 50 tests β†’ 1 database setup instead of 50!\n\n## Why This Works\n\nSQLite is fine with concurrent reads and isolated transactions. These tests:\n- βœ… Create different issues (no ID conflicts)\n- βœ… Just read back what they created\n- βœ… Don't depend on database state from other tests\n\nThey SHOULD share a database!\n\n## Real Numbers\n\nCurrent:\n- 279 tests Γ— (create dir + init SQLite + migrations) = **8 minutes**\n\nAfter fix:\n- 10 test suites Γ— (create dir + init SQLite + migrations) = **30 seconds**\n- 279 subtests running in parallel using those 10 DBs = **5 seconds**\n\n**Total: ~35 seconds instead of 8 minutes!**\n\n## Implementation Plan\n\n1. **Group related tests** into suites (Create, List, Update, Delete, etc.)\n2. **One setup per suite** instead of per test\n3. **Use t.Run() for subtests** with t.Parallel()\n4. **Keep tests that actually need isolation** separate (export/import tests, git operations)\n\nThis is way better than shuffling tests into folders!","notes":"## Progress Update (2025-11-21)\n\nβœ… **Completed**:\n- Audited all 280 tests, created TEST_SUITE_AUDIT.md ([deleted:[deleted:[deleted:bd-c49]]])\n- Refactored create_test.go to shared DB pattern ([deleted:[deleted:[deleted:bd-y6d]]])\n- Proven the pattern works: 11 tests now run in 0.04s with 1 DB instead of 11\n\n❌ **Current Reality**:\n- Overall test suite: Still 8+ minutes (no meaningful change)\n- Only 1 of 76 test files refactored\n- Saved ~10 DB initializations out of 280\n\n## Acceptance Criteria (REALISTIC)\n\nThis task is NOT complete until:\n- [ ] All P1 files refactored (create βœ…, dep, stale, comments, list, ready)\n- [ ] Test suite runs in \u003c 2 minutes\n- [ ] Measured and verified actual speedup\n\n## Next Steps\n\n1. Refactor remaining 5 P1 files: dep_test.go, stale_test.go, comments_test.go, list_test.go, ready_test.go\n2. Measure actual time improvement after each file\n3. Continue with P2 files if needed to hit \u003c2min target","status":"open","priority":1,"issue_type":"bug","created_at":"2025-11-21T11:37:47.886207-05:00","updated_at":"2025-11-23T21:31:18.598027-08:00","source_repo":".","dependencies":[{"issue_id":"bd-1rh","depends_on_id":"bd-c49","type":"blocks","created_at":"2025-11-21T11:49:26.347518-05:00","created_by":"daemon"}]} +{"id":"bd-1rh","content_hash":"2bf7c47993db5a35d15a724213910e231f5ea746893801427a422c68945949fa","title":"cmd/bd test suite is absurdly slow - 279 tests taking 8+ minutes","description":"# Problem\n\nThe cmd/bd test suite is painfully slow:\n- **279 tests** in cmd/bd alone\n- Full suite takes **8+ minutes** to run\n- Even with the 16 slowest integration tests now tagged with `integration` build tag, the remaining tests still take forever\n\nThis makes the development loop unusable. We can't wait 8+ minutes every time we want to run tests.\n\n# Root Cause Analysis\n\n## 1. Sheer Volume\n279 tests is too many for a single package. Even at 0.1s per test, that's 28 seconds minimum just for cmd/bd.\n\n## 2. Each Test Creates Full Database + Temp Directories\nEvery test does heavy setup:\n- Creates temp directory (`t.TempDir()` or `os.MkdirTemp`)\n- Initializes SQLite database\n- Sets up git repo in many cases\n- Creates full storage layer\n\nExample from the tests:\n```go\nfunc setupCLITestDB(t *testing.T) string {\n tmpDir := createTempDirWithCleanup(t)\n runBDInProcess(t, tmpDir, \"init\", \"--prefix\", \"test\", \"--quiet\")\n return tmpDir\n}\n```\n\nThis happens 279 times!\n\n## 3. Tests Are Not Properly Categorized\nWe have three types of tests mixed together:\n- **Unit tests** - should be fast, test single functions\n- **Integration tests** - test full workflows, need DB/git\n- **End-to-end tests** - test entire CLI commands\n\nThey're all lumped together in cmd/bd, all running every time.\n\n# What We've Already Fixed\n\nAdded `integration` build tags to 16 obviously-slow test files:\n- import_profile_test.go (performance benchmarking tests)\n- export_mtime_test.go (tests with time.Sleep calls)\n- cli_fast_test.go (full CLI integration tests)\n- delete_test.go, import_uncommitted_test.go, sync_local_only_test.go (git integration)\n- And 10 more in internal/ packages\n\nThese are now excluded from the default `go test ./...` run.\n\n# Proposed Solutions\n\n## Option 1: Shared Test Fixtures (Quick Win)\nCreate a shared test database that multiple tests can use:\n```go\nvar testDB *sqlite.SQLiteStorage\nvar testDBOnce sync.Once\n\nfunc getSharedTestDB(t *testing.T) storage.Storage {\n testDBOnce.Do(func() {\n // Create one DB for all tests\n })\n return testDB\n}\n```\n\n**Pros**: Easy to implement, immediate speedup\n**Cons**: Tests become less isolated, harder to debug failures\n\n## Option 2: Table-Driven Tests (Medium Win)\nCollapse similar tests into table-driven tests:\n```go\nfunc TestCreate(t *testing.T) {\n tests := []struct{\n name string\n args []string\n want string\n }{\n {\"basic issue\", []string{\"create\", \"Test\"}, \"created\"},\n {\"with description\", []string{\"create\", \"Test\", \"-d\", \"desc\"}, \"created\"},\n // ... 50 more cases\n }\n \n db := setupOnce(t) // Setup once, not 50 times\n for _, tt := range tests {\n t.Run(tt.name, func(t *testing.T) {\n // test using shared db\n })\n }\n}\n```\n\n**Pros**: Dramatically reduces setup overhead, tests run in parallel\n**Cons**: Requires refactoring, tests share more state\n\n## Option 3: Split cmd/bd Tests Into Packages (Big Win)\nMove tests into focused packages:\n- `cmd/bd/internal/clitests` - CLI integration tests (mark with integration tag)\n- `cmd/bd/internal/unittests` - Fast unit tests\n- Keep only essential tests in cmd/bd\n\n**Pros**: Clean separation, easy to run just fast tests\n**Cons**: Requires significant refactoring\n\n## Option 4: Parallel Execution (Quick Win)\nAdd `t.Parallel()` to independent tests:\n```go\nfunc TestSomething(t *testing.T) {\n t.Parallel() // Run this test concurrently with others\n // ...\n}\n```\n\n**Pros**: Easy to add, can cut time in half on multi-core machines\n**Cons**: Doesn't reduce actual test work, just parallelizes it\n\n## Option 5: In-Memory Databases (Medium Win)\nUse `:memory:` SQLite databases instead of file-based:\n```go\nstore, err := sqlite.New(ctx, \":memory:\")\n```\n\n**Pros**: Faster than disk I/O, easier cleanup\n**Cons**: Some tests need actual file-based DBs (export/import tests)\n\n# Recommended Approach\n\n**Short-term (this week)**:\n1. Add `t.Parallel()` to all independent tests in cmd/bd\n2. Use `:memory:` databases where possible\n3. Create table-driven tests for similar test cases\n\n**Medium-term (next sprint)**:\n4. Split cmd/bd tests into focused packages\n5. Mark more integration tests appropriately\n\n**Long-term (backlog)**:\n6. Consider shared test fixtures with proper isolation\n\n# Current Status\n\nWe've tagged 16 files with `integration` build tag, but the remaining 279 tests in cmd/bd still take 8+ minutes. This issue tracks fixing the cmd/bd test performance specifically.\n\n# Target\n\nGet `go test ./...` (without `-short` or `-tags=integration`) down to **under 30 seconds**.\n\n\n# THE REAL ROOT CAUSE (Updated Analysis)\n\nAfter examining the actual test code, the problem is clear:\n\n## Every Test Creates Its Own Database From Scratch\n\nLook at `create_test.go`:\n```go\nfunc TestCreate_BasicIssue(t *testing.T) {\n tmpDir := t.TempDir() // ← Creates temp dir\n testDB := filepath.Join(tmpDir, \".beads\", \"beads.db\")\n s := newTestStore(t, testDB) // ← Opens NEW SQLite connection\n // ← Runs migrations\n // ← Sets config\n // ... actual test (3 lines)\n}\n\nfunc TestCreate_WithDescription(t *testing.T) {\n tmpDir := t.TempDir() // ← Creates ANOTHER temp dir\n testDB := filepath.Join(tmpDir, \".beads\", \"beads.db\")\n s := newTestStore(t, testDB) // ← Opens ANOTHER SQLite connection\n // ... actual test (3 lines)\n}\n```\n\n**This happens 279 times!**\n\n## These Tests Don't Need Isolation!\n\nMost tests are just checking:\n- \"Can I create an issue with a title?\"\n- \"Can I create an issue with a description?\"\n- \"Can I add labels?\"\n\nThey don't conflict with each other. They could all share ONE database!\n\n## The Fix: Test Suites with Shared Setup\n\nInstead of:\n```go\nfunc TestCreate_BasicIssue(t *testing.T) {\n s := newTestStore(t, t.TempDir()+\"/db\") // ← Expensive!\n // test\n}\n\nfunc TestCreate_WithDesc(t *testing.T) {\n s := newTestStore(t, t.TempDir()+\"/db\") // ← Expensive!\n // test\n}\n```\n\nDo this:\n```go\nfunc TestCreate(t *testing.T) {\n // ONE setup for all subtests\n s := newTestStore(t, t.TempDir()+\"/db\")\n \n t.Run(\"basic_issue\", func(t *testing.T) {\n t.Parallel() // Can run concurrently - tests don't conflict\n // test using shared `s`\n })\n \n t.Run(\"with_description\", func(t *testing.T) {\n t.Parallel()\n // test using shared `s`\n })\n \n // ... 50 more subtests, all using same DB\n}\n```\n\n**Result**: 50 tests β†’ 1 database setup instead of 50!\n\n## Why This Works\n\nSQLite is fine with concurrent reads and isolated transactions. These tests:\n- βœ… Create different issues (no ID conflicts)\n- βœ… Just read back what they created\n- βœ… Don't depend on database state from other tests\n\nThey SHOULD share a database!\n\n## Real Numbers\n\nCurrent:\n- 279 tests Γ— (create dir + init SQLite + migrations) = **8 minutes**\n\nAfter fix:\n- 10 test suites Γ— (create dir + init SQLite + migrations) = **30 seconds**\n- 279 subtests running in parallel using those 10 DBs = **5 seconds**\n\n**Total: ~35 seconds instead of 8 minutes!**\n\n## Implementation Plan\n\n1. **Group related tests** into suites (Create, List, Update, Delete, etc.)\n2. **One setup per suite** instead of per test\n3. **Use t.Run() for subtests** with t.Parallel()\n4. **Keep tests that actually need isolation** separate (export/import tests, git operations)\n\nThis is way better than shuffling tests into folders!","notes":"## Progress Update (2025-11-21)\n\nβœ… **Completed**:\n- Audited all 280 tests, created TEST_SUITE_AUDIT.md ([deleted:[deleted:[deleted:bd-c49]]])\n- Refactored create_test.go to shared DB pattern ([deleted:[deleted:[deleted:bd-y6d]]])\n- Proven the pattern works: 11 tests now run in 0.04s with 1 DB instead of 11\n\n❌ **Current Reality**:\n- Overall test suite: Still 8+ minutes (no meaningful change)\n- Only 1 of 76 test files refactored\n- Saved ~10 DB initializations out of 280\n\n## Acceptance Criteria (REALISTIC)\n\nThis task is NOT complete until:\n- [ ] All P1 files refactored (create βœ…, dep, stale, comments, list, ready)\n- [ ] Test suite runs in \u003c 2 minutes\n- [ ] Measured and verified actual speedup\n\n## Next Steps\n\n1. Refactor remaining 5 P1 files: dep_test.go, stale_test.go, comments_test.go, list_test.go, ready_test.go\n2. Measure actual time improvement after each file\n3. Continue with P2 files if needed to hit \u003c2min target","status":"open","priority":1,"issue_type":"bug","created_at":"2025-11-21T11:37:47.886207-05:00","updated_at":"2025-11-23T21:25:52.366998-08:00","source_repo":".","dependencies":[{"issue_id":"bd-1rh","depends_on_id":"bd-c49","type":"blocks","created_at":"2025-11-21T11:49:26.347518-05:00","created_by":"daemon"}]} {"id":"bd-1vup","content_hash":"99df92e0d2e6f2998d9ef52c60ae1db55a2e52b84c3e935bf371517e5154ad77","title":"Test FK constraint via close","description":"","status":"closed","priority":4,"issue_type":"task","created_at":"2025-11-07T15:06:10.324045-08:00","updated_at":"2025-11-07T15:06:14.289835-08:00","closed_at":"2025-11-07T15:06:14.289835-08:00","source_repo":"."} {"id":"bd-1vv","content_hash":"1db907ddb55edaf7a4c06a566c4e1b8244fcd9ba5d7e2fca4d5c053e424ac515","title":"Add WebSocket support","description":"## Feature Request\n\n[Describe the desired feature]\n\n## Motivation\n\n[Why is this feature needed? What problem does it solve?]\n\n## Use Cases\n\n1. **Use Case 1**: [description]\n2. **Use Case 2**: [description]\n\n## Proposed Solution\n\n[High-level approach to implementing this feature]\n\n## Alternatives Considered\n\n- **Alternative 1**: [description and why not chosen]\n- **Alternative 2**: [description and why not chosen]\n","design":"## Technical Design\n\n[Detailed technical approach]\n\n## API Changes\n\n[New commands, flags, or APIs]\n\n## Data Model Changes\n\n[Database schema changes if any]\n\n## Implementation Notes\n\n- Note 1\n- Note 2\n\n## Testing Strategy\n\n- Unit tests: [scope]\n- Integration tests: [scope]\n- Manual testing: [steps]\n","acceptance_criteria":"- [ ] Feature implements all described use cases\n- [ ] All tests pass\n- [ ] Documentation updated (README, commands)\n- [ ] Examples added if applicable\n- [ ] No performance regressions\n","status":"open","priority":2,"issue_type":"feature","created_at":"2025-11-03T19:56:41.271215-08:00","updated_at":"2025-11-03T19:56:41.271215-08:00","source_repo":".","labels":["feature"]} -{"id":"bd-1w6i","content_hash":"5042c5d9e376206a6939b42950bb7074fc2012e33db54c291f85e667c1ca30b3","title":"Document blocked_issues_cache architecture and behavior","description":"Add comprehensive documentation about the blocked_issues_cache optimization to help future maintainers understand the design.\n\n## What to document\n\n1. **Architecture overview**\n - Why cache exists (performance: 752ms -\u003e 29ms)\n - When cache is used (GetReadyWork queries)\n - How cache is maintained (invalidation triggers)\n\n2. **Cache invalidation rules**\n - Invalidated on: dependency add/remove (blocks/parent-child only)\n - Invalidated on: any status change\n - Invalidated on: issue close\n - NOT invalidated on: related/discovered-from dependencies\n\n3. **Transaction safety**\n - All invalidations happen within transactions\n - Cache can use tx or direct db connection\n - Rebuild is atomic (DELETE + INSERT in same tx)\n\n4. **Performance characteristics**\n - Full rebuild on every invalidation\n - Rebuild is fast (\u003c50ms on 10K database)\n - Write complexity traded for read speed\n - Dependency changes are rare vs reads\n\n5. **Edge cases**\n - Parent-child transitive blocking\n - Closed issues don't block\n - Foreign key CASCADE handles deletions\n\n## Where to document\n\nAdd to these locations:\n\n1. **blocked_cache.go** - Add detailed package comment:\n```go\n// Package blocked_cache implements the blocked_issues_cache optimization.\n// \n// Performance: GetReadyWork originally used recursive CTE (752ms on 10K db).\n// With cache: Simple NOT EXISTS query (29ms on 10K db).\n//\n// Cache Maintenance:\n// - Rebuild triggered on dependency changes (blocks/parent-child only)\n// - Rebuild triggered on status changes \n// - Full rebuild (DELETE + INSERT) is fast enough for all cases\n// ...\n```\n\n2. **ARCHITECTURE.md** or **PERFORMANCE.md** (new file) - High-level overview\n\n3. **ready.go** - Update comment at line 84-85 with more detail\n\n## Related\n\n- [deleted:[deleted:bd-5qim]]: GetReadyWork optimization (implemented)\n- bd-13gm: Cache validation tests\n- bd-obdc: Cache rebuild command","status":"open","priority":3,"issue_type":"task","created_at":"2025-11-23T20:07:23.467296-08:00","updated_at":"2025-11-23T21:31:18.599579-08:00","source_repo":".","dependencies":[{"issue_id":"bd-1w6i","depends_on_id":"bd-5qim","type":"discovered-from","created_at":"2025-11-23T20:07:41.705188-08:00","created_by":"daemon"}]} +{"id":"bd-1w6i","content_hash":"5042c5d9e376206a6939b42950bb7074fc2012e33db54c291f85e667c1ca30b3","title":"Document blocked_issues_cache architecture and behavior","description":"Add comprehensive documentation about the blocked_issues_cache optimization to help future maintainers understand the design.\n\n## What to document\n\n1. **Architecture overview**\n - Why cache exists (performance: 752ms -\u003e 29ms)\n - When cache is used (GetReadyWork queries)\n - How cache is maintained (invalidation triggers)\n\n2. **Cache invalidation rules**\n - Invalidated on: dependency add/remove (blocks/parent-child only)\n - Invalidated on: any status change\n - Invalidated on: issue close\n - NOT invalidated on: related/discovered-from dependencies\n\n3. **Transaction safety**\n - All invalidations happen within transactions\n - Cache can use tx or direct db connection\n - Rebuild is atomic (DELETE + INSERT in same tx)\n\n4. **Performance characteristics**\n - Full rebuild on every invalidation\n - Rebuild is fast (\u003c50ms on 10K database)\n - Write complexity traded for read speed\n - Dependency changes are rare vs reads\n\n5. **Edge cases**\n - Parent-child transitive blocking\n - Closed issues don't block\n - Foreign key CASCADE handles deletions\n\n## Where to document\n\nAdd to these locations:\n\n1. **blocked_cache.go** - Add detailed package comment:\n```go\n// Package blocked_cache implements the blocked_issues_cache optimization.\n// \n// Performance: GetReadyWork originally used recursive CTE (752ms on 10K db).\n// With cache: Simple NOT EXISTS query (29ms on 10K db).\n//\n// Cache Maintenance:\n// - Rebuild triggered on dependency changes (blocks/parent-child only)\n// - Rebuild triggered on status changes \n// - Full rebuild (DELETE + INSERT) is fast enough for all cases\n// ...\n```\n\n2. **ARCHITECTURE.md** or **PERFORMANCE.md** (new file) - High-level overview\n\n3. **ready.go** - Update comment at line 84-85 with more detail\n\n## Related\n\n- [deleted:[deleted:bd-5qim]]: GetReadyWork optimization (implemented)\n- bd-13gm: Cache validation tests\n- bd-obdc: Cache rebuild command","status":"open","priority":3,"issue_type":"task","created_at":"2025-11-23T20:07:23.467296-08:00","updated_at":"2025-11-23T21:25:52.04642-08:00","source_repo":".","dependencies":[{"issue_id":"bd-1w6i","depends_on_id":"bd-5qim","type":"discovered-from","created_at":"2025-11-23T20:07:41.705188-08:00","created_by":"daemon"}]} {"id":"bd-1yi5","content_hash":"11044802d32a77f8ca574ca5902939bcc7e252880437bea7281aaf445db8db84","title":"Use -short flag in CI for PR checks","description":"Update CI configuration to use -short flag for PR checks, run full tests nightly.\n\nThe slow tests already support testing.Short() and will be skipped.\n\nExpected savings: ~20 seconds for PR checks (fast tests only)\n\nImplementation:\n- Update .github/workflows/ci.yml to add -short flag for PR tests\n- Create/update nightly workflow for full test runs\n- Update README/docs about test strategy\n\nFile: .github/workflows/ci.yml:30","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-04T01:24:17.279618-08:00","updated_at":"2025-11-04T10:25:10.616119-08:00","closed_at":"2025-11-04T10:25:10.616119-08:00","source_repo":".","dependencies":[{"issue_id":"bd-1yi5","depends_on_id":"bd-l5gq","type":"blocks","created_at":"2025-11-04T01:24:17.280453-08:00","created_by":"daemon"}]} {"id":"bd-22e0bde9","content_hash":"532c3b7af57bcf046114e2a3e9519fd07729251b3e81450a772d75d920d63e5d","title":"Add TestNWayCollision for 5+ clones","description":"## Overview\nAdd comprehensive tests for N-way (5+) collision resolution to verify the solution scales beyond 3 clones.\n\n## Purpose\nWhile TestThreeCloneCollision validates the basic N-way case, we need to verify:\n1. Solution scales to arbitrary N\n2. Performance is acceptable with more clones\n3. Convergence time is bounded\n4. No edge cases in larger collision groups\n\n## Implementation Tasks\n\n### 1. Create TestFiveCloneCollision\nFile: beads_twoclone_test.go (or new beads_nway_test.go)\n\n```go\nfunc TestFiveCloneCollision(t *testing.T) {\n // Test with 5 clones creating same ID with different content\n // Verify all 5 clones converge after sync rounds\n \n t.Run(\"SequentialSync\", func(t *testing.T) {\n testNCloneCollision(t, 5, \"A\", \"B\", \"C\", \"D\", \"E\")\n })\n \n t.Run(\"ReverseSync\", func(t *testing.T) {\n testNCloneCollision(t, 5, \"E\", \"D\", \"C\", \"B\", \"A\")\n })\n \n t.Run(\"RandomSync\", func(t *testing.T) {\n testNCloneCollision(t, 5, \"C\", \"A\", \"E\", \"B\", \"D\")\n })\n}\n```\n\n### 2. Implement generalized testNCloneCollision\nGeneralize the 3-clone test to handle arbitrary N:\n\n```go\nfunc testNCloneCollision(t *testing.T, numClones int, syncOrder ...string) {\n t.Helper()\n \n if len(syncOrder) != numClones {\n t.Fatalf(\"syncOrder length (%d) must match numClones (%d)\", \n len(syncOrder), numClones)\n }\n \n tmpDir := t.TempDir()\n \n // Setup remote and N clones\n remoteDir := setupBareRepo(t, tmpDir)\n cloneDirs := make(map[string]string)\n \n for i := 0; i \u003c numClones; i++ {\n name := string(rune('A' + i))\n cloneDirs[name] = setupClone(t, tmpDir, remoteDir, name)\n }\n \n // Each clone creates issue with same ID but different content\n for name, dir := range cloneDirs {\n createIssue(t, dir, fmt.Sprintf(\"Issue from clone %s\", name))\n }\n \n // Sync in specified order\n for _, name := range syncOrder {\n syncClone(t, cloneDirs[name], name)\n }\n \n // Final pull for convergence\n for name, dir := range cloneDirs {\n finalPull(t, dir, name)\n }\n \n // Verify all clones have all N issues\n expectedTitles := make(map[string]bool)\n for i := 0; i \u003c numClones; i++ {\n name := string(rune('A' + i))\n expectedTitles[fmt.Sprintf(\"Issue from clone %s\", name)] = true\n }\n \n for name, dir := range cloneDirs {\n titles := getTitles(t, dir)\n if !compareTitleSets(titles, expectedTitles) {\n t.Errorf(\"Clone %s missing issues: expected %v, got %v\", \n name, expectedTitles, titles)\n }\n }\n \n t.Log(\"βœ“ All\", numClones, \"clones converged successfully\")\n}\n```\n\n### 3. Add performance benchmarks\nTest convergence time and memory usage:\n\n```go\nfunc BenchmarkNWayCollision(b *testing.B) {\n for _, n := range []int{3, 5, 10, 20} {\n b.Run(fmt.Sprintf(\"N=%d\", n), func(b *testing.B) {\n for i := 0; i \u003c b.N; i++ {\n // Run N-way collision and measure time\n testNCloneCollisionBench(b, n)\n }\n })\n }\n}\n```\n\n### 4. Add convergence time tests\nVerify bounded convergence:\n\n```go\nfunc TestConvergenceTime(t *testing.T) {\n // Test that convergence happens within expected rounds\n // For N clones, should converge in at most N-1 sync rounds\n \n for n := 3; n \u003c= 10; n++ {\n t.Run(fmt.Sprintf(\"N=%d\", n), func(t *testing.T) {\n rounds := measureConvergenceRounds(t, n)\n maxExpected := n - 1\n if rounds \u003e maxExpected {\n t.Errorf(\"Convergence took %d rounds, expected ≀ %d\", \n rounds, maxExpected)\n }\n })\n }\n}\n```\n\n### 5. Add edge case tests\nTest boundary conditions:\n- All N clones have identical content (dedup works)\n- N-1 clones have same content, 1 differs\n- All N clones have unique content\n- Mix of collisions and non-collisions\n\n## Acceptance Criteria\n- TestFiveCloneCollision passes with all sync orders\n- All 5 clones converge to identical content\n- Performance is acceptable (\u003c 5 seconds for 5 clones)\n- Convergence time is bounded (≀ N-1 rounds)\n- Edge cases handled correctly\n- Benchmarks show scalability to 10+ clones\n\n## Files to Create/Modify\n- beads_twoclone_test.go or beads_nway_test.go\n- Add helper functions for N-clone setup\n\n## Testing Strategy\n\n### Test Matrix\n| N Clones | Sync Orders | Expected Result |\n|----------|-------------|-----------------|\n| 3 | Aβ†’Bβ†’C | Pass |\n| 3 | Cβ†’Bβ†’A | Pass |\n| 5 | Aβ†’Bβ†’Cβ†’Dβ†’E | Pass |\n| 5 | Eβ†’Dβ†’Cβ†’Bβ†’A | Pass |\n| 5 | Random | Pass |\n| 10 | Sequential | Pass |\n\n### Performance Targets\n- 3 clones: \u003c 2 seconds\n- 5 clones: \u003c 5 seconds\n- 10 clones: \u003c 15 seconds\n\n## Dependencies\n- Requires bd-cbed9619.5, bd-cbed9619.4, bd-cbed9619.3, bd-cbed9619.2 to be completed\n- TestThreeCloneCollision must pass first\n\n## Success Metrics\n- All tests pass for N ∈ {3, 5, 10}\n- Convergence time scales linearly (O(N))\n- Memory usage reasonable (\u003c 100MB for 10 clones)\n- No data corruption or loss in any scenario","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-29T23:05:13.974702-07:00","updated_at":"2025-10-31T12:00:43.197709-07:00","closed_at":"2025-10-31T12:00:43.197709-07:00","source_repo":"."} -{"id":"bd-23a8","content_hash":"7c54bea4624429ff0842a192489979e0a1eafdd872027a0934b1a1d9b0e80d33","title":"Test simple issue","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-02T17:11:04.464726-08:00","updated_at":"2025-11-04T11:10:23.529727-08:00","closed_at":"2025-11-04T11:10:23.529731-08:00","source_repo":".","comments":[{"id":23,"issue_id":"bd-23a8","author":"stevey","text":"Testing the new bd comment alias!","created_at":"2025-11-23T01:48:48Z"},{"id":24,"issue_id":"bd-23a8","author":"stevey","text":"Another test with JSON output","created_at":"2025-11-23T01:48:48Z"},{"id":25,"issue_id":"bd-23a8","author":"stevey","text":"Test comment from file\n","created_at":"2025-11-23T01:48:48Z"}]} -{"id":"bd-23o5","content_hash":"dc62c5c254daa81626702505e55935227c0e30890acdc472be3846c6d1d29ed6","title":"Update FAQ: How does OpenSpec/spec-driven development relate to Beads?","description":"Answer the question raised in GH discussion #240 about OpenSpec integration.\n\nAnswer Summary:\n- Single-agent: OpenSpec β†’ Beads β†’ Code\n- Multi-agent swarm: Use Gastown as coordination layer\n- Gastown provides OpenSpec-style planning infrastructure\n- Planning agents create specs, distribute as Beads issues\n- 'Gastown plans, Beads remembers, Agents execute'\n\nAction Items:\n1. Add FAQ entry explaining the architecture layers\n2. Link to Gastown planning design (gt-cke)\n3. Reference discussion #240 and rbergman's insights\n4. Clarify: Beads focuses on execution memory, not planning\n\nCross-Reference:\n- Gastown issue gt-cke: Design OpenSpec-style planning layer\n- GH discussion #240: https://github.com/steveyegge/beads/discussions/240\n\nKeep FAQ concise - detailed architecture lives in Gastown docs.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-23T14:52:23.786022-08:00","updated_at":"2025-11-23T20:02:19.359507-08:00","closed_at":"2025-11-23T20:02:19.359507-08:00","source_repo":"."} +{"id":"bd-23a8","content_hash":"7c54bea4624429ff0842a192489979e0a1eafdd872027a0934b1a1d9b0e80d33","title":"Test simple issue","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-02T17:11:04.464726-08:00","updated_at":"2025-11-04T11:10:23.529727-08:00","closed_at":"2025-11-04T11:10:23.529731-08:00","source_repo":"."} +{"id":"bd-23o5","content_hash":"04d3d16335be256c76140f399e0b7fbf5432442df65ebccbca9d8cb86dc4472b","title":"Update FAQ: How does OpenSpec/spec-driven development relate to Beads?","description":"Answer the question raised in GH discussion #240 about OpenSpec integration.\n\nAnswer Summary:\n- Single-agent: OpenSpec β†’ Beads β†’ Code\n- Multi-agent swarm: Use Gastown as coordination layer\n- Gastown provides OpenSpec-style planning infrastructure\n- Planning agents create specs, distribute as Beads issues\n- 'Gastown plans, Beads remembers, Agents execute'\n\nAction Items:\n1. Add FAQ entry explaining the architecture layers\n2. Link to Gastown planning design (gt-cke)\n3. Reference discussion #240 and rbergman's insights\n4. Clarify: Beads focuses on execution memory, not planning\n\nCross-Reference:\n- Gastown issue gt-cke: Design OpenSpec-style planning layer\n- GH discussion #240: https://github.com/steveyegge/beads/discussions/240\n\nKeep FAQ concise - detailed architecture lives in Gastown docs.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-23T14:52:23.786022-08:00","updated_at":"2025-11-23T20:02:19.359507-08:00","closed_at":"2025-11-23T20:02:19.359507-08:00","source_repo":"."} {"id":"bd-248bdc3e","content_hash":"85c98bac3b48e3cc8466d1b60e4a690fe198c4f795160cf175d7add4691749b5","title":"Add optional post-merge git hook example for bd sync","description":"Create example git hook that auto-runs bd sync after git pull/merge.\n\nAdd to examples/git-hooks/:\n- post-merge hook that checks if .beads/issues.jsonl changed\n- If changed: run `bd sync` automatically\n- Make it optional/documented (not auto-installed)\n\nBenefits:\n- Zero-friction sync after git pull\n- Complements auto-detection as belt-and-suspenders\n\nNote: post-merge hook already exists for pre-commit/post-merge. Extend it to support sync.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-25T22:47:14.668842-07:00","updated_at":"2025-11-06T20:06:49.217298-08:00","closed_at":"2025-11-06T19:51:37.787964-08:00","source_repo":"."} {"id":"bd-2530","content_hash":"ac8bc0c4d75082ac76200d092b3c1c476fd1523c9e83b890f829ee3dd7dcbb3d","title":"Issue with labels","description":"This is a description","design":"Use MVC pattern","acceptance_criteria":"All tests pass","status":"closed","priority":0,"issue_type":"feature","created_at":"2025-10-31T21:40:34.630173-07:00","updated_at":"2025-11-01T11:11:57.93151-07:00","closed_at":"2025-11-01T11:11:57.93151-07:00","source_repo":".","labels":["bug","critical"]} {"id":"bd-2752a7a2","content_hash":"064b1ae28914d2cfcca93724e60636c13a6818883dbbb13322772ec93d814170","title":"Create cmd/bd/daemon_watcher.go (~150 LOC)","description":"Implement FileWatcher using fsnotify to watch JSONL file and git refs. Handle platform differences (inotify/FSEvents/ReadDirectoryChangesW). Include edge case handling for file rename, event storm, watcher failure.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-29T23:05:13.887269-07:00","updated_at":"2025-10-31T18:30:24.131535-07:00","closed_at":"2025-10-31T18:30:24.131535-07:00","source_repo":"."} @@ -88,7 +88,7 @@ {"id":"bd-2ifg","content_hash":"1a32ca6b21a14e121fc8e1026d83d85683cd3ff3b500f56eb8a05398b89ebf51","title":"bd-hv01: Silent partial deletion failures cause DB inconsistency","description":"Problem: deletion_tracking.go:76-77 logs deletion errors as warnings but continues. If deletion fails midway (database locked, disk full), some issues delete but others don't. System thinks all deletions succeeded.\n\nImpact: Database diverges from JSONL, silent corruption, issues may resurrect on next sync.\n\nFix: Collect errors and fail the operation:\nvar deletionErrors []error\nfor _, id := range acceptedDeletions {\n if err := d.DeleteIssue(ctx, id); err != nil {\n deletionErrors = append(deletionErrors, fmt.Errorf(\"issue %s: %w\", id, err))\n }\n}\nif len(deletionErrors) \u003e 0 {\n return false, fmt.Errorf(\"deletion failures: %v\", deletionErrors)\n}\n\nFiles: cmd/bd/deletion_tracking.go:73-82","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-06T18:16:19.465137-08:00","updated_at":"2025-11-06T18:46:55.901973-08:00","closed_at":"2025-11-06T18:46:55.901973-08:00","source_repo":".","dependencies":[{"issue_id":"bd-2ifg","depends_on_id":"bd-rbxi","type":"parent-child","created_at":"2025-11-06T18:19:14.833477-08:00","created_by":"daemon"}]} {"id":"bd-2ku7","content_hash":"65cee891959383f7c8862b54b72c4bafae950ee47eecb47f0f842e6c10c8ba04","title":"Test integration issue","description":"This is a real integration test","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-07T19:07:11.528577-08:00","updated_at":"2025-11-07T22:07:17.343154-08:00","closed_at":"2025-11-07T21:55:09.426381-08:00","source_repo":"."} {"id":"bd-2o2","content_hash":"ec587855e11cbd34569de5f35e4c68404eb7f20926595615e852f73821aec950","title":"Add cancellation and timeout tests","description":"Add comprehensive tests for context cancellation and timeout behavior.\n\n## Context\nPart of context propagation work. Validates that bd-rtp and bd-yb8 work correctly.\n\n## Test Coverage Needed\n\n### 1. Cancellation Tests\n- [ ] Import operation cancelled mid-stream\n- [ ] Export operation cancelled mid-stream \n- [ ] Database query cancelled during long operation\n- [ ] No corruption after cancellation\n- [ ] Proper cleanup (defers execute, connections closed)\n\n### 2. Timeout Tests\n- [ ] Operations respect context deadlines\n- [ ] Appropriate error messages on timeout\n- [ ] State remains consistent after timeout\n\n### 3. Signal Handling Tests\n- [ ] SIGINT (Ctrl+C) triggers cancellation\n- [ ] SIGTERM triggers graceful shutdown\n- [ ] Multiple signals handled correctly\n\n## Implementation Approach\n```go\nfunc TestImportCancellation(t *testing.T) {\n ctx, cancel := context.WithCancel(context.Background())\n \n // Start import in goroutine\n go func() {\n err := runImport(ctx, largeFile)\n assert.Error(err, context.Canceled)\n }()\n \n // Cancel after short delay\n time.Sleep(100 * time.Millisecond)\n cancel()\n \n // Verify database integrity\n assertDatabaseConsistent(t, store)\n}\n```\n\n## Files to Create/Update\n- cmd/bd/import_test.go - cancellation tests\n- cmd/bd/export_test.go - cancellation tests\n- internal/storage/sqlite/*_test.go - context timeout tests\n\n## Acceptance Criteria\n- [ ] All critical operations have cancellation tests\n- [ ] Tests verify database integrity after cancellation\n- [ ] Signal handling tested (if feasible)\n- [ ] Test coverage \u003e80% for context paths","status":"closed","priority":3,"issue_type":"task","created_at":"2025-11-20T21:27:22.854636-05:00","updated_at":"2025-11-20T21:40:25.882758-05:00","closed_at":"2025-11-20T21:40:25.882758-05:00","source_repo":".","labels":["testing"],"dependencies":[{"issue_id":"bd-2o2","depends_on_id":"bd-yb8","type":"blocks","created_at":"2025-11-20T21:27:22.855574-05:00","created_by":"daemon"}]} -{"id":"bd-2q6d","content_hash":"3aab5ad2047ec7357b9f6d4f15447dd46bf8705686b400e78df186928827703e","title":"Beads commands operate on stale database without warning","description":"All beads read operations should validate database is in sync with JSONL before proceeding.\n\n**Current Behavior:**\n- Commands can query/read from stale database\n- Only mutation operations (like 'bd sync') check if JSONL is newer\n- User gets incorrect results without realizing database is out of sync\n\n**Expected Behavior:**\n- All beads commands should have pre-flight check for database freshness\n- If JSONL is newer than database, refuse to operate with error: \"Database out of sync. Run 'bd import' first.\"\n- Same safety check that exists for 'bd sync' should apply to ALL operations\n\n**Impact:**\n- Users make decisions based on incomplete/outdated data\n- Silent failures lead to confusion (e.g., thinking issues don't exist when they do)\n- Similar to running git commands on stale repo without being warned to pull\n\n**Example:**\n- Searched for bd-g9eu issue file: not found\n- Issue exists in .beads/issues.jsonl (in git)\n- Database was stale, but no warning was given\n- Led to incorrect conclusion that issue was already closed/deleted","notes":"## Implementation Complete\n\n**Phase 1: Created staleness check (cmd/bd/staleness.go)**\n- ensureDatabaseFresh() function checks JSONL mtime vs last_import_time\n- Returns error with helpful message when database is stale\n- Auto-skips in daemon mode (daemon has auto-import)\n\n**Phase 2: Added to all read commands**\n- list, show, ready, status, stale, info, duplicates, validate\n- Check runs before database queries in direct mode\n- Daemon mode already protected via checkAndAutoImportIfStale()\n\n**Phase 3: Code Review Findings**\nSee follow-up issues:\n- bd-XXXX: Add warning when staleness check errors\n- bd-YYYY: Improve CheckStaleness error handling\n- bd-ZZZZ: Refactor redundant daemon checks (low priority)\n\n**Testing:**\n- Build successful: go build ./cmd/bd\n- Binary works: ./bd --version\n- Ready for manual testing\n\n**Next Steps:**\n1. Test with stale database scenario\n2. Implement review improvements\n3. Close issue when tests pass","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-20T19:33:40.019297-05:00","updated_at":"2025-11-23T20:39:55.302066-08:00","closed_at":"2025-11-23T20:38:17.526252-08:00","source_repo":".","comments":[{"id":26,"issue_id":"bd-2q6d","author":"stevey","text":"# Updated Analysis\n\n## Root Cause\n\nThe bug has multiple contributing factors:\n\n1. **Daemon mode bypasses auto-import**: When running in daemon mode (most common), the `PersistentPreRun` returns early (main.go:332) before reaching auto-import logic (main.go:451-467)\n\n2. **No staleness validation on reads**: Read operations (list, show, search) don't verify database is fresh before returning results\n\n3. **Auto-import can be disabled**: Users with `--no-auto-import` can unknowingly operate on stale data\n\n## Current Auto-Import Behavior\n\nAuto-import DOES exist and uses SHA256 hash comparison:\n- Location: `autoflush.go:autoImportIfNewer()`\n- Stores last import hash in DB metadata: `last_import_hash`\n- Runs in `PersistentPreRun` for direct mode only\n- Skipped for: import, delete, sync --dry-run commands\n\n## Proposed Solution\n\nAdd lightweight hash-based staleness check to all read operations:\n\n### Implementation Points:\n1. **Before ANY database read** (list, show, search, ready, etc.):\n ```go\n func ensureDatabaseFresh(ctx context.Context) error {\n // Get stored import hash from DB\n storedHash, _ := store.GetMetadata(ctx, \"last_import_hash\")\n \n // Compute current JSONL hash\n currentHash := computeJSONLHash(findJSONLPath())\n \n if currentHash != storedHash {\n if autoImportEnabled {\n // Try auto-import\n autoImportIfNewer()\n // Re-check - fail if still stale\n } else {\n return fmt.Errorf(\"database out of sync with JSONL. Run 'bd import' or enable auto-import\")\n }\n }\n return nil\n }\n ```\n\n2. **Add to daemon RPC handlers** - daemon mode currently has NO staleness checking\n\n3. **Make check fast** - hash comparison is O(1) if JSONL hash is cached\n\n### Benefits:\n- Works in both daemon and direct mode\n- Minimal performance overhead (just hash comparison)\n- Catches all staleness cases\n- Clear error messages guide users to fix\n- Defense in depth - doesn't rely solely on auto-import\n\n### Alternatives Considered:\n- **mtime comparison**: Unreliable after git operations\n- **Block all reads when stale**: Too aggressive, breaks workflows \n- **Only check on mutations**: Current bug - reads return stale data\n- **Only rely on auto-import**: Fails in daemon mode and when disabled\n\n## Files to Modify:\n- `cmd/bd/list.go` - add check before SearchIssues\n- `cmd/bd/show.go` - add check before GetIssue\n- `cmd/bd/ready.go` - add check before GetReadyWork\n- `internal/rpc/server.go` - add check in daemon RPC handlers\n- Create `cmd/bd/staleness.go` - shared staleness check function","created_at":"2025-11-23T01:48:48Z"},{"id":27,"issue_id":"bd-2q6d","author":"stevey","text":"## Implementation Tasks\n\n### Phase 1: Core Infrastructure\n- [ ] Create `cmd/bd/staleness.go` with `ensureDatabaseFresh()` function\n- [ ] Add unit tests for staleness detection\n- [ ] Handle edge cases (missing JSONL, missing hash, etc.)\n\n### Phase 2: Direct Mode Read Commands\n- [ ] Add check to `cmd/bd/list.go`\n- [ ] Add check to `cmd/bd/show.go`\n- [ ] Add check to `cmd/bd/ready.go`\n- [ ] Add check to `cmd/bd/blocked.go`\n- [ ] Add check to `cmd/bd/stale.go`\n- [ ] Integration tests for direct mode\n\n### Phase 3: Daemon Mode\n- [ ] Add staleness check to daemon RPC handlers in `internal/rpc/server.go`\n- [ ] Ensure daemon can access JSONL path\n- [ ] Integration tests for daemon mode\n\n### Phase 4: Polish\n- [ ] Performance testing (check should be \u003c10ms)\n- [ ] Error message clarity\n- [ ] Documentation updates","created_at":"2025-11-23T01:48:48Z"}]} +{"id":"bd-2q6d","content_hash":"3aab5ad2047ec7357b9f6d4f15447dd46bf8705686b400e78df186928827703e","title":"Beads commands operate on stale database without warning","description":"All beads read operations should validate database is in sync with JSONL before proceeding.\n\n**Current Behavior:**\n- Commands can query/read from stale database\n- Only mutation operations (like 'bd sync') check if JSONL is newer\n- User gets incorrect results without realizing database is out of sync\n\n**Expected Behavior:**\n- All beads commands should have pre-flight check for database freshness\n- If JSONL is newer than database, refuse to operate with error: \"Database out of sync. Run 'bd import' first.\"\n- Same safety check that exists for 'bd sync' should apply to ALL operations\n\n**Impact:**\n- Users make decisions based on incomplete/outdated data\n- Silent failures lead to confusion (e.g., thinking issues don't exist when they do)\n- Similar to running git commands on stale repo without being warned to pull\n\n**Example:**\n- Searched for bd-g9eu issue file: not found\n- Issue exists in .beads/issues.jsonl (in git)\n- Database was stale, but no warning was given\n- Led to incorrect conclusion that issue was already closed/deleted","notes":"## Implementation Complete\n\n**Phase 1: Created staleness check (cmd/bd/staleness.go)**\n- ensureDatabaseFresh() function checks JSONL mtime vs last_import_time\n- Returns error with helpful message when database is stale\n- Auto-skips in daemon mode (daemon has auto-import)\n\n**Phase 2: Added to all read commands**\n- list, show, ready, status, stale, info, duplicates, validate\n- Check runs before database queries in direct mode\n- Daemon mode already protected via checkAndAutoImportIfStale()\n\n**Phase 3: Code Review Findings**\nSee follow-up issues:\n- bd-XXXX: Add warning when staleness check errors\n- bd-YYYY: Improve CheckStaleness error handling\n- bd-ZZZZ: Refactor redundant daemon checks (low priority)\n\n**Testing:**\n- Build successful: go build ./cmd/bd\n- Binary works: ./bd --version\n- Ready for manual testing\n\n**Next Steps:**\n1. Test with stale database scenario\n2. Implement review improvements\n3. Close issue when tests pass","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-20T19:33:40.019297-05:00","updated_at":"2025-11-23T20:39:55.302066-08:00","closed_at":"2025-11-23T20:38:17.526252-08:00","source_repo":"."} {"id":"bd-3","content_hash":"41ae09ef713b88fa3724ae81a255c55eb336b66c2a4173b6146bc298286021ba","title":"Investigate and upgrade to modernc.org/sqlite 1.39.1+","description":"We had to pin modernc.org/sqlite to v1.38.2 due to a FOREIGN KEY constraint regression in v1.39.1 (SQLite 3.50.4).\n\n**Issue:** [deleted:bd-47], GH #144\n\n**Symptom:** CloseIssue fails with \"FOREIGN KEY constraint failed (787)\" when called via MCP/daemon, but works fine via CLI.\n\n**Root Cause:** Unknown - likely stricter FK enforcement in SQLite 3.50.4 or modernc.org wrapper changes.\n\n**Workaround:** Pinned to v1.38.2 (SQLite 3.49.x)\n\n**TODO:**\n1. Monitor modernc.org/sqlite releases for fixes\n2. Check SQLite 3.50.5+ changelogs for FK-related fixes\n3. Investigate why daemon mode fails but CLI succeeds (connection reuse? transaction isolation?)\n4. Consider filing upstream issue with reproducible test case\n5. Upgrade when safe","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-07T09:43:47.856354-08:00","updated_at":"2025-11-07T15:06:26.240131-08:00","closed_at":"2025-11-07T15:06:26.240131-08:00","source_repo":"."} {"id":"bd-307","content_hash":"6c1bda0d392414f4bb16f078a18f3958a869d3d1ed72bde6cc9012739eae88ef","title":"Multi-repo hydration layer","description":"Build core infrastructure to hydrate database from N repos (Nβ‰₯1), with smart caching via file mtime tracking and routing writes to correct JSONL based on source_repo metadata.","design":"Components:\n- Config schema for repos.additional\n- source_repo metadata field (which repo owns each issue)\n- Hydration logic (read from N JSONLs)\n- Write routing (write to correct JSONL)\n- Smart caching (file mtime tracking to avoid re-parsing)\n- SQLite DB as cache layer","acceptance_criteria":"1. Can configure N repos via config.toml\n2. Database hydrates from all configured repos\n3. Writes route to correct JSONL via source_repo\n4. File mtime caching prevents re-parsing unchanged JSONLs\n5. Query performance \u003c100ms even with 5-10 polling interval\n6. N=1 (single repo) works unchanged","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-11-04T11:21:30.655765-08:00","updated_at":"2025-11-05T00:08:42.811877-08:00","closed_at":"2025-11-05T00:08:42.811879-08:00","source_repo":".","dependencies":[{"issue_id":"bd-307","depends_on_id":"bd-4ms","type":"parent-child","created_at":"2025-11-04T11:22:21.823652-08:00","created_by":"daemon"}]} {"id":"bd-317ddbbf","content_hash":"81a74ccf29037e5a780b12540a4059bab98b9a790a5a043a68118fc00a083cda","title":"Add BEADS_DAEMON_MODE flag handling","description":"Add environment variable BEADS_DAEMON_MODE (values: poll, events). Default to 'poll' for Phase 1. Wire into daemon startup to select runEventLoop vs runEventDrivenLoop.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-28T16:20:02.433638-07:00","updated_at":"2025-10-30T17:12:58.224373-07:00","closed_at":"2025-10-28T12:31:47.819136-07:00","source_repo":"."} @@ -143,7 +143,7 @@ {"id":"bd-4oqu","content_hash":"9d7a6f8fc07220e96e0d1b509579b9d7a292ffc52720b8bc78e5523743a18e38","title":"Test parent issue","description":"","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-11-05T13:00:39.737739-08:00","updated_at":"2025-11-05T13:01:11.635711-08:00","closed_at":"2025-11-05T13:01:11.635711-08:00","source_repo":"."} {"id":"bd-4oqu.1","content_hash":"fbeac3089798c66a2c85aa49d5abdc050a38c3c31209599ae1f2117c8ba9f180","title":"Test child direct","description":"","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-05T13:00:55.992712-08:00","updated_at":"2025-11-05T13:01:11.654435-08:00","closed_at":"2025-11-05T13:01:11.654435-08:00","source_repo":"."} {"id":"bd-4oqu.2","content_hash":"3dfea0ba8e0bfa2424411e65f9fc549af6edecb1490cee786a08d8ceff4c2ed6","title":"Test child daemon mode","description":"","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-05T13:01:06.642305-08:00","updated_at":"2025-11-05T13:01:11.669369-08:00","closed_at":"2025-11-05T13:01:11.669369-08:00","source_repo":"."} -{"id":"bd-4owj","content_hash":"dfe9fb665d2b51a55763759691cb7ca4e5cebfeeb3bf3bacaaa41a4c202a0635","title":"Fix race condition in client socket cleanup (client.go)","description":"**Location:** internal/rpc/client.go:44-76\n\n**Issue:** TryConnectWithTimeout() has race window between socket existence check and lock file check.\n\n**Problematic Sequence:**\n```go\nsocketExists := endpointExists(socketPath) // line 56\nif !socketExists {\n beadsDir := filepath.Dir(socketPath)\n running, _ := lockfile.TryDaemonLock(beadsDir) // line 61\n // RACE: socket could've been deleted between lines 56 and 61\n}\n```\n\n**Impact:** Could incorrectly report daemon as running when it crashed. Socket gets deleted during cleanup but lock file still held temporarily.\n\n**Fix:** Combine checks atomically or use transactional approach with proper locking.","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-11-23T19:46:51.375018-08:00","updated_at":"2025-11-23T20:57:38.757398-08:00","closed_at":"2025-11-23T20:57:38.757398-08:00","source_repo":"."} +{"id":"bd-4owj","content_hash":"4875cb2304119ab88a052b5a712dbf08fd6a54b15bf17677d74db04ddd09f8a8","title":"Fix race condition in client socket cleanup (client.go)","description":"**Location:** internal/rpc/client.go:44-76\n\n**Issue:** TryConnectWithTimeout() has race window between socket existence check and lock file check.\n\n**Problematic Sequence:**\n```go\nsocketExists := endpointExists(socketPath) // line 56\nif !socketExists {\n beadsDir := filepath.Dir(socketPath)\n running, _ := lockfile.TryDaemonLock(beadsDir) // line 61\n // RACE: socket could've been deleted between lines 56 and 61\n}\n```\n\n**Impact:** Could incorrectly report daemon as running when it crashed. Socket gets deleted during cleanup but lock file still held temporarily.\n\n**Fix:** Combine checks atomically or use transactional approach with proper locking.","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-11-23T19:46:51.375018-08:00","updated_at":"2025-11-23T20:57:38.757398-08:00","closed_at":"2025-11-23T20:57:38.757398-08:00","source_repo":"."} {"id":"bd-4ri","content_hash":"ecd7ab50ad20a55a52ce62fca06c31b885918c3ef00d924480967d171ed8ed4a","title":"Fix TestFallbackToDirectModeEnablesFlush deadlock causing 10min test timeout","description":"## Problem\n\nTestFallbackToDirectModeEnablesFlush in direct_mode_test.go deadlocks for 9m59s before timing out, causing the entire test suite to take 10+ minutes instead of \u003c10 seconds.\n\n## Root Cause\n\nDatabase lock contention between test cleanup and flushToJSONL():\n- Test cleanup (line 36) tries to close DB via defer\n- flushToJSONL() (line 132) is still accessing DB\n- Results in deadlock: database/sql.(*DB).Close() waits for mutex while GetJSONLFileHash() holds it\n\n## Stack Trace Evidence\n\n```\ngoroutine 512 [sync.Mutex.Lock, 9 minutes]:\ndatabase/sql.(*DB).Close(0x14000643790)\n .../database/sql/sql.go:927 +0x84\ngithub.com/steveyegge/beads/cmd/bd.TestFallbackToDirectModeEnablesFlush.func1()\n .../direct_mode_test.go:36 +0xf4\n\nWhile goroutine running flushToJSONL() holds DB connection via GetJSONLFileHash()\n```\n\n## Impact\n\n- Test suite: 10+ minutes β†’ should be \u003c10 seconds\n- ALL other tests pass in ~4 seconds\n- This ONE test accounts for 99.9% of test runtime\n\n## Related\n\nThis is the EXACT same issue documented in MAIN_TEST_REFACTOR_NOTES.md for why main_test.go refactoring was deferred - global state manipulation + DB cleanup = deadlock.\n\n## Fix Approaches\n\n1. **Add proper cleanup sequencing** - stop flush goroutines BEFORE closing DB\n2. **Use test-specific DB lifecycle** - ensure flush completes before cleanup\n3. **Mock the flush mechanism** - avoid real DB for testing this code path \n4. **Add explicit timeout handling** - fail fast with clear error instead of hanging\n\n## Files\n\n- cmd/bd/direct_mode_test.go:36-132\n- cmd/bd/autoflush.go:353 (validateJSONLIntegrity)\n- cmd/bd/autoflush.go:508 (flushToJSONLWithState)\n\n## Acceptance\n\n- Test passes without timeout\n- Test suite completes in \u003c10 seconds\n- No deadlock between cleanup and flush operations","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-21T20:09:00.794372-05:00","updated_at":"2025-11-23T15:15:00.482016-08:00","closed_at":"2025-11-23T15:15:00.482019-08:00","source_repo":"."} {"id":"bd-4ry","content_hash":"fc0b5a708c2cbef610437e2bd8dab08712d2b151becbe2080db1bc52ff4c03fa","title":"Clarify JSONL size bounds with multi-repo","description":"The contributor-workflow-analysis.md states (line 226): 'Keep beads.jsonl small enough for agents to read (\u003c25k)'\n\nWith multi-repo hydration, it's unclear whether this bound applies to:\n- Each individual JSONL file (likely intention)\n- The total hydrated size across all repos (unclear)\n- Both (most conservative)\n\nClarification needed because:\n- VC monitors .beads/issues.jsonl size to stay under limit\n- With multi-repo, VC needs to know if each additional repo also has 25k limit\n- Agents reading hydrated data need to know total size bounds\n- Performance characteristics depend on total vs per-repo limits\n\nExample scenario:\n- Primary repo: 20k JSONL\n- Planning repo: 15k JSONL\n- Total hydrated: 35k\nIs this acceptable or does it violate the \u003c25k principle?","acceptance_criteria":"- Documentation explicitly states size bound applies per-repo or total\n- Rationale explained (why that bound matters)\n- Guidance for monitoring size with multi-repo\n- If total bound exists, formula provided (e.g., sum of all repos \u003c25k)","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-03T20:24:50.042748-08:00","updated_at":"2025-11-05T14:18:00.550341-08:00","closed_at":"2025-11-05T14:18:00.550341-08:00","source_repo":"."} {"id":"bd-502e","content_hash":"0f40053f59ff205d858a9ddf0be845df1d52471cc25a812df78cb3d4667efbdd","title":"Add comprehensive tests for sync branch daemon logic","description":"The daemon sync branch functionality (bd-6545) was implemented but needs proper end-to-end testing.\n\nCurrent implementation:\n- daemon_sync_branch.go has syncBranchCommitAndPush() and syncBranchPull()\n- daemon_sync.go has been updated to use these functions when sync.branch is configured\n- All daemon tests pass, but no specific tests for sync branch behavior\n\nTesting needed:\n- Test that daemon commits to sync branch when sync.branch is configured\n- Test that daemon commits to current branch when sync.branch is NOT configured (backward compatibility)\n- Test that daemon pulls from sync branch and syncs JSONL back to main repo\n- Test worktree creation and health checks during daemon operations\n- Test error handling (missing branch, worktree corruption, etc.)\n\nKey challenge: Tests need to run in the context of the git repo (getGitRoot() uses current working directory), so test setup needs to properly change directory or mock the git root detection.\n\nReference existing daemon tests in daemon_test.go and daemon_autoimport_test.go for patterns.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-02T15:59:13.341491-08:00","updated_at":"2025-11-02T16:39:53.278313-08:00","closed_at":"2025-11-02T16:39:53.278313-08:00","source_repo":".","dependencies":[{"issue_id":"bd-502e","depends_on_id":"bd-6545","type":"parent-child","created_at":"2025-11-02T15:59:13.342331-08:00","created_by":"daemon"}]} @@ -168,14 +168,14 @@ {"id":"bd-5f26","content_hash":"5131931d43040061d669159635de863740ed90e7c946c4b646c36c53bc274d6f","title":"Refactor daemon.go into internal/daemonrunner","description":"Extract daemon runtime from daemon.go (1,565 lines) into internal/daemonrunner with focused modules: config.go, daemon.go, process.go, rpc_server.go, sync.go, git.go. Keep cobra command thin.","design":"New structure:\n- internal/daemonrunner/config.go: Config struct\n- internal/daemonrunner/daemon.go: Daemon struct + Start/Stop\n- internal/daemonrunner/process.go: PID/lock/socket handling\n- internal/daemonrunner/rpc_server.go: RPC lifecycle\n- internal/daemonrunner/sync.go: Export/import/commit/push logic\n- internal/daemonrunner/git.go: Git operations interface\n- cmd/bd/daemon.go: Thin cobra command","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-11-01T11:41:14.821017-07:00","updated_at":"2025-11-01T21:44:44.507747-07:00","closed_at":"2025-11-01T21:44:44.507747-07:00","source_repo":"."} {"id":"bd-5f483051","content_hash":"c14449fb07074c3ff76a653cc632f5795e2e0fb8f381c5f1a1f0dd831fe4f13f","title":"Implement bd resolve-conflicts (git merge conflicts in JSONL)","description":"Automatically detect and resolve git merge conflicts in .beads/issues.jsonl file.\n\nFeatures:\n- Detect conflict markers in JSONL\n- Parse conflicting issues from HEAD and BASE\n- Provide mechanical resolution (remap duplicate IDs)\n- Support AI-assisted resolution (requires internal/ai package)\n\nSee repair_commands.md lines 125-353 for design.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-28T19:37:55.722827-07:00","updated_at":"2025-11-06T19:36:13.970903-08:00","closed_at":"2025-11-06T19:26:45.397628-08:00","source_repo":"."} {"id":"bd-5ghm","content_hash":"c59589bb7dfd39111a6b0f2283ff014f282441c9a0568bec2b674b58835e9609","title":"Fix Windows test failure: TestNewSQLiteStorage cleanup error","description":"On Windows, TestNewSQLiteStorage fails during cleanup because the database file is still in use when t.TempDir() tries to clean up. \n\nTest failure: testing.go:1267: TempDir RemoveAll cleanup: remove C:\\Users\\RUNNER~1\\AppData\\Local\\Temp\\TestNewSQLiteStorage2543917185\\001\\test.db: The process cannot access the file because it is being used by another process.\n\nRoot cause: SQLite database connection not being properly closed before test ends. Need to ensure store.Close() is called or add defer close pattern.","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-11-23T20:16:26.552924-08:00","updated_at":"2025-11-23T21:16:32.851916-08:00","closed_at":"2025-11-23T21:11:58.482348-08:00","source_repo":"."} -{"id":"bd-5ibn","content_hash":"3e651d081ea1dec7e5e30aaa2f9f521f3b9eaff7832d0dd55e5e6f89525f6b94","title":"Latency test 1","description":"","notes":"Resetting stale in_progress status from old executor run (yesterday)","status":"open","priority":3,"issue_type":"task","created_at":"2025-11-20T12:16:30.703754-05:00","updated_at":"2025-11-21T14:38:35.458351-05:00","source_repo":"."} +{"id":"bd-5ibn","content_hash":"3e651d081ea1dec7e5e30aaa2f9f521f3b9eaff7832d0dd55e5e6f89525f6b94","title":"Latency test 1","description":"","notes":"Resetting stale in_progress status from old executor run (yesterday)","status":"open","priority":3,"issue_type":"task","created_at":"2025-11-20T12:16:30.703754-05:00","updated_at":"2025-11-23T17:20:17.497218-08:00","source_repo":"."} {"id":"bd-5iv","content_hash":"229ad9764bd3eb8b09441adefce960aede63fd1b5466d52cc74f112f5bb610ac","title":"Test Epic","description":"## Overview\n\n[Describe the high-level goal and scope of this epic]\n\n## Success Criteria\n\n- [ ] Criteria 1\n- [ ] Criteria 2\n- [ ] Criteria 3\n\n## Background\n\n[Provide context and motivation]\n\n## Scope\n\n**In Scope:**\n- Item 1\n- Item 2\n\n**Out of Scope:**\n- Item 1\n- Item 2\n","design":"## Architecture\n\n[Describe the overall architecture and approach]\n\n## Components\n\n- Component 1: [description]\n- Component 2: [description]\n\n## Dependencies\n\n[List external dependencies or constraints]\n","acceptance_criteria":"- [ ] All child issues are completed\n- [ ] Integration tests pass\n- [ ] Documentation is updated\n- [ ] Code review completed\n","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-11-03T20:15:03.864229-08:00","updated_at":"2025-11-05T00:25:06.538749-08:00","closed_at":"2025-11-05T00:25:06.538749-08:00","source_repo":".","labels":["epic"]} {"id":"bd-5ki8","content_hash":"d89e5e528819934bcb7ee162fa7e32c27298db5816ecf51bcc8ede1809f1d5b9","title":"Add integration tests for adapter library","description":"Test suite for beads_mail_adapter.py covering all scenarios.\n\nAcceptance Criteria:\n- Test enabled mode (server available)\n- Test disabled mode (server unavailable)\n- Test graceful degradation (server dies mid-operation)\n- Test reservation conflicts\n- Test message sending/receiving\n- Mock HTTP server for testing\n- 90%+ code coverage\n\nFile: lib/test_beads_mail_adapter.py","notes":"Test suite completed with 29 comprehensive tests covering:\n- Enabled mode (server available): 10 tests\n- Disabled mode (server unavailable): 2 tests \n- Graceful degradation: 4 tests\n- Reservation conflicts: 2 tests\n- Configuration: 5 tests\n- Health check scenarios: 3 tests\n- HTTP error handling: 3 tests\n\n**Performance**: All tests run in 10ms (fast!)\n\n**Coverage highlights**:\nβœ… Server health checks (ok, degraded, error, timeout)\nβœ… All API operations (reserve, release, notify, check_inbox, get_reservations)\nβœ… HTTP errors (404, 409 conflict, 500, 503)\nβœ… Network errors (timeout, connection refused)\nβœ… Malformed responses (bad JSON, empty body, plain text errors)\nβœ… Environment variable configuration\nβœ… Graceful degradation when server dies mid-operation\nβœ… Conflict handling with both JSON and plain text errors\nβœ… Dict wrapper responses ({\"messages\": [...]} and {\"reservations\": [...]})\nβœ… Custom TTL for reservations\nβœ… Default agent name fallback\n\nNo external dependencies, no slow integration tests, just fast unit tests with mocks.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-07T22:43:21.294596-08:00","updated_at":"2025-11-08T01:32:39.906342-08:00","closed_at":"2025-11-08T01:32:39.906342-08:00","source_repo":".","dependencies":[{"issue_id":"bd-5ki8","depends_on_id":"bd-m9th","type":"blocks","created_at":"2025-11-07T22:43:21.296024-08:00","created_by":"daemon"}]} {"id":"bd-5otr","content_hash":"d08e4780fc80ffd39e678cab64038d50c31ccf842d2d9f4e6e598746324f2711","title":"Create startup hook snippet for upgrade detection","description":"Provide a reusable startup hook that agents can use to detect bd upgrades automatically.\n\n## What to Create\nA bash script snippet that:\n1. Reads current bd version\n2. Compares to last-seen version in metadata.json\n3. Shows 'bd info --whats-new' output when version changes\n4. Updates metadata.json with new version\n5. Auto-runs 'bd hooks install' if hooks outdated\n\n## Where to Document\n- Create examples/hooks/startup-version-check.sh\n- Document in AGENTS.md with usage instructions\n- Add comment header explaining how to integrate with Claude Code, Cursor, etc.\n\n## Key Features\n- Works today with zero bd code changes\n- Leverages existing bd info --whats-new\n- Uses metadata.json for persistence\n- Auto-fixes outdated git hooks\n\n## Acceptance Criteria\n- Script works standalone\n- Clear integration instructions for popular AI environments\n- Handles edge cases (no metadata.json, first run, etc.)\n","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-23T16:21:52.07179-08:00","updated_at":"2025-11-23T16:29:30.969796-08:00","closed_at":"2025-11-23T16:29:30.969796-08:00","source_repo":".","dependencies":[{"issue_id":"bd-5otr","depends_on_id":"bd-nxgk","type":"parent-child","created_at":"2025-11-23T16:21:52.073748-08:00","created_by":"daemon"}]} {"id":"bd-5ots","content_hash":"ba3efab3e7a2b9bb2bd2dba3aace56cfbdd1b67efd1cfc4758d9c79919f632af","title":"SearchIssues N+1 query causes context timeout with GetLabels","description":"scanIssues() calls GetLabels in a loop for every issue, causing N+1 queries and context deadline exceeded errors when used with short timeouts or in-memory databases. This is especially problematic since SearchIssues already supports label filtering via SQL WHERE clauses.","acceptance_criteria":"- Optimize scanIssues to batch-load labels for all issues in one query\n- Or make label loading optional/lazy\n- Add test that calls SearchIssues repeatedly with label filters and short context timeouts","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-05T19:12:02.245879-08:00","updated_at":"2025-11-05T19:22:11.668682-08:00","closed_at":"2025-11-05T19:22:11.668682-08:00","source_repo":"."} {"id":"bd-5qim","content_hash":"33624c08883ff2b896f3274bd2180057030f7a66b96571b530bd266b14b26cea","title":"Optimize GetReadyWork performance - 752ms on 10K database (target: \u003c50ms)","description":"","notes":"# Performance Analysis (10K Issue Database)\n\nAnalyzed using CPU profiles from benchmark suite on Apple M2 Pro.\n\n## βœ… OPTIMIZATION COMPLETE\n\n**Current Performance (as of 2025-11-23):**\n- **10K database**: ~29ms (167K allocs, 16MB) βœ… **Target met!**\n- **20K database**: ~60ms (338K allocs, 53MB) - Acceptable for scale\n- **Original**: 752ms (before optimization)\n- **Improvement**: **25.8x faster** πŸŽ‰\n\n## Implementation\n\nThe cache optimization has been successfully implemented:\n\n1. βœ… **blocked_issues_cache table** (migration 015)\n - Materializes recursive CTE computation\n - Rebuilt on dependency/status changes\n - See: `internal/storage/sqlite/blocked_cache.go`\n\n2. βœ… **Cache invalidation triggers**\n - On dependency add/remove (`dependencies.go:156, 212`)\n - On status changes (`queries.go:521, 695`)\n - Only for 'blocks' and 'parent-child' dependency types\n\n3. βœ… **Database indexes verified**\n - `idx_dependencies_depends_on_type_issue`\n - `idx_dependencies_depends_on_type`\n - `idx_issues_status`\n - All recommended indexes in place\n\n## Benchmark Results\n\n```\nBenchmarkGetReadyWork_Large-10 (10K issues)\n 29ms per operation\n 167,447 allocations\n 15.9 MB allocated\n\nBenchmarkGetReadyWork_XLarge-10 (20K issues)\n 60ms per operation\n 337,819 allocations\n 53.4 MB allocated\n```\n\n## Original Performance Analysis\n\n| Operation | Time | Allocations | Memory |\n|----------------------------------|---------|-------------|--------|\n| bd ready (GetReadyWork) | ~752ms | 167,466 | 16MB |\n| bd list (SearchIssues no filter) | ~11.6ms | 89,214 | 5.8MB |\n| bd list (SearchIssues filtered) | ~9.2ms | 62,365 | 3.5MB |\n\n**Target: \u003c50ms for all operations on 10K database** βœ… **ACHIEVED**\n\n## Root Cause (Now Fixed)\n\nGetReadyWork originally used recursive CTE to propagate blocking on every call:\n- 65x slower than SearchIssues\n- Recalculated entire blocked issue tree on every call\n- Database syscalls: ~75% of CPU time\n\n## Solution\n\nCache-based approach implemented:\n- `blocked_issues_cache` table stores pre-computed blocked issues\n- Invalidated only when dependencies or issue status changes\n- Read queries use simple `NOT EXISTS` lookup instead of recursive CTE\n- Write complexity traded for read speed (ready called \u003e\u003e dependency changes)\n\n## Verification\n\nRun benchmarks to validate:\n```bash\ngo test -tags=bench -bench='BenchmarkGetReadyWork.*' -benchmem ./internal/storage/sqlite/\n```\n\nProfile files automatically generated in `internal/storage/sqlite/bench-cpu-*.prof`","status":"closed","priority":0,"issue_type":"bug","created_at":"2025-11-14T09:02:46.507526-08:00","updated_at":"2025-11-23T20:32:54.703672-08:00","closed_at":"2025-11-23T19:58:15.949755-08:00","source_repo":"."} -{"id":"bd-5xt","content_hash":"1a44abd45874666cea2170bb3559934f72acf3b5171d0b587cc49eef386e110d","title":"Log errors from timer-triggered flushes instead of discarding","description":"","status":"closed","priority":3,"issue_type":"task","created_at":"2025-11-20T21:22:06.694953-05:00","updated_at":"2025-11-21T10:59:00.406689-05:00","closed_at":"2025-11-20T21:35:53.117434-05:00","source_repo":".","comments":[{"id":20,"issue_id":"bd-5xt","author":"stevey","text":"In FlushManager.run() at flush_manager.go:197-200, timer-triggered flushes silently discard errors:\n\n```go\ncase \u003c-fm.timerFiredCh:\n if isDirty {\n _ = fm.performFlush(needsFullExport) // ← Error discarded!\n```\n\nUsers won't know if auto-flush is failing. Should at minimum log errors.\n\nConsider:\n- Log error with debug.Logf() or fmt.Fprintf(os.Stderr)\n- Optionally expose flush status via a Status() method\n- Track last flush error for diagnostics\n\nRelated: Code review finding #4 from bd-52 race condition fix review.","created_at":"2025-11-21T15:59:00Z"}]} -{"id":"bd-6049","content_hash":"16c54bc547f4ab180aee39efbb197709a47a39047f5bc2dd59e6e6b57ca8bc87","title":"bd doctor --json flag not working","description":"The --json flag on bd doctor command doesn't produce JSON output. It continues to show human-readable output instead. The flag is registered locally on doctorCmd but the code uses the global jsonOutput variable set by PersistentPreRun. Need to investigate why the flag isn't being honored.","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-11-02T17:08:18.170428-08:00","updated_at":"2025-11-02T18:41:01.376783-08:00","closed_at":"2025-11-02T18:41:01.376786-08:00","source_repo":".","comments":[{"id":28,"issue_id":"bd-6049","author":"stevey","text":"Fixed by removing the local --json flag definition in doctor.go that was shadowing the persistent --json flag from main.go. The doctor command now correctly uses the global jsonOutput variable.","created_at":"2025-11-23T01:48:48Z"}]} +{"id":"bd-5xt","content_hash":"1a44abd45874666cea2170bb3559934f72acf3b5171d0b587cc49eef386e110d","title":"Log errors from timer-triggered flushes instead of discarding","description":"","status":"closed","priority":3,"issue_type":"task","created_at":"2025-11-20T21:22:06.694953-05:00","updated_at":"2025-11-21T10:59:00.406689-05:00","closed_at":"2025-11-20T21:35:53.117434-05:00","source_repo":"."} +{"id":"bd-6049","content_hash":"16c54bc547f4ab180aee39efbb197709a47a39047f5bc2dd59e6e6b57ca8bc87","title":"bd doctor --json flag not working","description":"The --json flag on bd doctor command doesn't produce JSON output. It continues to show human-readable output instead. The flag is registered locally on doctorCmd but the code uses the global jsonOutput variable set by PersistentPreRun. Need to investigate why the flag isn't being honored.","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-11-02T17:08:18.170428-08:00","updated_at":"2025-11-02T18:41:01.376783-08:00","closed_at":"2025-11-02T18:41:01.376786-08:00","source_repo":"."} {"id":"bd-6214875c","content_hash":"d4d20e71bbf5c08f1fe1ed07f67b7554167aa165d4972ea51b5cacc1b256c4c1","title":"Split internal/rpc/server.go into focused modules","description":"The file `internal/rpc/server.go` is 2,273 lines with 50+ methods, making it difficult to navigate and prone to merge conflicts. Split into 8 focused files with clear responsibilities.\n\nCurrent structure: Single 2,273-line file with:\n- Connection handling\n- Request routing\n- All 40+ RPC method implementations\n- Storage caching\n- Health checks \u0026 metrics\n- Cleanup loops\n\nTarget structure:\n```\ninternal/rpc/\nβ”œβ”€β”€ server.go # Core server, connection handling (~300 lines)\nβ”œβ”€β”€ methods_issue.go # Issue operations (~400 lines)\nβ”œβ”€β”€ methods_deps.go # Dependency operations (~200 lines)\nβ”œβ”€β”€ methods_labels.go # Label operations (~150 lines)\nβ”œβ”€β”€ methods_ready.go # Ready work queries (~150 lines)\nβ”œβ”€β”€ methods_compact.go # Compaction operations (~200 lines)\nβ”œβ”€β”€ methods_comments.go # Comment operations (~150 lines)\nβ”œβ”€β”€ storage_cache.go # Storage caching logic (~300 lines)\n└── health.go # Health \u0026 metrics (~200 lines)\n```\n\nMigration strategy:\n1. Create new files with appropriate methods\n2. Keep `server.go` as main file with core server logic\n3. Test incrementally after each file split\n4. Final verification with full test suite","acceptance_criteria":"- All 50 methods split into appropriate files\n- Each file \u003c500 LOC\n- All methods remain on `*Server` receiver (no behavior change)\n- All tests pass: `go test ./internal/rpc/...`\n- Verify daemon works: start daemon, run operations, check health\n- Update internal documentation if needed\n- No change to public API","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-28T14:21:37.51524-07:00","updated_at":"2025-10-30T17:12:58.2179-07:00","closed_at":"2025-10-28T14:11:04.399811-07:00","source_repo":"."} {"id":"bd-6221bdcd","content_hash":"6749091ed73f5ec7b55af226b2ae8c9aa134759951435e08e65a363c674ea0c9","title":"Optimize cmd/bd test suite performance (currently 30+ minutes)","description":"CLI test suite is extremely slow (~30+ minutes for full run). Tests are poorly designed and need performance optimization before expanding coverage.\n\nCurrent coverage: 24.8% (improved from 20.2%)\n\n**Problem**: Tests take far too long to run, making development iteration painful.\n\n**Priority**: Fix test performance FIRST, then consider increasing coverage.\n\n**Investigation needed**:\n- Profile test execution to identify bottlenecks\n- Look for redundant git operations, database initialization, or daemon operations\n- Identify opportunities for test parallelization\n- Consider mocking or using in-memory databases where appropriate\n- Review test design patterns\n\n**Related**: bd-ktng mentions 13 CLI tests with redundant git init calls (31s total)\n\n**Goal**: Get full test suite under 1-2 minutes before adding more tests.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-29T14:06:27.951656-07:00","updated_at":"2025-11-08T22:42:08.862178-08:00","closed_at":"2025-11-08T22:41:05.766749-08:00","source_repo":".","dependencies":[{"issue_id":"bd-6221bdcd","depends_on_id":"bd-4d7fca8a","type":"blocks","created_at":"2025-10-29T19:52:05.532391-07:00","created_by":"import-remap"}]} {"id":"bd-627d","content_hash":"5b3d3d69ceac28dcbfbc2c7ea2f7a6ff2a3a02bc58ce02dcf6b05f8469e8bddc","title":"AI-supervised database migrations for safer schema evolution","description":"## Problem\n\nDatabase 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.\n\n## Current State\n\nMigrations run blindly with:\n- No pre-flight validation\n- No data integrity verification\n- No rollback on failure\n- Limited post-migration testing\n\nRecent issues:\n- GH #201: Migration didn't set issue_prefix config, breaking commands\n- bd-d355a07d: False positive \"data loss\" warnings on collision resolution\n- Users reported migration data loss (fixed but broader problem remains)\n\n## Proposal: AI-Supervised Migration Framework\n\nUse AI to supervise migrations through structured verification:\n\n### 1. Pre-Migration Analysis\n- AI reads migration code and current schema\n- Identifies potential data loss scenarios\n- Generates validation queries to verify assumptions\n- Creates snapshot queries for before/after comparison\n\n### 2. Migration Execution\n- Take database backup/snapshot\n- Run validation queries (pre-state)\n- Execute migration in transaction\n- Run validation queries (post-state)\n\n### 3. Post-Migration Verification\n- AI compares pre/post snapshots\n- Verifies data integrity invariants\n- Checks for unexpected data loss\n- Validates config completeness (like issue_prefix)\n\n### 4. Rollback on Anomalies\n- If AI detects data loss, rollback transaction\n- Present human-readable error report\n- Suggest fix before retrying\n\n## Example Flow\n\n```\n$ bd migrate\n\nβ†’ Analyzing migration plan...\nβ†’ AI identified 3 potential data loss scenarios\nβ†’ Generating validation queries...\nβ†’ Creating pre-migration snapshot...\nβ†’ Running migration in transaction...\nβ†’ Verifying post-migration state...\nβœ“ All 247 issues accounted for\nβœ“ Config table complete (issue_prefix: \"mcp\")\nβœ“ Dependencies intact (342 relationships verified)\nβ†’ Migration successful!\n```\n\nIf something goes wrong:\n```\n$ bd migrate\n\nβ†’ Analyzing migration plan...\nβ†’ AI identified issue: Missing issue_prefix config after migration\nβ†’ Recommendation: Add prefix detection step\nβ†’ Aborting migration - database unchanged\n```\n\n## Implementation Ideas\n\n### A. Migration Validator Tool\nCreate `bd migrate --validate` that:\n- Simulates migration on copy of database\n- Uses AI to verify data integrity\n- Reports potential issues before real migration\n\n### B. Migration Test Generator\nAI generates test cases for migrations:\n- Edge cases (empty DB, large DB, missing config)\n- Data integrity checks\n- Regression tests\n\n### C. Migration Invariants\nDefine invariants that AI checks:\n- Issue count should not decrease (unless collision resolution)\n- All required config keys present\n- Foreign key relationships intact\n- No orphaned dependencies\n\n### D. Self-Healing Migrations\nAI detects incomplete migrations and suggests fixes:\n- Missing config values (like GH #201)\n- Orphaned data\n- Index inconsistencies\n\n## Benefits\n\n1. **Catch edge cases**: AI explores scenarios humans miss\n2. **Self-documenting**: AI explains what migration does\n3. **Agent-friendly**: Agents can run migrations confidently\n4. **Fewer rollbacks**: Detect issues before committing\n5. **Better testing**: AI generates comprehensive test suites\n\n## Open Questions\n\n1. Which AI model? (Fast: Haiku, Thorough: Sonnet/GPT-4)\n2. How to balance safety vs migration speed?\n3. Should AI validation be required or optional?\n4. How to handle offline scenarios (no API access)?\n5. What invariants should always be checked?\n\n## Related Work\n\n- bd-b245: Migration registry (makes migrations introspectable)\n- GH #201: issue_prefix migration bug (motivating example)\n- bd-d355a07d: False positive data loss warnings","design":"## Architecture: Agent-Supervised Migrations (Inversion of Control)\n\n**Key principle:** Beads provides observability and validation primitives. AI agents supervise using their own reasoning. Beads NEVER makes AI API calls.\n\n## Phase 1: Migration Invariants (Pure Validation)\n\nCreate `internal/storage/sqlite/migration_invariants.go`:\n\n```go\ntype MigrationInvariant struct {\n Name string\n Description string\n Check func(*sql.DB, *Snapshot) error\n}\n\ntype Snapshot struct {\n IssueCount int\n ConfigKeys []string\n DependencyCount int\n LabelCount int\n}\n\nvar invariants = []MigrationInvariant{\n {\n Name: \"required_config_present\",\n Description: \"Required config keys must exist\",\n Check: checkRequiredConfig, // Would have caught GH #201\n },\n {\n Name: \"foreign_keys_valid\",\n Description: \"No orphaned dependencies or labels\",\n Check: checkForeignKeys,\n },\n {\n Name: \"issue_count_stable\",\n Description: \"Issue count should not decrease unexpectedly\",\n Check: checkIssueCount,\n },\n}\n\nfunc checkRequiredConfig(db *sql.DB, snapshot *Snapshot) error {\n required := []string{\"issue_prefix\", \"schema_version\"}\n for _, key := range required {\n var value string\n err := db.QueryRow(\"SELECT value FROM config WHERE key = ?\", key).Scan(\u0026value)\n if err != nil || value == \"\" {\n return fmt.Errorf(\"required config key missing: %s\", key)\n }\n }\n return nil\n}\n```\n\n## Phase 2: Dry-Run \u0026 Inspection Tools\n\nAdd `bd migrate --dry-run --json`:\n\n```json\n{\n \"pending_migrations\": [\n {\"name\": \"dirty_issues_table\", \"description\": \"Adds dirty_issues table\"},\n {\"name\": \"content_hash_column\", \"description\": \"Adds content_hash for collision resolution\"}\n ],\n \"current_state\": {\n \"schema_version\": \"0.9.9\",\n \"issue_count\": 247,\n \"config\": {\"schema_version\": \"0.9.9\"},\n \"missing_config\": [\"issue_prefix\"]\n },\n \"warnings\": [\n \"issue_prefix config not set - may break commands after migration\"\n ],\n \"invariants_to_check\": [\n \"required_config_present\",\n \"foreign_keys_valid\",\n \"issue_count_stable\"\n ]\n}\n```\n\nAdd `bd info --schema --json`:\n\n```json\n{\n \"tables\": [\"issues\", \"dependencies\", \"labels\", \"config\"],\n \"schema_version\": \"0.9.9\",\n \"config\": {},\n \"sample_issue_ids\": [\"mcp-1\", \"mcp-2\"],\n \"detected_prefix\": \"mcp\"\n}\n```\n\n## Phase 3: Pre/Post Snapshots with Rollback\n\nUpdate `RunMigrations()`:\n\n```go\nfunc RunMigrations(db *sql.DB) error {\n // Capture pre-migration snapshot\n snapshot := captureSnapshot(db)\n \n // Run migrations in transaction\n tx, err := db.Begin()\n if err != nil {\n return err\n }\n defer tx.Rollback()\n \n for _, migration := range migrations {\n if err := migration.Func(tx); err != nil {\n return fmt.Errorf(\"migration %s failed: %w\", migration.Name, err)\n }\n }\n \n // Verify invariants before commit\n if err := verifyInvariants(tx, snapshot); err != nil {\n return fmt.Errorf(\"post-migration validation failed (rolled back): %w\", err)\n }\n \n return tx.Commit()\n}\n```\n\n## Phase 4: MCP Tools for Agent Supervision\n\nAdd to beads-mcp:\n\n```python\n@server.tool()\nasync def inspect_migration(workspace_root: str) -\u003e dict:\n \"\"\"Get migration plan and current state for agent analysis.\n \n Agent should:\n 1. Review pending migrations\n 2. Check for warnings (missing config, etc.)\n 3. Verify invariants will pass\n 4. Decide whether to run bd migrate\n \"\"\"\n result = run_bd([\"migrate\", \"--dry-run\", \"--json\"], workspace_root)\n return json.loads(result.stdout)\n\n@server.tool() \nasync def get_schema_info(workspace_root: str) -\u003e dict:\n \"\"\"Get current database schema for migration analysis.\"\"\"\n result = run_bd([\"info\", \"--schema\", \"--json\"], workspace_root)\n return json.loads(result.stdout)\n```\n\n## Agent Workflow Example\n\n```python\n# Agent detects user wants to migrate\nmigration_plan = inspect_migration(\"/path/to/workspace\")\n\n# Agent analyzes (using its own reasoning, no API calls from beads)\nif \"issue_prefix\" in migration_plan[\"missing_config\"]:\n schema = get_schema_info(\"/path/to/workspace\")\n detected_prefix = schema[\"detected_prefix\"]\n \n # Agent fixes issue before migration\n run_bd([\"config\", \"set\", \"issue_prefix\", detected_prefix])\n \n# Now safe to migrate\nrun_bd([\"migrate\"])\n```\n\n## What Beads Provides\n\nβœ… Deterministic validation (invariants)\nβœ… Structured inspection (--dry-run, --explain)\nβœ… Rollback on invariant failure\nβœ… JSON output for agent parsing\n\n## What Beads Does NOT Do\n\n❌ No AI API calls\n❌ No external model access\n❌ No agent invocation\n\nAgents supervise migrations using their own reasoning and the inspection tools beads provides.","acceptance_criteria":"Phase 1: Migration invariants implemented and tested, checked after every migration, clear error messages when invariants fail.\n\nPhase 2: Snapshot capture before migrations, comparison after, rollback on verification failure.\n\nPhase 3 (stretch): AI validation optional flag implemented, AI can analyze migration code and generate custom validation queries.\n\nPhase 4 (stretch): Migration test fixtures created, all fixtures pass migrations, CI runs migration tests.","notes":"## Progress\n\n### βœ… Phase 1: Migration Invariants (COMPLETED)\n\n**Implemented:**\n- Created internal/storage/sqlite/migration_invariants.go with 3 invariants\n- Updated RunMigrations() to verify invariants after migrations\n- All tests pass βœ“\n\n### βœ… Phase 2: Inspection Tools (COMPLETED \u0026 PUSHED)\n\n**Commit:** 1abe4e7 - \"Add migration inspection tools for AI agents (bd-627d Phase 2)\"\n\n**Implemented:**\n1. βœ… bd migrate --inspect --json - Shows migration plan\n2. βœ… bd info --schema --json - Returns schema details\n3. βœ… Migration warnings system\n4. βœ… Documentation updated in AGENTS.md\n5. βœ… All tests pass\n\n### βœ… Phase 3: MCP Tools (COMPLETED \u0026 PUSHED)\n\n**Commit:** 2493693 - \"Add MCP tools for migration inspection (bd-627d Phase 3)\"\n\n**Implemented:**\n1. βœ… inspect_migration(workspace_root) tool in beads-mcp\n2. βœ… get_schema_info(workspace_root) tool in beads-mcp\n3. βœ… Abstract methods in BdClientBase\n4. βœ… CLI client implementations\n5. βœ… All tests pass\n\n**All phases complete!** Migration inspection fully integrated into MCP server.","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-11-02T12:57:10.722048-08:00","updated_at":"2025-11-02T14:31:25.095296-08:00","closed_at":"2025-11-02T14:31:25.095308-08:00","source_repo":"."} @@ -243,7 +243,7 @@ {"id":"bd-85d1","content_hash":"a82c0064b840eacb4896f68e73650a3e99aaeaffbb2a7269a857b6c4245b5572","title":"Add integration tests for multi-repo sync","description":"Test: Clone A deletes issue, Clone B imports Clone A's JSONL. Verify Clone B handles deletion gracefully with resurrection. Test concurrent imports with same orphans (should be idempotent). Test round-trip fidelity (exportβ†’delete parentβ†’importβ†’verify structure).","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-04T12:32:21.410318-08:00","updated_at":"2025-11-05T00:44:27.948465-08:00","closed_at":"2025-11-05T00:44:27.948467-08:00","source_repo":"."} {"id":"bd-8788","content_hash":"31af4635755d7ee1b09d75690de5e8d058417a176fd0b49490d3c968fb3a16a4","title":"Fix monitor-webui status filter","description":"","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-11-21T11:54:18.982820303-07:00","updated_at":"2025-11-21T11:54:36.091639066-07:00","closed_at":"2025-11-21T11:54:36.091639066-07:00","source_repo":"."} {"id":"bd-879d","content_hash":"9716c230d9b2793bd1e51d9e3c380c06caf7b3e9a0dd20253764af19e3de7ac8","title":"Test issue 1","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-02T09:44:12.538697729Z","updated_at":"2025-11-02T09:45:20.76214671Z","closed_at":"2025-11-02T09:45:20.76214671Z","source_repo":".","dependencies":[{"issue_id":"bd-879d","depends_on_id":"bd-d3e5","type":"discovered-from","created_at":"2025-11-02T09:44:22.103468321Z","created_by":"mrdavidlaing"}]} -{"id":"bd-87a0","content_hash":"b6c322852ff360ade9f0d46bb2af29a7cf3d3acc8b7469dcbb5d98bf48050240","title":"Publish @beads/bd package to npm registry","description":"Publish the npm package to the public npm registry:\n\n## Prerequisites\n- npm account created\n- Organization @beads created (or use different namespace)\n- npm login completed locally\n- Package tested locally (bd-f282 completed)\n\n## Publishing steps\n1. Verify package.json version matches current bd version\n2. Run npm pack and inspect tarball contents\n3. Test installation from tarball one more time\n4. Run npm publish --access public\n5. Verify package appears on https://www.npmjs.com/package/@beads/bd\n6. Test installation from registry: npm install -g @beads/bd\n\n## Post-publish\n- Add npm badge to README.md\n- Update CHANGELOG.md with npm package release\n- Announce in release notes\n\n## Note\n- May need to choose different name if @beads namespace unavailable\n- Alternative: beads-cli, bd-cli, or unscoped beads-issue-tracker","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-02T23:40:25.263569-08:00","updated_at":"2025-11-03T10:39:41.772338-08:00","closed_at":"2025-11-03T10:39:41.772338-08:00","source_repo":".","dependencies":[{"issue_id":"bd-87a0","depends_on_id":"bd-febc","type":"parent-child","created_at":"2025-11-02T23:40:33.014043-08:00","created_by":"daemon"}],"comments":[{"id":29,"issue_id":"bd-87a0","author":"stevey","text":"Package is ready to publish. All code complete and tested locally. Next steps: 1) npm login, 2) create @beads org if needed, 3) npm publish --access public. See npm-package/PUBLISHING.md for complete instructions.","created_at":"2025-11-23T01:48:48Z"}]} +{"id":"bd-87a0","content_hash":"b6c322852ff360ade9f0d46bb2af29a7cf3d3acc8b7469dcbb5d98bf48050240","title":"Publish @beads/bd package to npm registry","description":"Publish the npm package to the public npm registry:\n\n## Prerequisites\n- npm account created\n- Organization @beads created (or use different namespace)\n- npm login completed locally\n- Package tested locally (bd-f282 completed)\n\n## Publishing steps\n1. Verify package.json version matches current bd version\n2. Run npm pack and inspect tarball contents\n3. Test installation from tarball one more time\n4. Run npm publish --access public\n5. Verify package appears on https://www.npmjs.com/package/@beads/bd\n6. Test installation from registry: npm install -g @beads/bd\n\n## Post-publish\n- Add npm badge to README.md\n- Update CHANGELOG.md with npm package release\n- Announce in release notes\n\n## Note\n- May need to choose different name if @beads namespace unavailable\n- Alternative: beads-cli, bd-cli, or unscoped beads-issue-tracker","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-02T23:40:25.263569-08:00","updated_at":"2025-11-03T10:39:41.772338-08:00","closed_at":"2025-11-03T10:39:41.772338-08:00","source_repo":".","dependencies":[{"issue_id":"bd-87a0","depends_on_id":"bd-febc","type":"parent-child","created_at":"2025-11-02T23:40:33.014043-08:00","created_by":"daemon"}]} {"id":"bd-8900f145","content_hash":"4a07f36a9e5d24aaffb092c89e2273cb58f9de357d24eeb01fcde6a4079ba775","title":"Testing event-driven mode!","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-29T15:28:33.564871-07:00","updated_at":"2025-10-30T17:12:58.186325-07:00","closed_at":"2025-10-29T19:12:54.43368-07:00","source_repo":"."} {"id":"bd-8931","content_hash":"409c16d9e6c83c2bf6cccfa6ee6cb18e1e1eee032b522fb99500bb40f2a05649","title":"Daemon gets stuck when auto-import blocked by git conflicts","description":"CRITICAL: The daemon enters a corrupt state that breaks RPC commands when auto-import is triggered but git pull fails due to uncommitted changes.\n\nImpact: This is a data integrity and usability issue that could cause users to lose trust in Beads. The daemon silently fails for certain commands while appearing healthy.\n\nReproduction:\n1. Make local changes to issues (creates uncommitted .beads/beads.jsonl)\n2. Remote has updates (JSONL newer, triggers auto-import)\n3. Daemon tries to pull but fails: 'cannot pull with rebase: You have unstaged changes'\n4. Daemon enters bad state - 'bd show' and other commands return EOF\n5. 'bd list' still works, daemon process is running, no errors logged\n\nTechnical details:\n- Auto-import check runs in handleRequest() before processing RPC commands\n- When import is blocked, it appears to corrupt daemon state\n- Likely: deadlock, unclosed transaction, or storage handle corruption\n- Panic recovery (server_lifecycle_conn.go:183) didn't catch anything - not a panic\n\nRequired fix:\n- Auto-import must not block RPC command execution\n- Handle git pull failures gracefully without corrupting state\n- Consider: skip auto-import if git is dirty, queue import for later, or use separate goroutine\n- Add timeout/circuit breaker for import operations\n- Log clear warnings when auto-import is skipped\n\nWithout this fix, users in collaborative environments will frequently encounter mysterious EOF errors that require daemon restarts.","design":"Options to fix:\n\n1. Skip auto-import when git is dirty (safest, simplest)\n - Check git status before pull\n - Log warning and continue without import\n - User must manually import after cleaning git state\n\n2. Async import with timeout (better UX)\n - Run auto-import in background goroutine\n - Don't block RPC command execution\n - Timeout after 5s, log error if stuck\n - Use sync.Once or similar to prevent concurrent imports\n\n3. Transactional import with rollback\n - Wrap import in database transaction\n - Rollback if git operations fail\n - Ensure storage is never left in bad state\n\nRecommended: Combine #1 and #2\n- Check git status first, skip if dirty\n- If clean, do async import with timeout\n- Add metrics to track import success/failure rates","status":"closed","priority":0,"issue_type":"bug","created_at":"2025-11-02T17:15:25.181425-08:00","updated_at":"2025-11-03T12:08:12.949061-08:00","closed_at":"2025-11-03T12:08:12.949064-08:00","source_repo":".","dependencies":[{"issue_id":"bd-8931","depends_on_id":"bd-1048","type":"blocks","created_at":"2025-11-02T17:15:25.181857-08:00","created_by":"stevey"}]} {"id":"bd-897a","content_hash":"ae488407bf5e71242535f4c35b59b0981d2b8b338d1701f19acba2c8e93049f0","title":"Add UNIQUE constraint on external_ref column","description":"The external_ref column should have a UNIQUE constraint to prevent multiple issues from having the same external reference. This ensures data integrity when syncing from external systems (Jira, GitHub, Linear).\n\nCurrent behavior:\n- Multiple issues can have the same external_ref\n- GetIssueByExternalRef returns first match (non-deterministic with duplicates)\n\nProposed solution:\n- Add UNIQUE constraint to external_ref column\n- Add migration to check for and resolve existing duplicates\n- Update tests to verify constraint enforcement\n\nRelated: bd-1022","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-02T15:31:54.718005-08:00","updated_at":"2025-11-02T16:01:45.742666-08:00","closed_at":"2025-11-02T16:01:45.742666-08:00","source_repo":"."} @@ -257,7 +257,7 @@ {"id":"bd-8kde","content_hash":"2bc64e3d456f5490598f8d49e65a870d5b9b6c1579046a80f616a12d98908fc9","title":"bd delete bulk operations fight with auto-import/daemon causing data resurrection","description":"When bulk deleting issues (e.g., 244 closed issues older than 24h), the process fights with auto-import and daemon infrastructure:\n\n**Expected behavior:**\n- Delete 244 issues from 468-issue database\n- Export to JSONL (224 lines)\n- Commit and push\n- Result: 224 issues\n\n**Actual behavior:**\n- Delete 244 issues \n- Import runs (from stale git JSONL with 468 issues)\n- Resurrects deleted issues back into database\n- Export writes 356 lines (not 224)\n- Math: 468 - 244 = 224, but got 356 (132 issues resurrected)\n\n**Root cause:**\nAuto-import keeps re-importing from git during the delete operation, before the new JSONL is committed. The workflow is:\n1. Delete from DB\n2. Auto-import runs (reads old JSONL from git with deleted issues still present)\n3. Issues come back\n4. Export writes partially-deleted state\n\n**Solution options:**\n1. Add `--no-auto-import` flag to bulk delete operations\n2. Atomic delete-export-commit operation that suppresses imports\n3. Dedicated `bd prune` command that handles this correctly\n4. Lock file to prevent auto-import during bulk mutations\n\n**Impact:**\n- Bulk cleanup operations don't work reliably\n- Makes it nearly impossible to prune old closed issues\n- Confusing UX (delete 244, but only 112 actually removed)","notes":"**FIXED**: Auto-import now skips during delete operations to prevent resurrection.\n\n**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.\n\n**Solution implemented**:\n1. Added delete to skip list in main.go PersistentPreRun (alongside import and sync --dry-run)\n2. Delete operations now complete atomically without auto-import interference\n3. Added comprehensive test (TestBulkDeleteNoResurrection) to prevent regression\n\n**Test verification**:\n- Creates 20 issues, deletes 10\n- Verifies no resurrection after delete\n- Confirms JSONL has correct count (10 remaining)\n- All existing tests still pass","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-08T03:01:09.796852-08:00","updated_at":"2025-11-08T03:06:04.416994-08:00","closed_at":"2025-11-08T03:06:04.416994-08:00","source_repo":"."} {"id":"bd-8mfn","content_hash":"866a8afcdadb8e4e015aab6ab0b8882f48ae9856098181205013b992d2aa08f3","title":"bd message: Implement full message reading functionality","description":"The `bd message read` command is incomplete and doesn't actually fetch or display message content.\n\n**Location:** cmd/bd/message.go:413-441\n\n**Current Behavior:**\n- Only marks message as read\n- Prints placeholder text\n- Doesn't fetch message body\n\n**Expected:**\n- Fetch full message from Agent Mail resource API\n- Display sender, subject, timestamp, body\n- Consider markdown rendering\n\n**Blocker:** Core feature for message system MVP","status":"closed","priority":0,"issue_type":"bug","created_at":"2025-11-08T12:54:24.018957-08:00","updated_at":"2025-11-08T12:57:32.91854-08:00","closed_at":"2025-11-08T12:57:32.91854-08:00","source_repo":".","dependencies":[{"issue_id":"bd-8mfn","depends_on_id":"bd-6uix","type":"parent-child","created_at":"2025-11-08T12:55:54.811368-08:00","created_by":"daemon"}]} {"id":"bd-8ph6","content_hash":"c64a644d8f2ea530109e7e6ef569ebd18b553a793cce5a4bd657581d75304167","title":"Support Ubuntu 20.04 LTS (glibc compatibility issue)","description":"Starting at v0.22, precompiled binaries require GLIBC 2.32+ which is not available on Ubuntu 20.04 LTS (Focal Fossa). Ubuntu 20.04 has GLIBC 2.31.\n\nError:\n```\nbd: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.34' not found (required by bd)\nbd: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.32' not found (required by bd)\n```\n\nCurrent workarounds:\n1. Upgrade to Ubuntu 22.04+\n2. Build from source: `go build -o bd ./cmd/bd/`\n\nRoot cause: Go 1.24+ runtime requires newer glibc. CGO is already disabled in .goreleaser.yml.\n\nPossible solutions:\n- Pin Go version to 1.21 or 1.22 for releases\n- Use Docker/cross-compile with older build environment\n- Provide separate build for older distros\n- Document minimum requirements clearly","notes":"Decision: Document minimum requirements in README instead of pinning Go version.\n\nRationale:\n- Ubuntu 20.04 LTS standard support ended April 2025 (already EOL)\n- Pinning Go prevents security fixes, performance improvements, and new features\n- Users on EOL distros can upgrade OS or build from source\n- Added Requirements section to README with clear glibc 2.32+ requirement","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-11-07T14:25:47.055357-08:00","updated_at":"2025-11-07T14:30:15.755733-08:00","closed_at":"2025-11-07T14:30:15.755733-08:00","source_repo":"."} -{"id":"bd-8ql","content_hash":"d5bb8e88dc528e8d6f9873ce58279245bf3f6b889cc068961b32a85e9ede2c4a","title":"Remove misleading placeholder 'bd merge' command from duplicates output","description":"**Problem:**\nThe `bd duplicates` command suggests running a command that doesn't exist:\n```\nbd merge \u003csource-ids\u003e --into \u003ctarget-id\u003e\n```\n\nThis is confusing because:\n1. `bd merge` is actually a git 3-way JSONL merge driver (takes 4 file paths)\n2. The suggested syntax for merging duplicate issues is not implemented\n3. Line 75 in duplicates.go even has: `// TODO: performMerge implementation pending`\n\n**Current behavior:**\n- Users see suggested command that doesn't work\n- No indication that feature is unimplemented\n- Related to issue #349 item #2\n\n**Proposed fix:**\nReplace line 77 in cmd/bd/duplicates.go with either:\n\nOption A (conservative):\n```go\ncmd := fmt.Sprintf(\"# TODO: Merge %s into %s (merge command not yet implemented)\", \n strings.Join(sources, \" \"), target.ID)\n```\n\nOption B (actionable):\n```go\ncmd := fmt.Sprintf(\"# Duplicate found: %s\\n# Manual merge: Close duplicates with 'bd close %s' and link to %s as 'related'\", \n strings.Join(sources, \" \"), strings.Join(sources, \" \"), target.ID)\n```\n\n**Files to modify:**\n- cmd/bd/duplicates.go (line ~77)","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-11-20T20:48:01.707967-05:00","updated_at":"2025-11-23T14:14:13.331484-08:00","closed_at":"2025-11-20T20:59:13.416865-05:00","source_repo":".","labels":["bug","documentation","ux"],"comments":[{"id":17,"issue_id":"bd-8ql","author":"stevey","text":"Addresses GitHub issue #349 item 2: https://github.com/steveyegge/beads/issues/349\n\nUser confused by 'bd merge' help text. The help text is actually correct (it's a git merge driver), but the duplicates command suggests a non-existent 'bd merge \u003cids\u003e --into \u003ctarget\u003e' syntax for merging duplicate issues.","created_at":"2025-11-21T02:23:27Z"}]} +{"id":"bd-8ql","content_hash":"d5bb8e88dc528e8d6f9873ce58279245bf3f6b889cc068961b32a85e9ede2c4a","title":"Remove misleading placeholder 'bd merge' command from duplicates output","description":"**Problem:**\nThe `bd duplicates` command suggests running a command that doesn't exist:\n```\nbd merge \u003csource-ids\u003e --into \u003ctarget-id\u003e\n```\n\nThis is confusing because:\n1. `bd merge` is actually a git 3-way JSONL merge driver (takes 4 file paths)\n2. The suggested syntax for merging duplicate issues is not implemented\n3. Line 75 in duplicates.go even has: `// TODO: performMerge implementation pending`\n\n**Current behavior:**\n- Users see suggested command that doesn't work\n- No indication that feature is unimplemented\n- Related to issue #349 item #2\n\n**Proposed fix:**\nReplace line 77 in cmd/bd/duplicates.go with either:\n\nOption A (conservative):\n```go\ncmd := fmt.Sprintf(\"# TODO: Merge %s into %s (merge command not yet implemented)\", \n strings.Join(sources, \" \"), target.ID)\n```\n\nOption B (actionable):\n```go\ncmd := fmt.Sprintf(\"# Duplicate found: %s\\n# Manual merge: Close duplicates with 'bd close %s' and link to %s as 'related'\", \n strings.Join(sources, \" \"), strings.Join(sources, \" \"), target.ID)\n```\n\n**Files to modify:**\n- cmd/bd/duplicates.go (line ~77)","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-11-20T20:48:01.707967-05:00","updated_at":"2025-11-23T14:14:13.331484-08:00","closed_at":"2025-11-20T20:59:13.416865-05:00","source_repo":".","labels":["bug","documentation","ux"]} {"id":"bd-8rd","content_hash":"e5845f6bda21414b3715f9589c76f8a02594f4cb8691939ced6765329346e411","title":"Migration and onboarding for multi-repo","description":"Create migration tools, wizards, and documentation to help users adopt multi-repo workflow, with special focus on OSS contributor onboarding and team adoption scenarios.","design":"Components:\n- Migration guide documentation\n- bd migrate command to move issues between repos\n- bd init --contributor wizard for OSS setup\n- bd init --team wizard for team setup\n- Auto-detect scenarios and prompt users\n- Examples for common workflows (OSS, multi-phase, personas)\n\nScenarios:\n1. OSS contributor (fork workflow)\n2. Team member (branch workflow)\n3. Multi-phase development\n4. Multiple personas (architect/implementer)","acceptance_criteria":"1. Migration guide covers all scenarios\n2. bd migrate moves issues with filtering\n3. Init wizards guide common setups\n4. Examples demonstrate key workflows\n5. Auto-detection prompts users when appropriate\n6. Docs updated with multi-repo patterns\n7. Backward compatibility clearly documented","status":"closed","priority":2,"issue_type":"epic","created_at":"2025-11-04T11:22:13.491033-08:00","updated_at":"2025-11-07T16:08:24.951261-08:00","closed_at":"2025-11-07T16:03:09.75064-08:00","source_repo":".","dependencies":[{"issue_id":"bd-8rd","depends_on_id":"bd-4ms","type":"parent-child","created_at":"2025-11-04T11:22:21.858002-08:00","created_by":"daemon"}]} {"id":"bd-8wa","content_hash":"0cf757ff7ef5393901a61cfdfaa2d6f7ac627eaa1c62b63165050f21d9b5b390","title":"Code Review Sweep: thorough","description":"Perform thorough code review sweep based on accumulated activity.\n\n**AI Reasoning:**\nSignificant code volume added (150,273 lines) across multiple critical areas, including cmd/bd, internal/storage/sqlite, and internal/rpc. High file change count (616) indicates substantial refactoring or new functionality. The metrics suggest potential for subtle architectural or implementation issues that warrant review.\n\n**Scope:** thorough\n**Target Areas:** cmd/bd, internal/storage/sqlite, internal/rpc\n**Estimated Files:** 12\n**Estimated Cost:** $5\n\n**Task:**\nReview files for non-obvious issues that agents miss during focused work:\n- Inefficiencies (algorithmic, resource usage)\n- Subtle bugs (race conditions, off-by-one, copy-paste)\n- Poor patterns (coupling, complexity, duplication)\n- Missing best practices (error handling, docs, tests)\n- Unnamed anti-patterns\n\nFile discovered issues with detailed reasoning and suggestions.","acceptance_criteria":"- Reviewed target files for code quality issues\n- Filed discovered issues with detailed reasoning\n- Completed sweep according to scope criteria","status":"open","priority":1,"issue_type":"task","created_at":"2025-11-21T10:25:37.081296-05:00","updated_at":"2025-11-21T10:25:37.081296-05:00","source_repo":".","labels":["code-review-sweep","review-area:cmd/bd","review-area:internal/rpc","review-area:internal/storage/sqlite"]} {"id":"bd-8y1a","content_hash":"7290f181cb874705a9981d12c510f9506f7c74de40aafa1baa5a9b652e52495a","title":"Update Nix flake Go modules hash","description":"","status":"closed","priority":0,"issue_type":"bug","assignee":"claude","created_at":"2025-11-22T10:56:09.819863-08:00","updated_at":"2025-11-22T10:59:18.858399-08:00","closed_at":"2025-11-22T10:59:18.858399-08:00","source_repo":"."} @@ -308,17 +308,17 @@ {"id":"bd-ar2.2","content_hash":"c4dee35a25421d4058d5debd5bd83914b134ebdea5faa4b6a63852d0d82b7ae4","title":"Add multi-repo support to export metadata updates","description":"## Problem\nThe bd-ymj fix only updates metadata for the main jsonlPath, but the codebase supports multi-repo mode where exports write to multiple JSONL files.\n\nOther daemon_sync operations handle multi-repo correctly:\n- Lines 509-518: Snapshots captured for all multi-repo paths\n- Lines 578-587: Deletions applied for all multi-repo paths\n\nBut metadata updates are missing!\n\n## Investigation Needed\nMetadata is stored globally in database (`last_import_hash`, `last_import_mtime`), but multi-repo has per-repo JSONL files. Current schema may not support tracking multiple JSONL files.\n\nOptions:\n1. Store metadata per-repo (new schema)\n2. Store combined hash of all repos\n3. Document that multi-repo doesn't need this metadata (why?)\n\n## Solution (if needed)\n```go\n// After export\nif multiRepoPaths := getMultiRepoJSONLPaths(); multiRepoPaths != nil {\n // Multi-repo mode: update metadata for each JSONL\n for _, path := range multiRepoPaths {\n updateExportMetadata(exportCtx, store, path, log)\n }\n} else {\n // Single-repo mode: update metadata for main JSONL\n updateExportMetadata(exportCtx, store, jsonlPath, log)\n}\n```\n\n## Files\n- cmd/bd/daemon_sync.go (createExportFunc, createSyncFunc)\n- Possibly: internal/storage/sqlite/metadata.go (schema changes)\n\n## Related\nDepends on bd-ar2.1 (extract helper function first)","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-21T10:24:32.482102-05:00","updated_at":"2025-11-22T17:48:48.068263-08:00","closed_at":"2025-11-21T11:07:17.124957-05:00","source_repo":".","dependencies":[{"issue_id":"bd-ar2.2","depends_on_id":"bd-ar2","type":"parent-child","created_at":"2025-11-21T10:24:32.482559-05:00","created_by":"daemon"}]} {"id":"bd-ar2.3","content_hash":"143dac2e836dcf93264d5654d2d9aa0960777d186c0fea1b146c21158a002234","title":"Fix TestExportUpdatesMetadata to test actual daemon functions","description":"## Problem\nTestExportUpdatesMetadata (daemon_sync_test.go:296) manually replicates the metadata update logic rather than calling the fixed functions (createExportFunc/createSyncFunc).\n\nThis means:\n- Test verifies the CONCEPT works\n- But doesn't verify the IMPLEMENTATION in the actual daemon functions\n- If daemon code is wrong, test still passes\n\n## Current Test Flow\n```go\n// Test does:\nexportToJSONLWithStore() // ← Direct call\n// ... manual metadata update ...\nexportToJSONLWithStore() // ← Direct call again\n```\n\n## Should Be\n```go\n// Test should:\ncreateExportFunc(...)() // ← Call actual daemon function\n// ... verify metadata was updated by the function ...\ncreateExportFunc(...)() // ← Call again, should not fail\n```\n\n## Challenge\ncreateExportFunc returns a closure that's run by the daemon. Testing this requires:\n- Mock logger\n- Proper context setup\n- Git operations might need mocking\n\n## Files\n- cmd/bd/daemon_sync_test.go\n\n## Acceptance Criteria\n- Test calls actual createExportFunc and createSyncFunc\n- Test verifies metadata updated by daemon code, not test code\n- Both functions tested (export and sync)","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-21T10:24:46.756315-05:00","updated_at":"2025-11-22T17:48:48.068767-08:00","closed_at":"2025-11-21T11:07:25.321289-05:00","source_repo":".","dependencies":[{"issue_id":"bd-ar2.3","depends_on_id":"bd-ar2","type":"parent-child","created_at":"2025-11-21T10:24:46.757622-05:00","created_by":"daemon"}]} {"id":"bd-ar2.4","content_hash":"2fe8e7ac1334017eabaeb7a906f632d112b3040bb2f618c9cabc00311e7d2886","title":"Use TryResurrectParentChain instead of TryResurrectParent in GetNextChildID","description":"## Context\nCurrent bd-dvd fix uses TryResurrectParent, which only resurrects the immediate parent. For deeply nested hierarchies, this might not be sufficient.\n\n## Example Scenario\nCreating child with parent \"bd-abc.1.2\" where:\n- bd-abc exists in DB\n- bd-abc.1 was deleted (missing from DB, exists in JSONL)\n- bd-abc.1.2 was deleted (missing from DB, exists in JSONL)\n\nCurrent fix: Only tries to resurrect \"bd-abc.1.2\", fails because its parent \"bd-abc.1\" is missing.\n\n## Solution\nReplace TryResurrectParent with TryResurrectParentChain:\n\n```go\nif count == 0 {\n // Try to resurrect entire parent chain from JSONL history (bd-dvd fix)\n // This handles deeply nested hierarchies where intermediate parents are also missing\n resurrected, err := s.TryResurrectParentChain(ctx, parentID)\n if err != nil {\n return \"\", fmt.Errorf(\"failed to resurrect parent chain for %s: %w\", parentID, err)\n }\n if !resurrected {\n return \"\", fmt.Errorf(\"parent issue %s does not exist and could not be resurrected from JSONL history\", parentID)\n }\n}\n```\n\n## Investigation\n- Check if this scenario actually happens in practice\n- TryResurrectParentChain already exists (resurrection.go:174-209)\n- May be overkill if users always create parents before children\n\n## Files\n- internal/storage/sqlite/hash_ids.go\n\n## Testing\nAdd test case for deeply nested resurrection","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-21T10:25:01.376071-05:00","updated_at":"2025-11-22T17:48:48.069262-08:00","closed_at":"2025-11-21T11:40:47.682699-05:00","source_repo":".","dependencies":[{"issue_id":"bd-ar2.4","depends_on_id":"bd-ar2","type":"parent-child","created_at":"2025-11-21T10:25:01.376561-05:00","created_by":"daemon"}]} -{"id":"bd-ar2.5","content_hash":"16ae300a7e23d596aef9cb39d131e252556905c04ebc2fdaca2a295256ea1191","title":"Add error handling guidance for export metadata update failures","description":"## Problem\nThe bd-ymj fix treats all metadata update failures as warnings:\n\n```go\nif err := store.SetMetadata(ctx, \"last_import_hash\", currentHash); err != nil {\n log.log(\"Warning: failed to update last_import_hash: %v\", err)\n}\n```\n\nBut if metadata updates fail, the NEXT export will fail with \"JSONL content has changed since last import\".\n\n## Questions\n1. Should metadata failures be critical (return error)?\n2. Should we implement retry logic?\n3. Is warning acceptable (safe, just requires import before next export)?\n\n## Current Behavior\n- Metadata failure is silent (only logged)\n- User won't know until next export fails\n- Next export requires import first (safe but annoying)\n\n## Recommendation\nAdd clear comment explaining the trade-off:\n\n```go\n// Note: Metadata update failures are treated as warnings, not errors.\n// This is acceptable because the worst case is the next export will\n// require an import first, which is safe and prevents data loss.\n// Alternative: Make this critical and fail the export if metadata\n// updates fail (but this makes exports more fragile).\nif err := store.SetMetadata(ctx, \"last_import_hash\", currentHash); err != nil {\n log.log(\"Warning: failed to update last_import_hash: %v\", err)\n log.log(\"Next export may require running 'bd import' first\")\n}\n```\n\n## Files\n- cmd/bd/daemon_sync.go\n\n## Decision Needed\nChoose approach based on failure mode preferences","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-21T10:25:16.52788-05:00","updated_at":"2025-11-22T17:48:48.06977-08:00","closed_at":"2025-11-21T11:40:47.684741-05:00","source_repo":".","dependencies":[{"issue_id":"bd-ar2.5","depends_on_id":"bd-ar2","type":"parent-child","created_at":"2025-11-21T10:25:16.528351-05:00","created_by":"daemon"}],"comments":[{"id":30,"issue_id":"bd-ar2.5","author":"stevey","text":"## Code Review Finding (bd-ar2.1 implementation)\n\nThe extracted `updateExportMetadata` function doesn't return errors, making it impossible for callers to detect failures:\n\n```go\nfunc updateExportMetadata(ctx context.Context, store storage.Storage, jsonlPath string, log daemonLogger, keySuffix string) {\n currentHash, err := computeJSONLHash(jsonlPath)\n if err != nil {\n log.log(\"Warning: failed to compute JSONL hash for metadata update: %v\", err)\n return // ❌ Silent failure\n }\n // ...\n}\n```\n\nConsider returning errors so callers can decide how to handle them:\n```go\nfunc updateExportMetadata(...) error {\n // ... return errors\n}\n\n// Caller decides:\nif err := updateExportMetadata(...); err != nil {\n log.log(\"Warning: metadata update failed: %v\", err)\n log.log(\"Next export may require import first\")\n // Don't fail the export, just log\n}\n```","created_at":"2025-11-23T01:48:48Z"}]} +{"id":"bd-ar2.5","content_hash":"16ae300a7e23d596aef9cb39d131e252556905c04ebc2fdaca2a295256ea1191","title":"Add error handling guidance for export metadata update failures","description":"## Problem\nThe bd-ymj fix treats all metadata update failures as warnings:\n\n```go\nif err := store.SetMetadata(ctx, \"last_import_hash\", currentHash); err != nil {\n log.log(\"Warning: failed to update last_import_hash: %v\", err)\n}\n```\n\nBut if metadata updates fail, the NEXT export will fail with \"JSONL content has changed since last import\".\n\n## Questions\n1. Should metadata failures be critical (return error)?\n2. Should we implement retry logic?\n3. Is warning acceptable (safe, just requires import before next export)?\n\n## Current Behavior\n- Metadata failure is silent (only logged)\n- User won't know until next export fails\n- Next export requires import first (safe but annoying)\n\n## Recommendation\nAdd clear comment explaining the trade-off:\n\n```go\n// Note: Metadata update failures are treated as warnings, not errors.\n// This is acceptable because the worst case is the next export will\n// require an import first, which is safe and prevents data loss.\n// Alternative: Make this critical and fail the export if metadata\n// updates fail (but this makes exports more fragile).\nif err := store.SetMetadata(ctx, \"last_import_hash\", currentHash); err != nil {\n log.log(\"Warning: failed to update last_import_hash: %v\", err)\n log.log(\"Next export may require running 'bd import' first\")\n}\n```\n\n## Files\n- cmd/bd/daemon_sync.go\n\n## Decision Needed\nChoose approach based on failure mode preferences","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-21T10:25:16.52788-05:00","updated_at":"2025-11-22T17:48:48.06977-08:00","closed_at":"2025-11-21T11:40:47.684741-05:00","source_repo":".","dependencies":[{"issue_id":"bd-ar2.5","depends_on_id":"bd-ar2","type":"parent-child","created_at":"2025-11-21T10:25:16.528351-05:00","created_by":"daemon"}]} {"id":"bd-ar2.6","content_hash":"f39ade8d1ce69a8a0bc4dd993c85e767053af140e86e761d648cefc0a0732e8e","title":"Add transaction boundaries for export metadata updates","description":"## Problem\nMetadata updates happen after export, but there's no transaction ensuring atomicity between:\n1. JSONL file write (exportToJSONLWithStore)\n2. Metadata update (updateExportMetadata)\n3. Database mtime update (TouchDatabaseFile)\n\nIf process crashes between these steps, metadata will be inconsistent.\n\n## Example Failure Scenario\n```\n1. Export to JSONL succeeds\n2. [CRASH] Process killed before metadata update\n3. Next export: \"JSONL content has changed\" error\n4. User must run import to fix metadata\n```\n\n## Options\n\n### Option 1: Tolerate Inconsistency (Current)\n- Simple, no code changes\n- Safe (worst case: need import before next export)\n- Annoying for users if crashes are frequent\n\n### Option 2: Add Write-Ahead Log\n- Write metadata intent to temp file\n- Complete operations\n- Clean up temp file\n- More complex, better guarantees\n\n### Option 3: Store Metadata in JSONL Comments\n- Add metadata as JSON comment in JSONL file\n- Single atomic write\n- Requires JSONL format change\n\n### Option 4: Defensive Checks\n- On startup, verify metadata matches JSONL\n- Auto-fix if mismatch detected\n- Simplest improvement\n\n## Recommendation\nStart with Option 4 (defensive checks), consider others if needed.\n\n## Files\n- cmd/bd/daemon_sync.go\n- Possibly: cmd/bd/main.go (startup checks)\n\n## Related\nThis is lower priority - current behavior is safe, just not ideal","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-21T10:25:32.469469-05:00","updated_at":"2025-11-22T17:48:48.07026-08:00","closed_at":"2025-11-21T11:40:47.685571-05:00","source_repo":".","dependencies":[{"issue_id":"bd-ar2.6","depends_on_id":"bd-ar2","type":"parent-child","created_at":"2025-11-21T10:25:32.470004-05:00","created_by":"daemon"}]} {"id":"bd-ar2.7","content_hash":"26c901628d9d4119e87337b434d5127686a0acda9442348c1feacfd864e5f792","title":"Add edge case tests for GetNextChildID parent resurrection","description":"## Current Coverage\nTestGetNextChildID_ResurrectParent tests happy path only:\n- Parent exists in JSONL\n- Resurrection succeeds\n\n## Missing Test Cases\n\n### 1. Parent Not in JSONL\n- Parent doesn't exist in DB\n- Parent doesn't exist in JSONL either\n- Should return: \"could not be resurrected from JSONL history\"\n\n### 2. JSONL File Missing\n- Parent doesn't exist in DB\n- No issues.jsonl file exists\n- Should handle gracefully\n\n### 3. Malformed JSONL\n- Parent doesn't exist in DB\n- JSONL file exists but has invalid JSON\n- Should skip bad lines, continue searching\n\n### 4. Concurrent Resurrections\n- Multiple goroutines call GetNextChildID with same parent\n- Only one should resurrect, others should succeed\n- Test for race conditions\n\n### 5. Deeply Nested Missing Parents\n- Creating bd-abc.1.2.1 where:\n - bd-abc exists\n - bd-abc.1 missing (should fail with current fix)\n- Related to bd-ar2.4\n\n### 6. Content Hash Mismatch\n- Parent in JSONL has different content_hash than expected\n- Should still resurrect (content_hash is for integrity, not identity)\n\n## Files\n- internal/storage/sqlite/child_id_test.go\n\n## Implementation\n```go\nfunc TestGetNextChildID_ResurrectParent_NotInJSONL(t *testing.T) { ... }\nfunc TestGetNextChildID_ResurrectParent_NoJSONL(t *testing.T) { ... }\nfunc TestGetNextChildID_ResurrectParent_MalformedJSONL(t *testing.T) { ... }\nfunc TestGetNextChildID_ResurrectParent_Concurrent(t *testing.T) { ... }\n```","status":"closed","priority":3,"issue_type":"task","created_at":"2025-11-21T10:25:46.661849-05:00","updated_at":"2025-11-22T17:48:48.070745-08:00","closed_at":"2025-11-21T11:40:47.686231-05:00","source_repo":".","dependencies":[{"issue_id":"bd-ar2.7","depends_on_id":"bd-ar2","type":"parent-child","created_at":"2025-11-21T10:25:46.66235-05:00","created_by":"daemon"}]} -{"id":"bd-ar2.8","content_hash":"b240e0021797bf78b279a92177b2562e5f85514ae35bdb843bffdfc687cad145","title":"Add edge case tests for export metadata updates","description":"## Current Coverage\nTestExportUpdatesMetadata tests basic happy path only.\n\n## Missing Test Cases\n\n### 1. Multi-Repo Mode\n- Export with multi-repo configuration\n- Verify metadata updated for ALL JSONL files\n- Critical gap (related to bd-ar2.2)\n\n### 2. computeJSONLHash Failure\n- JSONL file deleted/inaccessible after export\n- Should log warning, not crash\n- Verify behavior on next export\n\n### 3. SetMetadata Failures\n- Database write-protected\n- Disk full\n- Should log warnings, continue\n\n### 4. os.Stat Failure\n- JSONL file deleted after export, before stat\n- Should handle gracefully (mtime just not updated)\n\n### 5. Concurrent Exports\n- Two daemon instances export simultaneously\n- Verify metadata doesn't get corrupted\n- Race condition test\n\n### 6. Clock Skew\n- System time goes backward between exports\n- Verify mtime handling still works\n\n### 7. Partial Export Failure\n- Multi-repo mode: some exports succeed, some fail\n- What metadata should be updated?\n\n### 8. Large JSONL Files\n- Performance test with large files (10k+ issues)\n- Verify hash computation doesn't timeout\n\n## Files\n- cmd/bd/daemon_sync_test.go\n\n## Implementation Priority\n1. Multi-repo test (P1 - related to critical issue)\n2. Failure handling tests (P2)\n3. Performance/edge cases (P3)","status":"closed","priority":3,"issue_type":"task","created_at":"2025-11-21T10:25:59.526543-05:00","updated_at":"2025-11-22T17:48:48.071281-08:00","closed_at":"2025-11-21T14:39:53.143561-05:00","source_repo":".","dependencies":[{"issue_id":"bd-ar2.8","depends_on_id":"bd-ar2","type":"parent-child","created_at":"2025-11-21T10:25:59.527032-05:00","created_by":"daemon"}],"comments":[{"id":31,"issue_id":"bd-ar2.8","author":"stevey","text":"## Code Review Finding (bd-ar2.3 implementation)\n\nTestUpdateExportMetadataMultiRepo tests the helper function in isolation, but doesn't verify that createExportFunc/createSyncFunc actually call it correctly in multi-repo mode.\n\nNeed integration test that:\n1. Sets up multi-repo config\n2. Creates issues in different repos\n3. Calls createExportFunc (or full daemon flow)\n4. Verifies metadata updated for ALL repos\n5. Verifies validatePreExport passes on subsequent export\n\nChallenge: These functions have complex dependencies (git, locks, etc.) so testing requires mocking or test harness.","created_at":"2025-11-23T01:48:48Z"}]} +{"id":"bd-ar2.8","content_hash":"b240e0021797bf78b279a92177b2562e5f85514ae35bdb843bffdfc687cad145","title":"Add edge case tests for export metadata updates","description":"## Current Coverage\nTestExportUpdatesMetadata tests basic happy path only.\n\n## Missing Test Cases\n\n### 1. Multi-Repo Mode\n- Export with multi-repo configuration\n- Verify metadata updated for ALL JSONL files\n- Critical gap (related to bd-ar2.2)\n\n### 2. computeJSONLHash Failure\n- JSONL file deleted/inaccessible after export\n- Should log warning, not crash\n- Verify behavior on next export\n\n### 3. SetMetadata Failures\n- Database write-protected\n- Disk full\n- Should log warnings, continue\n\n### 4. os.Stat Failure\n- JSONL file deleted after export, before stat\n- Should handle gracefully (mtime just not updated)\n\n### 5. Concurrent Exports\n- Two daemon instances export simultaneously\n- Verify metadata doesn't get corrupted\n- Race condition test\n\n### 6. Clock Skew\n- System time goes backward between exports\n- Verify mtime handling still works\n\n### 7. Partial Export Failure\n- Multi-repo mode: some exports succeed, some fail\n- What metadata should be updated?\n\n### 8. Large JSONL Files\n- Performance test with large files (10k+ issues)\n- Verify hash computation doesn't timeout\n\n## Files\n- cmd/bd/daemon_sync_test.go\n\n## Implementation Priority\n1. Multi-repo test (P1 - related to critical issue)\n2. Failure handling tests (P2)\n3. Performance/edge cases (P3)","status":"closed","priority":3,"issue_type":"task","created_at":"2025-11-21T10:25:59.526543-05:00","updated_at":"2025-11-22T17:48:48.071281-08:00","closed_at":"2025-11-21T14:39:53.143561-05:00","source_repo":".","dependencies":[{"issue_id":"bd-ar2.8","depends_on_id":"bd-ar2","type":"parent-child","created_at":"2025-11-21T10:25:59.527032-05:00","created_by":"daemon"}]} {"id":"bd-ar2.9","content_hash":"d7b949abf252bdf02a64e5a9fc579e650b6fcfb7fff91f2bbfd9588783818187","title":"Fix variable shadowing in GetNextChildID resurrection code","description":"## Problem\nMinor variable shadowing in hash_ids.go:\n\n```go\n// Line 33: err declared here\nerr := s.db.QueryRowContext(ctx, `SELECT COUNT(*) FROM issues WHERE id = ?`, parentID).Scan(\u0026count)\n\n// Line 38: err reused/shadowed here\nresurrected, err := s.TryResurrectParent(ctx, parentID)\n```\n\nWhile Go allows this, it can be confusing and some linters flag it.\n\n## Solution\nUse different variable name:\n\n```go\nresurrected, resurrectErr := s.TryResurrectParent(ctx, parentID)\nif resurrectErr != nil {\n return \"\", fmt.Errorf(\"failed to resurrect parent %s: %w\", parentID, resurrectErr)\n}\n```\n\n## Files\n- internal/storage/sqlite/hash_ids.go:38\n\n## Priority\nLow - code works correctly, just a style improvement","status":"closed","priority":3,"issue_type":"task","created_at":"2025-11-21T10:26:09.734162-05:00","updated_at":"2025-11-22T17:48:48.071927-08:00","closed_at":"2025-11-21T11:25:23.408878-05:00","source_repo":".","dependencies":[{"issue_id":"bd-ar2.9","depends_on_id":"bd-ar2","type":"parent-child","created_at":"2025-11-21T10:26:09.734618-05:00","created_by":"daemon"}]} {"id":"bd-au0","content_hash":"ae18be77bb65e3f3f299a0352553eba9919b16d91d8cc7c412387a5bb213625e","title":"Command Set Standardization \u0026 Flag Consistency","description":"Comprehensive improvements to bd command set based on 2025 audit findings.\n\n## Background\nSee docs/command-audit-2025.md for detailed analysis.\n\n## Goals\n1. Standardize flag naming and behavior across all commands\n2. Add missing flags for feature parity\n3. Fix naming confusion\n4. Improve consistency in JSON output\n\n## Success Criteria\n- All mutating commands support --dry-run (no --preview variants)\n- bd update supports label operations\n- bd search has filter parity with bd list\n- Priority flags accept both int and P0-P4 format everywhere\n- JSON output is consistent across all commands","status":"closed","priority":2,"issue_type":"epic","created_at":"2025-11-21T21:05:55.672749-05:00","updated_at":"2025-11-23T20:39:55.303537-08:00","closed_at":"2025-11-23T20:29:32.847963-08:00","source_repo":"."} -{"id":"bd-au0.1","content_hash":"c125f8efd60c701e268bdb0c06a472b5ce3c9bdcf9af5d973ec3437ec4200e46","title":"Standardize --dry-run flag across all commands","description":"Replace all instances of --preview with --dry-run for consistency.\n\n**Commands to update:**\n- clean: Change --preview to --dry-run\n\n**Commands to verify:**\n- cleanup, compact, delete, duplicates, epic close-eligible, import, sync\n\n**Testing:**\n- Ensure all mutating commands support --dry-run\n- Verify backward compatibility (deprecation warning for --preview?)\n- Update tests and documentation","notes":"All commands already use --dry-run consistently. Verified:\n- cleanup: line 130\n- compact: line 873\n- delete: line 559\n- duplicates: line 158\n- import: line 703\n- sync: line 333\n- epic close-eligible: line 208\n- clean: line 162\n\nNo --preview flags found in the codebase. This task appears to have been completed before the epic was created.","status":"closed","priority":0,"issue_type":"task","created_at":"2025-11-21T21:06:09.6033-05:00","updated_at":"2025-11-21T21:28:29.836473-05:00","closed_at":"2025-11-21T21:28:29.836473-05:00","source_repo":".","dependencies":[{"issue_id":"bd-au0.1","depends_on_id":"bd-au0","type":"parent-child","created_at":"2025-11-21T21:06:09.603828-05:00","created_by":"daemon"}]} +{"id":"bd-au0.1","content_hash":"9cbbb481d8441cb40a4a281f65b7a8522f842421d7bf41803011b84f2e0a7a96","title":"Standardize --dry-run flag across all commands","description":"Replace all instances of --preview with --dry-run for consistency.\n\n**Commands to update:**\n- clean: Change --preview to --dry-run\n\n**Commands to verify:**\n- cleanup, compact, delete, duplicates, epic close-eligible, import, sync\n\n**Testing:**\n- Ensure all mutating commands support --dry-run\n- Verify backward compatibility (deprecation warning for --preview?)\n- Update tests and documentation","notes":"All commands already use --dry-run consistently. Verified:\n- cleanup: line 130\n- compact: line 873\n- delete: line 559\n- duplicates: line 158\n- import: line 703\n- sync: line 333\n- epic close-eligible: line 208\n- clean: line 162\n\nNo --preview flags found in the codebase. This task appears to have been completed before the epic was created.","status":"closed","priority":0,"issue_type":"task","created_at":"2025-11-21T21:06:09.6033-05:00","updated_at":"2025-11-21T21:28:29.836473-05:00","closed_at":"2025-11-21T21:28:29.836473-05:00","source_repo":".","dependencies":[{"issue_id":"bd-au0.1","depends_on_id":"bd-au0","type":"parent-child","created_at":"2025-11-21T21:06:09.603828-05:00","created_by":"daemon"}]} {"id":"bd-au0.10","content_hash":"9ee750bc9cdf382f55804ed87b7320156fd496b745d2659262b09deea96735a0","title":"Add global verbosity flags (--verbose, --quiet)","description":"Add consistent verbosity controls across all commands.\n\n**Current state:**\n- bd init has --quiet flag\n- No other commands have verbosity controls\n- Debug output controlled by BD_VERBOSE env var\n\n**Proposal:**\nAdd persistent flags:\n- --verbose / -v: Enable debug output\n- --quiet / -q: Suppress non-essential output\n\n**Implementation:**\n- Add to rootCmd.PersistentFlags()\n- Replace BD_VERBOSE checks with flag checks\n- Standardize output levels:\n * Quiet: Errors only\n * Normal: Errors + success messages\n * Verbose: Errors + success + debug info\n\n**Files to modify:**\n- cmd/bd/main.go (add flags)\n- internal/debug/debug.go (respect flags)\n- Update all commands to respect quiet mode\n\n**Testing:**\n- Verify --verbose shows debug output\n- Verify --quiet suppresses normal output\n- Ensure errors always show regardless of mode","notes":"Analysis: This requires coordinating changes across main.go (add flags), debug/debug.go (add SetVerbose/SetQuiet functions), and potentially many command files. Current state: BD_DEBUG env var controls debug output via debug.Logf(). Implementation would need: 1) Add verboseFlag/quietFlag vars in main.go, 2) Update debug package to check flags, 3) Add PersistentPreRun logic to apply flags, 4) Test across all commands. This is P3 and less critical than completed P0/P1 tasks.","status":"closed","priority":3,"issue_type":"task","created_at":"2025-11-21T21:08:21.600209-05:00","updated_at":"2025-11-23T20:39:55.307301-08:00","closed_at":"2025-11-23T20:29:14.324705-08:00","source_repo":".","dependencies":[{"issue_id":"bd-au0.10","depends_on_id":"bd-au0","type":"parent-child","created_at":"2025-11-21T21:08:21.602557-05:00","created_by":"daemon"}]} {"id":"bd-au0.2","content_hash":"a2fcaf0cc3764b792cf4a7deccf6e7f38f9ea3ff91adda246c7b7da704ac9be4","title":"Add label operations to bd update command","description":"Add --add-label and --remove-label flags to bd update.\n\n**Implementation:**\n- Add flags: --add-label, --remove-label, --set-labels\n- Support multiple labels (repeatable flags)\n- Test with daemon and direct mode\n\n**Files to modify:**\n- cmd/bd/show.go (updateCmd definition)\n- Add RPC support in internal/rpc/protocol.go and server\n\n**Testing:**\n- Add/remove single label\n- Add/remove multiple labels\n- Set labels (replace all)\n- JSON output\n- Daemon mode vs direct mode","notes":"Architecture review complete:\n- Current: separate 'bd label add/remove' commands exist\n- UpdateArgs struct in protocol.go needs new fields: AddLabels, RemoveLabels, SetLabels\n- RPC server needs label operation support in Update handler\n- CLI flags needed: --add-label, --remove-label, --set-labels (repeatable)\n- Both daemon and direct mode need implementation\n- Tests needed for all modes\n\nThis is a moderate-sized feature requiring changes across:\n1. cmd/bd/show.go (updateCmd flags and logic)\n2. internal/rpc/protocol.go (UpdateArgs struct)\n3. internal/rpc/server_issues_epics.go (Update handler)\n4. Tests for daemon/direct modes","status":"closed","priority":0,"issue_type":"task","created_at":"2025-11-21T21:06:23.715557-05:00","updated_at":"2025-11-21T22:15:19.213541-05:00","closed_at":"2025-11-21T22:15:19.213543-05:00","source_repo":".","dependencies":[{"issue_id":"bd-au0.2","depends_on_id":"bd-au0","type":"parent-child","created_at":"2025-11-21T21:06:23.716044-05:00","created_by":"daemon"}]} -{"id":"bd-au0.3","content_hash":"51c9568427922dc2d497ebe32b9a57f7db0177ca760609078049c2b2bd72efec","title":"Fix --title vs --title-contains redundancy in bd list","description":"Clarify or consolidate --title and --title-contains flags in bd list command.\n\n**Analysis needed:**\n- Determine if these serve different purposes\n- Check actual implementation in cmd/bd/list.go\n- Review user expectations\n\n**Options:**\n1. Keep both if they have semantic difference (exact vs substring)\n2. Make one an alias of the other\n3. Remove --title-contains if truly redundant\n\n**Testing:**\n- Verify current behavior\n- Update documentation\n- Add tests for chosen approach","notes":"Investigation complete:\n\n--title and --title-contains serve DIFFERENT purposes:\n- --title: Maps to Query field (searches title, description, AND ID) - line 226\n- --title-contains: Maps to TitleContains field (searches title ONLY) - line 233\n\nThese are NOT redundant. The flag names are confusing:\n- --title is actually a general search\n- --title-contains is title-specific\n\nRECOMMENDATION: Rename --title to --query or --search for clarity\n- More intuitive: 'bd list --query foo' vs 'bd list --title foo'\n- Makes it clear it searches multiple fields\n- --title-contains remains for title-only searches\n\nAlternative: Keep as-is but improve documentation to clarify the difference.","status":"closed","priority":0,"issue_type":"task","created_at":"2025-11-21T21:06:37.597079-05:00","updated_at":"2025-11-21T21:31:53.446905-05:00","closed_at":"2025-11-21T21:31:53.446905-05:00","source_repo":".","dependencies":[{"issue_id":"bd-au0.3","depends_on_id":"bd-au0","type":"parent-child","created_at":"2025-11-21T21:06:37.597595-05:00","created_by":"daemon"}]} -{"id":"bd-au0.4","content_hash":"711036fe826d16c2c094bb1eb4978ed0ccb596aadc8a4d78550e3089ffc45922","title":"Standardize priority flag parsing across all commands","description":"Accept both integer (0-4) and P0-P4 format in all commands.\n\n**Commands to update:**\n- bd create: Currently accepts both βœ“\n- bd update: Currently accepts both βœ“\n- bd list: Only accepts int\n- bd search: Add priority filter (missing entirely)\n\n**Implementation:**\n- Create shared priority parsing function\n- Support both formats: '0', '1', 'P0', 'P1', etc.\n- Case-insensitive ('p0', 'P0')\n\n**Files to modify:**\n- cmd/bd/list.go\n- cmd/bd/search.go\n- Add utility function in internal/util/ or internal/types/","notes":"Implementation complete!\n\nChanges made to cmd/bd/list.go:\n1. Added validation import\n2. Changed priority flag from IntP to registerPriorityFlag (line 428)\n3. Changed priority-min/max from Int to String (lines 459-460)\n4. Updated priority parsing to use ValidatePriority (lines 90-97, 230-237)\n5. Updated priority-min/max parsing to use ValidatePriority (lines 195-210)\n\nTesting verified:\nβœ“ bd list -p P0 works\nβœ“ bd list -p 0 works \nβœ“ bd list --priority-min P1 --priority-max P2 works\nβœ“ bd list --priority-min 1 --priority-max 2 works\nβœ“ Invalid priorities rejected with clear error messages\nβœ“ All tests pass\n\nBoth integer (0-4) and P-format (P0-P4) now work consistently across all priority flags in bd list.","status":"closed","priority":0,"issue_type":"task","created_at":"2025-11-21T21:06:51.741518-05:00","updated_at":"2025-11-21T21:56:50.522813-05:00","closed_at":"2025-11-21T21:56:50.522813-05:00","source_repo":".","dependencies":[{"issue_id":"bd-au0.4","depends_on_id":"bd-au0","type":"parent-child","created_at":"2025-11-21T21:06:51.743218-05:00","created_by":"daemon"}]} +{"id":"bd-au0.3","content_hash":"1e0b7a9b5013837f2527fa48084c8702e0be66314b83f9ef621730c90c8e3b26","title":"Fix --title vs --title-contains redundancy in bd list","description":"Clarify or consolidate --title and --title-contains flags in bd list command.\n\n**Analysis needed:**\n- Determine if these serve different purposes\n- Check actual implementation in cmd/bd/list.go\n- Review user expectations\n\n**Options:**\n1. Keep both if they have semantic difference (exact vs substring)\n2. Make one an alias of the other\n3. Remove --title-contains if truly redundant\n\n**Testing:**\n- Verify current behavior\n- Update documentation\n- Add tests for chosen approach","notes":"Investigation complete:\n\n--title and --title-contains serve DIFFERENT purposes:\n- --title: Maps to Query field (searches title, description, AND ID) - line 226\n- --title-contains: Maps to TitleContains field (searches title ONLY) - line 233\n\nThese are NOT redundant. The flag names are confusing:\n- --title is actually a general search\n- --title-contains is title-specific\n\nRECOMMENDATION: Rename --title to --query or --search for clarity\n- More intuitive: 'bd list --query foo' vs 'bd list --title foo'\n- Makes it clear it searches multiple fields\n- --title-contains remains for title-only searches\n\nAlternative: Keep as-is but improve documentation to clarify the difference.","status":"closed","priority":0,"issue_type":"task","created_at":"2025-11-21T21:06:37.597079-05:00","updated_at":"2025-11-21T21:31:53.446905-05:00","closed_at":"2025-11-21T21:31:53.446905-05:00","source_repo":".","dependencies":[{"issue_id":"bd-au0.3","depends_on_id":"bd-au0","type":"parent-child","created_at":"2025-11-21T21:06:37.597595-05:00","created_by":"daemon"}]} +{"id":"bd-au0.4","content_hash":"3909dade754ef1909704ff9971e046b1c52a961b61105c9b1ff6bb94bf114f29","title":"Standardize priority flag parsing across all commands","description":"Accept both integer (0-4) and P0-P4 format in all commands.\n\n**Commands to update:**\n- bd create: Currently accepts both βœ“\n- bd update: Currently accepts both βœ“\n- bd list: Only accepts int\n- bd search: Add priority filter (missing entirely)\n\n**Implementation:**\n- Create shared priority parsing function\n- Support both formats: '0', '1', 'P0', 'P1', etc.\n- Case-insensitive ('p0', 'P0')\n\n**Files to modify:**\n- cmd/bd/list.go\n- cmd/bd/search.go\n- Add utility function in internal/util/ or internal/types/","notes":"Implementation complete!\n\nChanges made to cmd/bd/list.go:\n1. Added validation import\n2. Changed priority flag from IntP to registerPriorityFlag (line 428)\n3. Changed priority-min/max from Int to String (lines 459-460)\n4. Updated priority parsing to use ValidatePriority (lines 90-97, 230-237)\n5. Updated priority-min/max parsing to use ValidatePriority (lines 195-210)\n\nTesting verified:\nβœ“ bd list -p P0 works\nβœ“ bd list -p 0 works \nβœ“ bd list --priority-min P1 --priority-max P2 works\nβœ“ bd list --priority-min 1 --priority-max 2 works\nβœ“ Invalid priorities rejected with clear error messages\nβœ“ All tests pass\n\nBoth integer (0-4) and P-format (P0-P4) now work consistently across all priority flags in bd list.","status":"closed","priority":0,"issue_type":"task","created_at":"2025-11-21T21:06:51.741518-05:00","updated_at":"2025-11-21T21:56:50.522813-05:00","closed_at":"2025-11-21T21:56:50.522813-05:00","source_repo":".","dependencies":[{"issue_id":"bd-au0.4","depends_on_id":"bd-au0","type":"parent-child","created_at":"2025-11-21T21:06:51.743218-05:00","created_by":"daemon"}]} {"id":"bd-au0.5","content_hash":"7b8d86208659dee574682584badef58052d28a45e654b63405f7cd14824f23f9","title":"Add date and priority filters to bd search","description":"Add filter parity with bd list for consistent querying.\n\n**Missing filters to add:**\n- --priority, --priority-min, --priority-max\n- --created-after, --created-before\n- --updated-after, --updated-before\n- --closed-after, --closed-before\n- --empty-description, --no-assignee, --no-labels\n- --desc-contains, --notes-contains\n\n**Files to modify:**\n- cmd/bd/search.go\n- internal/rpc/protocol.go (SearchArgs)\n- internal/storage/storage.go (Search method)\n\n**Testing:**\n- All filter combinations\n- Date format parsing\n- Daemon and direct mode","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-21T21:07:05.496726-05:00","updated_at":"2025-11-23T20:39:55.303081-08:00","closed_at":"2025-11-23T20:12:36.523697-08:00","source_repo":".","dependencies":[{"issue_id":"bd-au0.5","depends_on_id":"bd-au0","type":"parent-child","created_at":"2025-11-21T21:07:05.497762-05:00","created_by":"daemon"}]} {"id":"bd-au0.6","content_hash":"e7a370d089aaa8240c182999ef16ec9d416f2badf8161f4fd1d7842af9e07c0a","title":"Add comprehensive filters to bd export","description":"Enhance bd export with filtering options for selective exports.\n\n**Currently only has:**\n- --status\n\n**Add filters:**\n- --label, --label-any\n- --assignee\n- --type\n- --priority, --priority-min, --priority-max\n- --created-after, --created-before\n- --updated-after, --updated-before\n\n**Use case:**\n- Export only open issues: bd export --status open\n- Export high-priority bugs: bd export --type bug --priority-max 1\n- Export recent issues: bd export --created-after 2025-01-01\n\n**Files to modify:**\n- cmd/bd/export.go\n- Reuse filter logic from list.go","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-21T21:07:19.431307-05:00","updated_at":"2025-11-23T20:39:55.301151-08:00","closed_at":"2025-11-23T20:18:52.274199-08:00","source_repo":".","dependencies":[{"issue_id":"bd-au0.6","depends_on_id":"bd-au0","type":"parent-child","created_at":"2025-11-21T21:07:19.432983-05:00","created_by":"daemon"}]} {"id":"bd-au0.7","content_hash":"dfb1dafbef637e6e05917037667c2d5dff7df7f8ddfd86ffa9c86ef220c55af4","title":"Audit and standardize JSON output across all commands","description":"Ensure consistent JSON format and error handling when --json flag is used.\n\n**Scope:**\n1. Verify all commands respect --json flag\n2. Standardize success response format\n3. Standardize error response format\n4. Document JSON schemas\n\n**Commands to audit:**\n- Core CRUD: create, update, delete, show, list, search βœ“\n- Queries: ready, blocked, stale, count, stats, status\n- Deps: dep add/remove/tree/cycles\n- Labels: label commands\n- Comments: comments add/list/delete\n- Epics: epic status/close-eligible\n- Export/import: already support --json βœ“\n\n**Testing:**\n- Success cases return valid JSON\n- Error cases return valid JSON (not plain text)\n- Consistent field naming (snake_case vs camelCase)\n- Array vs object wrapping consistency","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-21T21:07:35.304424-05:00","updated_at":"2025-11-23T20:39:55.304954-08:00","closed_at":"2025-11-23T20:13:37.581428-08:00","source_repo":".","dependencies":[{"issue_id":"bd-au0.7","depends_on_id":"bd-au0","type":"parent-child","created_at":"2025-11-21T21:07:35.305663-05:00","created_by":"daemon"}]} @@ -326,7 +326,7 @@ {"id":"bd-au0.9","content_hash":"c7d97697c6497067e95de386d595f21714d94ad75da7474d990cf56e9ca3278d","title":"Review and document rarely-used commands","description":"Document use cases or consider deprecation for infrequently-used commands.\n\n**Commands to review:**\n1. bd rename-prefix - How often is this used? Document use cases\n2. bd detect-pollution - Consider integrating into bd validate\n3. bd migrate-hash-ids - One-time migration, keep but document as legacy\n\n**For each command:**\n- Document typical use cases\n- Add examples to help text\n- Consider if it should be a subcommand instead\n- Add deprecation warning if appropriate\n\n**Not changing:**\n- duplicates βœ“ (useful for data quality)\n- repair-deps βœ“ (useful for fixing broken refs)\n- restore βœ“ (critical for compacted issues)\n- compact βœ“ (performance feature)\n\n**Deliverable:**\n- Updated help text\n- Documentation in ADVANCED.md\n- Deprecation plan if needed","status":"closed","priority":3,"issue_type":"task","created_at":"2025-11-21T21:08:05.588275-05:00","updated_at":"2025-11-23T20:39:55.305413-08:00","closed_at":"2025-11-23T20:23:42.58876-08:00","source_repo":".","dependencies":[{"issue_id":"bd-au0.9","depends_on_id":"bd-au0","type":"parent-child","created_at":"2025-11-21T21:08:05.59003-05:00","created_by":"daemon"}]} {"id":"bd-auf1","content_hash":"68ddc54d14d231775a25f6786b927c44719435cf6af2859592bcca6b55396533","title":"Clean up snapshot files after successful merge","description":"After a successful 3-way merge and import during 'bd sync', the snapshot files (beads.base.jsonl, beads.left.jsonl, and their .meta.json files) are left in the .beads/ directory indefinitely.\n\nThese files are only needed temporarily during the merge process:\n- beads.base.jsonl: snapshot from last successful import\n- beads.left.jsonl: snapshot before git pull\n\nOnce the merge succeeds and the new JSONL is imported, these files serve no purpose and should be cleaned up.\n\nCurrent behavior:\n- sync.go:269 calls updateBaseSnapshot() after successful import\n- UpdateBase() updates beads.base.jsonl to the new state\n- beads.left.jsonl is never removed\n- Both files accumulate in .beads/ directory\n\nExpected behavior:\n- After successful merge and import, clean up both snapshot files\n- Only retain snapshots between sync operations (create on export, use during merge, clean up after import)\n\nThe cleanup logic exists (SnapshotManager.Cleanup()) but is only called on validation failures (deletion_tracking.go:48), not on success.\n\nDiscovered in vc project where stale snapshot files from Nov 8 merge were still present.","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-11-08T22:39:56.460778-08:00","updated_at":"2025-11-23T14:14:13.332096-08:00","closed_at":"2025-11-08T22:47:51.96296-08:00","source_repo":"."} {"id":"bd-aysr","content_hash":"f8ff127568f471cc42391b1287cce69b376fb1b49bbef20a24d3394f57fba066","title":"Test numeric 1","description":"","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-05T12:58:41.498034-08:00","updated_at":"2025-11-05T12:58:44.73082-08:00","closed_at":"2025-11-05T12:58:44.73082-08:00","source_repo":"."} -{"id":"bd-ayw","content_hash":"825e5540d42018f2d2cad08f79581eb1b819320bbde4802409111fda485d6d53","title":"Add 'When to use daemon mode' decision tree to daemon.md","description":"**Problem:**\nUsers (especially local-only developers) see daemon-related messages but don't understand:\n- What daemon mode does (git sync automation)\n- Whether they need it\n- Why they see \"daemon_unsupported\" messages\n\nRelated to issue #349 item #3.\n\n**Current state:**\ncommands/daemon.md explains WHAT daemon does but not WHEN to use it.\n\n**Proposed addition:**\nAdd a \"When to Use Daemon Mode\" section after line 20 in commands/daemon.md with clear decision criteria:\n\n**βœ… You SHOULD use daemon mode if:**\n- Working in a team with git remote sync\n- Want automatic commit/push of issue changes\n- Need background auto-sync (5-second debounce)\n- Making frequent bd commands (performance benefit)\n\n**❌ You DON'T need daemon mode if:**\n- Solo developer with local-only tracking\n- Working in git worktrees (use --no-daemon)\n- Running one-off commands/scripts\n- Debugging database issues\n\n**Local-only users:** Direct mode is perfectly fine. Daemon mainly helps with git sync automation. You can use `bd sync` manually when needed.\n\n**Files to modify:**\n- commands/daemon.md (add section after line 20)","status":"closed","priority":3,"issue_type":"task","created_at":"2025-11-20T20:48:23.111621-05:00","updated_at":"2025-11-23T14:14:13.332678-08:00","closed_at":"2025-11-20T20:59:13.429263-05:00","source_repo":".","labels":["documentation","onboarding"],"comments":[{"id":18,"issue_id":"bd-ayw","author":"stevey","text":"Addresses GitHub issue #349 item 3: https://github.com/steveyegge/beads/issues/349\n\nLocal-only users see daemon-related messages without understanding when they need daemon mode vs when direct mode is sufficient. Need clear decision tree in daemon.md.","created_at":"2025-11-21T02:23:27Z"}]} +{"id":"bd-ayw","content_hash":"825e5540d42018f2d2cad08f79581eb1b819320bbde4802409111fda485d6d53","title":"Add 'When to use daemon mode' decision tree to daemon.md","description":"**Problem:**\nUsers (especially local-only developers) see daemon-related messages but don't understand:\n- What daemon mode does (git sync automation)\n- Whether they need it\n- Why they see \"daemon_unsupported\" messages\n\nRelated to issue #349 item #3.\n\n**Current state:**\ncommands/daemon.md explains WHAT daemon does but not WHEN to use it.\n\n**Proposed addition:**\nAdd a \"When to Use Daemon Mode\" section after line 20 in commands/daemon.md with clear decision criteria:\n\n**βœ… You SHOULD use daemon mode if:**\n- Working in a team with git remote sync\n- Want automatic commit/push of issue changes\n- Need background auto-sync (5-second debounce)\n- Making frequent bd commands (performance benefit)\n\n**❌ You DON'T need daemon mode if:**\n- Solo developer with local-only tracking\n- Working in git worktrees (use --no-daemon)\n- Running one-off commands/scripts\n- Debugging database issues\n\n**Local-only users:** Direct mode is perfectly fine. Daemon mainly helps with git sync automation. You can use `bd sync` manually when needed.\n\n**Files to modify:**\n- commands/daemon.md (add section after line 20)","status":"closed","priority":3,"issue_type":"task","created_at":"2025-11-20T20:48:23.111621-05:00","updated_at":"2025-11-23T14:14:13.332678-08:00","closed_at":"2025-11-20T20:59:13.429263-05:00","source_repo":".","labels":["documentation","onboarding"]} {"id":"bd-az0m","content_hash":"91dd58e84b57c84ae065004ef4c15d0b5330935a5fde35eed489a93452feb2e9","title":"Issue 1","description":"","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-20T19:43:48.754145-05:00","updated_at":"2025-11-20T19:43:48.754145-05:00","closed_at":"2025-11-07T21:55:09.42865-08:00","source_repo":".","dependencies":[{"issue_id":"bd-az0m","depends_on_id":"bd-bvo2","type":"related","created_at":"2025-11-07T19:07:21.069031-08:00","created_by":"daemon"}]} {"id":"bd-azqv","content_hash":"b4e68adcec7b19f567ebee47f505ca6b529c17b4c4b885282cfc564e8a874f9f","title":"Ready issue","description":"","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-07T19:04:22.247039-08:00","updated_at":"2025-11-07T22:07:17.344986-08:00","closed_at":"2025-11-07T21:55:09.429024-08:00","source_repo":"."} {"id":"bd-b0c8","content_hash":"87b423a42d509b9405b52b089b2ba92b33a90ad472d6d9094986b48715399a99","title":"Research hooks/skills approach for enforcing issue descriptions","description":"## Solution: Hooks/Skills (mentioned in discussion)\n\nResearch the hooks/skills system mentioned by riordanpawley in discussion #366:\nhttps://www.reddit.com/r/ClaudeAI/s/wrn2tjkMHX\n\n## Investigation Tasks\n\n1. Review the Reddit post to understand the approach\n2. Determine if beads hooks can enforce validation\n3. Check if Claude Code skills/hooks can intercept MCP calls\n4. Assess feasibility and user burden\n\n## Notes\n\nFrom discussion #366:\n\u003e I'm using a skills/hooks system to get Claude to do that kind of thing right similar to https://www.reddit.com/r/ClaudeAI/s/wrn2tjkMHX\n\nThis might be a client-side solution rather than server-side.\n\n## Deliverable\n\nDocument findings in issue notes, with recommendation on whether to pursue this approach.","status":"open","priority":3,"issue_type":"task","created_at":"2025-11-23T14:01:01.57079-08:00","updated_at":"2025-11-23T14:01:01.57079-08:00","source_repo":".","dependencies":[{"issue_id":"bd-b0c8","depends_on_id":"bd-0tr0","type":"discovered-from","created_at":"2025-11-23T14:01:01.572166-08:00","created_by":"daemon"}]} @@ -362,9 +362,9 @@ {"id":"bd-bzfy","content_hash":"90bbde4d90d68728a9377d5d966682dc836740f1be43a0cf80d3cc69002a560b","title":"Integrate beads-merge tool by @neongreen","description":"**Context**: @neongreen built a production-ready 3-way merge tool for JSONL files that works with both Git and Jujutsu. This is superior to our planned bd resolve-conflicts because it prevents conflicts proactively instead of resolving them after the fact.\n\n**Tool**: https://github.com/neongreen/mono/tree/main/beads-merge\n\n**What it does**:\n- 3-way merge of JSONL files (base, left, right)\n- Field-level merging (titles, status, priority, etc.)\n- Smart dependency merging (union + dedup)\n- Conflict markers for unresolvable conflicts\n- Exit code 1 for conflicts (standard)\n\n**Integration options**:\n\n1. **Recommend (minimal effort)** - Document in AGENTS.md + TROUBLESHOOTING.md\n2. **Bundle binary** - Include in releases (cross-platform builds)\n3. **Port to Go** - Reimplement in bd codebase\n4. **Auto-install hook** - During bd init, offer to install merge driver\n\n**Recommendation**: Start with option 1 (document), then option 2 (bundle) once proven.\n\n**Related**: bd-5f483051 (bd resolve-conflicts - can close as superseded)","notes":"Created GitHub issue to discuss integration approach with @neongreen: https://github.com/neongreen/mono/issues/240\n\nAwaiting their preference on:\n1. Vendor with attribution (fastest)\n2. Extract as importable module (best long-term)\n3. Keep as separate tool (current state)\n\nNext: Wait for response before proceeding with integration.\n\nUPDATE 2025-11-06: @neongreen gave permission to vendor! Quote: \"I switched from beads to my own thing (tk) so I'm very happy to give beads-merge away β€” feel free to move it into the beads repo and I will point mono's readme to beads\"\n\nNext: Vendor beads-merge with full attribution","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-11-05T11:31:44.906652-08:00","updated_at":"2025-11-06T18:19:16.233387-08:00","closed_at":"2025-11-06T15:38:37.052274-08:00","source_repo":"."} {"id":"bd-c01f","content_hash":"14269c39f13784e0ee793fae005b1869fea5c08af1bbdc4a2f841720278180d5","title":"Implement bd stale command to find abandoned/forgotten issues","description":"Add bd stale command to surface issues that haven't been updated recently and may need attention.\n\nUse cases:\n- In-progress issues with no recent activity (may be abandoned)\n- Open issues that have been forgotten\n- Issues that might be outdated or no longer relevant\n\nQuery logic should find non-closed issues where updated_at exceeds a time threshold.\n\nShould support:\n- --days N flag (default 30-90 days)\n- --status filter (e.g., only in_progress)\n- --json output for automation\n\nReferences GitHub issue #184 where user expected this command to exist.","design":"Implementation approach:\n1. Add new command in cmd/bd/stale.go\n2. Query issues with: status != 'closed' AND updated_at \u003c (now - N days)\n3. Support filtering by status (open, in_progress, blocked)\n4. Default threshold: 30 days (configurable via --days)\n5. JSON output for agent consumption\n6. Order by updated_at ASC (oldest first)","status":"closed","priority":2,"issue_type":"epic","created_at":"2025-10-31T22:48:46.85435-07:00","updated_at":"2025-10-31T22:54:33.704492-07:00","closed_at":"2025-10-31T22:54:33.704492-07:00","source_repo":"."} {"id":"bd-c13f","content_hash":"0e428b0589a6f763a32195b32241ec71141793101ee102df5df69d3c7fadfaaf","title":"Add unit tests for parent resurrection","description":"Test resurrection with deleted parent (should succeed), resurrection with never-existed parent (should fail gracefully), multi-level resurrection (bd-abc.1.2 with both parents missing). Verify tombstone creation and is_tombstone flag.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-04T12:32:21.325335-08:00","updated_at":"2025-11-05T00:08:42.813728-08:00","closed_at":"2025-11-05T00:08:42.813731-08:00","source_repo":"."} -{"id":"bd-c362","content_hash":"3e39635c6536808014161e1ead561a1ecf1e176fe28b7c2272a11dbeb7be8994","title":"Extract database search logic into helper function","description":"The logic for finding a database in a beads directory is duplicated:\n- FindDatabasePath() BEADS_DIR section (beads.go:141-169)\n- findDatabaseInTree() (beads.go:248-280)\n\nBoth implement the same search order:\n1. Check config.json first (single source of truth)\n2. Fall back to canonical beads.db\n3. Search for *.db files, filtering backups and vc.db\n\nRefactoring suggestion:\nExtract to a helper function like:\n func findDatabaseInBeadsDir(beadsDir string) string\n\nBenefits:\n- Single source of truth for database search logic\n- Easier to maintain and update search order\n- Reduces code duplication\n\nRelated to [deleted:[deleted:[deleted:[deleted:[deleted:bd-e16b]]]]] implementation.","status":"open","priority":3,"issue_type":"chore","created_at":"2025-11-02T18:34:02.831543-08:00","updated_at":"2025-11-23T21:31:18.598635-08:00","source_repo":".","dependencies":[{"issue_id":"bd-c362","depends_on_id":"bd-e16b","type":"blocks","created_at":"2025-11-02T18:34:02.832607-08:00","created_by":"daemon"}]} +{"id":"bd-c362","content_hash":"3e39635c6536808014161e1ead561a1ecf1e176fe28b7c2272a11dbeb7be8994","title":"Extract database search logic into helper function","description":"The logic for finding a database in a beads directory is duplicated:\n- FindDatabasePath() BEADS_DIR section (beads.go:141-169)\n- findDatabaseInTree() (beads.go:248-280)\n\nBoth implement the same search order:\n1. Check config.json first (single source of truth)\n2. Fall back to canonical beads.db\n3. Search for *.db files, filtering backups and vc.db\n\nRefactoring suggestion:\nExtract to a helper function like:\n func findDatabaseInBeadsDir(beadsDir string) string\n\nBenefits:\n- Single source of truth for database search logic\n- Easier to maintain and update search order\n- Reduces code duplication\n\nRelated to [deleted:[deleted:[deleted:[deleted:[deleted:bd-e16b]]]]] implementation.","status":"open","priority":3,"issue_type":"chore","created_at":"2025-11-02T18:34:02.831543-08:00","updated_at":"2025-11-23T21:25:52.437692-08:00","source_repo":".","dependencies":[{"issue_id":"bd-c362","depends_on_id":"bd-e16b","type":"blocks","created_at":"2025-11-02T18:34:02.832607-08:00","created_by":"daemon"}]} {"id":"bd-c3ei","content_hash":"33a1bd2deaee412d0523c512061f2e31e3f15340858b550869e43b4ccec5211f","title":"Migration guide documentation","description":"Write comprehensive migration guide covering: OSS contributor workflow, team workflow, multi-phase development, multiple personas. Include step-by-step instructions, troubleshooting, and backward compatibility notes.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-05T18:04:29.84662-08:00","updated_at":"2025-11-05T18:12:30.907835-08:00","closed_at":"2025-11-05T18:12:30.907835-08:00","source_repo":".","dependencies":[{"issue_id":"bd-c3ei","depends_on_id":"bd-8rd","type":"parent-child","created_at":"2025-11-05T18:04:39.028291-08:00","created_by":"daemon"}]} -{"id":"bd-c49","content_hash":"f8074b901fa233e2dde691205357ce3963e7e9c7e2b91f3a9d49b421914bcc49","title":"Audit all cmd/bd tests and group into suites","description":"Analyze all 279 tests in cmd/bd and identify:\n1. Which tests can share DB setup (most of them\\!)\n2. Which tests actually need isolation (export/import, git ops)\n3. Optimal grouping into test suites\n\nCreate a mapping document showing:\n- Current: 279 individual test functions\n- Proposed: ~10-15 test suites with subtests\n- Expected speedup per suite\n\nBlocks all refactoring work.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-21T11:49:19.438242-05:00","updated_at":"2025-11-21T15:15:29.50544-05:00","closed_at":"2025-11-21T15:15:29.50544-05:00","source_repo":"."} +{"id":"bd-c49","content_hash":"c1594c0e8df8fafa5c3a7295817f8660f653569d33f7f51d00b3d3c8ed51dc78","title":"Audit all cmd/bd tests and group into suites","description":"Analyze all 279 tests in cmd/bd and identify:\n1. Which tests can share DB setup (most of them\\!)\n2. Which tests actually need isolation (export/import, git ops)\n3. Optimal grouping into test suites\n\nCreate a mapping document showing:\n- Current: 279 individual test functions\n- Proposed: ~10-15 test suites with subtests\n- Expected speedup per suite\n\nBlocks all refactoring work.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-21T11:49:19.438242-05:00","updated_at":"2025-11-21T15:15:29.50544-05:00","closed_at":"2025-11-21T15:15:29.50544-05:00","source_repo":"."} {"id":"bd-c4rq","content_hash":"4c096e1d84c3ba5b5b4e107692b990a99166b4c99a4262fd26ec08297fb81046","title":"Refactor: Move staleness check inside daemon branch","description":"## Problem\n\nCurrently ensureDatabaseFresh() is called before the daemon mode check, but it checks daemonClient != nil internally and returns early. This is redundant.\n\n**Location:** All read commands (list.go:196, show.go:27, ready.go:102, status.go:80, etc.)\n\n## Current Pattern\n\nCall happens before daemon check, function checks daemonClient internally.\n\n## Better Pattern\n\nMove staleness check to direct mode branch only, after daemon check.\n\n## Impact\nLow - minor performance improvement (avoids one function call per command in daemon mode)\n\n## Effort\nMedium - requires refactoring 8 command files\n\n## Priority\nLow - can defer to future cleanup PR","status":"open","priority":3,"issue_type":"chore","created_at":"2025-11-20T20:17:45.119583-05:00","updated_at":"2025-11-20T20:17:45.119583-05:00","source_repo":"."} {"id":"bd-c77d","content_hash":"204eed7c89bcda47198a774340985706baf139c9e1a9f1311d7340dac2b64ec7","title":"Test SQLite WASM compatibility","description":"Verify modernc.org/sqlite works in WASM target. Child of epic bd-44d0.\n\n## Tasks\n- [ ] Compile minimal SQLite test to WASM\n- [ ] Test database create/open operations\n- [ ] Test query execution\n- [ ] Test JSONL import/export\n- [ ] Benchmark performance vs native\n\n## Decision Point\nIf modernc.org/sqlite issues, evaluate ncruces/go-sqlite3 alternative.","status":"closed","priority":0,"issue_type":"task","created_at":"2025-11-02T18:33:31.247537-08:00","updated_at":"2025-11-05T00:55:48.757762-08:00","closed_at":"2025-11-05T00:55:48.75777-08:00","source_repo":".","dependencies":[{"issue_id":"bd-c77d","depends_on_id":"bd-197b","type":"blocks","created_at":"2025-11-02T18:33:31.248112-08:00","created_by":"daemon"}]} {"id":"bd-c796","content_hash":"7231785c8ce4d15ce296f7e2d22d03b9d6610ed73dcc5501773f86782ffeaf03","title":"Extract batch operations to batch_ops.go","description":"Move validateBatchIssues, generateBatchIDs, bulkInsertIssues, bulkRecordEvents, bulkMarkDirty, CreateIssues to batch_ops.go","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-01T19:28:54.887487-07:00","updated_at":"2025-11-02T08:09:51.579971-08:00","closed_at":"2025-11-02T08:09:51.579978-08:00","source_repo":"."} @@ -434,7 +434,7 @@ {"id":"bd-e92","content_hash":"12073b3293b06f99051bc9c00188aeb520cd2e4792cf4694f1fa4b784e625e54","title":"Add test coverage for internal/autoimport package","description":"","design":"The autoimport package has only 1 test file. Need comprehensive tests. Target: 70% coverage","acceptance_criteria":"- At least 3 test files\n- Package coverage \u003e= 70%\n- Tests cover main functionality, error paths, edge cases","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-20T21:21:22.338577-05:00","updated_at":"2025-11-20T21:21:22.338577-05:00","source_repo":".","dependencies":[{"issue_id":"bd-e92","depends_on_id":"bd-ge7","type":"blocks","created_at":"2025-11-20T21:21:31.128625-05:00","created_by":"daemon"}]} {"id":"bd-e98221b3","content_hash":"4a4f6912d8de8bf0f9ae867be1a25d83c5a6991383e3aa192537747500bebc6a","title":"Update AGENTS.md and README.md with \"bd daemons\" documentation","description":"Document the new \"bd daemons\" command and all subcommands in AGENTS.md and README.md. Include examples and troubleshooting guidance.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-26T19:41:11.099254-07:00","updated_at":"2025-11-06T20:06:49.219318-08:00","closed_at":"2025-11-06T19:51:57.75321-08:00","source_repo":"."} {"id":"bd-eb3c","content_hash":"6c7a46d58e565a27e3a7a5375bb1ad8345094bdef422dce52239ee4b7e559143","title":"UX nightmare: multiple ways daemon can fail with misleading messages","description":"","status":"closed","priority":0,"issue_type":"epic","created_at":"2025-10-31T21:08:09.090553-07:00","updated_at":"2025-11-01T20:27:42.79962-07:00","closed_at":"2025-11-01T20:27:42.79962-07:00","source_repo":"."} -{"id":"bd-ee1","content_hash":"813f0cd17493750301a4bc258ac0b939db2edd7abaaf4b8bd1eb6fff9ea0c401","title":"Add security tests for WriteFile permissions in doctor command","description":"Test coverage gap identified by automated analysis (vc-217).\n\n**Original Issue:** [deleted:[deleted:[deleted:[deleted:bd-da96-baseline-lint]]]]\n\nIn cmd/bd/doctor/gitignore.go:98, os.WriteFile uses 0644 permissions, flagged by gosec G306 as potentially too permissive.\n\nAdd tests to verify:\n- File is created with appropriate permissions (0600 or less)\n- Existing file permissions are not loosened\n- File ownership is correct\n- Sensitive data handling if .gitignore contains secrets\n\nThis ensures .gitignore files are created with secure permissions to prevent unauthorized access.\n\n_This issue was automatically created by AI test coverage analysis._","status":"open","priority":1,"issue_type":"task","created_at":"2025-11-21T10:25:33.529153-05:00","updated_at":"2025-11-23T21:31:18.595509-08:00","source_repo":".","labels":["discovered:supervisor"],"dependencies":[{"issue_id":"bd-ee1","depends_on_id":"bd-da96-baseline-lint","type":"discovered-from","created_at":"2025-11-21T10:25:33.530705-05:00","created_by":"ai-supervisor"}]} +{"id":"bd-ee1","content_hash":"813f0cd17493750301a4bc258ac0b939db2edd7abaaf4b8bd1eb6fff9ea0c401","title":"Add security tests for WriteFile permissions in doctor command","description":"Test coverage gap identified by automated analysis (vc-217).\n\n**Original Issue:** [deleted:[deleted:[deleted:[deleted:bd-da96-baseline-lint]]]]\n\nIn cmd/bd/doctor/gitignore.go:98, os.WriteFile uses 0644 permissions, flagged by gosec G306 as potentially too permissive.\n\nAdd tests to verify:\n- File is created with appropriate permissions (0600 or less)\n- Existing file permissions are not loosened\n- File ownership is correct\n- Sensitive data handling if .gitignore contains secrets\n\nThis ensures .gitignore files are created with secure permissions to prevent unauthorized access.\n\n_This issue was automatically created by AI test coverage analysis._","status":"open","priority":1,"issue_type":"task","created_at":"2025-11-21T10:25:33.529153-05:00","updated_at":"2025-11-23T21:25:52.128342-08:00","source_repo":".","labels":["discovered:supervisor"],"dependencies":[{"issue_id":"bd-ee1","depends_on_id":"bd-da96-baseline-lint","type":"discovered-from","created_at":"2025-11-21T10:25:33.530705-05:00","created_by":"ai-supervisor"}]} {"id":"bd-eef03e0a","content_hash":"a7dd31781359f078a172d6d34ceed26be83a3bc8159c05c2026c96717e98a314","title":"Stress test: event storm handling","description":"Simulate 100+ rapid JSONL writes. Verify debouncer batches to single import. Verify no data loss. Test daemon stability.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-29T20:49:49.138725-07:00","updated_at":"2025-10-31T19:18:50.682925-07:00","closed_at":"2025-10-31T19:18:50.682925-07:00","source_repo":"."} {"id":"bd-ef72b864","content_hash":"81f5c4fcc229c3ba653d29fc71c9ae3be75ed672296e3e790a88498ee2df3a64","title":"Add MCP server functions for repair commands","description":"Expose new repair commands via MCP server for agent access:\n\nFunctions to add:\n- beads_repair_deps()\n- beads_detect_pollution()\n- beads_validate()\n- beads_resolve_conflicts() (when implemented)\n\nUpdate integrations/beads-mcp/src/beads_mcp/server.py\n\nSee repair_commands.md lines 803-884 for design.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-28T19:38:02.227921-07:00","updated_at":"2025-10-30T17:12:58.180404-07:00","closed_at":"2025-10-29T23:14:44.187562-07:00","source_repo":"."} {"id":"bd-ef85","content_hash":"56b7e0c048938940053b127e4f9ed578e797b99dc93d010138ec823efbe7842c","title":"Add --json flags to all bd commands for agent-friendly output","description":"","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-10-31T22:39:45.312496-07:00","updated_at":"2025-10-31T22:39:50.157022-07:00","closed_at":"2025-10-31T22:39:50.157022-07:00","source_repo":"."} @@ -444,7 +444,7 @@ {"id":"bd-eqjc","content_hash":"8acc3d91ca9f9bef36d19358cb7f24eac247583a0e6701036aaff92607474c21","title":"bd init creates nested .beads directories","description":"bd init sometimes creates .beads/.beads/ nested directories, which should never happen. This occurs fairly often and can cause confusion about which .beads directory is active. Need to add validation to detect if already inside a .beads directory and either error or use the parent .beads location.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-06T22:21:22.948727-08:00","updated_at":"2025-11-06T22:22:41.04958-08:00","closed_at":"2025-11-06T22:22:41.04958-08:00","source_repo":"."} {"id":"bd-es19","content_hash":"5c5951971ed466f30fa12e1d7f73457ecc430464726516f069e6659f762687e6","title":"BG's issue to reopen","description":"","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-20T19:43:48.756893-05:00","updated_at":"2025-11-20T19:43:48.756893-05:00","closed_at":"2025-11-07T21:57:59.90981-08:00","source_repo":"."} {"id":"bd-expt","content_hash":"6e14db64fb24882e4cf544ec24eaa994aba970fd0ae31c72dda2d8ea88560753","title":"RPC fast-fail: stat socket before dial, cap timeouts to 200ms","description":"Eliminate 5s delay when daemon socket is missing by:\n1. Add os.Stat(socketPath) check before dialing in TryConnect\n2. Return (nil, nil) immediately if socket doesn't exist\n3. Set default dial timeout to 200ms in TryConnect\n4. Keep TryConnectWithTimeout for explicit health/status checks (1-2s)\n\nThis prevents clients from waiting through full timeout when no daemon is running.","status":"closed","priority":0,"issue_type":"task","created_at":"2025-11-07T16:42:12.688526-08:00","updated_at":"2025-11-07T22:07:17.345918-08:00","closed_at":"2025-11-07T21:04:21.671436-08:00","source_repo":".","dependencies":[{"issue_id":"bd-expt","depends_on_id":"bd-ndyz","type":"discovered-from","created_at":"2025-11-07T16:42:12.689284-08:00","created_by":"daemon"}]} -{"id":"bd-exug","content_hash":"768f0ad015c779d71d9fd7ef17c8d72c4b22ab0125b9860aac8a46c010dc0dcf","title":"Fix inconsistent export error handling - fail fast vs graceful degradation","description":"**Location:** internal/rpc/server_export_import_auto.go:64-71\n\n**Issue:** Export operation fails entirely if ANY single issue's labels or comments fail to load. First error stops entire export.\n\n**Current Behavior:**\n```go\nfor _, issue := range issues {\n labels, err := store.GetLabels(ctx, issue.ID)\n if err != nil {\n return Response{\n Success: false,\n Error: fmt.Sprintf(\"failed to get labels for %s: %v\", issue.ID, err),\n }\n }\n}\n```\n\n**Impact:** One corrupted issue makes entire export fail. This is problematic for large databases where some corruption is expected over time.\n\n**Fix:** Either:\n1. Skip labels/comments for problematic issues with warning in export log, OR\n2. Implement retry logic with exponential backoff\n\n**Decision needed:** What's the right trade-off between data integrity and availability?","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-11-23T19:46:48.581549-08:00","updated_at":"2025-11-23T20:21:57.446056-08:00","closed_at":"2025-11-23T20:21:57.446056-08:00","source_repo":"."} +{"id":"bd-exug","content_hash":"e7c32e9fb3624c0e88866e76395465e6bfa37210f9295c32ad891b8ff086fae6","title":"Fix inconsistent export error handling - fail fast vs graceful degradation","description":"**Location:** internal/rpc/server_export_import_auto.go:64-71\n\n**Issue:** Export operation fails entirely if ANY single issue's labels or comments fail to load. First error stops entire export.\n\n**Current Behavior:**\n```go\nfor _, issue := range issues {\n labels, err := store.GetLabels(ctx, issue.ID)\n if err != nil {\n return Response{\n Success: false,\n Error: fmt.Sprintf(\"failed to get labels for %s: %v\", issue.ID, err),\n }\n }\n}\n```\n\n**Impact:** One corrupted issue makes entire export fail. This is problematic for large databases where some corruption is expected over time.\n\n**Fix:** Either:\n1. Skip labels/comments for problematic issues with warning in export log, OR\n2. Implement retry logic with exponential backoff\n\n**Decision needed:** What's the right trade-off between data integrity and availability?","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-11-23T19:46:48.581549-08:00","updated_at":"2025-11-23T20:21:57.446056-08:00","closed_at":"2025-11-23T20:21:57.446056-08:00","source_repo":"."} {"id":"bd-f0d9bcf2","content_hash":"00e0c7b440024e6257d1bac9c1d5af10f8a12ee1726478e4b5bab06e34bfb586","title":"Batch test 1","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-29T15:29:01.795728-07:00","updated_at":"2025-10-31T12:00:43.184078-07:00","closed_at":"2025-10-31T12:00:43.184078-07:00","source_repo":"."} {"id":"bd-f282","content_hash":"90043e5e39cbb062ce0ff6a323ce2d0a16465783742d06ac9da1df66d837e025","title":"Test npm package installation locally","description":"Verify npm package works before publishing:\n\n## Local testing\n- Run npm pack in npm/ directory\n- Install tarball globally: npm install -g beads-bd-0.21.5.tgz\n- Test basic commands:\n - bd --version\n - bd init --quiet --prefix test\n - bd create \"Test issue\" -p 1 --json\n - bd list --json\n - bd sync\n\n## Test environments\n- macOS (darwin-arm64 and darwin-amd64)\n- Linux (ubuntu docker container for linux-amd64)\n- Windows (optional, if available)\n\n## Validation\n- Binary downloads during postinstall\n- All bd commands work identically to native\n- No permission issues\n- Proper error messages on failure","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-02T23:40:05.71835-08:00","updated_at":"2025-11-03T10:31:45.382577-08:00","closed_at":"2025-11-03T10:31:45.382577-08:00","source_repo":".","dependencies":[{"issue_id":"bd-f282","depends_on_id":"bd-febc","type":"parent-child","created_at":"2025-11-02T23:40:32.968748-08:00","created_by":"daemon"}]} {"id":"bd-f8b764c9","content_hash":"45d0f351c47d2bc2c40f271d7442cd3d4facb8e2160b9378c8fd1e540687deb6","title":"Hash-based IDs with aliasing system","description":"Replace sequential auto-increment IDs (bd-1c63eb84, bd-9063acda) with content-hash based IDs (bd-af78e9a2) plus human-friendly aliases (#1, #2).\n\n## Motivation\nCurrent sequential IDs cause collision problems when multiple clones work offline:\n- Non-deterministic convergence in N-way scenarios (bd-cbed9619.1, bd-e6d71828)\n- Complex collision resolution logic (~2,100 LOC)\n- UNIQUE constraint violations during import\n- Requires coordination between workers\n\nHash-based IDs eliminate collisions entirely while aliases preserve human readability.\n\n## Benefits\n- βœ… Collision-free distributed ID generation\n- βœ… Eliminates ~2,100 LOC of collision handling code\n- βœ… Better git merge behavior (different IDs = different JSONL lines)\n- βœ… True offline-first workflows\n- βœ… Simpler auto-import (no remapping needed)\n- βœ… Enables parallel CI/CD workers without coordination\n\n## Design\n- Canonical ID: bd-af78e9a2 (8-char SHA256 prefix of title+desc+timestamp+creator)\n- Alias: #42 (auto-increment per workspace, mutable, display-only)\n- CLI accepts both: bd show bd-af78e9a2 OR bd show #42\n- JSONL stores hash IDs only (aliases reconstructed on import)\n- Alias conflicts resolved via content-hash ordering (deterministic)\n\n## Breaking Change\nThis is a v2.0 feature requiring migration. Provide bd migrate --hash-ids tool.\n\n## Timeline\n~9 weeks (Phase 1: Hash IDs 4w, Phase 2: Aliases 3w, Phase 3: Testing 2w)\n\n## Dependencies\nShould complete after bd-7c5915ae (cleanup validation) and before bd-710a4916 (CRDT).","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-10-29T21:23:49.592315-07:00","updated_at":"2025-10-31T12:32:32.6038-07:00","closed_at":"2025-10-31T12:32:32.6038-07:00","source_repo":"."} @@ -488,7 +488,7 @@ {"id":"bd-g5p7","content_hash":"6ef3578afcab8a96c6018ec27f64d36df05b32fe867ad50b5309cdefe6b7f486","title":"Extract duplicated validation logic from CLI commands","description":"~150 lines of identical validation logic duplicated between cmd_create.go and cmd_update.go\n\nDuplication found:\n- validateBeadFields(): 2 identical copies (50+ lines each) \n- parseTimeWithDefault(): 2 identical copies (30 lines each)\n- Flag definitions: 15+ duplicate registrations\n\nSolution: Extract to shared packages:\n- internal/validation/bead.go - Centralized validation\n- internal/utils/time.go - Consolidate time parsing (already exists)\n- cmd/bd/flags.go - Shared flag registration\n\nImpact: Changes require touching 2+ files; high risk of inconsistency; steep learning curve\n\nEffort: 4-6 hours","status":"closed","priority":0,"issue_type":"task","created_at":"2025-11-16T14:51:10.159953-08:00","updated_at":"2025-11-21T10:59:00.408364-05:00","closed_at":"2025-11-20T20:39:34.426726-05:00","source_repo":"."} {"id":"bd-g9eu","content_hash":"79fe2f96d06e3f0750b55f323bc104b02de6ab8a745e0bd36cf3425e125af89c","title":"Investigate TestRoutingIntegration failure","description":"TestRoutingIntegration/maintainer_with_SSH_remote failed during pre-commit check with \"expected role maintainer, got contributor\".\nThis occurred while running `go test -short ./...` on darwin/arm64.\nThe failure appears unrelated to storage/sqlite changes.\nNeed to investigate if this is a flaky test or environmental issue.","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-20T15:55:19.337094-08:00","updated_at":"2025-11-20T15:55:19.337094-08:00","source_repo":"."} {"id":"bd-gart","content_hash":"c4b3d68ec7d85a26e9c23ef529e4479b4741eade511d17f8f3602d412b0b3f0a","title":"Debug test 2","description":"","status":"closed","priority":3,"issue_type":"task","created_at":"2025-11-08T00:04:35.317835-08:00","updated_at":"2025-11-08T00:06:46.18875-08:00","closed_at":"2025-11-08T00:06:46.18875-08:00","source_repo":"."} -{"id":"bd-gdn","content_hash":"3411b7c03ec961d665181fbffa8f8b98a7809e296013786e743e371e92e9dc58","title":"Add functional tests for FlushManager correctness verification","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-20T21:21:53.967757-05:00","updated_at":"2025-11-21T10:59:00.4089-05:00","closed_at":"2025-11-20T21:35:53.1183-05:00","source_repo":".","comments":[{"id":21,"issue_id":"bd-gdn","author":"stevey","text":"Current race detector tests only verify \"no race detected\" but don't verify data correctness.\n\nNeed functional tests that:\n- Create real SQLite store with test data\n- Mark issues dirty and trigger flush\n- Verify JSONL file was updated correctly\n- Test debouncing actually reduces flush count\n- Verify shutdown performs final flush\n- Test recovery after flush failures\n\nExample test structure:\n```go\nfunc TestFlushManagerActuallyFlushes(t *testing.T) {\n // Setup real SQLite store in temp dir\n // Create test issue\n // Mark dirty via FlushManager\n // Wait for debounce + flush\n // Read JSONL file\n // Verify issue appears in JSONL with correct data\n}\n```\n\nRelated: Code review finding #3 from bd-52 race condition fix review.","created_at":"2025-11-21T15:59:00Z"}]} +{"id":"bd-gdn","content_hash":"3411b7c03ec961d665181fbffa8f8b98a7809e296013786e743e371e92e9dc58","title":"Add functional tests for FlushManager correctness verification","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-20T21:21:53.967757-05:00","updated_at":"2025-11-21T10:59:00.4089-05:00","closed_at":"2025-11-20T21:35:53.1183-05:00","source_repo":"."} {"id":"bd-gdzd","content_hash":"54a68b8b4c63fd88b33dbf8239de070a3c95f97d4a0aa5f64e694ff1384199b3","title":"Import fails on same-content-different-ID instead of treating as update","description":"## Problem\n\nThe importer still has rename detection (importer.go:482-500) that triggers when same content hash has different IDs. With hash IDs, this shouldn't happen, but when it does (test data, bugs, legacy data), the import fails:\n\n```\nfailed to handle rename bd-ce75 -\u003e bd-5a90: rename collision handling removed - should not occur with hash IDs\n```\n\n## Current Behavior\n\n1. Importer finds same content hash with different IDs\n2. Calls handleRename() (line 490)\n3. handleRename() errors out (line 294): \"rename collision handling removed\"\n4. Import fails\n\n## Expected Behavior\n\nSame content hash + different IDs should be treated as an **update**, not a rename:\n- Keep existing ID (already in database)\n- Update fields if incoming has newer timestamp\n- Discard incoming ID (it's wrong - hash should have generated same ID)\n\n## Impact\n\n- Import fails on legitimate edge cases (test data, data corruption)\n- Cryptic error message\n- Blocks sync operations\n\n## Fix\n\nIn handleRename() or import loop, instead of erroring:\n```go\n// Same content, different ID - treat as update\nif incoming.UpdatedAt.After(existing.UpdatedAt) {\n existing.Status = incoming.Status\n // ... copy other fields\n s.UpdateIssue(ctx, existing)\n}\nresult.Updated++\n```\n\n## Files\n- internal/importer/importer.go:271-294 (handleRename)\n- internal/importer/importer.go:482-500 (rename detection)\n\n## Repro\nImport JSONL with bd-ce75 and bd-5a90 (both \"Test parent issue\" but different content hashes).","status":"closed","priority":0,"issue_type":"bug","created_at":"2025-11-05T00:27:51.150233-08:00","updated_at":"2025-11-05T01:02:54.469971-08:00","closed_at":"2025-11-05T01:02:54.469979-08:00","source_repo":"."} {"id":"bd-ge7","content_hash":"84248781654b9924e1f4284058f141b73d761dead05ef9a3d1cc9b9f8cd4b60d","title":"Improve Beads test coverage from 46% to 80%","description":"","design":"Currently at 46% test coverage. Need to systematically improve coverage across all subsystems, focusing first on packages with minimal or no tests.\n\nTarget: 80% overall coverage\n\nApproach:\n- Break down by subsystem (internal/* packages)\n- Prioritize packages with 0-1 test files\n- Each child issue targets specific coverage goals\n- Focus on unit tests for core logic, error paths, and edge cases\n\nThis epic will be executed by the VC executor to test its ability to handle sustained multi-issue work.","acceptance_criteria":"- Overall test coverage reaches 80% or higher\n- All internal/* packages have at least 60% coverage\n- All packages with only 1 test file now have at least 3 test files\n- Quality gates (go test, golangci-lint) pass\n- Tests are maintainable and test actual behavior, not implementation details","status":"open","priority":1,"issue_type":"epic","created_at":"2025-11-20T21:21:03.700271-05:00","updated_at":"2025-11-20T21:21:03.700271-05:00","source_repo":"."} {"id":"bd-ggbc","content_hash":"bfb238f72474f25fcf132603ae45e6c97c7c1e60ad865062bff75f32f54a9135","title":"Update documentation for merge driver auto-config","description":"Update documentation to reflect the new merge driver auto-configuration during `bd init`.\n\n**Files to update:**\n- README.md - Mention merge driver setup in initialization section\n- AGENTS.md - Update onboarding section about merge driver\n- Possibly QUICKSTART.md\n\n**Content:**\n- Explain what the merge driver does\n- Show --skip-merge-driver flag usage\n- Manual installation steps for post-init setup","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-05T19:27:04.155662-08:00","updated_at":"2025-11-05T19:29:55.188122-08:00","closed_at":"2025-11-05T19:29:55.188122-08:00","source_repo":".","dependencies":[{"issue_id":"bd-ggbc","depends_on_id":"bd-32nm","type":"discovered-from","created_at":"2025-11-05T19:27:04.156491-08:00","created_by":"daemon"}]} @@ -498,7 +498,7 @@ {"id":"bd-gra","content_hash":"3530c1390ec7251ec2c5a0b4ce54e1619fb8a1cd13f2b8b157da9517a659b7f6","title":"Add error handling test for cmd.Help() in search command","description":"Test coverage gap identified by automated analysis (vc-217).\n\n**Original Issue:** [deleted:bd-da96-baseline-lint]\n\nIn cmd/bd/search.go:39, the return value of cmd.Help() is not checked, flagged by errcheck linter.\n\nAdd test to verify:\n- Error handling when cmd.Help() fails (e.g., output redirection fails)\n- Proper error propagation to caller\n- Command still exits gracefully on help error\n\nThis ensures the search command handles help errors properly and doesn't silently ignore failures.\n\n_This issue was automatically created by AI test coverage analysis._","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-21T10:25:33.52308-05:00","updated_at":"2025-11-23T16:05:29.740219-08:00","closed_at":"2025-11-21T19:31:21.889039-05:00","source_repo":".","labels":["discovered:supervisor"],"dependencies":[{"issue_id":"bd-gra","depends_on_id":"bd-da96-baseline-lint","type":"discovered-from","created_at":"2025-11-21T10:25:33.526016-05:00","created_by":"ai-supervisor"}]} {"id":"bd-gz0x","content_hash":"accf3e81a2e27e43c22b26c6aea4a0da418e63876e236cb462803e5700e2095e","title":"Fix daemon exiting after 5s on macOS due to PID 1 parent monitoring","description":"GitHub issue #278 reports that the daemon exits after \u003c=5 seconds on macOS because it incorrectly treats PID 1 (launchd) as a dead parent.\n\nWhen 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.\n\nFixed by changing the logic to treat PID 1 as a valid parent for detached daemons.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-09T16:15:34.606508-08:00","updated_at":"2025-11-09T16:15:37.46914-08:00","closed_at":"2025-11-09T16:15:37.46914-08:00","source_repo":"."} {"id":"bd-h4hc","content_hash":"43c11155d74ce32355129c3aac019c07279a4d31c0d58334e9fd5cb100108373","title":"Test child issue","description":"","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-05T13:00:42.368282-08:00","updated_at":"2025-11-05T13:01:11.64526-08:00","closed_at":"2025-11-05T13:01:11.64526-08:00","source_repo":"."} -{"id":"bd-h5gu","content_hash":"0c9b5d1c208359b84048672d6b9c864834a634c96769529c3c8f5f39b026e49c","title":"Add parent issue existence validation in create.go direct mode","description":"**Location:** cmd/bd/create.go:177-185\n\n**Issue:** When creating child issues in direct mode (daemon not running), code calls GetNextChildID() without validating parent issue exists first.\n\n**Current Code:**\n```go\nif parentID != \"\" \u0026\u0026 daemonClient == nil {\n childID, err := store.GetNextChildID(ctx, parentID)\n // No check: does parentID exist?\n}\n```\n\n**Impact:** Could create orphaned child issues pointing to non-existent parents, causing data integrity issues.\n\n**Fix:** Add existence check before generating child ID:\n```go\nparentIssue, err := store.GetIssue(ctx, parentID)\nif err != nil {\n fmt.Fprintf(os.Stderr, \"Error: parent issue %s not found\\n\", parentID)\n os.Exit(1)\n}\n```","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-23T19:46:38.838344-08:00","updated_at":"2025-11-23T20:39:54.445652-08:00","closed_at":"2025-11-23T20:39:54.445652-08:00","source_repo":"."} +{"id":"bd-h5gu","content_hash":"a54ec1399c113c136b11bcdc2f23348fc71f01e99920840bb26d26456aee00ee","title":"Add parent issue existence validation in create.go direct mode","description":"**Location:** cmd/bd/create.go:177-185\n\n**Issue:** When creating child issues in direct mode (daemon not running), code calls GetNextChildID() without validating parent issue exists first.\n\n**Current Code:**\n```go\nif parentID != \"\" \u0026\u0026 daemonClient == nil {\n childID, err := store.GetNextChildID(ctx, parentID)\n // No check: does parentID exist?\n}\n```\n\n**Impact:** Could create orphaned child issues pointing to non-existent parents, causing data integrity issues.\n\n**Fix:** Add existence check before generating child ID:\n```go\nparentIssue, err := store.GetIssue(ctx, parentID)\nif err != nil {\n fmt.Fprintf(os.Stderr, \"Error: parent issue %s not found\\n\", parentID)\n os.Exit(1)\n}\n```","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-23T19:46:38.838344-08:00","updated_at":"2025-11-23T20:39:54.445652-08:00","closed_at":"2025-11-23T20:39:54.445652-08:00","source_repo":"."} {"id":"bd-hdt","content_hash":"8e6cf1653ef2ea583b39a421b3d708763ab7c042d6cd494e77202a92af0a7398","title":"Implement auto-merge functionality in duplicates command","description":"The duplicates.go file has a TODO at line 95 to implement the performMerge function for automatic duplicate merging. Currently it just prints a warning message. This would automate the merge process instead of just suggesting commands.","status":"open","priority":2,"issue_type":"feature","created_at":"2025-11-21T18:55:02.828619-05:00","updated_at":"2025-11-21T18:55:02.828619-05:00","source_repo":"."} {"id":"bd-hpt5","content_hash":"68813818e69aa94128685887fe733adce22c0a373b2758219ae863340d4bf9d2","title":"show commit hash in 'bd version' when built from source'\n","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-13T13:26:14.662089379-07:00","updated_at":"2025-11-14T09:18:09.721428859-07:00","closed_at":"2025-11-14T09:18:09.721428859-07:00","source_repo":"."} {"id":"bd-hsl3","content_hash":"e0cccbc75edfcb54e0e6c3bd6749d7544327553a19773cf8b97edfafc11b2187","title":"Updated title","description":"","status":"closed","priority":0,"issue_type":"feature","created_at":"2025-11-07T19:07:12.92354-08:00","updated_at":"2025-11-07T22:07:17.346243-08:00","closed_at":"2025-11-07T21:57:59.911411-08:00","source_repo":"."} @@ -507,9 +507,9 @@ {"id":"bd-hw3c","content_hash":"83359ec96e2b8fc9ce2ece25d56bfbc1c1f948b27dfa56cc7b3715dc86c6d024","title":"Fix GH #227: bd edit broken pipe errors","description":"bd edit command gets \"broken pipe\" errors when using daemon mode because editing can take minutes and the daemon connection times out.\n\nSolution: Force bd edit to always use direct mode (--no-daemon) since it's human-only and interactive.\n\nFixed by checking cmd.Name() == \"edit\" in main.go PersistentPreRun and setting noDaemon = true.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-05T14:36:04.289431-08:00","updated_at":"2025-11-05T14:36:08.103964-08:00","closed_at":"2025-11-05T14:36:08.103964-08:00","source_repo":"."} {"id":"bd-hwmp","content_hash":"dc9fa0bdf033cf2b560624cea8ab231367a2e833544b18237cec69f0ad3be9ed","title":"Document bd info --whats-new in AGENTS.md","description":"Add prominent documentation about bd info --whats-new to help agents discover upgrade changes.\n\n## Changes Needed\n1. Add to 'What's New' section (line 13-28): Emphasize running bd info --whats-new after upgrades\n2. Add to 'Pro Tips for Agents' section (line 474-486): Include version check in session startup routine\n3. Document the bd hooks install command for keeping hooks in sync\n\n## Implementation\n- Update AGENTS.md with clear examples\n- Show both human-readable and --json output options\n- Link to the discussion #239 as motivation\n\n## Acceptance Criteria\n- Agents know to run bd info --whats-new after upgrades\n- Clear guidance on when/why to use it\n- Examples showing both output formats\n","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-23T16:21:50.533017-08:00","updated_at":"2025-11-23T16:27:43.543439-08:00","closed_at":"2025-11-23T16:27:43.543439-08:00","source_repo":".","dependencies":[{"issue_id":"bd-hwmp","depends_on_id":"bd-nxgk","type":"parent-child","created_at":"2025-11-23T16:21:50.533861-08:00","created_by":"daemon"}]} {"id":"bd-hy9p","content_hash":"817ba0e68f68de104f5da3a3574f6f5af0ccd4f1d58eb9193fabfd39949676dd","title":"Add --body-file flag to bd create for reading descriptions from files","description":"## Problem\n\nCreating issues with long/complex descriptions via CLI requires shell escaping gymnastics:\n\n```bash\n# Current workaround - awkward heredoc quoting\nbd create --title=\"...\" --description=\"$(cat \u003c\u003c'EOF'\n...markdown...\nEOF\n)\"\n\n# Often fails with quote escaping errors in eval context\n# Agents resort to writing temp files then reading them\n```\n\n## Proposed Solution\n\nAdd `--body-file` and `--description-file` flags to read description from a file, matching `gh` CLI pattern.\n\n```bash\n# Natural pattern that aligns with training data\ncat \u003e /tmp/desc.md \u003c\u003c 'EOF'\n...markdown content...\nEOF\n\nbd create --title=\"...\" --body-file=/tmp/desc.md\n```\n\n## Implementation\n\n### 1. Add new flags to `bd create`\n\n```go\ncreateCmd.Flags().String(\"body-file\", \"\", \"Read description from file (use - for stdin)\")\ncreateCmd.Flags().String(\"description-file\", \"\", \"Alias for --body-file\")\n```\n\n### 2. Flag precedence\n\n- If `--body-file` or `--description-file` is provided, read from file\n- If value is `-`, read from stdin\n- Otherwise fall back to `--body` or `--description` flag\n- If neither provided, description is empty (current behavior)\n\n### 3. Error handling\n\n- File doesn't exist β†’ clear error message\n- File not readable β†’ clear error message\n- stdin specified but not available β†’ clear error message\n\n## Benefits\n\nβœ… **Matches training data**: `gh issue create --body-file file.txt` is a common pattern\nβœ… **No shell escaping issues**: File content is read directly\nβœ… **Works with any content**: Markdown, special characters, quotes, etc.\nβœ… **Agent-friendly**: Agents already write complex content to temp files\nβœ… **User-friendly**: Easier for humans too when pasting long descriptions\n\n## Related Commands\n\nConsider adding similar support to:\n- `bd update --body-file` (for updating descriptions)\n- `bd comment --body-file` (if/when we add comments)\n\n## Examples\n\n```bash\n# From file\nbd create --title=\"Add new feature\" --body-file=feature.md\n\n# From stdin\necho \"Quick description\" | bd create --title=\"Bug fix\" --body-file=-\n\n# With other flags\nbd create \\\n --title=\"Security issue\" \\\n --type=bug \\\n --priority=0 \\\n --body-file=security-report.md \\\n --label=security\n```\n\n## Testing\n\n- Test with normal files\n- Test with stdin (`-`)\n- Test with non-existent files (error handling)\n- Test with binary files (should handle gracefully)\n- Test with empty files (valid - empty description)\n- Test that `--description-file` and `--body-file` are equivalent aliases","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-11-22T00:02:08.762684-08:00","updated_at":"2025-11-23T19:42:21.500168-08:00","closed_at":"2025-11-23T19:36:25.196139-08:00","source_repo":"."} -{"id":"bd-i00","content_hash":"eb91d1bd82defffa773c7706f4094ca1a322f1e7be017aebc91fd7eb8e6b7aad","title":"Convert magic numbers to named constants in FlushManager","description":"","status":"closed","priority":4,"issue_type":"task","created_at":"2025-11-20T21:22:17.845269-05:00","updated_at":"2025-11-21T10:59:00.409385-05:00","closed_at":"2025-11-20T21:35:53.11654-05:00","source_repo":".","comments":[{"id":22,"issue_id":"bd-i00","author":"stevey","text":"Several magic numbers should be named constants for clarity and maintainability:\n\nflush_manager.go:\n- Line 64: `10` (markDirtyCh buffer size)\n- Line 65: `1` (timerFiredCh buffer size)\n- Line 139: `30 * time.Second` (shutdown timeout)\n\nautoflush.go:\n- Line 562: `3` (flush failure threshold before warning)\n\nSuggested constants:\n```go\nconst (\n markDirtyBufferSize = 10 // Buffer rapid mark requests\n timerFiredBufferSize = 1 // Timer notifications coalesce\n shutdownTimeout = 30 * time.Second // Generous for large DBs\n flushFailureThreshold = 3 // Show warning after N failures\n)\n```\n\nRelated: Code review finding #6 from bd-52 race condition fix review.","created_at":"2025-11-21T15:59:00Z"}]} +{"id":"bd-i00","content_hash":"eb91d1bd82defffa773c7706f4094ca1a322f1e7be017aebc91fd7eb8e6b7aad","title":"Convert magic numbers to named constants in FlushManager","description":"","status":"closed","priority":4,"issue_type":"task","created_at":"2025-11-20T21:22:17.845269-05:00","updated_at":"2025-11-21T10:59:00.409385-05:00","closed_at":"2025-11-20T21:35:53.11654-05:00","source_repo":"."} {"id":"bd-i6eq","content_hash":"2cfe7d86931949dd2aca5485bb6d2acecc005519118443f4a0c744ea55ce85e9","title":"Review and merge open PRs","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-22T16:44:20.568499-08:00","updated_at":"2025-11-23T14:14:13.335959-08:00","closed_at":"2025-11-22T18:18:08.088054-08:00","source_repo":"."} -{"id":"bd-ia8r","content_hash":"80439086f76773b11c65e7e45afc582fbd47eb8aed0887fc672ef7b4a4b5c1dc","title":"Fix unvalidated dependency parsing in create.go","description":"**Location:** cmd/bd/create.go:278-298\n\n**Issue:** Dependency parsing loop breaks on first 'discovered-from' type without validating dependsOnID is non-empty.\n\n**Current Code:**\n```go\nif depType == types.DepDiscoveredFrom {\n discoveredFromParentID = dependsOnID // Could be \"\"!\n break\n}\n```\n\n**Impact:** Malformed dependency like \"discovered-from:\" (empty ID) will set discoveredFromParentID to empty string, causing line 303 to attempt getting issue with empty ID.\n\n**Fix:**\n```go\nif depType == types.DepDiscoveredFrom \u0026\u0026 dependsOnID != \"\" {\n discoveredFromParentID = dependsOnID\n break\n}\n```","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-23T19:46:42.662625-08:00","updated_at":"2025-11-23T20:51:14.548735-08:00","closed_at":"2025-11-23T20:51:14.548735-08:00","source_repo":"."} +{"id":"bd-ia8r","content_hash":"38d3bf613f8c11193cd498d285986b8a952f9477f310766e78d83914b8f51fca","title":"Fix unvalidated dependency parsing in create.go","description":"**Location:** cmd/bd/create.go:278-298\n\n**Issue:** Dependency parsing loop breaks on first 'discovered-from' type without validating dependsOnID is non-empty.\n\n**Current Code:**\n```go\nif depType == types.DepDiscoveredFrom {\n discoveredFromParentID = dependsOnID // Could be \"\"!\n break\n}\n```\n\n**Impact:** Malformed dependency like \"discovered-from:\" (empty ID) will set discoveredFromParentID to empty string, causing line 303 to attempt getting issue with empty ID.\n\n**Fix:**\n```go\nif depType == types.DepDiscoveredFrom \u0026\u0026 dependsOnID != \"\" {\n discoveredFromParentID = dependsOnID\n break\n}\n```","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-23T19:46:42.662625-08:00","updated_at":"2025-11-23T20:51:14.548735-08:00","closed_at":"2025-11-23T20:51:14.548735-08:00","source_repo":"."} {"id":"bd-ic1m","content_hash":"b837a8183ba2b636a3116deb35aa96d99fee84eabdfc8f8d93a91415c3ff4490","title":"Benchmark git traffic reduction","description":"Automated benchmark comparing git operations with/without Agent Mail.\n\nAcceptance Criteria:\n- Script that processes 50 issues\n- Counts git operations (pull, commit, push)\n- Generates comparison report\n- Verifies β‰₯70% reduction\n- Fails if regression detected\n\nFile: tests/benchmarks/git_traffic.py\n\nOutput: Without Agent Mail: 450 git operations, With Agent Mail: 135 git operations, Reduction: 70%","notes":"Implemented automated benchmark script with following features:\n- Processes configurable number of issues (default 50)\n- Compares git operations in two modes: git-only vs Agent Mail\n- Generates detailed comparison report with statistics\n- Exit code reflects pass/fail based on 70% reduction target\n- Results: 98.5% reduction (200 ops β†’ 3 ops) for 50 issues\n\nFiles created:\n- tests/benchmarks/git_traffic.py (main benchmark script)\n- tests/benchmarks/README.md (documentation)\n- tests/benchmarks/git_traffic_50_issues.md (sample results)\n\nThe benchmark vastly exceeds the 70% target, showing 98.5% reduction.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-07T22:43:21.486095-08:00","updated_at":"2025-11-08T02:08:19.648473-08:00","closed_at":"2025-11-08T02:08:19.648473-08:00","source_repo":".","dependencies":[{"issue_id":"bd-ic1m","depends_on_id":"bd-fzbg","type":"blocks","created_at":"2025-11-07T22:43:21.486966-08:00","created_by":"daemon"},{"issue_id":"bd-ic1m","depends_on_id":"bd-nemp","type":"blocks","created_at":"2025-11-07T22:43:21.487388-08:00","created_by":"daemon"}]} {"id":"bd-ihp9","content_hash":"e66bdd32aeb5a67440da6cb06bec0da001d28f123c34c2559352f7c98a6b2381","title":"Fix FOREIGN KEY constraint failures in AddComment and ApplyCompaction","description":"The 'CloseIssue', 'UpdateIssueID', and 'RemoveLabel' methods were fixed in PR #348 to prevent foreign key constraint failures when operating on non-existent issues.\n\nHowever, the Oracle identified two other methods that follow the same problematic pattern:\n1. `AddComment` (in `internal/storage/sqlite/events.go`)\n2. `ApplyCompaction` (in `internal/storage/sqlite/compact.go`)\n\nThese methods attempt to insert an event record after updating the issue, without verifying that the issue update actually affected any rows. This leads to a foreign key constraint failure if the issue does not exist.\n\nWe need to:\n1. Create reproduction tests for these failure cases\n2. Apply the same fix pattern: check `RowsAffected()` after the update, and return a proper \"issue not found\" error if it is 0, before attempting to insert the event.\n3. Standardize the error message format to \"issue %s not found\" or \"issue not found: %s\" for consistency.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-20T09:49:55.090644-08:00","updated_at":"2025-11-20T09:53:54.466769-08:00","closed_at":"2025-11-20T09:53:54.466769-08:00","source_repo":"."} {"id":"bd-iou5","content_hash":"4aaf92c783a9ff8acc47ec4a03409cfb9df9259ff73b184013422445bbd10932","title":"Detect and warn about outdated git hooks","description":"Users may have outdated git hooks installed that reference removed flags (e.g., --resolve-collisions). bd should detect this and warn users to reinstall.","design":"\n- Add version comments to hook templates (e.g., # bd-hooks-v0.21.0)\n- Check during 'bd info' or 'bd daemon start' (not every command to avoid overhead)\n- Compare installed hook version against current bd version\n- Warn with clear message: 'Git hooks are outdated (v0.X.Y), run: examples/git-hooks/install.sh'\n- Could also check if hooks exist but aren't installed at all","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-11-06T13:59:45.778781-08:00","updated_at":"2025-11-06T15:02:16.928192-08:00","closed_at":"2025-11-06T15:02:16.928192-08:00","source_repo":"."} @@ -520,9 +520,9 @@ {"id":"bd-iye7","content_hash":"1554b026ccacde081eb05d3889943d95ae9c75a21d3f06c346c57cbe2391dc46","title":"Add path normalization to getMultiRepoJSONLPaths()","description":"From bd-xo6b code review: getMultiRepoJSONLPaths() does not handle non-standard paths correctly.\n\nProblems:\n- No tilde expansion: ~/repos/foo treated as literal path\n- No absolute path conversion: ../other-repo breaks if working directory changes\n- No duplicate detection: If Primary=. and Additional=[.], same JSONL processed twice\n- No empty string handling: Empty paths create invalid /.beads/issues.jsonl\n\nImpact:\nConfig with tilde or relative paths will fail\n\nFix needed:\n1. Use filepath.Abs() for all paths\n2. Add tilde expansion via os.UserHomeDir()\n3. Deduplicate paths (use map to track seen paths)\n4. Filter out empty strings\n5. Validate paths exist and are readable\n\nFiles:\n- cmd/bd/deletion_tracking.go:333-358 (getMultiRepoJSONLPaths function)","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-06T19:31:51.882743-08:00","updated_at":"2025-11-06T19:35:41.246311-08:00","closed_at":"2025-11-06T19:35:41.246311-08:00","source_repo":".","dependencies":[{"issue_id":"bd-iye7","depends_on_id":"bd-xo6b","type":"discovered-from","created_at":"2025-11-06T19:32:12.267906-08:00","created_by":"daemon"}]} {"id":"bd-j3zt","content_hash":"531ad51101f41375a93d66b8d22105ce7c4913261db78b662bb759e802bc01e2","title":"Fix mypy errors in beads-mcp","description":"Running `mypy .` in `integrations/beads-mcp` reports 287 errors. These should be addressed to improve type safety and code quality.","status":"open","priority":3,"issue_type":"task","created_at":"2025-11-20T18:53:28.557708-05:00","updated_at":"2025-11-20T18:53:28.557708-05:00","source_repo":"."} {"id":"bd-j7e2","content_hash":"aeb3aec5ebb3b7554949f7161f58408c445983c993aaa5b31e4df93b083cf19c","title":"RPC diagnostics: BD_RPC_DEBUG timing logs","description":"Add lightweight diagnostic logging for RPC connection attempts:\n- BD_RPC_DEBUG=1 prints to stderr:\n - Socket path being dialed\n - Socket exists check result \n - Dial start/stop time\n - Connection outcome\n- Improve bd daemon --status messaging when lock not held\n\nThis helps field triage of connection issues without verbose daemon logs.","status":"closed","priority":3,"issue_type":"task","created_at":"2025-11-07T16:42:12.772364-08:00","updated_at":"2025-11-07T22:07:17.346817-08:00","closed_at":"2025-11-07T21:29:32.243458-08:00","source_repo":".","dependencies":[{"issue_id":"bd-j7e2","depends_on_id":"bd-ndyz","type":"discovered-from","created_at":"2025-11-07T16:42:12.773714-08:00","created_by":"daemon"}]} -{"id":"bd-jgxi","content_hash":"6ff94901125572693d3cff52afcd14f2d44b6baeb553dee149291eb32512c187","title":"Auto-migrate database on CLI version bump","description":"When CLI is upgraded (e.g., 0.24.0 β†’ 0.24.1), database version becomes stale. Add auto-migration in PersistentPreRun or daemon startup. Check dbVersion != CLIVersion and run bd migrate automatically. Fixes recurring UX issue where bd doctor shows version mismatch after every CLI upgrade.","status":"closed","priority":0,"issue_type":"feature","created_at":"2025-11-21T23:16:09.004619-08:00","updated_at":"2025-11-23T18:09:31.399945-08:00","closed_at":"2025-11-23T18:09:31.399945-08:00","source_repo":".","dependencies":[{"issue_id":"bd-jgxi","depends_on_id":"bd-tbz3","type":"parent-child","created_at":"2025-11-21T23:16:09.005513-08:00","created_by":"daemon"}]} +{"id":"bd-jgxi","content_hash":"df6bfb2c6dd83379e7f80a853ded3a75b9c806b7afe21f4261e2301584408dca","title":"Auto-migrate database on CLI version bump","description":"When CLI is upgraded (e.g., 0.24.0 β†’ 0.24.1), database version becomes stale. Add auto-migration in PersistentPreRun or daemon startup. Check dbVersion != CLIVersion and run bd migrate automatically. Fixes recurring UX issue where bd doctor shows version mismatch after every CLI upgrade.","status":"closed","priority":0,"issue_type":"feature","created_at":"2025-11-21T23:16:09.004619-08:00","updated_at":"2025-11-23T18:09:31.399945-08:00","closed_at":"2025-11-23T18:09:31.399945-08:00","source_repo":".","dependencies":[{"issue_id":"bd-jgxi","depends_on_id":"bd-tbz3","type":"parent-child","created_at":"2025-11-21T23:16:09.005513-08:00","created_by":"daemon"}]} {"id":"bd-jijf","content_hash":"9ecadb3d67b00337d8822ace5378edfe9b3baaa4e64a9e7edc5a2b43d82d9caf","title":"Fix: --parent flag doesn't create parent-child dependency","description":"When using `bd create --parent \u003cid\u003e`, the code generates a hierarchical child ID (e.g., bd-123.1) but never creates a parent-child dependency. This causes `bd epic status` to show zero children even though child issues exist.\n\nRoot cause: create.go generates child ID using store.GetNextChildID() but never calls store.AddDependency() with type parent-child.\n\nFix: After creating the issue when parentID is set, automatically add a parent-child dependency linking child -\u003e parent.","status":"closed","priority":0,"issue_type":"bug","created_at":"2025-11-15T13:15:22.138854-08:00","updated_at":"2025-11-15T13:18:29.301788-08:00","closed_at":"2025-11-15T13:18:29.301788-08:00","source_repo":"."} -{"id":"bd-jjua","content_hash":"40e73380589198a2e43bc484c7d55dd1d3bef620dbc1529ddaf54ca9282284e4","title":"Auto-invoke 3-way merge for JSONL conflicts","description":"Currently when git pull encounters merge conflicts in .beads/issues.jsonl, the post-merge hook fails with an error message pointing users to manual resolution or the beads-merge tool.\n\nThis is a poor user experience - the conflict detection is working, but we should automatically invoke the advanced 3-way merging instead of just telling users about it.\n\n**Current behavior:**\n- Detect conflict markers in JSONL\n- Display error with manual resolution options\n- Exit with failure\n\n**Desired behavior:**\n- Detect conflict markers in JSONL\n- Automatically invoke beads-merge 3-way merge\n- Only fail if automatic merge cannot resolve the conflicts\n\n**Reference:**\n- beads-merge tool: https://github.com/neongreen/mono/tree/main/beads-merge\n- Error occurs in post-merge hook during bd sync after git pull","status":"closed","priority":0,"issue_type":"bug","created_at":"2025-11-08T03:09:18.258708-08:00","updated_at":"2025-11-08T03:15:55.529652-08:00","closed_at":"2025-11-08T03:15:55.529652-08:00","source_repo":".","comments":[{"id":32,"issue_id":"bd-jjua","author":"stevey","text":"Implemented automatic 3-way merge resolution for JSONL conflicts.\n\n**Changes Made:**\n\n1. **Modified conflict detection in cmd/bd/import.go (lines 105-152)**\n - When git conflict markers are detected, instead of immediately failing, the system now attempts automatic resolution\n - Calls new `attemptAutoMerge()` function to invoke bd merge tool\n - If auto-merge succeeds, restarts import with the merged JSONL\n - If auto-merge fails, falls back to displaying manual resolution instructions\n\n2. **Added attemptAutoMerge() function (lines 469-585)**\n - Extracts the three git conflict stages: base (:1), ours/left (:2), theirs/right (:3)\n - Creates temporary files for each version\n - Invokes `bd merge` command to perform intelligent 3-way merge\n - Writes merged result back to original file\n - Auto-stages the resolved file with git add\n\n**How it works:**\n- When git pull creates conflicts in .beads/issues.jsonl\n- The post-merge hook runs `bd sync --import-only`\n- Import detects conflict markers on line scan\n- Automatically extracts conflict versions from git\n- Runs bd merge tool with field-level merge intelligence\n- If successful, continues import seamlessly\n- Only fails if conflicts cannot be auto-resolved\n\n**Benefits:**\n- Zero user intervention for most JSONL conflicts\n- Leverages existing bd merge 3-way merge logic\n- Maintains data integrity with field-level merging\n- Graceful fallback to manual resolution when needed\n\n**Testing:**\n- Code builds successfully\n- Ready for real-world testing on next git pull conflict\n\nThe solution transforms the error into an automatic resolution step, significantly improving user experience.","created_at":"2025-11-23T01:48:48Z"},{"id":33,"issue_id":"bd-jjua","author":"stevey","text":"**Discovery: Git merge driver was already configured but not being triggered**\n\nThe 3-way merge tool was properly vendored and `bd init` does configure the git merge driver:\n- `git config merge.beads.driver \"bd merge %A %O %L %R\"`\n- `.gitattributes` entry for `.beads/beads.jsonl merge=beads`\n\nThis should have prevented conflicts entirely by auto-invoking `bd merge` during git merge operations.\n\n**Root Cause:**\nHowever, the automatic merge driver doesn't help when conflicts reach the import stage, which happens in the post-merge hook flow:\n1. Git pull encounters conflicts\n2. Post-merge hook runs `bd sync --import-only`\n3. Import reads the JSONL file and detects conflict markers\n4. Previous behavior: fail with error message\n\nThe merge driver prevents conflicts during git operations, but if conflicts somehow make it through (or if the merge driver itself produces conflicts that it can't resolve), the import process needed fallback handling.\n\n**Our Solution:**\nAdded automatic 3-way merge invocation at the import stage as a safety net. This provides defense-in-depth:\n- Primary: git merge driver prevents most conflicts\n- Fallback: import auto-merge handles any that slip through\n\n**Bonus Discovery:**\nFound that `.beads/issues.jsonl` is a zombie file that keeps reappearing despite multiple removal attempts in git history. Renamed it to `.beads/issues.jsonl.zombie-do-not-use` with a warning message. The canonical file is `.beads/beads.jsonl`.","created_at":"2025-11-23T01:48:48Z"}]} +{"id":"bd-jjua","content_hash":"40e73380589198a2e43bc484c7d55dd1d3bef620dbc1529ddaf54ca9282284e4","title":"Auto-invoke 3-way merge for JSONL conflicts","description":"Currently when git pull encounters merge conflicts in .beads/issues.jsonl, the post-merge hook fails with an error message pointing users to manual resolution or the beads-merge tool.\n\nThis is a poor user experience - the conflict detection is working, but we should automatically invoke the advanced 3-way merging instead of just telling users about it.\n\n**Current behavior:**\n- Detect conflict markers in JSONL\n- Display error with manual resolution options\n- Exit with failure\n\n**Desired behavior:**\n- Detect conflict markers in JSONL\n- Automatically invoke beads-merge 3-way merge\n- Only fail if automatic merge cannot resolve the conflicts\n\n**Reference:**\n- beads-merge tool: https://github.com/neongreen/mono/tree/main/beads-merge\n- Error occurs in post-merge hook during bd sync after git pull","status":"closed","priority":0,"issue_type":"bug","created_at":"2025-11-08T03:09:18.258708-08:00","updated_at":"2025-11-08T03:15:55.529652-08:00","closed_at":"2025-11-08T03:15:55.529652-08:00","source_repo":"."} {"id":"bd-jo38","content_hash":"05e0df789df0a8056258cc1594c3f695d77bb735f2b2ae694d8fbb7c14c51bc9","title":"Add WaitGroup tracking to FileWatcher goroutines","description":"FileWatcher spawns goroutines without WaitGroup tracking, causing race condition on shutdown.\n\nLocation: cmd/bd/daemon_watcher.go:123-182, 215-291\n\nProblem:\n- Goroutines spawned without sync.WaitGroup\n- Close() cancels context but doesn't wait for goroutines to exit\n- Race condition: goroutine may access fw.debouncer during Close() cleanup\n- No guarantee goroutine stopped before fw.watcher.Close() is called\n\nSolution:\n- Add sync.WaitGroup field to FileWatcher\n- Track goroutines with wg.Add(1) and defer wg.Done()\n- Call wg.Wait() in Close() before cleanup\n\nImpact: Race condition on daemon shutdown; potential panic\n\nEffort: 2 hours","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-16T14:51:38.591371-08:00","updated_at":"2025-11-16T15:04:00.466334-08:00","closed_at":"2025-11-16T15:04:00.466334-08:00","source_repo":"."} {"id":"bd-jx90","content_hash":"3dfa306c43d7febfbd072d4bb5c1b6018f8a7301380bb128f53abb0eca5deb65","title":"Add simple cleanup command to delete closed issues","description":"Users want a simple command to delete all closed issues without requiring Anthropic API key (unlike compact). Requested in GH #243.","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-11-07T00:26:30.372137-08:00","updated_at":"2025-11-07T22:07:17.347122-08:00","closed_at":"2025-11-07T22:05:16.325863-08:00","source_repo":"."} {"id":"bd-k0j9","content_hash":"52d1e6f87bd7655018bd89dbbbaf8da66bdcba45de6138fd237810365a04606a","title":"Test dependency parent","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-05T11:23:02.505901-08:00","updated_at":"2025-11-05T11:23:20.91305-08:00","closed_at":"2025-11-05T11:23:20.91305-08:00","source_repo":"."} @@ -530,7 +530,7 @@ {"id":"bd-kazt","content_hash":"83b14f6b183318f85ae852db1caa593d5f6592a00b168ae057bb31238701d4fa","title":"Add tests for 3-way merge scenarios","description":"Comprehensive test coverage for merge logic.\n\n**Test cases**:\n- Simple field updates (left vs right)\n- Dependency merging (union + dedup)\n- Timestamp handling (max wins)\n- Deletion detection (deleted in one, modified in other)\n- Conflict generation (incompatible changes)\n- Issue resurrection prevention (bd-hv01 regression test)\n\n**Files**:\n- `internal/merge/merge_test.go`\n- `cmd/bd/merge_test.go`","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-05T18:42:20.472275-08:00","updated_at":"2025-11-06T15:52:41.863426-08:00","closed_at":"2025-11-06T15:52:41.863426-08:00","source_repo":".","dependencies":[{"issue_id":"bd-kazt","depends_on_id":"bd-qqvw","type":"parent-child","created_at":"2025-11-05T18:42:28.740517-08:00","created_by":"daemon"},{"issue_id":"bd-kazt","depends_on_id":"bd-oif6","type":"blocks","created_at":"2025-11-05T18:42:35.469582-08:00","created_by":"daemon"}]} {"id":"bd-kb4g","content_hash":"e68405211ed698918001dc1354242971a604bc140a026580f24e2a472747ff8c","title":"TestHooksCheckGitHooks failing - version mismatch (0.23.0 vs 0.23.1)","description":"The test is checking embedded hook versions and expecting 0.23.1, but got 0.23.0. This appears to be a version consistency issue that needs investigation.\n\nTest output:\n```\nHook pre-commit version mismatch: got 0.23.0, want 0.23.1\nHook post-merge version mismatch: got 0.23.0, want 0.23.1\nHook pre-push version mismatch: got 0.23.0, want 0.23.1\n```\n\nThis is blocking the landing of GH #274 fix.","status":"closed","priority":0,"issue_type":"bug","created_at":"2025-11-09T14:13:14.138537-08:00","updated_at":"2025-11-20T18:54:56.496852-05:00","closed_at":"2025-11-10T10:46:09.94181-08:00","source_repo":"."} {"id":"bd-kdoh","content_hash":"e017424d5478bc870b37142dba22ab2a4a863819d5d399b9224cc8992a0411b4","title":"Add tests for getMultiRepoJSONLPaths() edge cases","description":"From bd-xo6b code review: Missing test coverage for getMultiRepoJSONLPaths() edge cases.\n\nCurrent test gaps:\n- No tests for empty paths in config\n- No tests for duplicate paths\n- No tests for tilde expansion\n- No tests for relative paths\n- No tests for symlinks\n- No tests for paths with spaces\n- No tests for invalid/non-existent paths\n\nTest cases needed:\n\n1. Empty path handling:\n Primary = empty, Additional = [empty]\n Expected: Should either use . as default or error gracefully\n\n2. Duplicate detection:\n Primary = ., Additional = [., ./]\n Expected: Should return unique paths only\n\n3. Path normalization:\n Primary = ~/repos/main, Additional = [../other, ./foo/../bar]\n Expected: Should expand to absolute canonical paths\n\n4. Partial failure scenarios:\n What if snapshot capture succeeds for repos 1-2 but fails on repo 3?\n Test that system does not end up in inconsistent state\n\nFiles:\n- cmd/bd/deletion_tracking_test.go (add new tests)\n\nDependencies:\nDepends on fixing getMultiRepoJSONLPaths() path normalization first.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-06T19:31:52.921241-08:00","updated_at":"2025-11-06T20:06:49.220334-08:00","closed_at":"2025-11-06T19:53:34.515411-08:00","source_repo":".","dependencies":[{"issue_id":"bd-kdoh","depends_on_id":"bd-xo6b","type":"discovered-from","created_at":"2025-11-06T19:32:12.353459-08:00","created_by":"daemon"},{"issue_id":"bd-kdoh","depends_on_id":"bd-iye7","type":"blocks","created_at":"2025-11-06T19:32:13.688686-08:00","created_by":"daemon"}]} -{"id":"bd-keb","content_hash":"449e24b36012295a897592b083b8d730a93e08f0fb8195ebc5859a6b5263244a","title":"Add database maintenance commands section to QUICKSTART.md","description":"**Problem:**\nUsers don't discover `bd compact` or `bd cleanup` commands until their database grows large. These maintenance commands aren't mentioned in quickstart documentation.\n\nRelated to issue #349 item #4.\n\n**Current state:**\ndocs/QUICKSTART.md ends at line 217 with \"See README.md for full documentation\" but has no mention of maintenance operations.\n\n**Proposed addition:**\nAdd a \"Database Maintenance\" section after line 140 (before \"Advanced: Agent Mail\" section) covering:\n- When database grows (many closed issues)\n- How to view compaction statistics\n- How to compact old issues\n- How to delete closed issues\n- Warning about permanence\n\n**Example content:**\n```markdown\n## Database Maintenance\n\nAs your project accumulates closed issues, the database grows. Use these commands to manage size:\n\n```bash\n# View compaction statistics\nbd compact --stats\n\n# Preview compaction candidates (30+ days closed)\nbd compact --analyze --json\n\n# Apply agent-generated summary\nbd compact --apply --id bd-42 --summary summary.txt\n\n# Immediately delete closed issues (use with caution!)\nbd cleanup --force\n```\n\n**When to compact:**\n- Database file \u003e 10MB with many old closed issues\n- After major project milestones\n- Before archiving a project phase\n```\n\n**Files to modify:**\n- docs/QUICKSTART.md (add section after line 140)","status":"closed","priority":3,"issue_type":"task","created_at":"2025-11-20T20:48:40.488512-05:00","updated_at":"2025-11-23T14:14:13.336494-08:00","closed_at":"2025-11-20T20:59:13.439462-05:00","source_repo":".","labels":["documentation","onboarding"],"comments":[{"id":19,"issue_id":"bd-keb","author":"stevey","text":"Addresses GitHub issue #349 item 4: https://github.com/steveyegge/beads/issues/349\n\nUsers don't discover compact/cleanup commands until database grows large. Quickstart should mention maintenance operations.","created_at":"2025-11-21T02:23:27Z"}]} +{"id":"bd-keb","content_hash":"449e24b36012295a897592b083b8d730a93e08f0fb8195ebc5859a6b5263244a","title":"Add database maintenance commands section to QUICKSTART.md","description":"**Problem:**\nUsers don't discover `bd compact` or `bd cleanup` commands until their database grows large. These maintenance commands aren't mentioned in quickstart documentation.\n\nRelated to issue #349 item #4.\n\n**Current state:**\ndocs/QUICKSTART.md ends at line 217 with \"See README.md for full documentation\" but has no mention of maintenance operations.\n\n**Proposed addition:**\nAdd a \"Database Maintenance\" section after line 140 (before \"Advanced: Agent Mail\" section) covering:\n- When database grows (many closed issues)\n- How to view compaction statistics\n- How to compact old issues\n- How to delete closed issues\n- Warning about permanence\n\n**Example content:**\n```markdown\n## Database Maintenance\n\nAs your project accumulates closed issues, the database grows. Use these commands to manage size:\n\n```bash\n# View compaction statistics\nbd compact --stats\n\n# Preview compaction candidates (30+ days closed)\nbd compact --analyze --json\n\n# Apply agent-generated summary\nbd compact --apply --id bd-42 --summary summary.txt\n\n# Immediately delete closed issues (use with caution!)\nbd cleanup --force\n```\n\n**When to compact:**\n- Database file \u003e 10MB with many old closed issues\n- After major project milestones\n- Before archiving a project phase\n```\n\n**Files to modify:**\n- docs/QUICKSTART.md (add section after line 140)","status":"closed","priority":3,"issue_type":"task","created_at":"2025-11-20T20:48:40.488512-05:00","updated_at":"2025-11-23T14:14:13.336494-08:00","closed_at":"2025-11-20T20:59:13.439462-05:00","source_repo":".","labels":["documentation","onboarding"]} {"id":"bd-khnb","content_hash":"4f55475e1150be5a2710768a06f3162510814d96ffb2145b0a1693f5972ca5ae","title":"bd migrate --update-repo-id triggers auto-import that resurrects deleted issues","description":"**Bug:** Running `bd migrate --update-repo-id` can resurrect previously deleted issues from git history.\n\n## What Happened\n\nUser deleted 490 closed issues:\n- Deletion committed successfully (06d655a) with JSONL at 48 lines\n- Database had 48 issues after deletion\n- User ran `bd migrate --update-repo-id` to fix legacy database\n- Migration triggered daemon auto-import\n- JSONL had been restored to 538 issues (from commit 6cd3a32 - before deletion)\n- Auto-import loaded the old JSONL over the cleaned database\n- Result: 490 deleted issues resurrected\n\n## Root Cause\n\nThe auto-import logic in `cmd/bd/sync.go:130-136`:\n```go\nif isJSONLNewer(jsonlPath) {\n fmt.Println(\"β†’ JSONL is newer than database, importing first...\")\n if err := importFromJSONL(ctx, jsonlPath, renameOnImport); err != nil {\n```\n\nThis checks if JSONL mtime is newer than database and auto-imports. The problem:\n1. Git operations (pull, merge, checkout) can restore old JSONL files\n2. Restored file has recent mtime (time of git operation)\n3. Auto-import sees \"newer\" JSONL and imports it\n4. Old data overwrites current database state\n\n## Timeline\n\n- 19:59: Commit 6cd3a32 restored JSONL to 538 issues from d99222d\n- 20:22: Commit 3520321 (bd sync)\n- 20:23: Commit 06d655a deleted 490 issues β†’ JSONL now 48 lines\n- 20:23: User ran `bd migrate --update-repo-id`\n- Migration completed, daemon started\n- Daemon saw JSONL (restored earlier to 538) was \"newer\" than database\n- Auto-import resurrected 490 deleted issues\n\n## Impact\n\n- **Critical data loss bug** - user deletions can be undone silently\n- Affects any workflow that uses git branches, merges, or checkouts\n- Auto-import has no safety checks against importing older data\n- Users have no warning that old data will overwrite current state\n\n## Fix Options\n\n1. **Content-based staleness** (not mtime-based)\n - Compare JSONL content hash vs database content hash\n - Only import if content actually changed\n - Prevents re-importing old data with new mtime\n\n2. **Database timestamp check**\n - Store \"last export timestamp\" in database metadata\n - Only import JSONL if it's newer than last export\n - Prevents importing old JSONL after git operations\n\n3. **User confirmation**\n - Before auto-import, show diff of what will change\n - Require confirmation for large changes (\u003e10% issues affected)\n - Safety valve for destructive imports\n\n4. **Explicit sync mode**\n - Disable auto-import entirely\n - Require explicit `bd sync` or `bd import` commands\n - Trade convenience for safety\n\n## Recommended Solution\n\nCombination of #1 and #2:\n- Add `last_export_timestamp` to database metadata\n- Check JSONL mtime \u003e last_export_timestamp before importing\n- Add content hash check as additional safety\n- Show warning if importing would delete \u003e10 issues\n\nThis preserves auto-import convenience while preventing data loss.\n\n## Files Involved\n\n- `cmd/bd/sync.go:130-136` - Auto-import logic\n- `cmd/bd/daemon_sync.go` - Daemon export/import cycle\n- `internal/autoimport/autoimport.go` - Staleness detection\n\n## Reproduction Steps\n\n1. Create and delete some issues, commit to git\n2. Checkout an earlier commit (before deletion)\n3. Checkout back to current commit\n4. JSONL file now has recent mtime but old content\n5. Run any bd command that triggers auto-import\n6. Deleted issues are resurrected","status":"closed","priority":0,"issue_type":"bug","created_at":"2025-11-20T20:44:35.235807-05:00","updated_at":"2025-11-20T21:51:31.806158-05:00","closed_at":"2025-11-20T21:51:31.806158-05:00","source_repo":"."} {"id":"bd-kla1","content_hash":"825b411d37b412a1ee19e3ebc246b6725aca0f32b83e65c8b4680fa4ef2193ff","title":"Add bd init --contributor wizard","description":"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.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-05T18:04:29.958409-08:00","updated_at":"2025-11-05T19:27:33.07529-08:00","closed_at":"2025-11-05T18:53:51.267625-08:00","source_repo":".","dependencies":[{"issue_id":"bd-kla1","depends_on_id":"bd-8rd","type":"parent-child","created_at":"2025-11-05T18:04:39.120064-08:00","created_by":"daemon"}]} {"id":"bd-ktng","content_hash":"0a09f3e1549a70817f23aa57444811aaf18683ff9336944ff6e8c277ac5684b4","title":"Optimize CLI test suite - eliminate redundant git init calls","description":"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.","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-04T11:23:13.660276-08:00","updated_at":"2025-11-04T11:23:13.660276-08:00","source_repo":".","dependencies":[{"issue_id":"bd-ktng","depends_on_id":"bd-l5gq","type":"discovered-from","created_at":"2025-11-04T11:23:13.662102-08:00","created_by":"daemon"}]} @@ -540,7 +540,7 @@ {"id":"bd-l954","content_hash":"263dd2111cf0353b307f2e47489aa42ecf607e49b1316b54a6497cad9d3722b0","title":"Performance Testing Framework","description":"Add comprehensive performance testing for beads focusing on optimization guidance and validating 10K+ database scale. Uses standard Go tooling, follows existing patterns, minimal complexity.\n\nComponents:\n- Benchmark suite for critical operations at 10K-20K scale\n- Fixture generator for realistic test data (epic hierarchies, cross-links)\n- User diagnostics via bd doctor --perf\n- Always-on profiling integration\n\nGoals:\n- Identify bottlenecks for optimization work\n- Validate performance at 10K+ issue scale\n- Enable users to collect diagnostics for bug reports\n- Support both SQLite and JSONL import paths","status":"open","priority":2,"issue_type":"epic","created_at":"2025-11-13T22:22:11.203467-08:00","updated_at":"2025-11-13T22:22:11.203467-08:00","source_repo":"."} {"id":"bd-la9d","content_hash":"298e5922cb0e6460d1cf14d2b7230c63403e72fcb511fb31d3fe2e2f241fd18a","title":"Blocking issue","description":"","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-20T19:43:48.758706-05:00","updated_at":"2025-11-20T19:43:48.758706-05:00","closed_at":"2025-11-07T21:55:09.43148-08:00","source_repo":"."} {"id":"bd-lln","content_hash":"650962c39553fb85e797c10044f4f1d89b6311855c7727c3f82c49dfea2ced97","title":"Add tests for performFlush error handling in FlushManager","description":"Test coverage gap identified by automated analysis (vc-217).\n\n**Original Issue:** [deleted:bd-da96-baseline-lint]\n\nIn cmd/bd/flush_manager.go:269, the performFlush method is flagged by unparam as always returning nil, indicating the error return value is never used.\n\nAdd tests to determine:\n- Whether performFlush can actually return errors in failure scenarios\n- If error return is needed, add tests for error cases (disk full, permission denied, etc.)\n- If error return is not needed, refactor to remove unused return value\n- Test full export vs incremental export error handling\n\nThis ensures proper error handling in the flush mechanism and removes dead code if the return value is unnecessary.\n\n_This issue was automatically created by AI test coverage analysis._","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-21T10:25:33.533653-05:00","updated_at":"2025-11-23T16:05:29.738571-08:00","closed_at":"2025-11-21T19:31:21.876949-05:00","source_repo":".","labels":["discovered:supervisor"],"dependencies":[{"issue_id":"bd-lln","depends_on_id":"bd-da96-baseline-lint","type":"discovered-from","created_at":"2025-11-21T10:25:33.534913-05:00","created_by":"ai-supervisor"}]} -{"id":"bd-lm2q","content_hash":"b098ab750578221bdbc099aeb93f1275650c3636a6b93badbcb093a411a82d8d","title":"Fix `bd sync` failure due to daemon auto-export timestamp skew","description":"`bd sync` fails with false-positive \"JSONL is newer than database\" after daemon auto-export.\nRoot Cause: Daemon exports local changes to JSONL, updating its timestamp. `bd sync` sees JSONL.mtime \u003e DB.mtime and assumes external changes, blocking export.\nProposed Fixes:\n1. `bd sync` auto-imports if timestamp matches but content differs (or just auto-imports).\n2. Content-based comparison instead of timestamp only.\n","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-20T18:56:16.876685-05:00","updated_at":"2025-11-20T20:54:39.512574-05:00","closed_at":"2025-11-20T20:54:39.512574-05:00","source_repo":"."} +{"id":"bd-lm2q","content_hash":"e26fa6c461610f000935fb4ccd62239dd3ac22b5b1d2f0b440418f6e06551a4a","title":"Fix `bd sync` failure due to daemon auto-export timestamp skew","description":"`bd sync` fails with false-positive \"JSONL is newer than database\" after daemon auto-export.\nRoot Cause: Daemon exports local changes to JSONL, updating its timestamp. `bd sync` sees JSONL.mtime \u003e DB.mtime and assumes external changes, blocking export.\nProposed Fixes:\n1. `bd sync` auto-imports if timestamp matches but content differs (or just auto-imports).\n2. Content-based comparison instead of timestamp only.\n","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-20T18:56:16.876685-05:00","updated_at":"2025-11-20T20:54:39.512574-05:00","closed_at":"2025-11-20T20:54:39.512574-05:00","source_repo":"."} {"id":"bd-loka","content_hash":"07ae2db6da314a149bcfb0f05a7a161588d0169bfd3df0a8b278ee07548a5318","title":"Add built-in version tracking to bd","description":"Enhance bd to automatically track its own version in metadata.json and detect upgrades.\n\n## Features to Implement\n1. Auto-update metadata.json with 'last_bd_version' field on every bd command\n2. Add 'bd upgrade status' - check if version changed since last run\n3. Add 'bd upgrade review' - show what's new since last-seen version (not just last 3)\n4. Add 'bd upgrade ack' - mark current version as acknowledged\n5. Smart detection output when version changes (show hint on bd ready, bd list, etc.)\n\n## Implementation Details\n- Store last_bd_version in metadata.json\n- Store last_version_check timestamp\n- Compare on every bd command (cached check, low overhead)\n- Only show notification once per session until ack'd\n\n## Example Output\n```\n$ bd ready\nπŸ”„ bd upgraded from v0.23.0 to v0.24.2 since last use\nπŸ’‘ Run 'bd upgrade review' to see what changed\n\nReady work: 5 issues\n...\n```\n\n## Acceptance Criteria\n- Version automatically tracked in metadata.json\n- Upgrade detection works across sessions\n- New bd upgrade subcommands functional\n- Non-intrusive notifications (show once, then quiet)\n","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-11-23T16:21:53.951611-08:00","updated_at":"2025-11-23T17:06:34.003365-08:00","closed_at":"2025-11-23T17:06:34.003365-08:00","source_repo":".","dependencies":[{"issue_id":"bd-loka","depends_on_id":"bd-nxgk","type":"parent-child","created_at":"2025-11-23T16:21:53.952998-08:00","created_by":"daemon"}]} {"id":"bd-loka.1","content_hash":"e6d596b7181f5f22563f30f714b831c30ed916b9578debf79aea28c7de12991c","title":"Add LastBdVersion field to Config struct","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-23T16:56:27.336668-08:00","updated_at":"2025-11-23T16:56:52.180512-08:00","closed_at":"2025-11-23T16:56:52.180512-08:00","source_repo":".","dependencies":[{"issue_id":"bd-loka.1","depends_on_id":"bd-loka","type":"parent-child","created_at":"2025-11-23T16:56:27.337232-08:00","created_by":"daemon"}]} {"id":"bd-loka.2","content_hash":"71369d71229dc4bdcb17aa5df61f98c6dfc43a260d4b8370d8021af49b54bbae","title":"Add version tracking in PersistentPreRun","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-23T16:56:28.680947-08:00","updated_at":"2025-11-23T16:58:25.180851-08:00","closed_at":"2025-11-23T16:58:25.180851-08:00","source_repo":".","dependencies":[{"issue_id":"bd-loka.2","depends_on_id":"bd-loka","type":"parent-child","created_at":"2025-11-23T16:56:28.681524-08:00","created_by":"daemon"}]} @@ -567,19 +567,15 @@ {"id":"bd-ng56","content_hash":"f570cf399d412baa9b9209bae41140668269513e2d2127c47ddee70fa173d79d","title":"bd-hv01: Three full JSONL reads on every sync (performance)","description":"Problem: computeAcceptedDeletions reads three JSONL files completely into memory (base, left, merged). For 1000 issues at 1KB each, this is 3MB read and 3000 JSON parse operations.\n\nImpact: Acceptable now (~20-35ms overhead) but will be slow for large repos (10k+ issues).\n\nPossible optimizations: single-pass streaming, memory-mapped files, binary format, incremental snapshots.\n\nFiles: cmd/bd/deletion_tracking.go:101-208","status":"closed","priority":3,"issue_type":"task","created_at":"2025-11-06T18:16:25.653076-08:00","updated_at":"2025-11-06T20:06:49.220818-08:00","closed_at":"2025-11-06T19:41:04.67733-08:00","source_repo":".","dependencies":[{"issue_id":"bd-ng56","depends_on_id":"bd-rbxi","type":"parent-child","created_at":"2025-11-06T18:19:15.148149-08:00","created_by":"daemon"}]} {"id":"bd-nl8z","content_hash":"a573c9fe29cd810420b602fc5d2c105ace29a409f2294fd251baf515bef0b85e","title":"Documentation","description":"Complete documentation for Agent Mail integration to enable adoption.","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-11-07T22:42:37.969636-08:00","updated_at":"2025-11-08T03:09:48.253476-08:00","closed_at":"2025-11-08T02:34:57.887891-08:00","source_repo":".","dependencies":[{"issue_id":"bd-nl8z","depends_on_id":"bd-wfmw","type":"blocks","created_at":"2025-11-07T22:42:37.970621-08:00","created_by":"daemon"}]} {"id":"bd-nq41","content_hash":"33f9cfe6a0ef5200dcd5016317b43b1568ff9dc7303537d956bdab02029f6c63","title":"Fix Homebrew warning about Ruby file location","description":"Homebrew warning: Found Ruby file outside steveyegge/beads tap formula directory.\nWarning points to: /opt/homebrew/Library/Taps/steveyegge/homebrew-beads/bd.rb\nIt should likely be inside a Formula/ directory or similar structure expected by Homebrew taps.\n","status":"open","priority":2,"issue_type":"chore","created_at":"2025-11-20T18:56:21.226579-05:00","updated_at":"2025-11-20T18:56:21.226579-05:00","source_repo":"."} -<<<<<<< HEAD {"id":"bd-nqes","content_hash":"0063981ff72ee9d99ef59e43bf43369b4c8fc0e73479ce1e8bd9e91603b850a3","title":"bd-hv01: Non-atomic snapshot operations can cause data loss","description":"## Problem\nIn sync.go:146-155 and daemon_sync.go:502-505, snapshot capture failures are logged as warnings but sync continues:\n\n```go\nif err := exportToJSONL(ctx, jsonlPath); err != nil { ... }\nif err := captureLeftSnapshot(jsonlPath); err != nil {\n fmt.Fprintf(os.Stderr, \"Warning: failed to capture snapshot...\")\n}\n```\n\nIf export succeeds but snapshot capture fails, the merge uses stale snapshot data, potentially deleting wrong issues.\n\n## Impact\n- Critical data integrity issue\n- Could delete issues incorrectly during multi-workspace sync\n\n## Fix\nMake snapshot capture mandatory:\n```go\nif err := captureLeftSnapshot(jsonlPath); err != nil {\n return fmt.Errorf(\"failed to capture snapshot (required for deletion tracking): %w\", err)\n}\n```\n\n## Files Affected\n- cmd/bd/sync.go:146-155\n- cmd/bd/daemon_sync.go:502-505","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-06T18:15:33.574158-08:00","updated_at":"2025-11-06T18:46:55.874814-08:00","closed_at":"2025-11-06T18:46:55.874814-08:00","source_repo":".","dependencies":[{"issue_id":"bd-nqes","depends_on_id":"bd-rbxi","type":"parent-child","created_at":"2025-11-06T18:19:14.749153-08:00","created_by":"daemon"}]} {"id":"bd-nszi","content_hash":"7eb77a2db8edb51267c42176883ad97f11a83103720647c92a8de26e79e6ab3e","title":"Post-merge hook silently fails on JSONL conflicts, poor UX","description":"When git pull results in merge conflicts in .beads/issues.jsonl, the post-merge hook runs 'bd sync --import-only' which fails, but stderr was redirected to /dev/null. User only saw generic warning.\n\nFixed by capturing and displaying the actual error output, so users see 'Git conflict markers detected' message immediately.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-08T02:31:04.909925-08:00","updated_at":"2025-11-08T02:31:45.237286-08:00","closed_at":"2025-11-08T02:31:45.237286-08:00","source_repo":"."} -{"id":"bd-nxgk","content_hash":"b1124b39715075cd321a6996f662adf9af49871524a97890703819caf87f7da1","title":"Agent upgrade awareness system","description":"Make it easy for AI agents to discover and adapt to bd upgrades without manual intervention.\n\n## Problem\nWhen bd is upgraded (happens weekly), agents need to:\n1. Discover what changed\n2. Update their workflows/instructions\n3. Keep git hooks in sync\n4. Know which new features to adopt\n\nCurrently this requires manual prompting or re-running bd onboard, which is unreliable.\n\n## Solution Layers\n1. Documentation improvements (immediate)\n2. Startup hook snippet for detection (immediate, zero bd code)\n3. Built-in version tracking in bd (short-term)\n4. Separated canonical BD_GUIDE.md (long-term architectural)\n\n## Success Criteria\n- Agents automatically detect bd upgrades at session start\n- Agents see what changed without re-reading all docs\n- Git hooks stay in sync with bd version\n- bd-specific instructions separated from project instructions\n\n## Related Discussion\nGitHub Discussion #239: 'Upgrading beads: how to let the Agent know'\n","status":"closed","priority":2,"issue_type":"epic","created_at":"2025-11-23T16:21:14.431233-08:00","updated_at":"2025-11-23T21:16:26.811616-08:00","closed_at":"2025-11-23T21:16:26.811616-08:00","source_repo":"."} +{"id":"bd-nxgk","content_hash":"7f57fc1e58c18acce073f786cf2b39ad7df3b02f1bed758651ed06a08a4cfe9e","title":"Agent upgrade awareness system","description":"Make it easy for AI agents to discover and adapt to bd upgrades without manual intervention.\n\n## Problem\nWhen bd is upgraded (happens weekly), agents need to:\n1. Discover what changed\n2. Update their workflows/instructions\n3. Keep git hooks in sync\n4. Know which new features to adopt\n\nCurrently this requires manual prompting or re-running bd onboard, which is unreliable.\n\n## Solution Layers\n1. Documentation improvements (immediate)\n2. Startup hook snippet for detection (immediate, zero bd code)\n3. Built-in version tracking in bd (short-term)\n4. Separated canonical BD_GUIDE.md (long-term architectural)\n\n## Success Criteria\n- Agents automatically detect bd upgrades at session start\n- Agents see what changed without re-reading all docs\n- Git hooks stay in sync with bd version\n- bd-specific instructions separated from project instructions\n\n## Related Discussion\nGitHub Discussion #239: 'Upgrading beads: how to let the Agent know'\n","status":"closed","priority":2,"issue_type":"epic","created_at":"2025-11-23T16:21:14.431233-08:00","updated_at":"2025-11-23T21:16:26.811616-08:00","closed_at":"2025-11-23T21:16:26.811616-08:00","source_repo":"."} {"id":"bd-o43","content_hash":"4caa0f14a58127378a533362ec0292833b6d59195e503fab7505180c9c5c0438","title":"Add richer query capabilities to bd list","description":"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.\n\nMissing query capabilities:\n- Pattern matching: --title-contains, --desc-contains\n- Date ranges: --created-after, --updated-before, --closed-after\n- Empty/null checks: --empty-description, --no-assignee, --no-labels\n- Numeric ranges: --priority-min, --priority-max\n- Complex boolean logic: --and, --or operators\n- Full-text search: --search across all text fields\n- Negation: --not-status, --exclude-label\n\nExample use cases:\n- Find issues with empty descriptions\n- Find stale issues not updated in 30 days\n- Find high-priority bugs with no assignee\n- Search for keyword across title/description/notes\n\nImplementation approach:\n- Add query builder pattern to storage layer\n- Support --query DSL for complex queries\n- Keep simple flags for common cases\n- Add --json output for programmatic use","notes":"## Progress Update\n\n**Completed:**\n- βœ… Extended IssueFilter struct with new fields (pattern matching, date ranges, empty/null checks, priority ranges)\n- βœ… Updated SQLite SearchIssues implementation \n- βœ… Added CLI flags to list.go\n- βœ… Added parseTimeFlag helper\n- βœ… Comprehensive tests added - all passing\n\n**Remaining:**\n- ⚠️ RPC layer needs updating (internal/rpc/protocol.go ListArgs)\n- ⚠️ Daemon handler needs to forward new filters\n- ⚠️ End-to-end testing with daemon mode\n- πŸ“ Documentation updates\n\n**Files Modified:**\n- internal/types/types.go\n- internal/storage/sqlite/sqlite.go \n- cmd/bd/list.go\n- cmd/bd/list_test.go\n\n**Next Steps:**\n1. Update RPC protocol\n2. Update daemon handler \n3. Test with daemon mode\n4. Update docs","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-11-05T00:17:48.677493-08:00","updated_at":"2025-11-05T00:33:38.998433-08:00","closed_at":"2025-11-05T00:33:38.998433-08:00","source_repo":"."} {"id":"bd-o4qy","content_hash":"cd702a098b309eb05ef8e39dfa8e2b290e4ab23a96bca24819ce252c111ce221","title":"Improve CheckStaleness error handling","description":"## Problem\n\nCheckStaleness returns 'false' (not stale) for multiple error conditions instead of returning errors. This masks problems.\n\n**Location:** internal/autoimport/autoimport.go:253-285\n\n## Edge Cases That Return False\n\n1. **Invalid last_import_time format** (line 259-262)\n2. **No JSONL file found** (line 267-277) \n3. **JSONL stat fails** (line 279-282)\n\n## Fix\n\nReturn errors for abnormal conditions:\n\n```go\nlastImportTime, err := time.Parse(time.RFC3339, lastImportStr)\nif err != nil {\n return false, fmt.Errorf(\"corrupted last_import_time: %w\", err)\n}\n\nif jsonlPath == \"\" {\n return false, fmt.Errorf(\"no JSONL file found\")\n}\n\nstat, err := os.Stat(jsonlPath)\nif err != nil {\n return false, fmt.Errorf(\"cannot stat JSONL: %w\", err)\n}\n```\n\n## Impact\nMedium - edge cases are rare but should be handled\n\n## Effort \n30 minutes - requires updating callers in RPC server","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-11-20T20:17:27.606219-05:00","updated_at":"2025-11-23T20:39:55.304495-08:00","closed_at":"2025-11-23T20:35:41.214077-08:00","source_repo":".","dependencies":[{"issue_id":"bd-o4qy","depends_on_id":"bd-2q6d","type":"blocks","created_at":"2025-11-20T20:18:26.81065-05:00","created_by":"stevey"}]} {"id":"bd-o78","content_hash":"78933a15fcc41f57f5bcd182383d46bea752cacce623c0b48236d6774affaa63","title":"Enhance `bd doctor` to verify Claude Code integration","description":"Add checks to `bd doctor` that verify Claude Code integration is properly set up when .claude/ directory or Claude environment is detected.","design":"## Checks to Add\n\n### 1. Claude Environment Detection\n```go\nif isClaudeDetected() {\n fmt.Println(\"βœ“ Claude Code environment detected\")\n \n // Check what's installed\n hasMCP := isMCPServerInstalled()\n hasHooks := isClaudeSetupComplete()\n \n if hasMCP \u0026\u0026 hasHooks {\n fmt.Println(\"βœ“ MCP server installed\")\n fmt.Println(\"βœ“ Claude hooks installed (provides workflow reminders)\")\n } else if !hasMCP \u0026\u0026 hasHooks {\n fmt.Println(\"βœ“ Claude hooks installed (provides CLI reference)\")\n fmt.Println(\" Note: MCP server not detected (using CLI mode)\")\n } else if hasMCP \u0026\u0026 !hasHooks {\n fmt.Println(\"βœ“ MCP server installed\")\n fmt.Println(\"⚠ Claude hooks not installed\")\n fmt.Println(\" Hooks prevent agent from forgetting bd workflow after compaction\")\n fmt.Println(\" Run: bd setup claude\")\n } else {\n fmt.Println(\"⚠ Claude integration not set up\")\n fmt.Println(\" Run: bd setup claude\")\n // TODO (future): Recommend CLI approach once proven in production\n // fmt.Println(\" Tip: CLI mode (without MCP) uses fewer tokens\")\n }\n}\n\nfunc isMCPServerInstalled() bool {\n // Check ~/.claude/settings.json for beads MCP server\n home, _ := os.UserHomeDir()\n settingsPath := filepath.Join(home, \".claude/settings.json\")\n \n data, err := os.ReadFile(settingsPath)\n if err != nil {\n return false\n }\n \n var settings map[string]interface{}\n if err := json.Unmarshal(data, \u0026settings); err != nil {\n return false\n }\n \n // Check mcpServers section for beads\n mcpServers, ok := settings[\"mcpServers\"].(map[string]interface{})\n if !ok {\n return false\n }\n \n // Look for beads server (any key containing \"beads\")\n for key := range mcpServers {\n if strings.Contains(strings.ToLower(key), \"beads\") {\n return true\n }\n }\n \n return false\n}\n```\n\n### 2. Hook Installation Verification (MCP-Aware)\n\n```go\nfunc checkClaudeHooks() {\n home, _ := os.UserHomeDir()\n globalSettings := filepath.Join(home, \".claude/settings.json\")\n projectSettings := \".claude/settings.local.json\"\n \n globalHooks := hasBeadsHooks(globalSettings)\n projectHooks := hasBeadsHooks(projectSettings)\n \n if globalHooks {\n fmt.Println(\"βœ“ Global hooks installed\")\n } else if projectHooks {\n fmt.Println(\"βœ“ Project hooks installed\")\n } else {\n fmt.Println(\"⚠ No hooks installed\")\n fmt.Println(\" Run: bd setup claude\")\n return\n }\n \n // Check if hooks will work\n if !commandExists(\"bd\") {\n fmt.Println(\"⚠ 'bd' command not in PATH\")\n fmt.Println(\" Hooks won't work - ensure bd is installed globally\")\n }\n}\n\nfunc hasBeadsHooks(settingsPath string) bool {\n data, err := os.ReadFile(settingsPath)\n if err != nil {\n return false\n }\n \n var settings map[string]interface{}\n if err := json.Unmarshal(data, \u0026settings); err != nil {\n return false\n }\n \n hooks, ok := settings[\"hooks\"].(map[string]interface{})\n if !ok {\n return false\n }\n \n // Check SessionStart and PreCompact for \"bd prime\"\n for _, event := range []string{\"SessionStart\", \"PreCompact\"} {\n eventHooks, ok := hooks[event].([]interface{})\n if !ok {\n continue\n }\n \n for _, hook := range eventHooks {\n hookMap, _ := hook.(map[string]interface{})\n commands, _ := hookMap[\"hooks\"].([]interface{})\n for _, cmd := range commands {\n cmdMap, _ := cmd.(map[string]interface{})\n if cmdMap[\"command\"] == \"bd prime\" {\n return true\n }\n }\n }\n }\n \n return false\n}\n```\n\n### 3. AGENTS.md/CLAUDE.md Reference Check\n```go\n// Check if documentation references bd prime\nagentsContent := readFileIfExists(\"AGENTS.md\")\nclaudeContent := readFileIfExists(\"CLAUDE.md\")\n\nif strings.Contains(agentsContent, \"bd prime\") || strings.Contains(claudeContent, \"bd prime\") {\n // Verify bd prime command exists in current version\n if !commandExists(\"prime\") {\n fmt.Println(\"⚠ Documentation references 'bd prime' but command not found\")\n fmt.Println(\" Upgrade bd or remove references\")\n } else {\n fmt.Println(\"βœ“ Documentation references match installed features\")\n }\n}\n```\n\n### 4. Context Priming Test\n```go\n// Verify bd prime actually works\ncmd := exec.Command(\"bd\", \"prime\")\noutput, err := cmd.CombinedOutput()\n\nif err != nil {\n fmt.Println(\"⚠ 'bd prime' failed to execute\")\n fmt.Println(\" Error:\", err)\n} else if len(output) == 0 {\n fmt.Println(\"⚠ 'bd prime' produced no output\")\n fmt.Println(\" Expected workflow context markdown\")\n} else {\n // Check if output adapts to MCP mode\n hasMCP := isMCPServerInstalled()\n outputStr := string(output)\n \n if hasMCP \u0026\u0026 strings.Contains(outputStr, \"mcp__plugin_beads_beads__\") {\n fmt.Println(\"βœ“ bd prime detected MCP mode (workflow reminders)\")\n } else if !hasMCP \u0026\u0026 strings.Contains(outputStr, \"bd ready\") {\n fmt.Println(\"βœ“ bd prime using CLI mode (full command reference)\")\n } else {\n fmt.Println(\"⚠ bd prime output may not be adapting to environment\")\n }\n}\n```\n\n## Output Format Examples\n\n### With MCP and Hooks\n```\nbd doctor\n\nDatabase:\nβœ“ Database found at .beads/beads.db\nβœ“ Git hooks installed\n\nClaude Code Integration:\nβœ“ Claude Code environment detected\nβœ“ MCP server installed\nβœ“ Claude hooks installed (provides workflow reminders)\nβœ“ bd prime detected MCP mode (workflow reminders)\nβœ“ Documentation references match installed features\n\nSync Status:\nβœ“ No sync issues detected\n```\n\n### Without MCP, With Hooks\n```\nbd doctor\n\nDatabase:\nβœ“ Database found at .beads/beads.db\nβœ“ Git hooks installed\n\nClaude Code Integration:\nβœ“ Claude Code environment detected\nβœ“ Claude hooks installed (provides CLI reference)\n Note: MCP server not detected (using CLI mode)\nβœ“ bd prime using CLI mode (full command reference)\n\nSync Status:\nβœ“ No sync issues detected\n```\n\n### No Integration\n```\nbd doctor\n\nDatabase:\nβœ“ Database found at .beads/beads.db\nβœ“ Git hooks installed\n\nClaude Code Integration:\nβœ“ Claude Code environment detected\n⚠ Claude integration not set up\n Run: bd setup claude\n\nSync Status:\nβœ“ No sync issues detected\n```\n\n## Future Enhancement (Post-Production Validation)\n\nOnce CLI mode is proven in production, add recommendation:\n\n```go\nif isClaudeDetected() \u0026\u0026 !hasMCP \u0026\u0026 !hasHooks {\n fmt.Println(\"⚠ Claude integration not set up\")\n fmt.Println(\" Run: bd setup claude\")\n fmt.Println(\" Tip: CLI mode (without MCP) uses fewer tokens than MCP server\")\n fmt.Println(\" Both approaches work equally well - choose based on preference\")\n}\n```\n\nThis recommendation should only be added after CLI mode with `bd prime` is validated in real-world usage.","acceptance_criteria":"- bd doctor checks for Claude environment\n- Verifies hook installation if .claude/ exists\n- Checks AGENTS.md/CLAUDE.md for bd prime references\n- Detects version mismatches between docs and installed bd\n- Provides actionable suggestions (bd setup claude, upgrade)\n- Tests cover detection logic","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-11T23:30:05.782406-08:00","updated_at":"2025-11-23T21:21:46.857937-08:00","closed_at":"2025-11-23T21:11:53.412111-08:00","source_repo":".","dependencies":[{"issue_id":"bd-o78","depends_on_id":"bd-rpn","type":"blocks","created_at":"2025-11-11T23:30:05.783234-08:00","created_by":"daemon"},{"issue_id":"bd-o78","depends_on_id":"bd-br8","type":"blocks","created_at":"2025-11-11T23:30:05.783647-08:00","created_by":"daemon"},{"issue_id":"bd-o78","depends_on_id":"bd-90v","type":"parent-child","created_at":"2025-11-11T23:31:27.886095-08:00","created_by":"daemon"}]} -{"id":"bd-obdc","content_hash":"fe7ac547d667b6e7dd713f1120fc2dbea3afa77a59a481358ca484f15cb47c36","title":"Add 'bd doctor --rebuild-cache' command for cache recovery","description":"Add admin command to manually rebuild the blocked_issues_cache table for recovery scenarios.\n\n## Use cases\n\n1. **Cache corruption recovery**\n - If cache gets out of sync with actual dependencies\n - Manual rebuild as safety measure\n\n2. **Post-migration verification**\n - After database migrations that affect dependencies\n - Verify cache is correctly populated\n\n3. **Debugging**\n - Compare cache state with actual blocking calculations\n - Troubleshoot performance issues\n\n## Implementation\n\nAdd flag to bd doctor command:\n\n```bash\nbd doctor --rebuild-cache\n```\n\nShould:\n- Call `SQLiteStorage.invalidateBlockedCache()` directly\n- Print before/after cache statistics\n- Show timing information\n- Exit code 0 on success\n\nExample output:\n```\nRebuilding blocked_issues_cache...\nBefore: 15 blocked issues\nAfter: 15 blocked issues\nRebuilt in 12ms\nβœ“ Cache rebuild complete\n```\n\n## Files to modify\n\n- cmd/bd/doctor.go - add --rebuild-cache flag\n- internal/storage/sqlite/blocked_cache.go - maybe add public RebuildBlockedCache() method\n\n## Related\n\n- [deleted:[deleted:bd-5qim]]: GetReadyWork performance optimization\n- bd-13gm: Add cache validation tests","status":"open","priority":3,"issue_type":"feature","created_at":"2025-11-23T20:07:07.331501-08:00","updated_at":"2025-11-23T21:31:18.600059-08:00","source_repo":".","dependencies":[{"issue_id":"bd-obdc","depends_on_id":"bd-5qim","type":"discovered-from","created_at":"2025-11-23T20:07:40.642297-08:00","created_by":"daemon"}]} +{"id":"bd-obdc","content_hash":"fe7ac547d667b6e7dd713f1120fc2dbea3afa77a59a481358ca484f15cb47c36","title":"Add 'bd doctor --rebuild-cache' command for cache recovery","description":"Add admin command to manually rebuild the blocked_issues_cache table for recovery scenarios.\n\n## Use cases\n\n1. **Cache corruption recovery**\n - If cache gets out of sync with actual dependencies\n - Manual rebuild as safety measure\n\n2. **Post-migration verification**\n - After database migrations that affect dependencies\n - Verify cache is correctly populated\n\n3. **Debugging**\n - Compare cache state with actual blocking calculations\n - Troubleshoot performance issues\n\n## Implementation\n\nAdd flag to bd doctor command:\n\n```bash\nbd doctor --rebuild-cache\n```\n\nShould:\n- Call `SQLiteStorage.invalidateBlockedCache()` directly\n- Print before/after cache statistics\n- Show timing information\n- Exit code 0 on success\n\nExample output:\n```\nRebuilding blocked_issues_cache...\nBefore: 15 blocked issues\nAfter: 15 blocked issues\nRebuilt in 12ms\nβœ“ Cache rebuild complete\n```\n\n## Files to modify\n\n- cmd/bd/doctor.go - add --rebuild-cache flag\n- internal/storage/sqlite/blocked_cache.go - maybe add public RebuildBlockedCache() method\n\n## Related\n\n- [deleted:[deleted:bd-5qim]]: GetReadyWork performance optimization\n- bd-13gm: Add cache validation tests","status":"closed","priority":3,"issue_type":"feature","created_at":"2025-11-23T20:07:07.331501-08:00","updated_at":"2025-11-23T21:35:08.042436-08:00","closed_at":"2025-11-23T21:35:08.042436-08:00","source_repo":".","dependencies":[{"issue_id":"bd-obdc","depends_on_id":"bd-5qim","type":"discovered-from","created_at":"2025-11-23T20:07:40.642297-08:00","created_by":"daemon"}]} {"id":"bd-obxt","content_hash":"7e57a01427663290ada787e0f45cf0df28208ed6cda632e9caf2bdb7e9bb077a","title":"Fix bd doctor to recommend issues.jsonl as canonical (not beads.jsonl)","description":"","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-21T23:27:02.008716-08:00","updated_at":"2025-11-21T23:44:06.081448-08:00","closed_at":"2025-11-21T23:44:06.081448-08:00","source_repo":"."} {"id":"bd-oif6","content_hash":"5732dcbfd354e39ae9249cbae70f08ec1ccf026a812129519dfda5a8588e5ad1","title":"Vendor beads-merge Go code into internal/merge/","description":"Copy beads-merge source code from @neongreen's repo into bd codebase.\n\n**Tasks**:\n- Create `internal/merge/` package\n- Copy merge algorithm code\n- Add attribution header to all files\n- Update imports to use bd's internal types\n- Add LICENSE/ATTRIBUTION file crediting @neongreen\n- Keep original algorithm intact\n\n**Source**: https://github.com/neongreen/mono/tree/main/beads-merge","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-05T18:42:20.405283-08:00","updated_at":"2025-11-05T18:52:53.71713-08:00","closed_at":"2025-11-05T18:52:53.71713-08:00","source_repo":".","dependencies":[{"issue_id":"bd-oif6","depends_on_id":"bd-qqvw","type":"parent-child","created_at":"2025-11-05T18:42:28.69196-08:00","created_by":"daemon"}]} -======= -{"id":"bd-obdc","content_hash":"fe7ac547d667b6e7dd713f1120fc2dbea3afa77a59a481358ca484f15cb47c36","title":"Add 'bd doctor --rebuild-cache' command for cache recovery","description":"Add admin command to manually rebuild the blocked_issues_cache table for recovery scenarios.\n\n## Use cases\n\n1. **Cache corruption recovery**\n - If cache gets out of sync with actual dependencies\n - Manual rebuild as safety measure\n\n2. **Post-migration verification**\n - After database migrations that affect dependencies\n - Verify cache is correctly populated\n\n3. **Debugging**\n - Compare cache state with actual blocking calculations\n - Troubleshoot performance issues\n\n## Implementation\n\nAdd flag to bd doctor command:\n\n```bash\nbd doctor --rebuild-cache\n```\n\nShould:\n- Call `SQLiteStorage.invalidateBlockedCache()` directly\n- Print before/after cache statistics\n- Show timing information\n- Exit code 0 on success\n\nExample output:\n```\nRebuilding blocked_issues_cache...\nBefore: 15 blocked issues\nAfter: 15 blocked issues\nRebuilt in 12ms\nβœ“ Cache rebuild complete\n```\n\n## Files to modify\n\n- cmd/bd/doctor.go - add --rebuild-cache flag\n- internal/storage/sqlite/blocked_cache.go - maybe add public RebuildBlockedCache() method\n\n## Related\n\n- [deleted:[deleted:bd-5qim]]: GetReadyWork performance optimization\n- bd-13gm: Add cache validation tests","status":"closed","priority":3,"issue_type":"feature","created_at":"2025-11-23T20:07:07.331501-08:00","updated_at":"2025-11-23T21:35:08.042436-08:00","closed_at":"2025-11-23T21:35:08.042436-08:00","source_repo":"."} ->>>>>>> 25c241f (bd sync: 2025-11-23 21:37:19) {"id":"bd-ola6","content_hash":"79461888e8a7875bf3623b8db44ea004f73a2374daa52ae9cb3fc9d3ce5e6a8b","title":"Implement transaction retry logic for SQLITE_BUSY","description":"BEGIN IMMEDIATE fails immediately on SQLITE_BUSY instead of retrying with exponential backoff.\n\nLocation: internal/storage/sqlite/sqlite.go:223-225\n\nProblem:\n- Under concurrent write load, BEGIN IMMEDIATE can fail with SQLITE_BUSY\n- Current implementation fails immediately instead of retrying\n- Results in spurious failures under normal concurrent usage\n\nSolution: Implement exponential backoff retry:\n- Retry up to N times (e.g., 5)\n- Backoff: 10ms, 20ms, 40ms, 80ms, 160ms\n- Check for context cancellation between retries\n- Only retry on SQLITE_BUSY/database locked errors\n\nImpact: Spurious failures under concurrent write load\n\nEffort: 3 hours","status":"open","priority":1,"issue_type":"feature","created_at":"2025-11-16T14:51:31.247147-08:00","updated_at":"2025-11-16T14:51:31.247147-08:00","source_repo":"."} {"id":"bd-omx1","content_hash":"e61d74adb03fc8275c97242df8ce0e4146db7e49271e4e86c3379b4a3fbab0d8","title":"Add `bd merge` command wrapping 3-way merge logic","description":"Implement CLI command to invoke beads-merge functionality.\n\n**Interface**:\n```bash\nbd merge \u003coutput\u003e \u003cbase\u003e \u003cleft\u003e \u003cright\u003e\nbd merge --debug \u003coutput\u003e \u003cbase\u003e \u003cleft\u003e \u003cright\u003e\n```\n\n**Behavior**:\n- Exit code 0 on clean merge\n- Exit code 1 if conflicts (write conflict markers)\n- Support --debug flag for verbose output\n- Match beads-merge's existing behavior\n\n**File**: `cmd/bd/merge.go`","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-05T18:42:20.427429-08:00","updated_at":"2025-11-05T19:01:29.071365-08:00","closed_at":"2025-11-05T19:01:29.071365-08:00","source_repo":".","dependencies":[{"issue_id":"bd-omx1","depends_on_id":"bd-qqvw","type":"parent-child","created_at":"2025-11-05T18:42:28.709123-08:00","created_by":"daemon"},{"issue_id":"bd-omx1","depends_on_id":"bd-oif6","type":"blocks","created_at":"2025-11-05T18:42:35.436444-08:00","created_by":"daemon"}]} {"id":"bd-p0zr","content_hash":"5e518ce89ce35cb4b5b534b8c1287679b7984bc73f7c6747773962277d2ad1bc","title":"bd message: Improve type safety with typed parameter structs","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-08T12:54:29.675678-08:00","updated_at":"2025-11-08T12:58:59.559643-08:00","closed_at":"2025-11-08T12:58:59.559643-08:00","source_repo":".","dependencies":[{"issue_id":"bd-p0zr","depends_on_id":"bd-6uix","type":"parent-child","created_at":"2025-11-08T12:55:55.058354-08:00","created_by":"daemon"}]} @@ -609,7 +605,7 @@ {"id":"bd-r79z","content_hash":"2972e60ecf73426a5349415689e57a2404800ee61468ed6d295ab7d4b2c5c7e0","title":"GH#245: Windows MCP subprocess timeout for git rev-parse","description":"User reports git detection timing out on Windows in MCP server, but CLI works fine.\n\nPath: C:\\Users\\chris\\Documents\\DEV_R\\quarto-cli\nError: Git repository detection timed out after 5s\nWorks fine in CLI: `git rev-parse --show-toplevel` succeeds\n\nHypothesis: subprocess.run() with asyncio.to_thread() may have Windows-specific issues or the MCP runtime environment may not have proper PATH/git access.\n\nPotential fixes:\n1. Add subprocess shell=True on Windows\n2. Increase timeout further for Windows\n3. Add better error logging to capture subprocess stderr\n4. Skip git resolution entirely on timeout and just use provided path","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-07T16:31:37.531223-08:00","updated_at":"2025-11-07T19:00:44.358543-08:00","closed_at":"2025-11-07T19:00:44.358543-08:00","source_repo":"."} {"id":"bd-rb75","content_hash":"e91418eb7abda986ddb57feaee1b91867043de8c0883d71c21dc1bf4047f5824","title":"Clean up merge conflict artifacts in .beads directory","description":"After resolving merge conflicts in .beads/beads.jsonl, leftover artifacts remain as untracked files:\n- .beads/beads.base.jsonl\n- .beads/beads.left.jsonl\n\nThese appear to be temporary files created during merge conflict resolution.\n\nOptions to fix:\n1. Add these patterns to .beads/.gitignore automatically\n2. Clean up these files after successful merge resolution\n3. Document that users should delete them manually\n4. Add a check in 'bd sync' or 'bd doctor' to detect and remove stale merge artifacts\n\nPreferred solution: Add *.base.jsonl and *.left.jsonl patterns to .beads/.gitignore during 'bd init', and optionally clean them up automatically after successful import.","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-11-06T19:09:16.114274-08:00","updated_at":"2025-11-06T19:13:44.630402-08:00","closed_at":"2025-11-06T19:13:44.630402-08:00","source_repo":"."} {"id":"bd-rbxi","content_hash":"df423e4150f6f3b5a19467b8cb41a4b90475cc9ced45ed577ebbe9e3e75279f9","title":"bd-hv01: Deletion tracking production readiness","description":"Epic to track all improvements and fixes needed to make the deletion tracking implementation ([deleted:bd-hv01]) production-ready.\n\nThe core 3-way merge algorithm is sound, but there are critical issues around atomicity, error handling, and edge cases that need to be addressed before this can be safely used in production.\n\nCritical path (P1):\n- Non-atomic snapshot operations\n- Brittle JSON string comparison\n- Silent partial deletion failures\n- Race conditions in concurrent scenarios\n\nFollow-up work (P2-P3):\n- Test coverage for edge cases and multi-repo mode\n- Performance optimizations\n- Code refactoring and observability\n\nRelated commit: 708a81c","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-11-06T18:18:24.315646-08:00","updated_at":"2025-11-08T03:12:04.15385-08:00","closed_at":"2025-11-08T02:19:19.780741-08:00","source_repo":"."} -{"id":"bd-rcmg","content_hash":"3b7e12b9b4a0679521b701016e851816f76f4b84d266919079836daf03393590","title":"Fix N+1 query pattern in export operations (GetLabels/GetIssueComments)","description":"**Location:** internal/rpc/server_export_import_auto.go:64-84\n\n**Issue:** Export operations call GetLabels() and GetIssueComments() in a loop for each issue, creating N+1 query pattern. For 100 issues this creates 201 queries instead of ~3-5.\n\n**Current Code:**\n```go\nfor _, issue := range issues {\n labels, err := store.GetLabels(ctx, issue.ID) // 1 query per issue!\n issue.Labels = labels\n}\nfor _, issue := range issues {\n comments, err := store.GetIssueComments(ctx, issue.ID) // 1 query per issue!\n issue.Comments = comments\n}\n```\n\n**Fix:** Implement batch query methods like GetLabelsForIssues() and GetCommentsForIssues() that load all data in 1-2 queries total.\n\n**Impact:** Performance degradation on large exports. This is already done correctly for dependencies.","status":"closed","priority":0,"issue_type":"bug","created_at":"2025-11-23T19:46:37.565199-08:00","updated_at":"2025-11-23T19:52:54.952483-08:00","closed_at":"2025-11-23T19:52:54.952483-08:00","source_repo":"."} +{"id":"bd-rcmg","content_hash":"bed638c103ddf88ed4f9b639e8871d3c62d8bbbbdb42f61264038d71a2e5e76c","title":"Fix N+1 query pattern in export operations (GetLabels/GetIssueComments)","description":"**Location:** internal/rpc/server_export_import_auto.go:64-84\n\n**Issue:** Export operations call GetLabels() and GetIssueComments() in a loop for each issue, creating N+1 query pattern. For 100 issues this creates 201 queries instead of ~3-5.\n\n**Current Code:**\n```go\nfor _, issue := range issues {\n labels, err := store.GetLabels(ctx, issue.ID) // 1 query per issue!\n issue.Labels = labels\n}\nfor _, issue := range issues {\n comments, err := store.GetIssueComments(ctx, issue.ID) // 1 query per issue!\n issue.Comments = comments\n}\n```\n\n**Fix:** Implement batch query methods like GetLabelsForIssues() and GetCommentsForIssues() that load all data in 1-2 queries total.\n\n**Impact:** Performance degradation on large exports. This is already done correctly for dependencies.","status":"closed","priority":0,"issue_type":"bug","created_at":"2025-11-23T19:46:37.565199-08:00","updated_at":"2025-11-23T19:52:54.952483-08:00","closed_at":"2025-11-23T19:52:54.952483-08:00","source_repo":"."} {"id":"bd-rfj","content_hash":"c38dcf80ea98c965123622c1ff4c9faddefd226609c1f3ad59143182b1f00114","title":"Add unit tests for hasJSONLChanged() function","description":"The hasJSONLChanged() function has no unit tests. Should test:\n- Normal case: hash matches\n- Normal case: hash differs\n- Edge case: empty file\n- Edge case: missing metadata (first run)\n- Edge case: corrupted metadata\n- Edge case: file read errors\n- Edge case: invalid hash format in metadata\n\nAlso add performance benchmarks for large JSONL files.","status":"closed","priority":3,"issue_type":"task","created_at":"2025-11-20T21:31:10.389481-05:00","updated_at":"2025-11-20T21:40:02.664516-05:00","closed_at":"2025-11-20T21:40:02.664516-05:00","source_repo":".","dependencies":[{"issue_id":"bd-rfj","depends_on_id":"bd-khnb","type":"blocks","created_at":"2025-11-20T21:31:10.39058-05:00","created_by":"daemon"}]} {"id":"bd-ri6d","content_hash":"62b887c13232eeabf1d1b25a514b6044ff6ea7b510a06cbd5a736beabe722c43","title":"bd message: Fix inefficient client-side filtering for --unread-only","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-08T12:54:28.614867-08:00","updated_at":"2025-11-08T12:58:59.551512-08:00","closed_at":"2025-11-08T12:58:59.551512-08:00","source_repo":".","dependencies":[{"issue_id":"bd-ri6d","depends_on_id":"bd-6uix","type":"parent-child","created_at":"2025-11-08T12:55:55.012455-08:00","created_by":"daemon"}]} {"id":"bd-rpn","content_hash":"4b0c8a22edcf49b95f1caba51397f5a6289bc170a69084bc3c39267a8f43d888","title":"Implement `bd prime` command for AI context loading","description":"Create a `bd prime` command that outputs AI-optimized markdown containing essential Beads workflow context. This provides an alternative to the MCP server for token-conscious users and enables context recovery after compaction/clearing.","design":"## Implementation\n\nCreate `cmd/bd/prime.go` that outputs AI-optimized markdown with **adaptive content based on MCP detection**.\n\n## MCP-Aware Output Strategy\n\n`bd prime` detects if MCP server is active and adjusts output accordingly:\n\n**With MCP detected** (~500 tokens):\n- Workflow reminders only\n- \"Use bd MCP tools, not markdown TODOs\"\n- Session management tips\n- NO CLI command syntax (user has native MCP tools)\n\n**Without MCP** (~1-2k tokens):\n- Full workflow rules\n- Complete CLI command reference with examples\n- All command syntax and options\n\n**Why this matters:**\n- MCP users don't need CLI docs (they have native function calls)\n- Non-MCP users need full command reference\n- Same hook works for all users, adapts to their environment\n- Reduces token waste for MCP users\n\n## MCP Detection Logic\n\n```go\nfunc isMCPActive() bool {\n // Check environment variables that Claude Code sets when MCP servers are loaded\n // Options to investigate:\n // 1. Check for CLAUDE_MCP_SERVERS environment variable\n // 2. Check for specific MCP server process indicators\n // 3. Parse ~/.claude/settings.json for enabled MCP servers\n // 4. Check for MCP socket/connection availability\n \n // Fallback: assume MCP if we can't determine\n // (safer to output less and have user call with --full flag)\n return checkMCPEnvironment()\n}\n```\n\n**Alternative: Command flag for explicit control:**\n```bash\nbd prime # Auto-detect MCP\nbd prime --full # Force full output (ignore MCP detection)\nbd prime --mcp # Force MCP mode (minimal output)\n```\n\n## Discovery Logic\n\n**Skip PersistentPreRun database initialization:**\nAdd \"prime\" to noDbCommands list in main.go so it doesn't require .beads/ upfront.\n\n**Silent, cross-platform execution:**\n```go\nvar primeCmd = \u0026cobra.Command{\n Use: \"prime\",\n Short: \"Output AI-optimized workflow context\",\n Run: func(cmd *cobra.Command, args []string) {\n // Find .beads/ directory (walks up tree like bd does)\n dbPath := beads.FindDatabasePath()\n if dbPath == \"\" {\n // Not in a beads project - silent exit with success\n // CRITICAL: No stderr output, exit 0\n // This enables cross-platform hook integration\n os.Exit(0)\n }\n \n // Detect MCP mode (unless overridden by flags)\n mcpMode := isMCPActive()\n if fullFlag {\n mcpMode = false\n }\n if mcpFlag {\n mcpMode = true\n }\n \n // Output workflow context (adaptive based on MCP)\n if err := outputPrimeContext(mcpMode); err != nil {\n // Suppress all errors - silent exit with success\n // Never write to stderr (breaks Windows compatibility)\n os.Exit(0)\n }\n },\n}\n```\n\n**Why silent execution matters:**\n- **Cross-platform**: No shell-specific syntax needed (`2\u003e/dev/null`, `|| true`)\n- **Hook-friendly**: Can be called directly from JSON: `\"command\": \"bd prime\"`\n- **Windows compatible**: Works in cmd.exe, PowerShell, bash\n- **Non-beads projects**: No error noise when run outside beads projects\n\n## Output Formats\n\n### MCP Mode (~500 tokens)\n```markdown\n# Beads Workflow Context\n\n\u003e **You have native bd MCP tools available** - use them instead of markdown TODOs\n\u003e Run `bd prime --full` for complete CLI reference if needed\n\n## Core Workflow Rules\n\n**Task Tracking:**\n- Use bd MCP tools for ALL work tracking (never markdown TODOs)\n- Check available work: use `mcp__plugin_beads_beads__ready` tool\n- Create issues: use `mcp__plugin_beads_beads__create` tool\n- Update status: use `mcp__plugin_beads_beads__update` tool\n\n**Session Management:**\n- Start: Check `ready` tool for available work\n- During: Keep issues updated with `update` tool\n- End: Verify sync status, close completed issues\n\n**Git Integration:**\n- Hooks auto-sync issues with git commits\n- Run `sync` tool at session end to push to remote\n\n**Need help?** \n- Use `show` tool for issue details\n- Check AGENTS.md for complete workflow\n- Run `bd prime --full` for CLI command reference\n```\n\n### Non-MCP Mode (~1-2k tokens)\n```markdown\n# Beads Workflow Context\n\n\u003e **Context Recovery**: Run `bd prime` after compaction, clear, or new session\n\u003e Hooks auto-call this in Claude Code when .beads/ detected\n\n## Core Rules\n- Track ALL work in bd (no markdown TODOs)\n- Git workflow: hooks auto-sync, run `bd sync` at session end\n- Session management: check `bd ready` for available work\n\n## Essential Commands\n\n### Finding Work\n- `bd ready` - Show issues ready to work (no blockers)\n- `bd list --status=open` - All open issues\n- `bd list --status=in_progress` - Your active work\n- `bd show \u003cid\u003e` - Detailed issue view with dependencies\n\n### Creating \u0026 Updating\n- `bd create --title=\"...\" --type=task|bug|feature` - New issue\n- `bd update \u003cid\u003e --status=in_progress` - Claim work\n- `bd update \u003cid\u003e --assignee=username` - Assign to someone\n- `bd close \u003cid\u003e` - Mark complete\n- `bd close \u003cid\u003e --reason=\"explanation\"` - Close with reason\n\n### Dependencies \u0026 Blocking\n- `bd dep \u003cfrom\u003e \u003cto\u003e` - Add blocker dependency (from blocks to)\n- `bd blocked` - Show all blocked issues\n- `bd show \u003cid\u003e` - See what's blocking/blocked by this issue\n\n### Sync \u0026 Collaboration\n- `bd sync` - Sync with git remote (run at session end)\n- `bd sync --status` - Check sync status without syncing\n\n### Project Health\n- `bd stats` - Project statistics (open/closed/blocked counts)\n- `bd doctor` - Check for issues (sync problems, missing hooks)\n\n## Common Workflows\n\n**Starting work:**\n```bash\nbd ready # Find available work\nbd show \u003cid\u003e # Review issue details\nbd update \u003cid\u003e --status=in_progress # Claim it\n```\n\n**Completing work:**\n```bash\nbd close \u003cid\u003e # Mark done\nbd sync # Push to remote\n```\n\n**Creating dependent work:**\n```bash\nbd create --title=\"Implement feature X\" --type=feature\nbd create --title=\"Write tests for X\" --type=task\nbd dep beads-xxx beads-yyy # Feature blocks tests\n```\n\nFor complete docs: AGENTS.md, QUICKSTART.md, `bd --help`\n```\n\n## Behavior Guarantees\n\n1. **Never writes to stderr** (all errors suppressed internally)\n2. **Always exits 0** (success) even when:\n - Not in a beads project\n - .beads/ not found\n - Any internal error occurs\n3. **Cross-platform compatible** (no shell-specific syntax)\n4. **Hook-safe** (can be called directly without wrappers)\n5. **MCP-aware** (adapts output based on user's tool environment)\n\n## Files\n- `cmd/bd/prime.go` - Command implementation with MCP detection\n- `cmd/bd/prime_test.go` - Tests (including MCP mode switching)\n- Update `cmd/bd/main.go` - Add \"prime\" to noDbCommands list","acceptance_criteria":"- `bd prime` outputs markdown format\n- Output is ~1-2k tokens\n- Output includes workflow rules and command reference\n- Command has unit tests\n- Documentation updated in AGENTS.md","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-11-11T23:28:42.74124-08:00","updated_at":"2025-11-12T08:30:15.711595-08:00","closed_at":"2025-11-12T08:30:15.711595-08:00","source_repo":".","dependencies":[{"issue_id":"bd-rpn","depends_on_id":"bd-90v","type":"parent-child","created_at":"2025-11-11T23:31:20.357861-08:00","created_by":"daemon"}]} @@ -626,7 +622,7 @@ {"id":"bd-t4u1","content_hash":"5558c6e25c6aae4be03fd9f112d892f6e69dc020dee2292a24ec185fb7b6a054","title":"False positive detection by Kaspersky Antivirus (Trojan)","description":"Kaspersky Antivirus falsely detects beads (bd.exe v0.23.1) as a Trojan (PDM:Trojan.Win32.Generic) and removes it.\nEvent: Malicious object detected\nComponent: System Watcher\nObject name: bd.exe\n","status":"open","priority":1,"issue_type":"task","created_at":"2025-11-20T18:56:12.498187-05:00","updated_at":"2025-11-20T18:56:12.498187-05:00","source_repo":"."} {"id":"bd-t596","content_hash":"6264185777b70f01cd5762c310671175311c9e245d925fa1b3e7a3743c32a9ab","title":"Create comments.go with comment methods","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-23T18:08:15.987782-08:00","updated_at":"2025-11-23T18:13:57.446443-08:00","closed_at":"2025-11-23T18:13:57.446443-08:00","source_repo":"."} {"id":"bd-t5o","content_hash":"0685a34b3db702956f3ae1478eb6f746db3023ed9cf6a84d94deea9c43bba61d","title":"Document error handling strategy for metadata update failures","description":"Multiple places silently ignore metadata update failures (sync.go:614-617, import.go:320-322) with non-fatal warnings. This is intentional (degrades gracefully to mtime-based approach) but not well documented.\n\nAdd comments explaining:\n- Why these failures are non-fatal\n- How system degrades gracefully\n- What the fallback behavior is (mtime-based detection)","status":"closed","priority":3,"issue_type":"task","created_at":"2025-11-20T21:31:12.366861-05:00","updated_at":"2025-11-20T21:36:16.972395-05:00","closed_at":"2025-11-20T21:36:16.972395-05:00","source_repo":".","dependencies":[{"issue_id":"bd-t5o","depends_on_id":"bd-khnb","type":"blocks","created_at":"2025-11-20T21:31:12.367744-05:00","created_by":"daemon"}]} -{"id":"bd-t7ds","content_hash":"3630de801d736dad717659cd622311ef722a288134ffd2070978f25115ab9d88","title":"Implement log rotation for daemon.log","description":"**File:** .beads/daemon.log (currently 5.7 MB)\n\n**Issue:** Daemon log can grow unbounded with no rotation policy. Could consume disk space on long-running daemons.\n\n**Recommended Solution:**\n- Implement log rotation with retention policy\n- Default: max 50MB per file, keep 7 files\n- Configuration option in config.yaml\n- Use standard log rotation library or implement simple rotation\n\n**Impact:** Low priority but good operational hygiene for production use.","status":"closed","priority":3,"issue_type":"feature","created_at":"2025-11-23T19:46:54.186691-08:00","updated_at":"2025-11-23T21:31:12.716417-08:00","closed_at":"2025-11-23T21:31:12.716417-08:00","source_repo":"."} +{"id":"bd-t7ds","content_hash":"0752f0f5d23dc3a1832cbf3f391b37892f78a80958edb08484c32e5b59c22fe6","title":"Implement log rotation for daemon.log","description":"**File:** .beads/daemon.log (currently 5.7 MB)\n\n**Issue:** Daemon log can grow unbounded with no rotation policy. Could consume disk space on long-running daemons.\n\n**Recommended Solution:**\n- Implement log rotation with retention policy\n- Default: max 50MB per file, keep 7 files\n- Configuration option in config.yaml\n- Use standard log rotation library or implement simple rotation\n\n**Impact:** Low priority but good operational hygiene for production use.","status":"closed","priority":3,"issue_type":"feature","created_at":"2025-11-23T19:46:54.186691-08:00","updated_at":"2025-11-23T21:37:42.460167-08:00","closed_at":"2025-11-23T21:31:12.716417-08:00","source_repo":"."} {"id":"bd-tbz3","content_hash":"ee74a320cde913118634715dbb19c5aaab593c463b5611dc209dafd86f28c5a8","title":"bd init UX Improvements","description":"bd init leaves users with incomplete setup, requiring manual bd doctor --fix. Issues found: (1) git hooks not installed if user declines prompt, (2) no auto-migration when CLI is upgraded, (3) stale merge driver configs from old versions. Fix by making bd init more robust with better defaults and auto-migration.","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-11-21T23:16:00.333543-08:00","updated_at":"2025-11-23T20:32:54.704813-08:00","closed_at":"2025-11-23T19:55:59.15083-08:00","source_repo":"."} {"id":"bd-tmdx","content_hash":"0976d6529458902f06108d5d316fda3bf6ed299eaa684501aada481d9e4b10a5","title":"Investigate database pollution - unexpected issue count increases","description":"Two repositories showing unexpected issue counts:\n- ~/src/beads: 280 issues (expected ~209-220)\n- ~/src/dave/beads: 895 issues (675 open, 149 closed)\n\nThis suggests database pollution - issues from one repository leaking into another. Need to investigate:\n1. Run bd detect-pollution on both repos\n2. Check for cross-repo contamination\n3. Identify source of pollution (daemon? multi-repo config? import issues?)\n4. Clean up polluted databases\n5. Prevent future pollution","status":"closed","priority":0,"issue_type":"bug","created_at":"2025-11-06T22:50:16.957689-08:00","updated_at":"2025-11-07T00:05:38.994405-08:00","closed_at":"2025-11-07T00:05:38.994405-08:00","source_repo":"."} {"id":"bd-tne","content_hash":"2a6596980450714800bddc88e106026743a1a131e96f09198eb7dc2a16d75ca4","title":"Add Claude setup tip with dynamic priority","description":"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.","design":"## Implementation\n\nAdd to tip registry in `cmd/bd/tips.go`:\n\n```go\n{\n ID: \"claude_setup\",\n Condition: func() bool {\n return isClaudeDetected() \u0026\u0026 !isClaudeSetupComplete()\n },\n Message: \"Run 'bd setup claude' to enable automatic context recovery in Claude Code\",\n Frequency: 24 * time.Hour, // Daily minimum gap\n Priority: 100, // Highest priority\n Probability: 0.6, // 60% chance when eligible\n}\n```\n\n## Detection Logic\n\n```go\nfunc isClaudeDetected() bool {\n // Check environment variables\n if os.Getenv(\"CLAUDE_CODE\") != \"\" || os.Getenv(\"ANTHROPIC_CLI\") != \"\" {\n return true\n }\n // Check if .claude/ directory exists\n if _, err := os.Stat(filepath.Join(os.Getenv(\"HOME\"), \".claude\")); err == nil {\n return true\n }\n return false\n}\n\nfunc isClaudeSetupComplete() bool {\n // Check for global installation\n home, err := os.UserHomeDir()\n if err == nil {\n _, err1 := os.Stat(filepath.Join(home, \".claude/commands/prime_beads.md\"))\n _, err2 := os.Stat(filepath.Join(home, \".claude/hooks/sessionstart\"))\n if err1 == nil \u0026\u0026 err2 == nil {\n return true // Global hooks installed\n }\n }\n \n // Check for project installation\n _, err1 := os.Stat(\".claude/commands/prime_beads.md\")\n _, err2 := os.Stat(\".claude/hooks/sessionstart\")\n return err1 == nil \u0026\u0026 err2 == nil\n}\n```\n\n## Priority and Probability Behavior\n\n**Why 60% probability?**\n- Important message (priority 100) but not critical\n- Daily frequency + 60% = shows ~4 times per week\n- Avoids spam while staying visible\n- Balances persistence with user experience\n\n**Comparison with other probabilities:**\n- 100% probability: Shows EVERY day (annoying)\n- 80% probability: Shows ~6 days per week (too frequent)\n- 60% probability: Shows ~4 days per week (balanced)\n- 40% probability: Shows ~3 days per week (might be missed)\n\n**Auto-stops when setup complete:**\n- Condition becomes false after `bd setup claude`\n- No manual dismissal needed\n- Tip naturally disappears from rotation","acceptance_criteria":"- Claude setup tip added to registry\n- isClaudeDetected() checks environment and filesystem\n- isClaudeSetupComplete() verifies hook installation\n- Tip shows daily until setup complete\n- Tip stops showing after setup\n- Unit tests for detection functions","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-11T23:29:29.871324-08:00","updated_at":"2025-11-11T23:50:29.756454-08:00","source_repo":".","dependencies":[{"issue_id":"bd-tne","depends_on_id":"bd-d4i","type":"blocks","created_at":"2025-11-11T23:29:29.872081-08:00","created_by":"daemon"},{"issue_id":"bd-tne","depends_on_id":"bd-br8","type":"blocks","created_at":"2025-11-11T23:29:29.87252-08:00","created_by":"daemon"}]} @@ -651,7 +647,7 @@ {"id":"bd-wfmw","content_hash":"21706f1701be9fb51fa9e17d1dded6343bc2585e4bdb608239a20c5853d00220","title":"Integration Layer Implementation","description":"Build the adapter layer that makes Agent Mail optional and non-intrusive.","notes":"Progress: bd-m9th (Python adapter library) completed with full test coverage. Next: bd-fzbg (update python-agent example with Agent Mail integration).","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-11-07T22:42:09.356429-08:00","updated_at":"2025-11-08T00:20:30.888756-08:00","closed_at":"2025-11-08T00:20:30.888756-08:00","source_repo":".","dependencies":[{"issue_id":"bd-wfmw","depends_on_id":"bd-spmx","type":"blocks","created_at":"2025-11-07T22:42:09.357488-08:00","created_by":"daemon"}]} {"id":"bd-wgu4","content_hash":"31cf5cc105fee5de26f4c2756b8368c90b18eb5f65c656eb0d90f96b23daf21d","title":"Standardize daemon detection: use tryDaemonLock probe before RPC","description":"Before attempting RPC connection, call tryDaemonLock() to check if lock is held:\n- If lock NOT held: skip RPC attempt (no daemon running)\n- If lock IS held: proceed with RPC + short timeout\n\nThis is extremely cheap and eliminates unnecessary connection attempts.\n\nApply across all client entry points that probe for daemon.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-07T16:42:12.709802-08:00","updated_at":"2025-11-07T20:15:23.282181-08:00","closed_at":"2025-11-07T20:15:23.282181-08:00","source_repo":".","dependencies":[{"issue_id":"bd-wgu4","depends_on_id":"bd-ndyz","type":"discovered-from","created_at":"2025-11-07T16:42:12.710564-08:00","created_by":"daemon"}]} {"id":"bd-wh24","content_hash":"d39a74dc105558f12ba776349a8513a5293bd7aac7ffb3498e419c370de56149","title":"Fix Windows test failure: File permissions in TestAtomicWriteFile","description":"On Windows, file permissions work differently. The test expects 0600 but gets 0666. Windows doesn't support Unix-style file permissions in the same way. Need to either skip this check on Windows or adjust expectations.\n\nTest failure: utils_test.go:39: file permissions mismatch: got 666, want 600\n\nRoot cause: Windows filesystem doesn't support Unix-style permission bits. Need to use runtime.GOOS check or skip permission validation on Windows.","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-11-23T20:16:14.190555-08:00","updated_at":"2025-11-23T21:16:32.850024-08:00","closed_at":"2025-11-23T21:12:01.320284-08:00","source_repo":"."} -{"id":"bd-woro","content_hash":"ea0cffdac7fcc712387fbeece501de3e8d6be739822141bd48ea8a5b953be156","title":"Separate canonical BD_GUIDE.md from AGENTS.md","description":"Create architectural separation between bd-specific instructions and project-specific instructions.\n\n## Problem\nCurrently AGENTS.md mixes:\n- bd tool documentation (changes with bd upgrades)\n- Project-specific workflow (stable, manually maintained)\n\nThis makes it hard to update bd instructions without touching project docs.\n\n## Solution\n1. Generate .beads/BD_GUIDE.md from 'bd onboard' output\n2. Mark it as auto-generated (never manually edit)\n3. Version-stamp header with bd version\n4. AGENTS.md references it instead of duplicating content\n5. Auto-update BD_GUIDE.md when bd version changes\n\n## Implementation\n- Add 'bd onboard --output .beads/BD_GUIDE.md' option\n- Detect version changes and offer to regenerate\n- Add header: '\u003c!-- Auto-generated by bd v0.24.2 - DO NOT EDIT --\u003e'\n- Update AGENTS.md to reference BD_GUIDE.md\n\n## Benefits\n- Clear separation of concerns\n- Deterministic updates (no agent LLM involved)\n- Git-trackable diffs show exactly what changed\n- Progressive disclosure (agents read when needed)\n\n## Acceptance Criteria\n- BD_GUIDE.md auto-generated and version-stamped\n- AGENTS.md references it appropriately\n- Upgrade workflow auto-updates BD_GUIDE.md\n- Git diffs clearly show bd instruction changes\n","status":"closed","priority":3,"issue_type":"feature","created_at":"2025-11-23T16:21:55.451925-08:00","updated_at":"2025-11-23T21:16:14.466241-08:00","closed_at":"2025-11-23T21:16:14.466241-08:00","source_repo":".","dependencies":[{"issue_id":"bd-woro","depends_on_id":"bd-nxgk","type":"parent-child","created_at":"2025-11-23T16:21:55.453758-08:00","created_by":"daemon"}]} +{"id":"bd-woro","content_hash":"56f0b12b92aee264b139da823e441d0e8fb86d908affe28ed484544e7902e62c","title":"Separate canonical BD_GUIDE.md from AGENTS.md","description":"Create architectural separation between bd-specific instructions and project-specific instructions.\n\n## Problem\nCurrently AGENTS.md mixes:\n- bd tool documentation (changes with bd upgrades)\n- Project-specific workflow (stable, manually maintained)\n\nThis makes it hard to update bd instructions without touching project docs.\n\n## Solution\n1. Generate .beads/BD_GUIDE.md from 'bd onboard' output\n2. Mark it as auto-generated (never manually edit)\n3. Version-stamp header with bd version\n4. AGENTS.md references it instead of duplicating content\n5. Auto-update BD_GUIDE.md when bd version changes\n\n## Implementation\n- Add 'bd onboard --output .beads/BD_GUIDE.md' option\n- Detect version changes and offer to regenerate\n- Add header: '\u003c!-- Auto-generated by bd v0.24.2 - DO NOT EDIT --\u003e'\n- Update AGENTS.md to reference BD_GUIDE.md\n\n## Benefits\n- Clear separation of concerns\n- Deterministic updates (no agent LLM involved)\n- Git-trackable diffs show exactly what changed\n- Progressive disclosure (agents read when needed)\n\n## Acceptance Criteria\n- BD_GUIDE.md auto-generated and version-stamped\n- AGENTS.md references it appropriately\n- Upgrade workflow auto-updates BD_GUIDE.md\n- Git diffs clearly show bd instruction changes\n","status":"closed","priority":3,"issue_type":"feature","created_at":"2025-11-23T16:21:55.451925-08:00","updated_at":"2025-11-23T21:16:14.466241-08:00","closed_at":"2025-11-23T21:16:14.466241-08:00","source_repo":".","dependencies":[{"issue_id":"bd-woro","depends_on_id":"bd-nxgk","type":"parent-child","created_at":"2025-11-23T16:21:55.453758-08:00","created_by":"daemon"}]} {"id":"bd-wpkz","content_hash":"58003aaff85c85ba5c314fb5b253e0b79094484059a8fecedb9474ea4f984458","title":"Run tests to ensure refactoring didn't break anything","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-23T18:08:17.264759-08:00","updated_at":"2025-11-23T18:15:22.990153-08:00","closed_at":"2025-11-23T18:15:22.990153-08:00","source_repo":".","dependencies":[{"issue_id":"bd-wpkz","depends_on_id":"bd-9csf","type":"blocks","created_at":"2025-11-23T18:08:30.928086-08:00","created_by":"daemon"},{"issue_id":"bd-wpkz","depends_on_id":"bd-wrfz","type":"blocks","created_at":"2025-11-23T18:08:31.009873-08:00","created_by":"daemon"},{"issue_id":"bd-wpkz","depends_on_id":"bd-x2ba","type":"blocks","created_at":"2025-11-23T18:08:31.080663-08:00","created_by":"daemon"},{"issue_id":"bd-wpkz","depends_on_id":"bd-t596","type":"blocks","created_at":"2025-11-23T18:08:31.153866-08:00","created_by":"daemon"}]} {"id":"bd-wrfz","content_hash":"a03a18ee69cedc5e7e9c7553d27168fd1935b8d77c863b4888a2b73fec9531bf","title":"Create queries.go with core issue CRUD methods","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-23T18:08:13.46714-08:00","updated_at":"2025-11-23T18:12:55.233765-08:00","closed_at":"2025-11-23T18:12:55.233765-08:00","source_repo":"."} {"id":"bd-wta","content_hash":"eee40bbe4e00af632ad46e1461a25e4b0e5508bea115422aea0772381eec0d84","title":"Add performance benchmarks for multi-repo hydration","description":"The contributor-workflow-analysis.md asserts sub-second queries (line 702) and describes smart caching via file mtime tracking (Decision #4, lines 584-618), but doesn't provide concrete performance benchmarks.\n\nVC's requirement (from VC feedback section):\n- Executor polls GetReadyWork() every 5-10 seconds\n- Queries must be sub-second (ideally \u003c100ms)\n- Smart caching must avoid re-parsing JSONLs on every query\n\nSuggested performance targets to validate:\n- File stat overhead: \u003c1ms per repo\n- Hydration (when needed): \u003c500ms for typical JSONL (\u003c25k)\n- Query (from cache): \u003c10ms\n- Total GetReadyWork(): \u003c100ms (VC's requirement)\n\nAlso test at scale:\n- N=1 repo (baseline)\n- N=3 repos (typical)\n- N=10 repos (edge case)\n\nThese benchmarks are critical for library consumers like VC that run automated polling loops.","acceptance_criteria":"- Performance benchmark suite created for multi-repo hydration\n- Benchmarks cover file stat, hydration, and query times\n- Tests at N=1, N=3, N=10 repo scales\n- Results documented in contributor-workflow-analysis.md\n- Performance targets met or issues filed for optimization","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-03T20:24:39.331528-08:00","updated_at":"2025-11-05T14:17:15.079226-08:00","closed_at":"2025-11-05T14:17:15.079226-08:00","source_repo":"."} @@ -663,7 +659,7 @@ {"id":"bd-xryv","content_hash":"7aadbfa4e6359a5836100b6615cebc3ff0cdccd9702cb5f6be35f30f2da72310","title":"Fix Windows test failure: Directory permissions in TestEnsureDir","description":"On Windows, directory permissions work differently. The test expects 0755 but gets 0777. Windows doesn't support Unix-style file permissions in the same way. Need to either skip this check on Windows or adjust expectations.\n\nTest failure: utils_test.go:138: directory permissions mismatch: got 777, want 755\n\nRoot cause: Windows filesystem doesn't support Unix-style permission bits. Need to use runtime.GOOS check or skip permission validation on Windows.","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-11-23T20:16:19.809172-08:00","updated_at":"2025-11-23T21:16:32.844841-08:00","closed_at":"2025-11-23T21:11:59.735835-08:00","source_repo":"."} {"id":"bd-xwo","content_hash":"48264aedbfd8cd9ea8ab6ca37882497be431f2827004554058645b610adc3009","title":"Fix validatePreExport to use content hash instead of mtime","description":"validatePreExport() in integrity.go:70 still uses isJSONLNewer() (mtime-based), creating inconsistent behavior. Auto-import correctly uses hasJSONLChanged() (hash-based) but export validation still uses the old mtime approach. This can cause false positive blocks after git operations.\n\nFix: Replace isJSONLNewer() call with hasJSONLChanged() in validatePreExport().\n\nImpact: Without this fix, the bd-khnb solution is incomplete - we prevent resurrection but still have export blocking issues.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-20T21:31:03.183164-05:00","updated_at":"2025-11-20T21:34:00.200803-05:00","closed_at":"2025-11-20T21:34:00.200803-05:00","source_repo":".","dependencies":[{"issue_id":"bd-xwo","depends_on_id":"bd-khnb","type":"blocks","created_at":"2025-11-20T21:31:03.184049-05:00","created_by":"daemon"}]} {"id":"bd-xzrv","content_hash":"45b45aaa47b9fc254ce74750b92f5527862672d9826c7ad59e006bdb1bc9939f","title":"Write Agent Mail integration guide","description":"Comprehensive guide for setting up and using Agent Mail with Beads.\n\nAcceptance Criteria:\n- Installation instructions\n- Configuration (environment variables)\n- Architecture diagram\n- Benefits and tradeoffs\n- When to use vs not use\n- Troubleshooting section\n- Migration from git-only mode\n\nFile: docs/AGENT_MAIL.md\n\nSections:\n- Quick start\n- How it works\n- Integration points\n- Graceful degradation\n- Multi-machine deployment\n- FAQ","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-07T22:42:51.231066-08:00","updated_at":"2025-11-08T00:40:38.798162-08:00","closed_at":"2025-11-08T00:40:38.798162-08:00","source_repo":".","dependencies":[{"issue_id":"bd-xzrv","depends_on_id":"bd-fzbg","type":"blocks","created_at":"2025-11-07T22:42:51.232246-08:00","created_by":"daemon"}]} -{"id":"bd-y6d","content_hash":"d13fc9682bf8abee565cf5724c32c56ead5c080cf257ad604b0a3d508a01a4b8","title":"Refactor create_test.go to use shared DB setup","description":"Convert TestCreate_* functions to use test suites with shared database setup.\n\nExample transformation:\n- Before: 10 separate tests, each with newTestStore() \n- After: 1 TestCreate() with 10 t.Run() subtests sharing one DB\n\nEstimated speedup: 10x faster (1 DB setup instead of 10)","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-21T11:48:56.858213-05:00","updated_at":"2025-11-21T15:15:31.315407-05:00","closed_at":"2025-11-21T15:15:31.315407-05:00","source_repo":".","dependencies":[{"issue_id":"bd-y6d","depends_on_id":"bd-1rh","type":"blocks","created_at":"2025-11-21T11:49:09.660182-05:00","created_by":"daemon"},{"issue_id":"bd-y6d","depends_on_id":"bd-c49","type":"blocks","created_at":"2025-11-21T11:49:26.410452-05:00","created_by":"daemon"}]} +{"id":"bd-y6d","content_hash":"9d63262aa6b79d03e9fd1639833d0827b74743aad0a430d0478e46034776bc13","title":"Refactor create_test.go to use shared DB setup","description":"Convert TestCreate_* functions to use test suites with shared database setup.\n\nExample transformation:\n- Before: 10 separate tests, each with newTestStore() \n- After: 1 TestCreate() with 10 t.Run() subtests sharing one DB\n\nEstimated speedup: 10x faster (1 DB setup instead of 10)","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-21T11:48:56.858213-05:00","updated_at":"2025-11-21T15:15:31.315407-05:00","closed_at":"2025-11-21T15:15:31.315407-05:00","source_repo":".","dependencies":[{"issue_id":"bd-y6d","depends_on_id":"bd-1rh","type":"blocks","created_at":"2025-11-21T11:49:09.660182-05:00","created_by":"daemon"},{"issue_id":"bd-y6d","depends_on_id":"bd-c49","type":"blocks","created_at":"2025-11-21T11:49:26.410452-05:00","created_by":"daemon"}]} {"id":"bd-yb8","content_hash":"9579eb6536ba3a6fe6c62e7275f467c6926b08e78861a77869878849fb2f3b17","title":"Propagate context through command handlers","description":"Thread context from signal-aware parent through all command handlers.\n\n## Context\nPart of context propagation work. Builds on bd-rtp (signal-aware contexts).\n\n## Current State\nMany command handlers create their own context.Background() locally instead of receiving context from parent.\n\n## Implementation\n1. Add context parameter to command handler functions\n2. Pass context from cobra command Run/RunE closures\n3. Update all storage operations to use propagated context\n\n## Example Pattern\n```go\n// Before\nRun: func(cmd *cobra.Command, args []string) {\n ctx := context.Background()\n store.GetIssues(ctx, ...)\n}\n\n// After \nRun: func(cmd *cobra.Command, args []string) {\n // ctx comes from parent signal-aware context\n store.GetIssues(ctx, ...)\n}\n```\n\n## Files to Update\n- All cmd/bd/*.go command handlers\n- Ensure context flows from main -\u003e cobra -\u003e handlers -\u003e storage\n\n## Benefits\n- Commands respect cancellation signals\n- Consistent context handling\n- Enables timeouts and deadlines\n\n## Acceptance Criteria\n- [ ] All command handlers use propagated context\n- [ ] No new context.Background() calls in command handlers\n- [ ] Context flows from signal handler to storage layer","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-11-20T21:27:02.854242-05:00","updated_at":"2025-11-20T21:37:32.44525-05:00","closed_at":"2025-11-20T21:37:32.44525-05:00","source_repo":".","dependencies":[{"issue_id":"bd-yb8","depends_on_id":"bd-rtp","type":"blocks","created_at":"2025-11-20T21:27:02.854904-05:00","created_by":"daemon"}]} {"id":"bd-ybv5","content_hash":"52f6d2143a3e9d63937e7dee2cfb4055740132d3c0831c3e948210179336820f","title":"Refactor AGENTS.md to use external references","description":"Suggestion to use external references (e.g., \"ALWAYS REFER TO ./beads/prompt.md\") instead of including all instructions directly within AGENTS.md.\nReasons:\n1. Agents can follow external references.\n2. Prevents context pollution/stuffing in AGENTS.md as more tools append instructions.\n","status":"open","priority":3,"issue_type":"task","created_at":"2025-11-20T18:55:53.259144-05:00","updated_at":"2025-11-20T18:55:53.259144-05:00","source_repo":"."} {"id":"bd-ye0d","content_hash":"40962ef4e144b58167a07ae13458b40cedff3f3549fccab3a172ca908cd754bc","title":"troubleshoot GH#278 daemon exits every few secs","description":"","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-13T06:27:23.39509215-07:00","updated_at":"2025-11-13T06:27:23.39509215-07:00","source_repo":"."} @@ -673,7 +669,7 @@ {"id":"bd-yuf7","content_hash":"97e18d89914d698df5ec673d40ff980a87a29e1435a887ec2b5dd77d7d412a79","title":"bd config set succeeds but doesn't persist to config.toml","description":"Commands like `bd config set daemon.auto_push true` return \"Set daemon.auto_push = true\" but the config file is never created and `bd info --json | jq '.config'` returns null.\n\n**Steps to reproduce:**\n1. Run `bd config set daemon.auto_push true`\n2. See success message: \"Set daemon.auto_push = true\"\n3. Check `cat .beads/config.toml` β†’ file doesn't exist\n4. Check `bd info --json | jq '.config'` β†’ returns null\n\n**Expected:**\n- .beads/config.toml should be created with the setting\n- bd info should show the config value\n\n**Impact:**\nUsers can't enable auto-push/auto-commit via CLI as documented in AGENTS.md","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-08T01:14:58.726198-08:00","updated_at":"2025-11-08T01:17:41.377912-08:00","closed_at":"2025-11-08T01:17:41.377912-08:00","source_repo":"."} {"id":"bd-yvlc","content_hash":"7447f9c24de76b56a3e753619c20571c3ca4ec0fb69a12b917def9d9580b1854","title":"URGENT: main branch has failing tests (syncbranch migration error)","description":"The main branch has failing tests that are blocking CI for all PRs.\n\n## Problem\nAll syncbranch_test.go tests failing with:\n\"migration external_ref_column failed: failed to create index on external_ref: sqlite3: SQL logic error: no such table: main.issues\"\n\n## Evidence\n- Last 5 CI runs on main: ALL FAILED\n- Tests fail locally on current main (bd6dca5)\n- Affects: TestGet, TestSet, TestUnset in internal/syncbranch\n\n## Impact\n- Blocking all PR merges\n- CI shows red for all branches\n- Can't trust test results\n\n## Root Cause\nMigration order issue - trying to create index on external_ref column before the issues table exists, or before the external_ref column is added to the issues table.\n\n## Quick Fix Needed\nNeed to investigate migration order in internal/storage/sqlite/migrations.go and ensure:\n1. issues table is created first\n2. external_ref column is added to issues table\n3. THEN index on external_ref is created\n\nThis is CRITICAL - main should never have breaking tests.","design":"Investigation steps:\n1. Check internal/storage/sqlite/migrations.go\n2. Verify migration order and dependencies\n3. Look at external_ref_column migration specifically\n4. Ensure proper table/column creation before index\n5. Test fix locally with fresh database\n6. Push fix to main\n7. Verify CI passes","acceptance_criteria":"- All tests pass on main branch\n- CI is green\n- syncbranch_test.go tests all passing","status":"closed","priority":0,"issue_type":"bug","created_at":"2025-11-15T12:25:31.51688-08:00","updated_at":"2025-11-15T12:43:11.489612-08:00","closed_at":"2025-11-15T12:43:11.489612-08:00","source_repo":"."} {"id":"bd-yxy","content_hash":"690b6c0348a09a625425c83cd076dce7e1d3c050aae32624047336b9c416eeb2","title":"Add command injection prevention tests for git rm in merge command","description":"Test coverage gap identified by automated analysis (vc-217).\n\n**Original Issue:** [deleted:bd-da96-baseline-lint]\n\nIn cmd/bd/merge.go:121, exec.Command is called with variable fullPath, flagged by gosec G204 for potential command injection.\n\nAdd tests covering:\n- File paths with shell metacharacters (;, |, \u0026, $, etc.)\n- Paths with spaces and special characters\n- Paths attempting command injection (e.g., 'file; rm -rf /')\n- Validation that fullPath is properly sanitized\n- Only valid git-tracked files can be removed\n\nThis is a critical security path preventing arbitrary command execution.\n\n_This issue was automatically created by AI test coverage analysis._","status":"closed","priority":0,"issue_type":"task","created_at":"2025-11-21T10:25:33.531631-05:00","updated_at":"2025-11-23T16:05:29.741791-08:00","closed_at":"2025-11-21T19:31:21.853136-05:00","source_repo":".","labels":["discovered:supervisor"],"dependencies":[{"issue_id":"bd-yxy","depends_on_id":"bd-da96-baseline-lint","type":"discovered-from","created_at":"2025-11-21T10:25:33.533126-05:00","created_by":"ai-supervisor"}]} -{"id":"bd-z0yn","content_hash":"d642aa388f336290811fa0a5f8f7a546f676ca9727f0d21072300219bccf037b","title":"Channel isolation test - beads","description":"","notes":"Resetting stale in_progress status from old executor run (13 days old)","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-08T04:21:17.327983-08:00","updated_at":"2025-11-21T14:38:35.459782-05:00","source_repo":"."} +{"id":"bd-z0yn","content_hash":"d642aa388f336290811fa0a5f8f7a546f676ca9727f0d21072300219bccf037b","title":"Channel isolation test - beads","description":"","notes":"Resetting stale in_progress status from old executor run (13 days old)","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-08T04:21:17.327983-08:00","updated_at":"2025-11-23T17:20:17.499617-08:00","source_repo":"."} {"id":"bd-z3s3","content_hash":"24d99dc1a9a5f35af962137f5709d4b0f1b6a9ec91511c30a2517d790640cce8","title":"Create deployment scripts for GCP","description":"Automated provisioning scripts for GCP Compute Engine deployment.\n\nAcceptance Criteria:\n- Terraform/gcloud scripts\n- Static IP allocation\n- Firewall rules\n- NGINX reverse proxy config\n- TLS setup (Let's Encrypt)\n- Systemd service file\n\nFile: deployment/agent-mail/gcp/","status":"open","priority":3,"issue_type":"task","created_at":"2025-11-07T22:43:43.294839-08:00","updated_at":"2025-11-07T22:43:43.294839-08:00","source_repo":".","dependencies":[{"issue_id":"bd-z3s3","depends_on_id":"bd-9li4","type":"blocks","created_at":"2025-11-07T23:04:27.982336-08:00","created_by":"daemon"}]} {"id":"bd-z528","content_hash":"3f332e9997d2b7eb0af23885820df5f607fe08671a2615cadec941bbe7d36f68","title":"Prevent test pollution in production database","description":"The bd-vxdr cleanup revealed test issues were created during manual testing in the production workspace (Nov 2-4, template feature development).\n\n**Root cause:** Manual testing with `./bd create \"Test issue\"` pollutes the production .beads database.\n\n**Prevention strategies:**\n1. Use TEST_DB environment variable for manual testing\n2. Add warning when creating issues with \"Test\" prefix\n3. Improve developer docs about testing workflow\n4. Consider adding `bd test-mode` command for isolated testing","notes":"**Implementation completed:**\n\n1. βœ… Added warning when creating issues with \"Test\" prefix in production database\n - Shows yellow warning with ⚠ symbol\n - Suggests using BEADS_DB for isolated testing\n - Warning appears in create.go after title validation\n\n2. βœ… Documented BEADS_DB testing workflow in AGENTS.md\n - Added \"Testing Workflow\" section in Development Guidelines\n - Includes manual testing examples with BEADS_DB\n - Includes automated testing examples with t.TempDir()\n - Clear warning about not polluting production database\n\n3. ⚠️ Decided against bd test-mode command\n - BEADS_DB already provides simple, flexible isolation\n - Additional command would add complexity without much benefit\n - Current approach follows Unix philosophy (env vars for config)\n\n**Files modified:**\n- cmd/bd/create.go - Added Test prefix warning\n- AGENTS.md - Added Testing Workflow section\n\n**Testing:**\n- Verified warning appears when creating \"Test\" prefix issues\n- Verified BEADS_DB isolation works correctly\n- Built successfully with `go build`","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-07T16:07:28.255289-08:00","updated_at":"2025-11-07T23:18:08.386514-08:00","closed_at":"2025-11-07T22:43:28.669908-08:00","source_repo":"."} {"id":"bd-zbq2","content_hash":"56dfd7f2c09dafd232a1ae26063744c89a1ba317e50a3429ec19b73ee1402993","title":"bd export should verify JSONL line count matches database count","description":"After export completes, bd should verify that the JSONL file line count matches the number of issues exported. This would catch silent failures where the export appears to succeed but doesn't actually write all issues.\n\nReal-world scenario from VC project:\n- Ran direct SQL DELETE to remove 240 issues \n- Ran 'bd export -o .beads/issues.jsonl'\n- No error shown, appeared to succeed\n- But JSONL file was not updated (still had old line count)\n- Later session found all 240 issues still in JSONL\n- Had to repeat the cleanup\n\nIf export had verified line count, it would have immediately shown:\n Error: Export verification failed\n Expected: 276 issues\n JSONL file: 516 lines\n Mismatch indicates export failed to write all issues\n\nThis is especially important because:\n1. JSONL is source of truth in git\n2. Silent export failures cause data inconsistency\n3. Users assume export succeeded if no error shown\n4. The verification is cheap (just count lines)\n\nImplementation:\n- After writing JSONL, count lines in file\n- Compare to len(exportedIDs)\n- If mismatch, remove temp file and return error\n- Show clear error message with both counts","design":"In cmd/bd/export.go, after atomic rename (line ~301):\n\n1. Count lines in final JSONL file:\n - Read file and count newlines\n - Or reuse countIssuesInJSONL() helper (already exists)\n\n2. Compare to len(exportedIDs)\n\n3. If mismatch:\n - Log error with both counts\n - Optionally: remove the bad JSONL file (or leave for debugging?)\n - Return error (exit 1)\n\n4. Consider adding --skip-verify flag for edge cases\n\nEdge cases:\n- Partial line writes (corrupted file)\n- File system issues\n- Race conditions (another process modifying JSONL during export)\n\nThe countIssuesInJSONL() function already exists at line 20, can reuse it.","acceptance_criteria":"1. bd export verifies JSONL line count after write\n2. Clear error shown if mismatch detected\n3. Test case that simulates partial write failure\n4. Does not affect export performance significantly (line counting is fast)","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-11-05T14:24:56.278249-08:00","updated_at":"2025-11-05T15:09:41.636141-08:00","closed_at":"2025-11-05T14:31:24.494885-08:00","source_repo":"."} @@ -685,4 +681,4 @@ {"id":"bd-zpnq","content_hash":"e96e651c806b522dfc4dfffe17f44e75a5a690bd6fcfe4c6471920e4a715103e","title":"Daemons don't exit when parent process dies, causing accumulation and race conditions","description":"Multiple daemon processes accumulate over time because daemons don't automatically stop when their parent process (e.g., coding agent) is killed. This causes:\n\n1. Race conditions: 8+ daemons watching same .beads/beads.db, each with own 30s debounce timer\n2. Git conflicts: Multiple daemons racing to commit/push .beads/issues.jsonl\n3. Resource waste: Orphaned daemons from sessions days/hours old still running\n\nExample: User had 8 daemons from multiple sessions (12:37AM, 7:20PM, 7:22PM, 7:47PM, 9:19PM yesterday + 9:54AM, 10:55AM today).\n\nSolutions to consider:\n1. Track parent PID and exit when parent dies\n2. Use single global daemon instead of per-session\n3. Document manual cleanup: pkill -f \"bd daemon\"\n4. Add daemon lifecycle management (auto-cleanup of stale daemons)","notes":"Implementation complete:\n\n1. Added ParentPID field to DaemonLockInfo struct (stored in daemon.lock JSON)\n2. Daemon now tracks parent PID via os.Getppid() at startup\n3. Both event loops (polling and event-driven) check parent process every 10 seconds\n4. Daemon gracefully exits if parent process dies (detected via isProcessRunning check)\n5. Handles edge cases:\n - ParentPID=0: Older daemons without tracking (ignored)\n - ParentPID=1: Adopted by init means parent died (exits)\n - Otherwise checks if parent process is still running\n\nThe fix prevents daemon accumulation by ensuring orphaned daemons automatically exit within 10 seconds of parent death.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-07T18:48:41.65456-08:00","updated_at":"2025-11-07T18:53:26.382573-08:00","closed_at":"2025-11-07T18:53:26.382573-08:00","source_repo":"."} {"id":"bd-zqmb","content_hash":"252347e3b30b33a1d0529e9d4e3c4c5402f5e32449967f704b7fc9ec09f02c0d","title":"Fix goroutine leak in daemon restart","description":"Fire-and-forget goroutine in daemon restart leaks on every restart.\n\nLocation: cmd/bd/daemons.go:251\n\nProblem:\ngo func() { _ = daemonCmd.Wait() }()\n\n- Spawns goroutine without timeout or cancellation\n- If daemon command never completes, goroutine leaks forever\n- Each daemon restart leaks one more goroutine\n\nSolution: Add timeout and cleanup:\ngo func() {\n done := make(chan struct{})\n go func() {\n _ = daemonCmd.Wait()\n close(done)\n }()\n \n select {\n case \u003c-done:\n // Exited normally\n case \u003c-time.After(10 * time.Second):\n // Timeout - daemon should have forked by now\n _ = daemonCmd.Process.Kill()\n }\n}()\n\nImpact: Goroutine leak on every daemon restart\n\nEffort: 2 hours","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-16T14:52:01.897215-08:00","updated_at":"2025-11-16T15:04:00.497517-08:00","closed_at":"2025-11-16T15:04:00.497517-08:00","source_repo":"."} {"id":"bd-zwpw","content_hash":"f08173f44c8454bf15b265aa9d3242004e7ee2bc25867b02676746154a9cc6fe","title":"Test dependency child","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-05T11:23:05.998311-08:00","updated_at":"2025-11-05T11:23:30.389454-08:00","closed_at":"2025-11-05T11:23:30.389454-08:00","source_repo":".","dependencies":[{"issue_id":"bd-zwpw","depends_on_id":"bd-k0j9","type":"blocks","created_at":"2025-11-05T11:23:05.998981-08:00","created_by":"daemon"}]} -{"id":"bd-zwtq","content_hash":"40629a1be3372b82bd3e0d65f99106465631bb0b7a2b8a8bf16c0c3ee0c274b0","title":"Run bd doctor at end of bd init to verify setup","description":"Run bd doctor diagnostics at end of bd init (after line 398 in init.go). If issues found, warn user immediately: '⚠ Setup incomplete. Run bd doctor --fix to complete setup.' Catches configuration problems before user encounters them in normal workflow.","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-11-21T23:16:09.596778-08:00","updated_at":"2025-11-23T19:18:30.349125-08:00","closed_at":"2025-11-23T19:18:30.349125-08:00","source_repo":".","dependencies":[{"issue_id":"bd-zwtq","depends_on_id":"bd-tbz3","type":"parent-child","created_at":"2025-11-21T23:16:09.597617-08:00","created_by":"daemon"}]} +{"id":"bd-zwtq","content_hash":"612e24033ea5e95b977146c46b6973a99b62801df859b2d841ad1bdb620d9274","title":"Run bd doctor at end of bd init to verify setup","description":"Run bd doctor diagnostics at end of bd init (after line 398 in init.go). If issues found, warn user immediately: '⚠ Setup incomplete. Run bd doctor --fix to complete setup.' Catches configuration problems before user encounters them in normal workflow.","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-11-21T23:16:09.596778-08:00","updated_at":"2025-11-23T19:18:30.349125-08:00","closed_at":"2025-11-23T19:18:30.349125-08:00","source_repo":".","dependencies":[{"issue_id":"bd-zwtq","depends_on_id":"bd-tbz3","type":"parent-child","created_at":"2025-11-21T23:16:09.597617-08:00","created_by":"daemon"}]}