diff --git a/.beads/beads.jsonl b/.beads/beads.jsonl index 65fa4247..b65eb620 100644 --- a/.beads/beads.jsonl +++ b/.beads/beads.jsonl @@ -49,7 +49,7 @@ {"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"]} +{"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":26,"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-24T05:37:42Z"}]} {"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"}]} @@ -60,7 +60,7 @@ {"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":"."} +{"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":27,"issue_id":"bd-23a8","author":"stevey","text":"Testing the new bd comment alias!","created_at":"2025-11-24T05:37:42Z"},{"id":28,"issue_id":"bd-23a8","author":"stevey","text":"Another test with JSON output","created_at":"2025-11-24T05:37:42Z"},{"id":29,"issue_id":"bd-23a8","author":"stevey","text":"Test comment from file\n","created_at":"2025-11-24T05:37:42Z"}]} {"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"]} @@ -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":"."} +{"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":30,"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-24T05:37:42Z"},{"id":31,"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-24T05:37:42Z"}]} {"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":"."} @@ -174,8 +174,8 @@ {"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":"."} -{"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-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":32,"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-24T05:37:42Z"}]} +{"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":33,"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-24T05:37:42Z"}]} {"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"}]} +{"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":34,"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-24T05:37:42Z"}]} {"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"]} +{"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":35,"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-24T05:37:42Z"}]} {"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,10 +308,10 @@ {"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"}]} +{"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":36,"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-24T05:37:42Z"}]} {"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"}]} +{"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":37,"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-24T05:37:42Z"}]} {"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":"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"}]} @@ -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"]} +{"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":38,"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-24T05:37:42Z"}]} {"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"}]} @@ -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":"."} +{"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":39,"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-24T05:37:42Z"}]} {"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"}]} @@ -507,7 +507,7 @@ {"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":"."} +{"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":40,"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-24T05:37:42Z"}]} {"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":"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"}]} @@ -522,7 +522,7 @@ {"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":"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":"."} +{"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":41,"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-24T05:37:42Z"},{"id":42,"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-24T05:37:42Z"}]} {"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"]} +{"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":43,"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-24T05:37:42Z"}]} {"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"}]}