From f4a2f87affb46438d7f5f164173b3d54042fa383 Mon Sep 17 00:00:00 2001 From: Steve Yegge Date: Wed, 12 Nov 2025 12:46:27 -0800 Subject: [PATCH] Fix #274: Add automatic .beads/.gitignore upgrade (#300) * Fix #274: Add automatic .beads/.gitignore upgrade Implements three mechanisms to ensure users get updated gitignore: 1. bd doctor --fix: Manually upgrade gitignore 2. Daemon auto-upgrade: Upgrades on startup if outdated 3. bd init idempotent: Safe to re-run, always updates gitignore The gitignore template now lives in cmd/bd/doctor/gitignore.go for consistent updates across all three mechanisms. Fixes: #274 * Remove test binary Amp-Thread-ID: https://ampcode.com/threads/T-7042cfcc-ac97-43d7-a40f-3fa1bb4e1c2b Co-authored-by: Amp * Fix critical issues: remove merge artifact and apply gitignore template - Remove .beads/beads.left.jsonl (merge artifact that shouldn't be committed) - Apply new gitignore template to .beads/.gitignore (was missing patterns) Amp-Thread-ID: https://ampcode.com/threads/T-7042cfcc-ac97-43d7-a40f-3fa1bb4e1c2b Co-authored-by: Amp * bd sync: 2025-11-12 11:09:30 * Retrigger CI Amp-Thread-ID: https://ampcode.com/threads/T-8d532264-6d5e-4b68-88e9-e4511851b64a Co-authored-by: Amp * Fix duplicate DoctorCheck type definition * Trigger CI after fixing type conflict Amp-Thread-ID: https://ampcode.com/threads/T-8d532264-6d5e-4b68-88e9-e4511851b64a Co-authored-by: Amp --------- Co-authored-by: Amp --- .beads/.gitignore | 15 ++++-- .beads/beads.jsonl | 63 +++++++++++----------- cmd/bd/daemon.go | 12 +++++ cmd/bd/doctor.go | 42 ++++++++++++++- cmd/bd/doctor/gitignore.go | 104 +++++++++++++++++++++++++++++++++++++ cmd/bd/init.go | 41 +++------------ 6 files changed, 204 insertions(+), 73 deletions(-) create mode 100644 cmd/bd/doctor/gitignore.go diff --git a/.beads/.gitignore b/.beads/.gitignore index 2bd10629..f438450f 100644 --- a/.beads/.gitignore +++ b/.beads/.gitignore @@ -1,5 +1,6 @@ # SQLite databases *.db +*.db?* *.db-journal *.db-wal *.db-shm @@ -14,11 +15,15 @@ bd.sock db.sqlite bd.db +# Merge artifacts (temporary files from 3-way merge) +beads.base.jsonl +beads.base.meta.json +beads.left.jsonl +beads.left.meta.json +beads.right.jsonl +beads.right.meta.json + # Keep JSONL exports and config (source of truth for git) -!*.jsonl +!issues.jsonl !metadata.json !config.json - -# 3-way merge snapshot files (local-only, for deletion tracking) -beads.base.jsonl -beads.left.jsonl diff --git a/.beads/beads.jsonl b/.beads/beads.jsonl index 99947a5a..0ae2b5ae 100644 --- a/.beads/beads.jsonl +++ b/.beads/beads.jsonl @@ -13,7 +13,7 @@ {"id":"bd-09b5f2f5","content_hash":"02c69c90dc76c4982976362b9cb00ce01bc3fc3d17618feec3a02bab6fa4d196","title":"Daemon fails to auto-import after git pull updates JSONL","description":"After git pull updates .beads/issues.jsonl, daemon doesn't automatically re-import changes, causing stale data to be shown until next sync cycle (up to 5 minutes).\n\nReproduction:\n1. Repo A: Close issues, export, commit, push\n2. Repo B: git pull (successfully updates .beads/issues.jsonl)\n3. bd show \u003cissue\u003e shows OLD status from daemon's SQLite db\n4. JSONL on disk has correct new status\n\nRoot cause: Daemon sync cycle runs on timer (5min). When user manually runs git pull, daemon doesn't detect JSONL was updated externally and continues serving stale data from SQLite.\n\nImpact:\n- High for AI agents using beads in git workflows\n- Breaks fundamental git-as-source-of-truth model\n- Confusing UX: git log shows commit, bd shows old state\n- Data consistency issues between JSONL and daemon\n\nSee WYVERN_SYNC_ISSUE.md for full analysis.","design":"Three possible solutions:\n\nOption 1: Auto-detect and re-import (recommended)\n- Before serving any bd command, check if .beads/issues.jsonl mtime \u003e last import time\n- If newer, auto-import before processing request\n- Fast check, minimal overhead\n\nOption 2: File watcher in daemon\n- Daemon watches .beads/issues.jsonl for mtime changes\n- Auto-imports when file changes\n- More complex, requires file watching infrastructure\n\nOption 3: Explicit sync command\n- User runs `bd sync` after git pull\n- Manual, error-prone, defeats automation\n\nRecommended: Option 1 (auto-detect) + Option 3 (explicit sync) as fallback.","acceptance_criteria":"1. After git pull updates .beads/issues.jsonl, next bd command sees fresh data\n2. No manual import or daemon restart required\n3. Performance impact \u003c 10ms per command (mtime check is fast)\n4. Works in both daemon and non-daemon modes\n5. Test: Two repo clones, update in one, pull in other, verify immediate sync","notes":"**Fixed in v0.21.2!**\n\nThe daemon auto-import is fully implemented:\n- internal/autoimport package handles staleness detection\n- internal/importer package provides shared import logic (used by both CLI and daemon)\n- daemon's checkAndAutoImportIfStale() calls autoimport.AutoImportIfNewer()\n- importFunc uses importer.ImportIssues() with auto-rename enabled\n- All tests passing\n\nThe critical data corruption bug is FIXED:\n✅ After git pull, daemon detects JSONL is newer (mtime check)\n✅ Daemon auto-imports before serving requests\n✅ No stale data served\n✅ No data loss in multi-agent workflows\n\nVerification needed: Run two-repo test to confirm end-to-end behavior.","status":"closed","priority":0,"issue_type":"epic","created_at":"2025-10-25T23:13:12.270766-07:00","updated_at":"2025-11-01T16:52:50.931197-07:00","closed_at":"2025-11-01T16:52:50.931197-07:00","source_repo":"."} {"id":"bd-0a90","content_hash":"8f19f9a9e01ccf3a4dd42673a84610f2550db9a9e744806105dc3b9e070f4e46","title":"bd show --json doesn't include dependency type field","description":"Fix GitHub issue #202. The JSON output from bd show and bd list commands should include the dependency type field (and optionally created_at, created_by) to match internal storage format and enable better tooling integration.","notes":"PR #203 updated with cleaner implementation: https://github.com/steveyegge/beads/pull/203\n\n## Final Implementation\n\nCleanest possible approach - no internal helper methods needed:\n\n**Design:**\n- `GetDependenciesWithMetadata()` / `GetDependentsWithMetadata()` - canonical implementations with full SQL query\n- `GetDependencies()` / `GetDependents()` - thin wrappers that strip metadata for backward compat\n- `scanIssuesWithDependencyType()` - shared helper for scanning rows with dependency type\n\n**Benefits:**\n- Single source of truth - the `...WithMetadata()` methods ARE the implementation\n- Eliminated ~139 lines of duplicated SQL and scanning code\n- All tests passing (14 dependency-related tests)\n- Backward compatible\n- dependency_type field appears correctly in JSON output\n\n**Note on scan helpers:**\nThe duplication between `scanIssues()` and `scanIssuesWithDependencyType()` is necessary because they handle different SQL result shapes (16 vs 17 columns). This is justified as they serve fundamentally different purposes based on query structure.","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-11-02T09:42:08.712725096Z","updated_at":"2025-11-02T11:50:54.292546-08:00","closed_at":"2025-11-02T11:50:54.292546-08:00","external_ref":"https://github.com/steveyegge/beads/issues/202","source_repo":"."} {"id":"bd-0d9c","content_hash":"a61ba371d6c50f21a92e4debeaaa00a4c3eb77ef96fbcdfa89f80e9b13ffff7a","title":"YABB: Spurious issue updates during normal operations","description":"Issue bd-627d was updated during config refactoring session without any actual changes to it. Only timestamps and content_hash changed.\n\nObserved: Running various bd commands (list, create, etc.) caused bd-627d updated_at to change from 14:14 to 14:31.\n\nExpected: Issues should only be updated when explicitly modified.\n\nThis causes:\n- Dirty JSONL after every session\n- False conflicts in git\n- Confusing git history\n\nLikely culprit: Daemon auto-import/export cycle or database migration touching all issues.","notes":"Investigated thoroughly - unable to reproduce. The import logic has IssueDataChanged() checks before calling UpdateIssue (importer/importer.go:458). All tests pass. May have been fixed by recent refactorings. Closing as cannot reproduce - please reopen with specific repro steps if it occurs again.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-02T14:36:31.023552-08:00","updated_at":"2025-11-02T16:27:39.023535-08:00","closed_at":"2025-11-02T16:27:39.023539-08:00","source_repo":"."} -{"id":"bd-0dcea000","content_hash":"5f3eccf8635195729691e83818486c31c81e608d939e03a2241f944f645ce90d","title":"Add tests for internal/importer package","description":"Currently 0.0% coverage. Need tests for JSONL import logic including collision detection and resolution.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-29T14:06:21.071024-07:00","updated_at":"2025-11-08T18:06:20.150657-08:00","closed_at":"2025-11-08T18:06:20.150657-08:00","source_repo":".","dependencies":[{"issue_id":"bd-0dcea000","depends_on_id":"bd-cbed9619.5","type":"blocks","created_at":"2025-10-29T19:52:05.531279-07:00","created_by":"import-remap"},{"issue_id":"bd-0dcea000","depends_on_id":"bd-cbed9619.4","type":"blocks","created_at":"2025-10-29T19:52:05.53166-07:00","created_by":"import-remap"}]} +{"id":"bd-0dcea000","content_hash":"a6fc218b07d270e3498957525c39a869f7c850d687339b6d758a246be20c9591","title":"Add tests for internal/importer package","description":"Currently 0.0% coverage. Need tests for JSONL import logic including collision detection and resolution.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-29T14:06:21.071024-07:00","updated_at":"2025-11-08T18:06:20.150657-08:00","closed_at":"2025-11-08T18:06:20.150657-08:00","source_repo":".","dependencies":[{"issue_id":"bd-0dcea000","depends_on_id":"bd-cbed9619.5","type":"blocks","created_at":"2025-10-29T19:52:05.531279-07:00","created_by":"import-remap"},{"issue_id":"bd-0dcea000","depends_on_id":"bd-cbed9619.4","type":"blocks","created_at":"2025-10-29T19:52:05.53166-07:00","created_by":"import-remap"}]} {"id":"bd-0do3","content_hash":"e6d85ab6360e5704e3d6792eade15bbec8d19d13b878c15e4021f3375cb3d515","title":"Test issue 0","description":"","status":"closed","priority":0,"issue_type":"task","created_at":"2025-11-07T19:00:15.156832-08:00","updated_at":"2025-11-07T22:07:17.340826-08:00","closed_at":"2025-11-07T21:55:09.425092-08:00","source_repo":"."} {"id":"bd-0e1f2b1b","content_hash":"c0b1677fe3f4aa3f395ae4d79bff5362632d5db26477bf571c09f9177b8741ef","title":"Event-driven daemon architecture","description":"Replace 5-second polling sync loop with event-driven architecture that reacts instantly to changes. Eliminates stale data issues while reducing CPU ~60%. Key components: FileWatcher (fsnotify), Debouncer (500ms), RPC mutation events, optional git hooks. Target latency: \u003c500ms (vs 5000ms). See event_driven_daemon.md for full design.","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-10-28T16:20:02.430479-07:00","updated_at":"2025-10-30T17:12:58.221424-07:00","closed_at":"2025-10-28T16:30:26.631191-07:00","source_repo":"."} {"id":"bd-0e74","content_hash":"d8ab25b7a6ac1ba0e5012677cac3ac1320d3ca1059df97c979aab8c43ecb579d","title":"Comprehensive testing for separate branch workflow","description":"Comprehensive testing for separate branch workflow including unit tests, integration tests, and performance testing.\n\nTasks:\n- Unit tests for worktree management\n- Unit tests for config parsing\n- Integration tests: create/update/close → beads branch\n- Integration test: merge beads → main\n- Integration test: protected branch scenario\n- Integration test: network failure recovery\n- Integration test: config change handling\n- Manual testing guide\n- Performance testing (worktree overhead)\n\nTest scenarios: fresh setup, issue operations, merge workflow, protected branch, error handling, migration, multiple workspaces, sparse checkout\n\nEstimated effort: 4-5 days","acceptance_criteria":"- All unit tests pass\n- All integration tests pass\n- Manual testing guide works\n- No data loss in any scenario\n- Performance acceptable (\u003c 100ms overhead per commit)","notes":"Completed comprehensive test coverage. Added 4 new integration tests: config change handling, multiple concurrent clones (3-way), performance testing (avg 77ms \u003c 150ms target), and network failure recovery. All tests pass. Coverage includes fresh setup, issue ops, error handling, multiple workspaces, sparse checkout, config changes, network failures, and performance.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-02T15:22:35.580741-08:00","updated_at":"2025-11-02T21:40:35.337464-08:00","closed_at":"2025-11-02T21:40:35.337468-08:00","source_repo":".","dependencies":[{"issue_id":"bd-0e74","depends_on_id":"bd-a101","type":"parent-child","created_at":"2025-11-02T15:22:51.348226-08:00","created_by":"stevey"}]} @@ -28,7 +28,7 @@ {"id":"bd-1445","content_hash":"b3272105f48a2b0f11d2cf669d3e7e5c93a5e6c491cbabddf16872966618de0a","title":"Create shared insert/event/dirty helpers","description":"Create issues.go (insertIssue/insertIssues), events.go (recordCreatedEvent/recordCreatedEvents), dirty.go (markDirty/markDirtyBatch). Refactor single and bulk create paths to use these.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-01T11:41:14.882142-07:00","updated_at":"2025-11-02T15:28:11.99706-08:00","closed_at":"2025-11-02T15:28:11.997063-08:00","source_repo":"."} {"id":"bd-149","content_hash":"4865a0eaf982fedd744f824f990037f40763be2a133e4c3bb4e28971f8372428","title":"Auth tokens expire too quickly","description":"## Summary\n\n[Brief description of the bug]\n\n## Steps to Reproduce\n\n1. Step 1\n2. Step 2\n3. Step 3\n\n## Expected Behavior\n\n[What should happen]\n\n## Actual Behavior\n\n[What actually happens]\n\n## Environment\n\n- OS: [e.g., macOS 15.7.1]\n- Version: [e.g., bd 0.20.1]\n- Additional context: [any relevant details]\n\n## Additional Context\n\n[Screenshots, logs, or other relevant information]\n","design":"## Root Cause Analysis\n\n[Describe the underlying cause once identified]\n\n## Proposed Fix\n\n[Outline the solution approach]\n\n## Impact Assessment\n\n- Affected features: [list]\n- Breaking changes: [yes/no and details]\n- Migration needed: [yes/no and details]\n","acceptance_criteria":"- [ ] Bug no longer reproduces with original steps\n- [ ] Regression tests added\n- [ ] Related edge cases tested\n- [ ] Documentation updated if behavior changed\n","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-03T19:54:10.671488-08:00","updated_at":"2025-11-05T00:25:06.427601-08:00","closed_at":"2025-11-05T00:25:06.427601-08:00","source_repo":".","labels":["bug"]} {"id":"bd-164b","content_hash":"5cddac4d59502d1a6b3999f2dd85e1719389c8f9ea15f3515a62d52049d03645","title":"Add template support for issue creation","description":"Support creating issues from predefined templates to streamline common workflows like epics, bug reports, or feature proposals.\n\nExample usage:\n bd create --from-template epic \"Phase 3 Features\"\n bd create --from-template bug \"Login failure\"\n bd template list\n bd template create epic\n\nTemplates should include:\n- Pre-filled description structure\n- Suggested priority and type\n- Common labels\n- Design/acceptance criteria sections\n\nImplementation notes:\n- Store templates in .beads/templates/ directory\n- Support YAML or JSON format\n- Ship with built-in templates (epic, bug, feature)\n- Allow custom project-specific templates","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-11-03T18:10:18.985902-08:00","updated_at":"2025-11-03T19:56:41.287303-08:00","closed_at":"2025-11-03T19:56:41.287303-08:00","source_repo":"."} -{"id":"bd-17d5","content_hash":"a0e9affb9666bb33ffb26aa9aab151a80b94b37578667aa439bbcccd842243ef","title":"bd sync false positive: conflict detection triggers on JSON-encoded angle brackets in issue content","description":"The bd sync --import-only command incorrectly detects conflict markers when issue descriptions contain the text '\u003c\u003c\u003c\u003c\u003c\u003c\u003c' or '\u003e\u003e\u003e\u003e\u003e\u003e\u003e' as legitimate content (e.g., documentation about git conflict markers).\n\n**Reproduction:**\n1. Create issue with design field containing: 'Read file, extract \u003c\u003c\u003c\u003c\u003c\u003c\u003c / ======= / \u003e\u003e\u003e\u003e\u003e\u003e\u003e markers'\n2. Export to JSONL (gets JSON-encoded as \\u003c\\u003c\\u003c...)\n3. Commit and push\n4. Pull from remote\n5. bd sync --import-only fails with: 'Git conflict markers detected in JSONL file'\n\n**Root cause:**\nThe conflict detection appears to decode JSON before checking for conflict markers, causing false positives when issue content legitimately contains these strings.\n\n**Expected behavior:**\nConflict detection should only trigger on actual git conflict markers (literal '\u003c\u003c\u003c\u003c\u003c\u003c\u003c' bytes in the raw file), not on JSON-encoded content within issue fields.\n\n**Test case:**\nVC project at ~/src/dave/vc has vc-85 'JSONL Conflict Parser' which documents conflict parsing and triggers this bug.\n\n**Suggested fixes:**\n1. Only scan for literal '\u003c\u003c\u003c\u003c\u003c\u003c\u003c' bytes (not decoded JSON content)\n2. Parse JSONL first and only flag unparseable lines\n3. Check git merge state (git status) to confirm actual conflict\n4. Add --skip-conflict-check flag for override","acceptance_criteria":"- bd sync works with vc-85 issue in VC project\n- Conflict detection only triggers on actual git conflict markers\n- False positives eliminated for legitimate issue content\n- Regression test added with conflict marker text in issue description","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-08T13:02:54.730745-08:00","updated_at":"2025-11-08T13:07:37.108225-08:00","closed_at":"2025-11-08T13:07:37.108225-08:00","source_repo":"."} +{"id":"bd-17d5","content_hash":"2ab13adb479424b0c7e9a090534f631b0dfb9139c529eca881d166b80a205419","title":"bd sync false positive: conflict detection triggers on JSON-encoded angle brackets in issue content","description":"The bd sync --import-only command incorrectly detects conflict markers when issue descriptions contain the text '\u003c\u003c\u003c\u003c\u003c\u003c\u003c' or '\u003e\u003e\u003e\u003e\u003e\u003e\u003e' as legitimate content (e.g., documentation about git conflict markers).\n\n**Reproduction:**\n1. Create issue with design field containing: 'Read file, extract \u003c\u003c\u003c\u003c\u003c\u003c\u003c / ======= / \u003e\u003e\u003e\u003e\u003e\u003e\u003e markers'\n2. Export to JSONL (gets JSON-encoded as \\u003c\\u003c\\u003c...)\n3. Commit and push\n4. Pull from remote\n5. bd sync --import-only fails with: 'Git conflict markers detected in JSONL file'\n\n**Root cause:**\nThe conflict detection appears to decode JSON before checking for conflict markers, causing false positives when issue content legitimately contains these strings.\n\n**Expected behavior:**\nConflict detection should only trigger on actual git conflict markers (literal '\u003c\u003c\u003c\u003c\u003c\u003c\u003c' bytes in the raw file), not on JSON-encoded content within issue fields.\n\n**Test case:**\nVC project at ~/src/dave/vc has vc-85 'JSONL Conflict Parser' which documents conflict parsing and triggers this bug.\n\n**Suggested fixes:**\n1. Only scan for literal '\u003c\u003c\u003c\u003c\u003c\u003c\u003c' bytes (not decoded JSON content)\n2. Parse JSONL first and only flag unparseable lines\n3. Check git merge state (git status) to confirm actual conflict\n4. Add --skip-conflict-check flag for override","acceptance_criteria":"- bd sync works with vc-85 issue in VC project\n- Conflict detection only triggers on actual git conflict markers\n- False positives eliminated for legitimate issue content\n- Regression test added with conflict marker text in issue description","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-08T13:02:54.730745-08:00","updated_at":"2025-11-08T13:07:37.108225-08:00","closed_at":"2025-11-08T13:07:37.108225-08:00","source_repo":"."} {"id":"bd-17fa2d21","content_hash":"b909e616bec8d75eaf6ab0c2deb90ad047740d44892194afeaa5deb07f15f43a","title":"Batch test 2","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-29T15:29:01.877052-07:00","updated_at":"2025-10-31T12:00:43.183657-07:00","closed_at":"2025-10-31T12:00:43.183657-07:00","source_repo":"."} {"id":"bd-1863608e","content_hash":"beec1c2a11e22fcdfb13b4436918e820038c76f6d873d59be616b415148e741e","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-0dcea000, bd-4d7fca8a 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-29T20:02:47.954306-07:00","updated_at":"2025-10-30T17:12:58.182217-07:00","closed_at":"2025-10-28T20:47:28.317007-07:00","source_repo":"."} {"id":"bd-197b","content_hash":"0077ab3305b0c5a4b8cc600b1a2f4f30b64a289e4674c3b90110ac537c3f8224","title":"Set up WASM build pipeline","description":"Configure Go→WASM compilation pipeline. Child of epic bd-44d0.\n\n## Tasks\n- [ ] Create build-wasm.sh script (GOOS=js GOARCH=wasm)\n- [ ] Test basic WASM module loading in Node.js\n- [ ] Set up wasm_exec.js wrapper\n- [ ] Add WASM build to CI/CD\n- [ ] Document build process\n\n## Validation\n- bd.wasm compiles successfully\n- Can load in Node.js without errors\n- Bundle size \u003c10MB","status":"closed","priority":0,"issue_type":"task","created_at":"2025-11-02T18:33:19.407373-08:00","updated_at":"2025-11-05T00:55:48.755936-08:00","closed_at":"2025-11-05T00:55:48.755941-08:00","source_repo":".","dependencies":[{"issue_id":"bd-197b","depends_on_id":"bd-44d0","type":"blocks","created_at":"2025-11-02T18:33:19.407904-08:00","created_by":"daemon"}]} @@ -46,12 +46,12 @@ {"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-1ls","content_hash":"af79708476d560abaac3cbe9c537bcf43c2100dcb1d676954ea604486f75d199","title":"Override test","description":"## Overview\n\n[Describe the high-level goal and scope of this epic]\n\n## Success Criteria\n\n- [ ] Criteria 1\n- [ ] Criteria 2\n- [ ] Criteria 3\n\n## Background\n\n[Provide context and motivation]\n\n## Scope\n\n**In Scope:**\n- Item 1\n- Item 2\n\n**Out of Scope:**\n- Item 1\n- Item 2\n","design":"## Architecture\n\n[Describe the overall architecture and approach]\n\n## Components\n\n- Component 1: [description]\n- Component 2: [description]\n\n## Dependencies\n\n[List external dependencies or constraints]\n","acceptance_criteria":"- [ ] All child issues are completed\n- [ ] Integration tests pass\n- [ ] Documentation is updated\n- [ ] Code review completed\n","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-03T20:15:10.01471-08:00","updated_at":"2025-11-03T22:07:10.946574-08:00","closed_at":"2025-11-03T22:07:10.946574-08:00","source_repo":".","labels":["epic"]} {"id":"bd-1mzt","content_hash":"3dffe5c0934f51c6fa526a952a975e808665d80e7c69dffbe910aabc87d32a7b","title":"Client self-heal: remove stale pid when lock free + socket missing","description":"When client detects:\n- Socket is missing AND\n- tryDaemonLock shows lock NOT held\n\nThen automatically:\n1. Remove stale daemon.pid file\n2. Optionally auto-start daemon (behind BEADS_AUTO_START_DAEMON=1 env var)\n\nThis prevents stale artifacts from accumulating after daemon crashes.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-07T16:42:12.75205-08:00","updated_at":"2025-11-07T22:07:17.342845-08:00","closed_at":"2025-11-07T21:21:15.317562-08:00","source_repo":".","dependencies":[{"issue_id":"bd-1mzt","depends_on_id":"bd-ndyz","type":"discovered-from","created_at":"2025-11-07T16:42:12.753099-08:00","created_by":"daemon"}]} -{"id":"bd-1nrn","content_hash":"bc091a6fed46130e6cb791c4d58c777b904e22f92cc6921d231053abf48c3c4b","title":"Issue 2 to reopen","description":"","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-07T19:04:20.157016-08:00","updated_at":"2025-11-08T02:06:34.746105-08:00","closed_at":"2025-11-08T02:06:34.746105-08:00","source_repo":"."} +{"id":"bd-1nrn","content_hash":"8aebd77c19946d60143f7b7f699d1bcf6e8792c347f6d7c41a2ffbba744bfa8e","title":"Issue 2 to reopen","description":"","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-07T19:04:20.157016-08:00","updated_at":"2025-11-08T02:06:34.746105-08:00","closed_at":"2025-11-08T02:06:34.746105-08:00","source_repo":"."} {"id":"bd-1vup","content_hash":"99df92e0d2e6f2998d9ef52c60ae1db55a2e52b84c3e935bf371517e5154ad77","title":"Test FK constraint via close","description":"","status":"closed","priority":4,"issue_type":"task","created_at":"2025-11-07T15:06:10.324045-08:00","updated_at":"2025-11-07T15:06:14.289835-08:00","closed_at":"2025-11-07T15:06:14.289835-08:00","source_repo":"."} {"id":"bd-1vv","content_hash":"1db907ddb55edaf7a4c06a566c4e1b8244fcd9ba5d7e2fca4d5c053e424ac515","title":"Add WebSocket support","description":"## Feature Request\n\n[Describe the desired feature]\n\n## Motivation\n\n[Why is this feature needed? What problem does it solve?]\n\n## Use Cases\n\n1. **Use Case 1**: [description]\n2. **Use Case 2**: [description]\n\n## Proposed Solution\n\n[High-level approach to implementing this feature]\n\n## Alternatives Considered\n\n- **Alternative 1**: [description and why not chosen]\n- **Alternative 2**: [description and why not chosen]\n","design":"## Technical Design\n\n[Detailed technical approach]\n\n## API Changes\n\n[New commands, flags, or APIs]\n\n## Data Model Changes\n\n[Database schema changes if any]\n\n## Implementation Notes\n\n- Note 1\n- Note 2\n\n## Testing Strategy\n\n- Unit tests: [scope]\n- Integration tests: [scope]\n- Manual testing: [steps]\n","acceptance_criteria":"- [ ] Feature implements all described use cases\n- [ ] All tests pass\n- [ ] Documentation updated (README, commands)\n- [ ] Examples added if applicable\n- [ ] No performance regressions\n","status":"open","priority":2,"issue_type":"feature","created_at":"2025-11-03T19:56:41.271215-08:00","updated_at":"2025-11-03T19:56:41.271215-08:00","source_repo":".","labels":["feature"]} {"id":"bd-1yi5","content_hash":"11044802d32a77f8ca574ca5902939bcc7e252880437bea7281aaf445db8db84","title":"Use -short flag in CI for PR checks","description":"Update CI configuration to use -short flag for PR checks, run full tests nightly.\n\nThe slow tests already support testing.Short() and will be skipped.\n\nExpected savings: ~20 seconds for PR checks (fast tests only)\n\nImplementation:\n- Update .github/workflows/ci.yml to add -short flag for PR tests\n- Create/update nightly workflow for full test runs\n- Update README/docs about test strategy\n\nFile: .github/workflows/ci.yml:30","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-04T01:24:17.279618-08:00","updated_at":"2025-11-04T10:25:10.616119-08:00","closed_at":"2025-11-04T10:25:10.616119-08:00","source_repo":".","dependencies":[{"issue_id":"bd-1yi5","depends_on_id":"bd-l5gq","type":"blocks","created_at":"2025-11-04T01:24:17.280453-08:00","created_by":"daemon"}]} {"id":"bd-22e0bde9","content_hash":"532c3b7af57bcf046114e2a3e9519fd07729251b3e81450a772d75d920d63e5d","title":"Add TestNWayCollision for 5+ clones","description":"## Overview\nAdd comprehensive tests for N-way (5+) collision resolution to verify the solution scales beyond 3 clones.\n\n## Purpose\nWhile TestThreeCloneCollision validates the basic N-way case, we need to verify:\n1. Solution scales to arbitrary N\n2. Performance is acceptable with more clones\n3. Convergence time is bounded\n4. No edge cases in larger collision groups\n\n## Implementation Tasks\n\n### 1. Create TestFiveCloneCollision\nFile: beads_twoclone_test.go (or new beads_nway_test.go)\n\n```go\nfunc TestFiveCloneCollision(t *testing.T) {\n // Test with 5 clones creating same ID with different content\n // Verify all 5 clones converge after sync rounds\n \n t.Run(\"SequentialSync\", func(t *testing.T) {\n testNCloneCollision(t, 5, \"A\", \"B\", \"C\", \"D\", \"E\")\n })\n \n t.Run(\"ReverseSync\", func(t *testing.T) {\n testNCloneCollision(t, 5, \"E\", \"D\", \"C\", \"B\", \"A\")\n })\n \n t.Run(\"RandomSync\", func(t *testing.T) {\n testNCloneCollision(t, 5, \"C\", \"A\", \"E\", \"B\", \"D\")\n })\n}\n```\n\n### 2. Implement generalized testNCloneCollision\nGeneralize the 3-clone test to handle arbitrary N:\n\n```go\nfunc testNCloneCollision(t *testing.T, numClones int, syncOrder ...string) {\n t.Helper()\n \n if len(syncOrder) != numClones {\n t.Fatalf(\"syncOrder length (%d) must match numClones (%d)\", \n len(syncOrder), numClones)\n }\n \n tmpDir := t.TempDir()\n \n // Setup remote and N clones\n remoteDir := setupBareRepo(t, tmpDir)\n cloneDirs := make(map[string]string)\n \n for i := 0; i \u003c numClones; i++ {\n name := string(rune('A' + i))\n cloneDirs[name] = setupClone(t, tmpDir, remoteDir, name)\n }\n \n // Each clone creates issue with same ID but different content\n for name, dir := range cloneDirs {\n createIssue(t, dir, fmt.Sprintf(\"Issue from clone %s\", name))\n }\n \n // Sync in specified order\n for _, name := range syncOrder {\n syncClone(t, cloneDirs[name], name)\n }\n \n // Final pull for convergence\n for name, dir := range cloneDirs {\n finalPull(t, dir, name)\n }\n \n // Verify all clones have all N issues\n expectedTitles := make(map[string]bool)\n for i := 0; i \u003c numClones; i++ {\n name := string(rune('A' + i))\n expectedTitles[fmt.Sprintf(\"Issue from clone %s\", name)] = true\n }\n \n for name, dir := range cloneDirs {\n titles := getTitles(t, dir)\n if !compareTitleSets(titles, expectedTitles) {\n t.Errorf(\"Clone %s missing issues: expected %v, got %v\", \n name, expectedTitles, titles)\n }\n }\n \n t.Log(\"✓ All\", numClones, \"clones converged successfully\")\n}\n```\n\n### 3. Add performance benchmarks\nTest convergence time and memory usage:\n\n```go\nfunc BenchmarkNWayCollision(b *testing.B) {\n for _, n := range []int{3, 5, 10, 20} {\n b.Run(fmt.Sprintf(\"N=%d\", n), func(b *testing.B) {\n for i := 0; i \u003c b.N; i++ {\n // Run N-way collision and measure time\n testNCloneCollisionBench(b, n)\n }\n })\n }\n}\n```\n\n### 4. Add convergence time tests\nVerify bounded convergence:\n\n```go\nfunc TestConvergenceTime(t *testing.T) {\n // Test that convergence happens within expected rounds\n // For N clones, should converge in at most N-1 sync rounds\n \n for n := 3; n \u003c= 10; n++ {\n t.Run(fmt.Sprintf(\"N=%d\", n), func(t *testing.T) {\n rounds := measureConvergenceRounds(t, n)\n maxExpected := n - 1\n if rounds \u003e maxExpected {\n t.Errorf(\"Convergence took %d rounds, expected ≤ %d\", \n rounds, maxExpected)\n }\n })\n }\n}\n```\n\n### 5. Add edge case tests\nTest boundary conditions:\n- All N clones have identical content (dedup works)\n- N-1 clones have same content, 1 differs\n- All N clones have unique content\n- Mix of collisions and non-collisions\n\n## Acceptance Criteria\n- TestFiveCloneCollision passes with all sync orders\n- All 5 clones converge to identical content\n- Performance is acceptable (\u003c 5 seconds for 5 clones)\n- Convergence time is bounded (≤ N-1 rounds)\n- Edge cases handled correctly\n- Benchmarks show scalability to 10+ clones\n\n## Files to Create/Modify\n- beads_twoclone_test.go or beads_nway_test.go\n- Add helper functions for N-clone setup\n\n## Testing Strategy\n\n### Test Matrix\n| N Clones | Sync Orders | Expected Result |\n|----------|-------------|-----------------|\n| 3 | A→B→C | Pass |\n| 3 | C→B→A | Pass |\n| 5 | A→B→C→D→E | Pass |\n| 5 | E→D→C→B→A | Pass |\n| 5 | Random | Pass |\n| 10 | Sequential | Pass |\n\n### Performance Targets\n- 3 clones: \u003c 2 seconds\n- 5 clones: \u003c 5 seconds\n- 10 clones: \u003c 15 seconds\n\n## Dependencies\n- Requires bd-cbed9619.5, bd-cbed9619.4, bd-cbed9619.3, bd-cbed9619.2 to be completed\n- TestThreeCloneCollision must pass first\n\n## Success Metrics\n- All tests pass for N ∈ {3, 5, 10}\n- Convergence time scales linearly (O(N))\n- Memory usage reasonable (\u003c 100MB for 10 clones)\n- No data corruption or loss in any scenario","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-29T23:05:13.974702-07:00","updated_at":"2025-10-31T12:00:43.197709-07:00","closed_at":"2025-10-31T12:00:43.197709-07:00","source_repo":"."} -{"id":"bd-23a8","content_hash":"7c54bea4624429ff0842a192489979e0a1eafdd872027a0934b1a1d9b0e80d33","title":"Test simple issue","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-02T17:11:04.464726-08:00","updated_at":"2025-11-04T11:10:23.529727-08:00","closed_at":"2025-11-04T11:10:23.529731-08:00","source_repo":".","comments":[{"id":1,"issue_id":"bd-23a8","author":"stevey","text":"Testing the new bd comment alias!","created_at":"2025-11-12T09:55:23Z"},{"id":2,"issue_id":"bd-23a8","author":"stevey","text":"Another test with JSON output","created_at":"2025-11-12T09:55:23Z"},{"id":3,"issue_id":"bd-23a8","author":"stevey","text":"Test comment from file\n","created_at":"2025-11-12T09:55:23Z"}]} +{"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":1,"issue_id":"bd-23a8","author":"stevey","text":"Testing the new bd comment alias!","created_at":"2025-11-08T09:49:23Z"},{"id":2,"issue_id":"bd-23a8","author":"stevey","text":"Another test with JSON output","created_at":"2025-11-08T09:49:23Z"},{"id":3,"issue_id":"bd-23a8","author":"stevey","text":"Test comment from file\n","created_at":"2025-11-08T09:49:23Z"}]} {"id":"bd-248bdc3e","content_hash":"85c98bac3b48e3cc8466d1b60e4a690fe198c4f795160cf175d7add4691749b5","title":"Add optional post-merge git hook example for bd sync","description":"Create example git hook that auto-runs bd sync after git pull/merge.\n\nAdd to examples/git-hooks/:\n- post-merge hook that checks if .beads/issues.jsonl changed\n- If changed: run `bd sync` automatically\n- Make it optional/documented (not auto-installed)\n\nBenefits:\n- Zero-friction sync after git pull\n- Complements auto-detection as belt-and-suspenders\n\nNote: post-merge hook already exists for pre-commit/post-merge. Extend it to support sync.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-25T22:47:14.668842-07:00","updated_at":"2025-11-06T20:06:49.217298-08:00","closed_at":"2025-11-06T19:51:37.787964-08:00","source_repo":"."} {"id":"bd-2530","content_hash":"ac8bc0c4d75082ac76200d092b3c1c476fd1523c9e83b890f829ee3dd7dcbb3d","title":"Issue with labels","description":"This is a description","design":"Use MVC pattern","acceptance_criteria":"All tests pass","status":"closed","priority":0,"issue_type":"feature","created_at":"2025-10-31T21:40:34.630173-07:00","updated_at":"2025-11-01T11:11:57.93151-07:00","closed_at":"2025-11-01T11:11:57.93151-07:00","source_repo":".","labels":["bug","critical"]} {"id":"bd-2752a7a2","content_hash":"064b1ae28914d2cfcca93724e60636c13a6818883dbbb13322772ec93d814170","title":"Create cmd/bd/daemon_watcher.go (~150 LOC)","description":"Implement FileWatcher using fsnotify to watch JSONL file and git refs. Handle platform differences (inotify/FSEvents/ReadDirectoryChangesW). Include edge case handling for file rename, event storm, watcher failure.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-29T23:05:13.887269-07:00","updated_at":"2025-10-31T18:30:24.131535-07:00","closed_at":"2025-10-31T18:30:24.131535-07:00","source_repo":"."} @@ -111,7 +111,7 @@ {"id":"bd-4ba5908b","content_hash":"70b8d577e5f65acb215f1c4caf18fdafcbd124db14fbc0e70132eea2b1848a93","title":"Implement content-hash based collision resolution for deterministic convergence","description":"The current collision resolution uses creation timestamps to decide which issue to keep vs. remap. This is non-deterministic when two clones create issues at nearly the same time.\n\nRoot cause of bd-71107098:\n- Clone A creates test-1=\"Issue from clone A\" at T0\n- Clone B creates test-1=\"Issue from clone B\" at T0+30ms\n- Clone B syncs first, remaps Clone A's to test-2\n- Clone A syncs second, sees collision, remaps Clone B's to test-2\n- Result: titles are swapped between clones\n\nSolution:\n- Use content-based hashing (title + description + priority + type)\n- Deterministic winner: always keep issue with lower hash\n- Same collision on different clones produces same result (idempotent)\n\nImplementation:\n- Modify ScoreCollisions in internal/storage/sqlite/collision.go\n- Replace timestamp-based scoring with content hash comparison\n- Ensure hash function is stable across platforms","notes":"Rename detection successfully implemented and tested!\n\n**What was implemented:**\n1. Content-hash based rename detection in DetectCollisions\n2. When importing JSONL, if an issue has different ID but same content as DB issue, treat as rename\n3. Delete old ID and accept new ID from JSONL\n4. Added post-import re-export in sync command to flush rename changes\n5. Added post-import commit to capture rename changes\n\n**Test results:**\nTestTwoCloneCollision now shows full convergence:\n- Clone A: test-2=\"Issue from clone A\", test-1=\"Issue from clone B\"\n- Clone B: test-1=\"Issue from clone B\", test-2=\"Issue from clone A\"\n\nBoth clones have **identical content** (titles match IDs correctly). Only timestamps differ (expected).\n\n**What remains:**\n- Test still expects exact JSON match including timestamps\n- Could normalize timestamp comparison, but content convergence is the critical success metric\n- The two-clone collision workflow now works without data corruption!","status":"closed","priority":0,"issue_type":"task","created_at":"2025-10-28T17:04:11.530026-07:00","updated_at":"2025-10-30T17:12:58.225987-07:00","closed_at":"2025-10-28T17:18:27.777019-07:00","source_repo":".","dependencies":[{"issue_id":"bd-4ba5908b","depends_on_id":"bd-71107098","type":"blocks","created_at":"2025-10-28T17:04:18.149604-07:00","created_by":"daemon"}]} {"id":"bd-4c18","content_hash":"d3d162cefdf9f3637ffb0ead341f48ffefe50fdf5e6ff9edc3ffcd05cdd703b4","title":"bd delete fails to find closed issues","description":"## Steps to Reproduce\n1. Close some issues with `bd close`\n2. Try to delete them with `bd delete \u003cids\u003e --force`\n3. Get error \"issues not found\"\n\n## Expected Behavior\nShould delete the closed issues\n\n## Actual Behavior\n```\nError: issues not found: bd-74ee, bd-9b13, bd-72w, bd-149, bd-5iv, bd-78w\n```\n\nBut `bd list --status closed --json` shows they exist.\n\n## Root Cause\nLikely the delete command is only looking for open issues, or there's a race condition with auto-import.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-03T20:57:31.763179-08:00","updated_at":"2025-11-03T21:31:18.677629-08:00","closed_at":"2025-11-03T21:31:18.677629-08:00","source_repo":"."} {"id":"bd-4cyb","content_hash":"1d02ccb8a552b2dec49bdfc3a7ed70b3307bcdebcaa8a563902a86a8bdcf7507","title":"Test graceful degradation when server unavailable","description":"Verify that agents continue working normally when Agent Mail server is stopped or unreachable.\n\nAcceptance Criteria:\n- Agent detects server unavailable on startup\n- Logs \"falling back to Beads-only mode\"\n- All bd commands work normally\n- Agent can claim issues (no reservations, like today)\n- Git sync operates as normal\n- No errors or crashes\n\nSuccess Metric: Zero functional difference when Agent Mail unavailable","status":"closed","priority":0,"issue_type":"task","created_at":"2025-11-07T22:42:00.094481-08:00","updated_at":"2025-11-08T01:51:40.349332-08:00","closed_at":"2025-11-08T00:20:29.841174-08:00","source_repo":".","dependencies":[{"issue_id":"bd-4cyb","depends_on_id":"bd-6hji","type":"blocks","created_at":"2025-11-07T23:03:53.054449-08:00","created_by":"daemon"}]} -{"id":"bd-4d7fca8a","content_hash":"5da2fc1fc0cbade7e4cfaf7fdb87b58487ce7661443e6ad4083f2f8de655e206","title":"Add tests for internal/utils package","description":"Currently 0.0% coverage. Need tests for utility functions including issue ID parsing and validation.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-29T14:06:24.066403-07:00","updated_at":"2025-11-08T17:57:28.956561-08:00","closed_at":"2025-11-08T17:57:28.956561-08:00","source_repo":".","dependencies":[{"issue_id":"bd-4d7fca8a","depends_on_id":"bd-cbed9619.5","type":"blocks","created_at":"2025-10-29T19:52:05.52888-07:00","created_by":"import-remap"},{"issue_id":"bd-4d7fca8a","depends_on_id":"bd-cbed9619.4","type":"blocks","created_at":"2025-10-29T19:52:05.529565-07:00","created_by":"import-remap"},{"issue_id":"bd-4d7fca8a","depends_on_id":"bd-0dcea000","type":"blocks","created_at":"2025-10-29T19:52:05.529982-07:00","created_by":"import-remap"}]} +{"id":"bd-4d7fca8a","content_hash":"57a2b25548d175bdd495044afa0ddb0739118c7faa2fc0860b13aaabb2635c23","title":"Add tests for internal/utils package","description":"Currently 0.0% coverage. Need tests for utility functions including issue ID parsing and validation.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-29T14:06:24.066403-07:00","updated_at":"2025-11-08T17:57:28.956561-08:00","closed_at":"2025-11-08T17:57:28.956561-08:00","source_repo":".","dependencies":[{"issue_id":"bd-4d7fca8a","depends_on_id":"bd-cbed9619.5","type":"blocks","created_at":"2025-10-29T19:52:05.52888-07:00","created_by":"import-remap"},{"issue_id":"bd-4d7fca8a","depends_on_id":"bd-cbed9619.4","type":"blocks","created_at":"2025-10-29T19:52:05.529565-07:00","created_by":"import-remap"},{"issue_id":"bd-4d7fca8a","depends_on_id":"bd-0dcea000","type":"blocks","created_at":"2025-10-29T19:52:05.529982-07:00","created_by":"import-remap"}]} {"id":"bd-4d80b7b1","content_hash":"7465ff154e916f0101dcd2aed683c2ffb72abdb3f1c8b60467a760441232d35b","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-cb64c226.2], 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-10-24T11:49:12.836292-07:00","updated_at":"2025-11-07T14:55:51.908404-08:00","closed_at":"2025-11-07T14:55:51.908404-08:00","source_repo":"."} {"id":"bd-4e21b5ad","content_hash":"8029d0c5b14261648d3d17d8bc26413183962eab2875772cd2585db92c0104a6","title":"Add test case for symmetric collision (both clones create same ID simultaneously)","description":"TestTwoCloneCollision demonstrates the problem, but we need a simpler unit test for the collision resolver itself.\n\nTest should verify:\n- Two issues with same ID, different content\n- Content hash determines winner deterministically \n- Result is same regardless of which clone imports first\n- No title swapping occurs\n\nThis can be a simpler test than the full integration test.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-29T17:46:10.046999-07:00","updated_at":"2025-10-31T12:00:43.196705-07:00","closed_at":"2025-10-31T12:00:43.196705-07:00","source_repo":"."} {"id":"bd-4f582ec8","content_hash":"dbf986afd3a1641a2b701645a85cc3576888c6ecd0ecf217b16f4535448facee","title":"Test auto-start in fred","description":"","status":"closed","priority":3,"issue_type":"task","created_at":"2025-10-30T17:46:16.668088-07:00","updated_at":"2025-10-31T12:00:43.185723-07:00","closed_at":"2025-10-31T12:00:43.185723-07:00","source_repo":"."} @@ -144,11 +144,11 @@ {"id":"bd-5ibn","content_hash":"b7c7980704c017ba234dc80e8fb3f57617e3e911fea0385b70ad9dbfdefd438a","title":"Latency test 1","description":"","status":"in_progress","priority":3,"issue_type":"task","created_at":"2025-11-10T10:50:39.603332-08:00","updated_at":"2025-11-10T10:50:39.603332-08:00","source_repo":"."} {"id":"bd-5iv","content_hash":"229ad9764bd3eb8b09441adefce960aede63fd1b5466d52cc74f112f5bb610ac","title":"Test Epic","description":"## Overview\n\n[Describe the high-level goal and scope of this epic]\n\n## Success Criteria\n\n- [ ] Criteria 1\n- [ ] Criteria 2\n- [ ] Criteria 3\n\n## Background\n\n[Provide context and motivation]\n\n## Scope\n\n**In Scope:**\n- Item 1\n- Item 2\n\n**Out of Scope:**\n- Item 1\n- Item 2\n","design":"## Architecture\n\n[Describe the overall architecture and approach]\n\n## Components\n\n- Component 1: [description]\n- Component 2: [description]\n\n## Dependencies\n\n[List external dependencies or constraints]\n","acceptance_criteria":"- [ ] All child issues are completed\n- [ ] Integration tests pass\n- [ ] Documentation is updated\n- [ ] Code review completed\n","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-11-03T20:15:03.864229-08:00","updated_at":"2025-11-05T00:25:06.538749-08:00","closed_at":"2025-11-05T00:25:06.538749-08:00","source_repo":".","labels":["epic"]} {"id":"bd-5ki8","content_hash":"d89e5e528819934bcb7ee162fa7e32c27298db5816ecf51bcc8ede1809f1d5b9","title":"Add integration tests for adapter library","description":"Test suite for beads_mail_adapter.py covering all scenarios.\n\nAcceptance Criteria:\n- Test enabled mode (server available)\n- Test disabled mode (server unavailable)\n- Test graceful degradation (server dies mid-operation)\n- Test reservation conflicts\n- Test message sending/receiving\n- Mock HTTP server for testing\n- 90%+ code coverage\n\nFile: lib/test_beads_mail_adapter.py","notes":"Test suite completed with 29 comprehensive tests covering:\n- Enabled mode (server available): 10 tests\n- Disabled mode (server unavailable): 2 tests \n- Graceful degradation: 4 tests\n- Reservation conflicts: 2 tests\n- Configuration: 5 tests\n- Health check scenarios: 3 tests\n- HTTP error handling: 3 tests\n\n**Performance**: All tests run in 10ms (fast!)\n\n**Coverage highlights**:\n✅ Server health checks (ok, degraded, error, timeout)\n✅ All API operations (reserve, release, notify, check_inbox, get_reservations)\n✅ HTTP errors (404, 409 conflict, 500, 503)\n✅ Network errors (timeout, connection refused)\n✅ Malformed responses (bad JSON, empty body, plain text errors)\n✅ Environment variable configuration\n✅ Graceful degradation when server dies mid-operation\n✅ Conflict handling with both JSON and plain text errors\n✅ Dict wrapper responses ({\"messages\": [...]} and {\"reservations\": [...]})\n✅ Custom TTL for reservations\n✅ Default agent name fallback\n\nNo external dependencies, no slow integration tests, just fast unit tests with mocks.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-07T22:43:21.294596-08:00","updated_at":"2025-11-08T01:52:23.359176-08:00","closed_at":"2025-11-08T01:32:39.906342-08:00","source_repo":".","dependencies":[{"issue_id":"bd-5ki8","depends_on_id":"bd-m9th","type":"blocks","created_at":"2025-11-07T22:43:21.296024-08:00","created_by":"daemon"}]} -{"id":"bd-5ohb","content_hash":"426f1e44ca47486e2fa5b97832a635612ac9fcb98064f00559c8833480f11bd6","title":"Issue to reopen with reason","description":"","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-07T19:00:18.583903-08:00","updated_at":"2025-11-08T02:06:17.805253-08:00","closed_at":"2025-11-08T02:06:17.805253-08:00","source_repo":"."} +{"id":"bd-5ohb","content_hash":"c7432e58e6518764c9e88b92b16becbb545e179f187becf13aa980f1b93c8192","title":"Issue to reopen with reason","description":"","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-07T19:00:18.583903-08:00","updated_at":"2025-11-08T02:06:17.805253-08:00","closed_at":"2025-11-08T02:06:17.805253-08:00","source_repo":"."} {"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-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":4,"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-12T09:55:23Z"}]} +{"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":4,"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-08T09:49:23Z"}]} {"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:41:05.766749-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-6221bdcd","content_hash":"6fe008205e84cf7ab85ed80827e44f0410520737c1bb86ccd14719f917472004","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:41:05.766749-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":"."} {"id":"bd-62a0","content_hash":"b8b2a58a86211a19aed9d21ec5215b4f14ef341ee95d4ed845e1412840d00fd7","title":"Create WASM build infrastructure (Makefile, scripts)","description":"Set up build tooling for WASM compilation:\n- Add GOOS=js GOARCH=wasm build target\n- Copy wasm_exec.js from Go distribution\n- Create wrapper script for Node.js execution\n- Add build task to Makefile or build script","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-02T21:58:07.286826-08:00","updated_at":"2025-11-02T22:23:49.376789-08:00","closed_at":"2025-11-02T22:23:49.376789-08:00","source_repo":".","dependencies":[{"issue_id":"bd-62a0","depends_on_id":"bd-44d0","type":"parent-child","created_at":"2025-11-02T22:23:49.423064-08:00","created_by":"stevey"}]} {"id":"bd-63e9","content_hash":"7c709804b6d15ce63897344b0674dfae6a4fe97e3ae2768585e2a3407484bad0","title":"Fix Nix flake build test failures","description":"Nix build is failing during test phase with same test errors as Windows.\n\n**Error:**\n```\nerror: Cannot build '/nix/store/rgyi1j44dm6ylrzlg2h3z97axmfq9hzr-beads-0.9.9.drv'.\nReason: builder failed with exit code 1.\nFAIL github.com/steveyegge/beads/cmd/bd 16.141s\n```\n\nThis may be related to test environment setup or the same issues affecting Windows tests.","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-11-02T09:29:37.2851-08:00","updated_at":"2025-11-04T11:10:23.531386-08:00","closed_at":"2025-11-04T11:10:23.531389-08:00","source_repo":".","dependencies":[{"issue_id":"bd-63e9","depends_on_id":"bd-1231","type":"blocks","created_at":"2025-11-02T09:29:37.28618-08:00","created_by":"stevey"}]} @@ -180,10 +180,10 @@ {"id":"bd-7324","content_hash":"639f5eef2922178daae7416831b850bf58ebeb39b8b91e7124387e0b6dfea33c","title":"Add is_tombstone flag to schema","description":"Optionally add is_tombstone boolean field to issues table. Marks resurrected parents that were deleted. Allows distinguishing tombstones from normal deleted issues. Update schema.go and create migration.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-04T12:31:59.745076-08:00","updated_at":"2025-11-05T00:44:27.947578-08:00","closed_at":"2025-11-05T00:44:27.947584-08:00","source_repo":"."} {"id":"bd-736d","content_hash":"4743b1f41ff07fee3daa63240f0d5f7ac3f876e928b22c4ce0bee2cdf544e53a","title":"Refactor path canonicalization into helper function","description":"The path canonicalization logic (filepath.Abs + EvalSymlinks) is duplicated in 3 places:\n- beads.go:131-137 (BEADS_DIR handling)\n- cmd/bd/main.go:446-451 (--no-db cleanup)\n- cmd/bd/nodb.go:26-31 (--no-db initialization)\n\nRefactoring suggestion:\nExtract to a helper function like:\n func canonicalizePath(path string) string\n\nThis would:\n- Reduce code duplication\n- Make the logic easier to maintain\n- Ensure consistent behavior across all path handling\n\nRelated to bd-e16b implementation.","status":"open","priority":3,"issue_type":"chore","created_at":"2025-11-02T18:33:47.727443-08:00","updated_at":"2025-11-02T18:33:47.727443-08:00","source_repo":"."} {"id":"bd-73iz","content_hash":"6003ff8e78d951d6a708f6aac6bcf841637977cab4f4a93a80b3dc2bab3287cb","title":"Test issue 1","description":"","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-07T19:04:17.430269-08:00","updated_at":"2025-11-07T22:07:17.344468-08:00","closed_at":"2025-11-07T21:55:09.427697-08:00","source_repo":"."} -{"id":"bd-73n8","content_hash":"298e5922cb0e6460d1cf14d2b7230c63403e72fcb511fb31d3fe2e2f241fd18a","title":"Blocking issue","description":"","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-07T19:06:46.156536-08:00","updated_at":"2025-11-08T02:06:46.038302-08:00","closed_at":"2025-11-08T02:06:46.038302-08:00","source_repo":"."} +{"id":"bd-73n8","content_hash":"d8808071441c4faaa429c2100b421348df1750118ac618c6d68437064eb060c5","title":"Blocking issue","description":"","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-07T19:06:46.156536-08:00","updated_at":"2025-11-08T02:06:46.038302-08:00","closed_at":"2025-11-08T02:06:46.038302-08:00","source_repo":"."} {"id":"bd-74ee","content_hash":"476deaacd64c91c96e5c9aca9ba0640dcf0f3854f9f11bbaa25a8ae80af3adf3","title":"Frontend task","description":"","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-03T19:11:59.358631-08:00","updated_at":"2025-11-05T00:25:06.457813-08:00","closed_at":"2025-11-05T00:25:06.457813-08:00","source_repo":".","labels":["frontend","week1"]} {"id":"bd-763c","content_hash":"31265106d3d8856bdda09f00708f6efdda862abc97a14f8e2bcacc8535870099","title":"~/src/beads daemon has 'sql: database is closed' errors - zombie daemon","description":"","status":"closed","priority":0,"issue_type":"bug","created_at":"2025-10-31T21:08:03.388007-07:00","updated_at":"2025-10-31T21:52:04.214274-07:00","closed_at":"2025-10-31T21:52:04.214274-07:00","source_repo":".","dependencies":[{"issue_id":"bd-763c","depends_on_id":"bd-2752a7a2","type":"discovered-from","created_at":"2025-10-31T21:08:03.388716-07:00","created_by":"stevey"}]} -{"id":"bd-76cu","content_hash":"66fd2d53d97eb8dcb3231e82702ca7eb0f1887dc9b3ee2b2865e0d5158ca7311","title":"Issue 2","description":"","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-07T19:04:21.562329-08:00","updated_at":"2025-11-08T02:06:40.397755-08:00","closed_at":"2025-11-08T02:06:40.397755-08:00","source_repo":"."} +{"id":"bd-76cu","content_hash":"2236f911e6f321a74aa61bdf702d24949e44a68ed511d12dd011aa4103c89230","title":"Issue 2","description":"","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-07T19:04:21.562329-08:00","updated_at":"2025-11-08T02:06:40.397755-08:00","closed_at":"2025-11-08T02:06:40.397755-08:00","source_repo":"."} {"id":"bd-77gm","content_hash":"b227320f0cf0c889a1e0d617922c572a48eee563c9afb1662b44a22e183c0c80","title":"Import reports misleading '0 created, 0 updated' when actually importing all issues","description":"When running 'bd import' on a fresh database (no existing issues), the command reports 'Import complete: 0 created, 0 updated' even though it successfully imported all issues from the JSONL file.\n\n**Steps to reproduce:**\n1. Delete .beads/beads.db\n2. Run: bd import .beads/issues.jsonl\n3. Observe output: 'Import complete: 0 created, 0 updated'\n4. Run: bd list\n5. Confirm: All issues are actually present in the database\n\n**Expected behavior:**\nReport the actual number of issues imported, e.g., 'Import complete: 523 created, 0 updated'\n\n**Actual behavior:**\n'Import complete: 0 created, 0 updated' (misleading - makes user think import failed)\n\n**Impact:**\n- Users think import failed when it succeeded\n- Confusing during database sync operations (e.g., after git pull)\n- Makes debugging harder (can't tell if import actually worked)\n\n**Context:**\nDiscovered during VC session when syncing database after git pull. The misleading message caused confusion about whether the database was properly synced with the canonical JSONL file.","acceptance_criteria":"- Import command reports accurate count of created/updated issues\n- Fresh database import shows 'N created' where N is the actual number\n- Update operations show 'N updated' where N is the actual number changed\n- Message clearly indicates success vs failure","status":"open","priority":2,"issue_type":"bug","created_at":"2025-11-09T16:20:13.191156-08:00","updated_at":"2025-11-09T16:20:13.191156-08:00","source_repo":"."} {"id":"bd-78w","content_hash":"dd79ef79bf68b3a87f3a5b8d50fdfba9d6c6f7e6d728713e37dd34cf9fff835e","title":"Test Epic 2","description":"## Overview\n\n[Describe the high-level goal and scope of this epic]\n\n## Success Criteria\n\n- [ ] Criteria 1\n- [ ] Criteria 2\n- [ ] Criteria 3\n\n## Background\n\n[Provide context and motivation]\n\n## Scope\n\n**In Scope:**\n- Item 1\n- Item 2\n\n**Out of Scope:**\n- Item 1\n- Item 2\n","design":"## Architecture\n\n[Describe the overall architecture and approach]\n\n## Components\n\n- Component 1: [description]\n- Component 2: [description]\n\n## Dependencies\n\n[List external dependencies or constraints]\n","acceptance_criteria":"- [ ] All child issues are completed\n- [ ] Integration tests pass\n- [ ] Documentation is updated\n- [ ] Code review completed\n","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-11-03T20:15:03.878216-08:00","updated_at":"2025-11-05T00:25:06.566242-08:00","closed_at":"2025-11-05T00:25:06.566242-08:00","source_repo":".","labels":["epic"]} {"id":"bd-7a00c94e","content_hash":"5ea01765a9fdf5c4c75f485b1db26c942eaaa762f1cdcb497306a78c65132721","title":"Rapid 2","description":"","status":"closed","priority":3,"issue_type":"task","created_at":"2025-10-29T19:11:57.430725-07:00","updated_at":"2025-11-08T01:49:23.458912-08:00","closed_at":"2025-11-07T23:18:52.352188-08:00","source_repo":"."} @@ -199,20 +199,20 @@ {"id":"bd-7eed","content_hash":"38bc75490042cd3b3dea4dd9c7fd0ce576212b2c31ccf3d51992d1dc73b0fbd9","title":"Remove obsolete stale.go command (executor tables never implemented)","description":"","status":"closed","priority":2,"issue_type":"chore","created_at":"2025-10-31T21:27:05.555369-07:00","updated_at":"2025-10-31T21:27:11.427631-07:00","closed_at":"2025-10-31T21:27:11.427631-07:00","source_repo":"."} {"id":"bd-7fe8","content_hash":"106aa3a1717d3c2a6ff518a8881976fd70911b006714b04f47327959d7ca1444","title":"Fix linting error in migrate.go","description":"Linter reports error:\n```\ncmd/bd/migrate.go:647:37: cleanupWALFiles - result 0 (error) is always nil (unparam)\n```\n\nThe `cleanupWALFiles` function always returns nil, so the error return type should be removed or the function should actually return errors when appropriate.","status":"closed","priority":2,"issue_type":"chore","created_at":"2025-11-02T09:29:37.279747-08:00","updated_at":"2025-11-02T09:46:52.18793-08:00","closed_at":"2025-11-02T09:46:52.18793-08:00","source_repo":".","dependencies":[{"issue_id":"bd-7fe8","depends_on_id":"bd-1231","type":"blocks","created_at":"2025-11-02T09:29:37.280881-08:00","created_by":"stevey"}]} {"id":"bd-7kua","content_hash":"2dedc0d0d5444db45ab146cc59f3c51bc4bfc3c864da43d3c086a9153613c29f","title":"Reduce sync rounds in multiclone tests","description":"Analyze and reduce the number of sync rounds in hash multiclone tests.\n\nCurrent state:\n- TestHashIDs_MultiCloneConverge: 1 round of syncs across 3 clones\n- TestHashIDs_IdenticalContentDedup: 2 rounds across 2 clones\n\nInvestigation needed:\n- Profile to see how much time each sync takes\n- Determine minimum rounds needed for convergence\n- Consider making rounds configurable via env var\n\nFile: beads_hash_multiclone_test.go:70, :132","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-04T01:24:18.405038-08:00","updated_at":"2025-11-04T10:26:34.449434-08:00","closed_at":"2025-11-04T10:26:34.449434-08:00","source_repo":".","dependencies":[{"issue_id":"bd-7kua","depends_on_id":"bd-l5gq","type":"blocks","created_at":"2025-11-04T01:24:18.405883-08:00","created_by":"daemon"}]} -{"id":"bd-7so1","content_hash":"35b394c75f08f60e3a8bf4cb5f837fd7644ae1bbc7a050d0f4b78d01c9e7a33e","title":"Issue 1 to reopen","description":"","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-07T19:04:20.12433-08:00","updated_at":"2025-11-08T02:06:29.112482-08:00","closed_at":"2025-11-08T02:06:29.112482-08:00","source_repo":"."} +{"id":"bd-7so1","content_hash":"65e5dcb12407f83aad0c37c06127fcf76cf00bf581adab726b221da75c6c7f74","title":"Issue 1 to reopen","description":"","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-07T19:04:20.12433-08:00","updated_at":"2025-11-08T02:06:29.112482-08:00","closed_at":"2025-11-08T02:06:29.112482-08:00","source_repo":"."} {"id":"bd-8072","content_hash":"32bd0e33433bbf535cb56eb47828ac80ebecc57512e9039420a39cd2342790d2","title":"Add import.orphan_handling config option","description":"Add configuration option to control orphan handling behavior: 'strict' (fail on missing parent, current behavior), 'resurrect' (auto-resurrect from JSONL, recommended default), 'skip' (skip orphaned issues with warning), 'allow' (import orphans without validation). Update CONFIG.md documentation.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-04T12:32:08.569239-08:00","updated_at":"2025-11-05T00:44:27.948157-08:00","closed_at":"2025-11-05T00:44:27.94816-08:00","source_repo":"."} {"id":"bd-812a","content_hash":"0d802dec82dff53e88e68bb4f1fef75754165a590996ff8b1578ff93e781622d","title":"Add unit tests for import ordering","description":"Test topological sort: import [child, parent] should succeed, import [parent.1.2, parent, parent.1] should sort correctly. Verify depth-based batching works. Test max depth limits.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-04T12:32:21.278448-08:00","updated_at":"2025-11-05T00:08:42.812949-08:00","closed_at":"2025-11-05T00:08:42.812952-08:00","source_repo":"."} {"id":"bd-81a","content_hash":"0f43da9e36bc3c5db20f302b82021377685a9425f519a36bab5a2cf1b85f13d8","title":"Add programmatic tip injection API","description":"Allow tips to be programmatically injected at runtime based on detected conditions. This enables dynamic tips (not just pre-defined ones) to be shown with custom priority and frequency.","design":"## API Design\n\nAdd to `cmd/bd/tips.go`:\n\n```go\n// InjectTip adds a dynamic tip to the registry at runtime\nfunc InjectTip(id, message string, priority int, frequency time.Duration, probability float64, condition func() bool) {\n tipsMutex.Lock()\n defer tipsMutex.Unlock()\n \n tips = append(tips, Tip{\n ID: id,\n Condition: condition,\n Message: message,\n Frequency: frequency,\n Priority: priority,\n Probability: probability,\n })\n}\n\n// RemoveTip removes a tip from the registry\nfunc RemoveTip(id string) {\n tipsMutex.Lock()\n defer tipsMutex.Unlock()\n \n for i, tip := range tips {\n if tip.ID == id {\n tips = append(tips[:i], tips[i+1:]...)\n return\n }\n }\n}\n```\n\n## Use Cases\n\n### Example 1: Critical Security Update\n```go\n// In bd version check code\nif criticalSecurityUpdate {\n InjectTip(\n \"security_update\",\n fmt.Sprintf(\"CRITICAL: Security update available (bd %s). Update immediately!\", remoteVersion),\n 100, // Highest priority\n 0, // No frequency limit\n 1.0, // Always show (100% probability)\n func() bool { return true },\n )\n}\n```\n\n### Example 2: New Version Available\n```go\n// In bd version check code\nif remoteVersion \u003e currentVersion {\n InjectTip(\n \"upgrade_available\",\n fmt.Sprintf(\"New bd version %s available (you have %s). Run: go install github.com/steveyegge/beads/cmd/bd@latest\", remoteVersion, currentVersion),\n 90, // High priority\n 7 * 24 * time.Hour, // Weekly\n 0.8, // 80% probability (frequent but not always)\n func() bool { return true },\n )\n}\n```\n\n### Example 3: Large Issue Count Suggestion\n```go\n// In bd list code\nif issueCount \u003e 100 {\n InjectTip(\n \"use_filters\",\n \"You have many issues. Use filters: 'bd list --status=open --priority=1'\",\n 50, // Medium priority\n 14 * 24 * time.Hour, // Bi-weekly\n 0.4, // 40% probability (occasional suggestion)\n func() bool { return true },\n )\n}\n```\n\n### Example 4: No Dependencies Used\n```go\n// After analyzing project\nif hasIssues \u0026\u0026 noDependenciesCreated {\n InjectTip(\n \"try_dependencies\",\n \"Try using dependencies: 'bd dep \u003cissue\u003e \u003cblocks-issue\u003e' to track blockers\",\n 30, // Low priority\n 30 * 24 * time.Hour, // Monthly\n 0.3, // 30% probability (low-key suggestion)\n func() bool { return true },\n )\n}\n```\n\n## Probability Guidelines\n\n- **1.0 (100%)**: Critical security, breaking changes, data loss prevention\n- **0.7-0.9 (70-90%)**: Important updates, major new features\n- **0.4-0.6 (40-60%)**: General tips, workflow improvements, feature discovery\n- **0.1-0.3 (10-30%)**: Nice-to-know features, advanced tips, optional optimizations\n\n## Thread Safety\n- Use mutex to protect tip registry\n- Safe for concurrent command execution\n- Deterministic testing via BEADS_TIP_SEED env var","acceptance_criteria":"- InjectTip() API exists and is documented\n- RemoveTip() API exists\n- Thread-safe with mutex protection\n- Can inject tips from any command\n- Injected tips participate in priority/frequency rotation\n- Unit tests for injection API\n- Example usage in code comments","status":"open","priority":2,"issue_type":"feature","created_at":"2025-11-11T23:29:46.645583-08:00","updated_at":"2025-11-11T23:50:12.209135-08:00","source_repo":".","dependencies":[{"issue_id":"bd-81a","depends_on_id":"bd-d4i","type":"blocks","created_at":"2025-11-11T23:29:46.646327-08:00","created_by":"daemon"}]} {"id":"bd-81abb639","content_hash":"ddf6496e654e8cd8e69620a08e2d607d8c8bda152a8dc884908e29747d39376d","title":"Investigate jujutsu VCS as potential solution for conflict-free merging","description":"## Context\nCurrent N-way collision resolution struggles with Git line-based merge model. When 5+ clones create issues with same ID, Git merge conflicts require manual resolution, and our collision resolver can fail during convergence rounds.\n\n## Research Question\nCould jujutsu (jj) provide better conflict handling for JSONL files?\n\n## Jujutsu Overview\n- Next-gen VCS built on libgit2\n- Designed to handle conflicts as first-class citizens\n- Supports conflict-free replicated data types (CRDTs) in some scenarios\n- Better handling of concurrent edits\n- Can work with Git repos (compatible with existing infrastructure)\n\n## Investigation Tasks\n1. JSONL Merge Behavior - How does jj handle line-by-line JSONL conflicts?\n2. Integration Feasibility - Can beads use jj as backend while maintaining Git compatibility?\n3. Conflict Resolution Model - Does jj conflict model map to our collision resolution?\n4. Operational Transform Support - Does jj implement operational transforms?\n\n## Deliverables\n1. Technical report on jj merge algorithm for JSONL\n2. Proof-of-concept: 5-clone collision test using jj instead of Git\n3. Performance comparison: Git vs jj for beads workload\n4. Recommendation: Adopt, experiment further, or abandon\n\n## References\n- https://github.com/martinvonz/jj\n- Related to bd-e6d71828, bd-7a2b58fc","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-29T20:02:47.953008-07:00","updated_at":"2025-10-30T17:12:58.19464-07:00","closed_at":"2025-10-29T20:47:52.910985-07:00","source_repo":"."} {"id":"bd-824","content_hash":"ba893642ee6145900797db1937943f5dc38e848ed85e74307bcfa0352c2130a6","title":"Add migration guide for library consumers","description":"The contributor-workflow-analysis.md has excellent migration examples for CLI users (lines 508-549) but lacks examples for library consumers like VC that use beadsLib in Go/TypeScript code.\n\nLibrary consumers need to know:\n- Whether their existing code continues to work unchanged (backward compatibility)\n- How config.toml is automatically read (transparent hydration)\n- When and how to use explicit multi-repo configuration\n- What happens if config.toml doesn't exist (defaults)\n\nExample needed:\n```go\n// Before (v0.17.3)\nstore, err := beadsLib.NewSQLiteStorage(\".beads/vc.db\")\n\n// After (v0.18.0 with multi-repo) - still works!\nstore, err := beadsLib.NewSQLiteStorage(\".beads/vc.db\")\n// Automatically reads .beads/config.toml if present\n\n// Explicit multi-repo (if needed)\ncfg := beadsLib.Config{\n Primary: \".beads/vc.db\",\n Additional: []string{\"~/.beads-planning\"},\n}\nstore, err := beadsLib.NewStorageWithConfig(cfg)\n```","acceptance_criteria":"- Section added to contributor-workflow-analysis.md for library consumers\n- Code examples showing backward compatibility\n- Code examples showing explicit multi-repo configuration\n- Guidance on when library consumers should use multi-repo vs single-repo","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-03T20:24:17.748337-08:00","updated_at":"2025-11-05T14:15:44.154675-08:00","closed_at":"2025-11-05T14:15:44.154675-08:00","source_repo":"."} -{"id":"bd-82dv","content_hash":"a5f24bc24c6b85c34577386af16ec2f20dc0b7816a91f484169e6e06bb46d1d3","title":"cmd/bd tests fail without -short flag (parallel test deadlock)","description":"","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-08T22:58:38.72748-08:00","updated_at":"2025-11-09T12:54:44.557562-08:00","closed_at":"2025-11-09T12:54:44.557562-08:00","source_repo":"."} +{"id":"bd-82dv","content_hash":"872b8d8f96db62a6faf618a264a1c3eec23bf75beb544be5afc75ca00262117a","title":"cmd/bd tests fail without -short flag (parallel test deadlock)","description":"","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-08T22:58:38.72748-08:00","updated_at":"2025-11-09T12:54:44.557562-08:00","closed_at":"2025-11-09T12:54:44.557562-08:00","source_repo":"."} {"id":"bd-833559b3","content_hash":"d4b0ded6c4696813257f7e3fa84913e3e159690b74f78c909e68debae8d1e727","title":"bd validate - Comprehensive health check","description":"Run all validation checks in one command.\n\nChecks:\n- Duplicates\n- Orphaned dependencies\n- Test pollution\n- Git conflicts\n\nSupports --fix-all for auto-repair.\n\nDepends on bd-cbed9619.1, bd-0dcea000, bd-2752a7a2, bd-9826b69a.\n\nFiles: cmd/bd/validate.go (new)","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-29T20:02:47.957692-07:00","updated_at":"2025-11-05T00:16:42.294117-08:00","closed_at":"2025-11-05T00:16:42.294117-08:00","source_repo":"."} {"id":"bd-8507","content_hash":"96a07fcf39392143fa9c75cbc96f54136809609f6ced80dd9581ec9144d54b1f","title":"Publish bd-wasm to npm","description":"Package and publish WASM build to npm. Child of epic bd-44d0.\n\n## Tasks\n- [ ] Optimize WASM bundle (compression)\n- [ ] Create README for npm package\n- [ ] Set up npm publishing workflow\n- [ ] Publish v0.1.0-alpha\n- [ ] Test installation in clean environment\n- [ ] Update beads AGENTS.md with installation instructions\n\n## Package Name\nbd-wasm (or @beads/wasm-cli)","status":"closed","priority":0,"issue_type":"task","created_at":"2025-11-02T18:33:31.371535-08:00","updated_at":"2025-11-05T00:55:48.757492-08:00","closed_at":"2025-11-05T00:55:48.757494-08:00","source_repo":".","dependencies":[{"issue_id":"bd-8507","depends_on_id":"bd-197b","type":"blocks","created_at":"2025-11-02T18:33:31.372224-08:00","created_by":"daemon"}]} {"id":"bd-8534","content_hash":"05b543a341ac0210f6025318e2eaead1da295b8d270fd17356fa3337c856607d","title":"Switch from modernc.org/sqlite to ncruces/go-sqlite3 for WASM support","description":"modernc.org/sqlite depends on modernc.org/libc which has no js/wasm support (platform-specific syscalls). Need to switch to ncruces/go-sqlite3 which wraps a WASM build of SQLite using wazero runtime.\n\nKey differences:\n- ncruces/go-sqlite3: Uses WASM build of SQLite + wazero runtime\n- modernc.org/sqlite: Pure Go translation, requires libc for syscalls\n\nThis is a prerequisite for bd-62a0 (WASM build infrastructure).","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-02T22:14:27.627154-08:00","updated_at":"2025-11-02T22:23:49.377223-08:00","closed_at":"2025-11-02T22:23:49.377223-08:00","source_repo":".","dependencies":[{"issue_id":"bd-8534","depends_on_id":"bd-44d0","type":"parent-child","created_at":"2025-11-02T22:23:49.555691-08:00","created_by":"stevey"}]} -{"id":"bd-85487065","content_hash":"f11f458db379288179b4c2434eacee8940eac910781a74c721c7e6e889f76bc1","title":"Add tests for internal/autoimport package","description":"Currently 0.0% coverage. Need tests for auto-import functionality that detects and imports updated JSONL files.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-29T14:06:18.154805-07:00","updated_at":"2025-11-08T18:06:25.811317-08:00","closed_at":"2025-11-08T18:06:25.811317-08:00","source_repo":"."} +{"id":"bd-85487065","content_hash":"637cbd56af122b175ff060b4df050871fe86124c5d883ba7f8a17f2f95479613","title":"Add tests for internal/autoimport package","description":"Currently 0.0% coverage. Need tests for auto-import functionality that detects and imports updated JSONL files.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-29T14:06:18.154805-07:00","updated_at":"2025-11-08T18:06:25.811317-08:00","closed_at":"2025-11-08T18:06:25.811317-08:00","source_repo":"."} {"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-879d","content_hash":"9716c230d9b2793bd1e51d9e3c380c06caf7b3e9a0dd20253764af19e3de7ac8","title":"Test issue 1","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-02T09:44:12.538697729Z","updated_at":"2025-11-02T09:45:20.76214671Z","closed_at":"2025-11-02T09:45:20.76214671Z","source_repo":".","dependencies":[{"issue_id":"bd-879d","depends_on_id":"bd-d3e5","type":"discovered-from","created_at":"2025-11-02T09:44:22.103468321Z","created_by":"mrdavidlaing"}]} -{"id":"bd-87a0","content_hash":"b6c322852ff360ade9f0d46bb2af29a7cf3d3acc8b7469dcbb5d98bf48050240","title":"Publish @beads/bd package to npm registry","description":"Publish the npm package to the public npm registry:\n\n## Prerequisites\n- npm account created\n- Organization @beads created (or use different namespace)\n- npm login completed locally\n- Package tested locally (bd-f282 completed)\n\n## Publishing steps\n1. Verify package.json version matches current bd version\n2. Run npm pack and inspect tarball contents\n3. Test installation from tarball one more time\n4. Run npm publish --access public\n5. Verify package appears on https://www.npmjs.com/package/@beads/bd\n6. Test installation from registry: npm install -g @beads/bd\n\n## Post-publish\n- Add npm badge to README.md\n- Update CHANGELOG.md with npm package release\n- Announce in release notes\n\n## Note\n- May need to choose different name if @beads namespace unavailable\n- Alternative: beads-cli, bd-cli, or unscoped beads-issue-tracker","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-02T23:40:25.263569-08:00","updated_at":"2025-11-03T10:39:41.772338-08:00","closed_at":"2025-11-03T10:39:41.772338-08:00","source_repo":".","dependencies":[{"issue_id":"bd-87a0","depends_on_id":"bd-febc","type":"parent-child","created_at":"2025-11-02T23:40:33.014043-08:00","created_by":"daemon"}],"comments":[{"id":5,"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-12T09:55:23Z"}]} +{"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":5,"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-08T09:49:23Z"}]} {"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":"."} @@ -228,7 +228,7 @@ {"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-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-8v37","content_hash":"5c5951971ed466f30fa12e1d7f73457ecc430464726516f069e6659f762687e6","title":"BG's issue to reopen","description":"","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-07T19:04:19.450509-08:00","updated_at":"2025-11-08T02:06:23.470867-08:00","closed_at":"2025-11-08T02:06:23.470867-08:00","source_repo":"."} +{"id":"bd-8v37","content_hash":"74aa57ab28e70fb995a1e154379a17a211bc10ffae8e5901213661b154941981","title":"BG's issue to reopen","description":"","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-07T19:04:19.450509-08:00","updated_at":"2025-11-08T02:06:23.470867-08:00","closed_at":"2025-11-08T02:06:23.470867-08:00","source_repo":"."} {"id":"bd-8zf2","content_hash":"6aaca1fd593b88220f2d8e41f7af9b0cbce6d9152ac4d0b9d2ffe3b8f464adc5","title":"MCP server loses workspace context after Amp restart - causes silent failures","description":"**CRITICAL BUG**: The beads MCP server loses workspace context when Amp restarts, leading to silent failures and potential data corruption.\n\n## Reproduction\n1. Start Amp with beads MCP server configured\n2. Call `mcp__beads__set_context(workspace_root=\"/path/to/project\")`\n3. Use MCP tools successfully (e.g., `mcp__beads__show`, `mcp__beads__list`)\n4. Restart Amp (new thread/session)\n5. Try to use MCP tools without calling `set_context` again\n6. **Result**: \"Not connected\" or \"No workspace set\" errors\n\n## Impact\n- Amp agents silently fail when trying to read/update beads issues\n- May attempt to create duplicate issues because they can't see existing ones\n- Potential for data corruption if operating on wrong database\n- Breaks multi-session workflows\n- Creates confusion: CLI works (`./bd`) but MCP tools don't\n\n## Current Workaround\nManually call `mcp__beads__set_context()` at start of every Amp session.\n\n## Root Cause\nMCP server is stateful and doesn't persist workspace context across restarts.\n\n## Proposed Fix\n**Option 1 (Best)**: Auto-detect workspace from current working directory\n- Match behavior of CLI `./bd` commands\n- Check for `.beads/` directory in current dir or parents\n- No manual context setting needed\n\n**Option 2**: Persist context in MCP server state file\n- Save last workspace_root to `~/.config/beads/mcp_context.json`\n- Restore on server startup\n\n**Option 3**: Require explicit context in every MCP call\n- Add optional `workspace_root` parameter to all MCP tools\n- Fall back to saved context if not provided\n\nAcceptance:\n- MCP tools work across Amp restarts without manual set_context()\n- Auto-detection matches CLI behavior (walks up from CWD)\n- Clear error message when no workspace found\n- set_context() still works for explicit override\n- BEADS_WORKING_DIR env var support\n- Integration test validates restart behavior","design":"**Recommended Implementation: Option 1 (Auto-detect)**\n\n1. Workspace Discovery Algorithm (same as CLI):\n - Start from CWD or provided directory\n - Walk up directory tree looking for .beads/beads.db\n - Cache result for performance\n\n2. MCP Tool Wrapper Changes:\n - Before each MCP tool execution, check if workspace is set\n - If not set, try auto-detection from CWD\n - If found, auto-connect and cache\n - If not found, return clear error with instructions\n\n3. Fallback Behavior:\n - Auto-detect from CWD first\n - Check BEADS_WORKING_DIR env var\n - Check ~/.config/beads/last_workspace (persisted)\n - Return actionable error if all fail\n\n4. Backwards Compatibility:\n - Keep set_context() working for explicit control\n - Auto-detect is always tried first if no explicit context\n - set_context() takes precedence over auto-detect","status":"closed","priority":0,"issue_type":"bug","created_at":"2025-11-07T23:50:52.083111-08:00","updated_at":"2025-11-07T23:58:44.397502-08:00","closed_at":"2025-11-07T23:58:44.397502-08:00","source_repo":"."} {"id":"bd-8zpg","content_hash":"31c8e1312c7d75e9c17f9557f86bc642ca47e5c9a39d4f7e76429cc61bc9793d","title":"Add tests for bd init --contributor wizard","description":"Write integration tests for the contributor wizard:\n- Test fork detection logic\n- Test planning repo creation\n- Test config setup\n- Test with/without upstream remote\n- Test with SSH vs HTTPS origins","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-05T18:58:18.171851-08:00","updated_at":"2025-11-06T18:19:16.232739-08:00","closed_at":"2025-11-06T16:14:06.341689-08:00","source_repo":"."} {"id":"bd-9063acda","content_hash":"0ea4606188e376705c46a14e5d64da1b706aad47a39054a732c21330db601960","title":"Clean up linter errors (914 total issues)","description":"The codebase has 914 linter issues reported by golangci-lint. While many are documented as baseline in LINTING.md, we should clean these up systematically to improve code quality and maintainability.","design":"Break down by linter category, prioritizing high-impact issues:\n1. dupl (7) - Code duplication\n2. goconst (12) - Repeated strings\n3. gocyclo (11) - High complexity functions\n4. revive (78) - Style issues\n5. gosec (102) - Security warnings\n6. errcheck (683) - Unchecked errors (many in tests)","acceptance_criteria":"All linter categories reduced to acceptable levels, with remaining baseline documented in LINTING.md","notes":"Reduced from 56 to 41 issues locally, then to 0 issues.\n\n**Fixed in commits:**\n- c2c7eda: Fixed 15 actual errors (dupl, gosec, revive, staticcheck, unparam)\n- 963181d: Configured exclusions to get to 0 issues locally\n\n**Current status:**\n- ✅ Local: golangci-lint reports 0 issues\n- ❌ CI: Still failing (see [deleted:bd-cb64c226.1])\n\n**Problem:**\nConfig v2 format or golangci-lint-action@v8 compatibility issue causing CI to fail despite local success.\n\n**Next:** Debug [deleted:bd-cb64c226.1] to fix CI/local discrepancy","status":"closed","priority":2,"issue_type":"epic","created_at":"2025-10-24T01:01:12.997982-07:00","updated_at":"2025-11-04T11:10:23.532431-08:00","closed_at":"2025-11-04T11:10:23.532433-08:00","source_repo":"."} @@ -251,7 +251,7 @@ {"id":"bd-9f20","content_hash":"fd9e463ab1b81e62f5ae1441e8c3a661361031a30e6a95502152bb4d7eecf7b2","title":"DetectCycles SQL query has bug preventing cycle detection","description":"The DetectCycles function's SQL query has a bug in the LIKE filter that prevents it from detecting cycles.\n\nCurrent code (line 571):\n```sql\nAND p.path NOT LIKE '%' || d.depends_on_id || '→%'\n```\n\nThis prevents ANY revisit to nodes, including returning to the start node to complete a cycle.\n\nFix:\n```sql\nAND (d.depends_on_id = p.start_id OR p.path NOT LIKE '%' || d.depends_on_id || '→%')\n```\n\nThis allows revisiting the start node (to detect the cycle) while still preventing intermediate node revisits.\n\nImpact: Currently DetectCycles cannot detect any cycles, but this hasn't been noticed because AddDependency prevents cycles from being created. The function would only matter if cycles were manually inserted into the database.","status":"closed","priority":3,"issue_type":"bug","created_at":"2025-11-01T22:50:32.552763-07:00","updated_at":"2025-11-01T22:52:02.247443-07:00","closed_at":"2025-11-01T22:52:02.247443-07:00","source_repo":"."} {"id":"bd-9f4a","content_hash":"f7fc76124f76636ef40af114a47509885fa9e5af9d2fddaf8820a46542086e42","title":"Document external_ref in content hash behavior","description":"The content hash includes external_ref, which has implications that should be documented.\n\nCurrent behavior:\n- external_ref is included in content hash calculation (collision.go:158-160)\n- Changing external_ref changes content hash\n- This means: local issue → add external_ref → different hash\n\nImplications:\n- Local issue + external_ref addition = looks like 'new content'\n- May not match by content hash in some scenarios\n- Generally correct behavior, but subtle\n\nAction items:\n- Document in code comments\n- Add to ARCHITECTURE.md or similar\n- Add test demonstrating this behavior\n- Consider if this is desired long-term\n\nRelated: bd-1022\nFiles: internal/storage/sqlite/collision.go:158-160","status":"closed","priority":4,"issue_type":"task","created_at":"2025-11-02T15:32:47.715458-08:00","updated_at":"2025-11-08T03:54:04.854833-08:00","closed_at":"2025-11-08T02:20:01.004638-08:00","source_repo":"."} {"id":"bd-9li4","content_hash":"7ae7b885e82a2de333584c01f690dbc3ecb924603f18e316f5c91cc44e2256f8","title":"Create Docker image for Agent Mail","description":"Containerize Agent Mail server for easy deployment.\n\nAcceptance Criteria:\n- Dockerfile with Python 3.14\n- Health check endpoint\n- Volume mount for storage\n- Environment variable configuration\n- Multi-arch builds (amd64, arm64)\n\nFile: deployment/agent-mail/Dockerfile","status":"open","priority":3,"issue_type":"task","created_at":"2025-11-07T22:43:43.231964-08:00","updated_at":"2025-11-07T22:43:43.231964-08:00","source_repo":"."} -{"id":"bd-9mnw","content_hash":"91dd58e84b57c84ae065004ef4c15d0b5330935a5fde35eed489a93452feb2e9","title":"Issue 1","description":"","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-07T19:07:16.329643-08:00","updated_at":"2025-11-08T02:06:51.688224-08:00","closed_at":"2025-11-08T02:06:51.688224-08:00","source_repo":"."} +{"id":"bd-9mnw","content_hash":"942bdfde12b32d268a7643fb64e4f92fa466cb6564434283a38378f1ce44973e","title":"Issue 1","description":"","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-07T19:07:16.329643-08:00","updated_at":"2025-11-08T02:06:51.688224-08:00","closed_at":"2025-11-08T02:06:51.688224-08:00","source_repo":"."} {"id":"bd-9msn","content_hash":"69ef2ebc5a847eb407c37e9039391d8ebc761a4cee3b60537de4f5a12011bec3","title":"Add monitoring and alerting","description":"Observability for production Agent Mail server.\n\nAcceptance Criteria:\n- Health check endpoint (/health)\n- Prometheus metrics export\n- Grafana dashboard\n- Alerts for server downtime\n- Alerts for high error rate\n- Log aggregation config\n\nFile: deployment/agent-mail/monitoring/","status":"open","priority":3,"issue_type":"task","created_at":"2025-11-07T22:43:43.354117-08:00","updated_at":"2025-11-07T22:43:43.354117-08:00","source_repo":".","dependencies":[{"issue_id":"bd-9msn","depends_on_id":"bd-z3s3","type":"blocks","created_at":"2025-11-07T23:04:28.050074-08:00","created_by":"daemon"}]} {"id":"bd-9rw1","content_hash":"17ad82d17e34ca2bfab2fa7240517520e3c42953a780282664f50cf038c97688","title":"Support P-prefix priority format (P0-P4) in create and update commands","description":"","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-11-05T13:56:04.796826-08:00","updated_at":"2025-11-05T13:56:08.157061-08:00","closed_at":"2025-11-05T13:56:08.157061-08:00","source_repo":"."} {"id":"bd-9v7l","content_hash":"10b1c2ca4d67587bdf220cf7ae04253eb01edca8a59756431bc3d453cbb85008","title":"bd status \"Recent Activity\" is misleading - should use git history","description":"## Problem\n\n`bd status` shows \"Recent Activity (last 7 days)\" but the numbers are wrong. It only looks at database timestamps, not git history. Says \"141 issues closed in last 7 days\" when thousands have actually come and go.\n\n## Issues\n\n1. Only queries database timestamps, not git history\n2. 7 days is too long a window\n3. Numbers don't reflect actual activity in JSONL git history\n\n## Proposed Fix\n\nEither:\n- Query git history of `.beads/beads.jsonl` to get actual activity (last 24-48 hours)\n- Remove \"Recent Activity\" section entirely if not useful\n- Make time window configurable and default to 24h\n\n## Example Output (Current)\n```\nRecent Activity (last 7 days):\nIssues Created: 174\nIssues Closed: 141\nIssues Updated: 37\n```\nThis is misleading when thousands of issues have actually cycled through.","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-11-05T01:03:00.234813-08:00","updated_at":"2025-11-06T18:47:42.682987-08:00","closed_at":"2025-11-06T18:47:42.682987-08:00","source_repo":"."} @@ -264,7 +264,7 @@ {"id":"bd-ad5e","content_hash":"67fdba1ba5b838384b16b82ff45e200cb5fd4960795bb5ae29d6fdec549170ca","title":"Add AI planning docs management guidance to bd onboard (GH-196)","description":"Enhanced bd onboard command to provide guidance for managing AI-generated planning documents (Claude slop).\n\nAddresses GitHub issue #196: https://github.com/steveyegge/beads/issues/196\n\nChanges:\n- Added Managing AI-Generated Planning Documents section to bd onboard\n- Recommends using history/ directory for ephemeral planning files\n- Updated AGENTS.md to demonstrate the pattern\n- Added comprehensive tests\n\nCommit: d46177d","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-11-02T17:11:33.183636-08:00","updated_at":"2025-11-02T17:12:05.599633-08:00","closed_at":"2025-11-02T17:12:05.599633-08:00","source_repo":"."} {"id":"bd-aec5439f","content_hash":"1b42289a0cb1da0626a69c6f004bf62fc9ba6e3a0f8eb70159c5f1446497020b","title":"Update LINTING.md with current baseline","description":"After cleanup, document the remaining acceptable baseline in LINTING.md so we can track regression.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-27T18:53:10.38679-07:00","updated_at":"2025-11-06T20:06:49.218701-08:00","closed_at":"2025-11-06T19:41:08.661851-08:00","source_repo":"."} {"id":"bd-aewm","content_hash":"b9f0ebb0c99a35c39c918250a1220f74bfcd77905b85c66715b36d1df9c5ec4b","title":"bd-hv01: Missing cleanup of .merged temp file on failure","description":"Problem: deletion_tracking.go:49 creates tmpMerged file but does not clean up on failure, causing disk space leak and potential interference with subsequent syncs.\n\nFix: Add defer os.Remove(tmpMerged) after creating temp file path.\n\nFiles: cmd/bd/deletion_tracking.go:38-89","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-11-06T18:16:24.326719-08:00","updated_at":"2025-11-06T18:46:55.924379-08:00","closed_at":"2025-11-06T18:46:55.924379-08:00","source_repo":".","dependencies":[{"issue_id":"bd-aewm","depends_on_id":"bd-rbxi","type":"parent-child","created_at":"2025-11-06T18:19:15.061462-08:00","created_by":"daemon"}]} -{"id":"bd-auf1","content_hash":"0e60a1a40065ce53b0adcbd9863b45694a94ccc455ce7020154ce10b2c5d4b03","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.","acceptance_criteria":"- Snapshot files are removed after successful merge and import\n- Files are created fresh on next 'bd sync' export step\n- Validation failure path still cleans up (existing behavior)\n- Tests verify cleanup happens in success path","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-11-08T22:39:56.460778-08:00","updated_at":"2025-11-08T22:47:51.96296-08:00","closed_at":"2025-11-08T22:47:51.96296-08:00","source_repo":"."} +{"id":"bd-auf1","content_hash":"ea41d9f0d51e0f06236b87c73175e63004ebb8d099c269312b8443eab2a33326","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.","acceptance_criteria":"- Snapshot files are removed after successful merge and import\n- Files are created fresh on next 'bd sync' export step\n- Validation failure path still cleans up (existing behavior)\n- Tests verify cleanup happens in success path","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-11-08T22:39:56.460778-08:00","updated_at":"2025-11-08T22:47:51.96296-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-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-b121","content_hash":"5d71e793a6de110be977bf87cfd25c3b461f452a1e8e44633452de1f8343a098","title":"Fix :memory: database connection pool issue causing \"no such table\" errors","description":"Critical bug in v0.21.6 where :memory: databases with cache=shared create multiple connections in the pool, causing intermittent \"no such table\" errors. SQLite's shared cache for in-memory databases only works reliably with a single connection.\n\nRoot cause: Missing db.SetMaxOpenConns(1) after sql.Open() for :memory: databases.\n\nImpact: 37 test failures in VC project, affects all consumers using :memory: for testing.","acceptance_criteria":"- Add db.SetMaxOpenConns(1) for :memory: databases only\n- Verify VC test suite passes (37 previously failing tests)\n- Add a test in Beads that reproduces the issue\n- Document the pool limitation in code comments\n- Release as Beads v0.21.7","status":"closed","priority":0,"issue_type":"bug","created_at":"2025-11-04T00:52:56.318619-08:00","updated_at":"2025-11-05T11:31:27.50439-08:00","closed_at":"2025-11-05T00:50:00.558124-08:00","source_repo":"."} @@ -274,7 +274,7 @@ {"id":"bd-b4b0","content_hash":"ab3833b7a2cd79e39cbf6e41e35da88c8c45581dff3862bad2b8476b37c3b494","title":"Implement fs bridge layer for WASM (Go syscall/js to Node.js fs)","description":"Go's os package in WASM returns 'not implemented on js' for mkdir and other file operations. Need to create a bridge layer that:\n\n1. Detects WASM environment (GOOS=js)\n2. Uses syscall/js to call Node.js fs module functions\n3. Implements wrappers for:\n - os.MkdirAll\n - os.ReadFile / os.WriteFile\n - os.Open / os.Create\n - os.Stat / os.Lstat\n - filepath operations\n \nApproach:\n- Create internal/wasm/fs_bridge.go with //go:build js \u0026\u0026 wasm\n- Export Node.js fs functions to Go using global.readFileSync, global.writeFileSync, etc.\n- Wrap in Go API that matches os package signatures\n- Update beads.go and storage layer to use bridge when in WASM\n\nThis unblocks bd-4462 (basic WASM testing) and [deleted:bd-5bbf] (feature parity testing).","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-02T22:22:42.796412-08:00","updated_at":"2025-11-03T22:16:38.855334-08:00","closed_at":"2025-11-02T22:47:49.586218-08:00","source_repo":".","dependencies":[{"issue_id":"bd-b4b0","depends_on_id":"bd-44d0","type":"parent-child","created_at":"2025-11-02T22:23:49.585675-08:00","created_by":"stevey"}]} {"id":"bd-b501fcc1","content_hash":"4cb17f88a8299c0a297b42946c4eaab91fb3f364ba8cd83fe2ee9ff11cb87822","title":"Unit tests for Debouncer","description":"Test debouncer batches multiple triggers into single action. Test timer reset on subsequent triggers. Test cancel during wait. Test thread safety.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-29T19:42:29.86146-07:00","updated_at":"2025-10-31T17:54:06.880513-07:00","closed_at":"2025-10-31T17:54:06.880513-07:00","source_repo":"."} {"id":"bd-b54c","content_hash":"1e4750bb1f7a113f3b9b1586927bf1552c60902c8e87243b4958a98e2e6fe43a","title":"Document Claude Code for Web SessionStart hook","description":"Create documentation for using bd in Claude Code for Web:\n\n## Documentation locations\n- README.md - Add Claude Code for Web section\n- Create docs/CLAUDE_CODE_WEB.md with detailed instructions\n\n## SessionStart hook example\n```json\n{\n \"sessionStart\": {\n \"script\": \"npm install -g @beads/bd \u0026\u0026 bd init --quiet --prefix bd || true\"\n }\n}\n```\n\n## Documentation should cover\n- How to configure SessionStart hook in .claude/settings.json\n- Verification: Check bd is installed (bd --version)\n- Basic workflow in Claude Code for Web\n- Troubleshooting common issues\n- Note about network restrictions and why npm approach works\n\n## Examples\n- Creating issues in web sandbox\n- Syncing with git in web environment\n- Using MCP server (if applicable)","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-02T23:40:15.362379-08:00","updated_at":"2025-11-03T10:31:45.382915-08:00","closed_at":"2025-11-03T10:31:45.382915-08:00","source_repo":".","dependencies":[{"issue_id":"bd-b54c","depends_on_id":"bd-febc","type":"parent-child","created_at":"2025-11-02T23:40:32.991889-08:00","created_by":"daemon"}]} -{"id":"bd-b55e2ac2","content_hash":"dbcecb8b95f9f2939d97c61bd8cbe331bea866f47600bded213d3122e311c356","title":"Fix autoimport tests for content-hash collision scoring","description":"## Overview\nThree autoimport tests are failing after bd-cbed9619.4 because they expect behavior based on the old reference-counting collision resolution, but the system now uses deterministic content-hash scoring.\n\n## Failing Tests\n1. `TestAutoImportMultipleCollisionsRemapped` - expects local versions preserved\n2. `TestAutoImportAllCollisionsRemapped` - expects local versions preserved \n3. `TestAutoImportCollisionRemapMultipleFields` - expects specific collision resolution behavior\n\n## Root Cause\nThese tests were written when ScoreCollisions used reference counting to determine which version to keep. Now it uses content-hash comparison (introduced in commit 2e87329), which produces different but deterministic results.\n\n## Example\nOld behavior: Issue with more references would be kept\nNew behavior: Issue with lexicographically lower content hash is kept\n\n## Solution\nUpdate each test to:\n1. Verify the new content-hash based behavior is correct\n2. Check that the remapped issue (not necessarily local/remote) has the expected content\n3. Ensure dependencies are preserved on the correct remapped issue\n\n## Acceptance Criteria\n- All three autoimport tests pass\n- Tests verify content-hash determinism (same collision always resolves the same way)\n- Tests check dependency preservation on remapped issues\n- Test documentation explains content-hash scoring expectations\n\n## Files to Modify\n- `cmd/bd/autoimport_collision_test.go`\n\n## Testing\nRun: `go test ./cmd/bd -run \"TestAutoImport.*Collision\" -v`","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-28T19:17:28.358028-07:00","updated_at":"2025-11-08T15:58:44.909873-08:00","closed_at":"2025-11-08T15:58:44.909873-08:00","source_repo":"."} +{"id":"bd-b55e2ac2","content_hash":"44122b61b1dcd06407ecf36f57577ea72c5df6dc8cc2a8c1b173b37d16a10267","title":"Fix autoimport tests for content-hash collision scoring","description":"## Overview\nThree autoimport tests are failing after bd-cbed9619.4 because they expect behavior based on the old reference-counting collision resolution, but the system now uses deterministic content-hash scoring.\n\n## Failing Tests\n1. `TestAutoImportMultipleCollisionsRemapped` - expects local versions preserved\n2. `TestAutoImportAllCollisionsRemapped` - expects local versions preserved \n3. `TestAutoImportCollisionRemapMultipleFields` - expects specific collision resolution behavior\n\n## Root Cause\nThese tests were written when ScoreCollisions used reference counting to determine which version to keep. Now it uses content-hash comparison (introduced in commit 2e87329), which produces different but deterministic results.\n\n## Example\nOld behavior: Issue with more references would be kept\nNew behavior: Issue with lexicographically lower content hash is kept\n\n## Solution\nUpdate each test to:\n1. Verify the new content-hash based behavior is correct\n2. Check that the remapped issue (not necessarily local/remote) has the expected content\n3. Ensure dependencies are preserved on the correct remapped issue\n\n## Acceptance Criteria\n- All three autoimport tests pass\n- Tests verify content-hash determinism (same collision always resolves the same way)\n- Tests check dependency preservation on remapped issues\n- Test documentation explains content-hash scoring expectations\n\n## Files to Modify\n- `cmd/bd/autoimport_collision_test.go`\n\n## Testing\nRun: `go test ./cmd/bd -run \"TestAutoImport.*Collision\" -v`","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-28T19:17:28.358028-07:00","updated_at":"2025-11-08T15:58:44.909873-08:00","closed_at":"2025-11-08T15:58:44.909873-08:00","source_repo":"."} {"id":"bd-b5a3","content_hash":"d58f635721d24b7761782f83df452a67f794080d2c41cb4f6fad2f27ef2cf0b6","title":"Extract Daemon struct and config into internal/daemonrunner","description":"Create internal/daemonrunner with Config struct and Daemon struct. Move daemon runtime logic from cmd/bd/daemon.go Run function into Daemon.Start/Stop methods.","notes":"Refactoring complete! Created internal/daemonrunner package with:\n- Config struct (config.go)\n- Daemon struct with Start/Stop methods (daemon.go)\n- RPC server lifecycle (rpc.go)\n- Sync loop implementation (sync.go)\n- Git operations (git.go)\n- Process management (process.go, flock_*.go)\n- Logger setup (logger.go)\n- Platform-specific signal handling (signals_*.go)\n- Database fingerprint validation (fingerprint.go)\n\nBuild succeeds and most daemon tests pass. Import functionality still delegated to cmd/bd (marked with TODO(bd-b5a3)).","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-01T11:41:14.843103-07:00","updated_at":"2025-11-01T20:23:46.475885-07:00","closed_at":"2025-11-01T20:23:46.475888-07:00","source_repo":"."} {"id":"bd-b6b2","content_hash":"6d2b2f1bbec6b9aa956e5e84c6b78da699a72a487d2317c6533215d574d2209f","title":"Feature with design","description":"This is a description","design":"Use MVC pattern","acceptance_criteria":"All tests pass","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-10-31T21:40:34.612465-07:00","updated_at":"2025-11-04T11:10:23.533636-08:00","closed_at":"2025-11-04T11:10:23.533638-08:00","source_repo":"."} {"id":"bd-b7d2","content_hash":"cd78e03d80898095a2f7f56c7f000b50e9e3be7b2416797d11f4640e5a0e583a","title":"Add sync.branch configuration","description":"Add configuration layer to support sync.branch setting via config file, environment variable, or CLI flag.\n\nTasks:\n- Add sync.branch field to config schema\n- Add BEADS_SYNC_BRANCH environment variable\n- Add --branch flag to bd init\n- Add bd config get/set sync.branch commands\n- Validation (branch name format, conflicts)\n- Config migration for existing users\n\nEstimated effort: 1-2 days","acceptance_criteria":"- Can set sync.branch via config file, env var, or CLI\n- bd config get sync.branch returns configured value\n- Invalid branch names rejected with clear error\n- Backward compatible (empty = current branch)","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-02T15:22:35.560141-08:00","updated_at":"2025-11-04T11:10:23.533911-08:00","closed_at":"2025-11-04T11:10:23.533913-08:00","source_repo":".","dependencies":[{"issue_id":"bd-b7d2","depends_on_id":"bd-a101","type":"parent-child","created_at":"2025-11-02T15:22:48.356847-08:00","created_by":"stevey"}]} @@ -285,8 +285,8 @@ {"id":"bd-bdhn","content_hash":"ddbc003327e0492285b53fd765e90a816b9cea1e4cf9fc8797e8a465a1e834bd","title":"bd message: Add input validation for --importance flag","description":"The --importance flag accepts any string without validation, leading to confusing server errors.\n\n**Location:** cmd/bd/message.go:256-258\n\n**Fix:**\n- Add flag validation for: low, normal, high, urgent\n- Add shell completion support\n- Validate in runMessageSend before sending\n\n**Impact:** Better UX, prevents confusing errors","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-08T12:54:26.43027-08:00","updated_at":"2025-11-08T12:57:59.65367-08:00","closed_at":"2025-11-08T12:57:59.65367-08:00","source_repo":".","dependencies":[{"issue_id":"bd-bdhn","depends_on_id":"bd-6uix","type":"parent-child","created_at":"2025-11-08T12:55:54.910841-08:00","created_by":"daemon"}]} {"id":"bd-be7a","content_hash":"d9043a7a49f8e42dc88c3c01aaa178c1560b67c1637c3373b39c387272e8b725","title":"Create npm package structure with package.json","description":"Set up initial npm package structure for @beads/bd:\n\n## Files to create\n- npm/package.json - Package metadata, dependencies, scripts\n- npm/bin/bd - CLI wrapper script that invokes native binary\n- npm/.gitignore - Ignore downloaded binaries\n- npm/README.md - Installation and usage instructions\n\n## package.json structure\n- Name: @beads/bd (scoped package)\n- Main: index.js (exports binary path)\n- Bin: bin/bd (CLI entry point)\n- Scripts: postinstall (download binary)\n- Keywords: issue-tracker, cli, beads, bd\n- License: MIT\n\n## Bin wrapper\nSimple Node.js script that:\n- Spawns native binary with child_process.spawn\n- Passes through all arguments and stdio\n- Exits with binary's exit code","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-02T23:39:47.416779-08:00","updated_at":"2025-11-03T10:31:45.381258-08:00","closed_at":"2025-11-03T10:31:45.381258-08:00","source_repo":".","dependencies":[{"issue_id":"bd-be7a","depends_on_id":"bd-febc","type":"parent-child","created_at":"2025-11-02T23:40:32.923859-08:00","created_by":"daemon"}]} {"id":"bd-bgca","content_hash":"c617d03baef137f2425cea14eb5346012e556b35e9048f0601fe8d719b5b705f","title":"Latency test manual","description":"","status":"closed","priority":3,"issue_type":"task","created_at":"2025-11-08T00:04:25.028223-08:00","updated_at":"2025-11-08T00:06:46.169654-08:00","closed_at":"2025-11-08T00:06:46.169654-08:00","source_repo":"."} -{"id":"bd-biwp","content_hash":"0e10fbd7c9acb4a476010f29f0669b76613acb8b05302657e894f9a255aa3cc7","title":"Support local-only git repos without remote origin","description":"Daemon crashes when working with local git repos that don't have origin remote configured. Should gracefully degrade to local-only mode: skip git pull/push operations but maintain daemon features (RPC server, auto-flush, JSONL export).","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-11-09T16:09:50.677769-08:00","updated_at":"2025-11-09T16:16:56.588548-08:00","closed_at":"2025-11-09T16:16:56.588548-08:00","external_ref":"gh#279","source_repo":"."} -{"id":"bd-br8","content_hash":"f1a57b3f4bb55c4b9c92689554d28399c7edacf7aa12c65fd046b6f3680b48ba","title":"Implement `bd setup claude` command for Claude Code integration","description":"Create a `bd setup claude` command that installs Claude Code integration files (slash commands and hooks). This is idempotent and safe to run multiple times.","design":"## Implementation\n\nCreate `cmd/bd/setup.go` with subcommand `claude` that installs hooks via **JSON configuration** (Claude Code's native hook system).\n\n### Command Interface\n```bash\nbd setup claude # Install globally (default)\nbd setup claude --project # Install for this project only\nbd setup claude --check # Verify installation\nbd setup claude --remove # Remove bd hooks\n```\n\n### Claude Code Hook Architecture\n\n**Claude Code uses JSON configuration, NOT file discovery:**\n- Hooks defined in `settings.json` as arrays\n- Multiple tools coexist natively (parallel execution)\n- Configuration-based, not directory-based\n\n**Configuration files:**\n- Global: `~/.claude/settings.json`\n- Project: `./.claude/settings.json` or `./.claude/settings.local.json`\n\n### What Gets Installed\n\n**settings.json configuration only** (no script files needed):\n```json\n{\n \"hooks\": {\n \"SessionStart\": [\n {\n \"matcher\": \"\",\n \"hooks\": [\n {\n \"type\": \"command\",\n \"command\": \"bd prime\"\n }\n ]\n }\n ],\n \"PreCompact\": [\n {\n \"matcher\": \"\",\n \"hooks\": [\n {\n \"type\": \"command\",\n \"command\": \"bd prime\"\n }\n ]\n }\n ]\n }\n}\n```\n\n**Why no script files:**\n- `bd prime` is cross-platform (no shell syntax needed)\n- `bd prime` always exits 0 (no `|| true` needed)\n- `bd prime` never writes to stderr (no `2\u003e/dev/null` needed)\n- Simpler: one file to manage (settings.json), not two\n- More portable: no file permissions, no path dependencies\n\n### Installation Logic\n\n```go\nfunc setupClaude(global bool) error {\n var settingsPath string\n \n if global {\n home, _ := os.UserHomeDir()\n settingsPath = filepath.Join(home, \".claude/settings.json\")\n } else {\n settingsPath = \".claude/settings.local.json\"\n }\n \n // Update settings.json (merge with existing)\n return updateSettingsJSON(settingsPath, addBeadsHooks)\n}\n\nfunc updateSettingsJSON(path string, updateFn func(map[string]interface{})) error {\n // Create parent directory if needed\n os.MkdirAll(filepath.Dir(path), 0755)\n \n // Read existing settings (or create empty)\n var settings map[string]interface{}\n if data, err := os.ReadFile(path); err == nil {\n json.Unmarshal(data, \u0026settings)\n } else {\n settings = make(map[string]interface{})\n }\n \n // Apply updates\n updateFn(settings)\n \n // Write back atomically\n data, _ := json.MarshalIndent(settings, \"\", \" \")\n return atomicWriteFile(path, data, 0644)\n}\n\nfunc addBeadsHooks(settings map[string]interface{}) {\n hooks, _ := settings[\"hooks\"].(map[string]interface{})\n if hooks == nil {\n hooks = make(map[string]interface{})\n settings[\"hooks\"] = hooks\n }\n \n // Add SessionStart hook if not present\n addHookCommand(hooks, \"SessionStart\", \"bd prime\")\n \n // Add PreCompact hook if not present\n addHookCommand(hooks, \"PreCompact\", \"bd prime\")\n}\n\nfunc addHookCommand(hooks map[string]interface{}, event, command string) {\n // Get or create event array\n eventHooks, _ := hooks[event].([]interface{})\n if eventHooks == nil {\n eventHooks = []interface{}{}\n }\n \n // Check if bd hook already registered\n for _, hook := range eventHooks {\n hookMap, _ := hook.(map[string]interface{})\n commands, _ := hookMap[\"hooks\"].([]interface{})\n for _, cmd := range commands {\n cmdMap, _ := cmd.(map[string]interface{})\n if cmdMap[\"command\"] == command {\n fmt.Println(\"✓ Hook already registered:\", event)\n return // Already present\n }\n }\n }\n \n // Add bd hook to array\n newHook := map[string]interface{}{\n \"matcher\": \"\",\n \"hooks\": []interface{}{\n map[string]interface{}{\n \"type\": \"command\",\n \"command\": command,\n },\n },\n }\n \n eventHooks = append(eventHooks, newHook)\n hooks[event] = eventHooks\n fmt.Println(\"✓ Registered hook:\", event)\n}\n```\n\n### Slash Command (Optional)\n\n**`.claude/commands/prime_beads.md`:**\n```markdown\n---\ndescription: Load Beads workflow context\n---\n\nRun `bd prime` to refresh bd workflow understanding.\n```\n\n### Integration with `bd init`\n\nAfter git hooks:\n```go\nif isClaudeDetected() \u0026\u0026 !quietMode {\n fmt.Println(\"\\nClaude Code Integration:\")\n fmt.Println(\" Install hooks to prevent agent from forgetting bd workflow?\")\n fmt.Println(\" (Works with MCP server or CLI approach)\")\n \n choice := promptYesNo(\"Install Claude hooks globally?\")\n if choice {\n setupClaude(true) // global=true\n }\n}\n```\n\n### Safe Multi-Tool Coexistence\n\n**Why this approach is safe:**\n- JSON arrays support multiple tools natively\n- Each tool gets its own array entry\n- Parallel execution (no conflicts)\n- Removal only touches bd entries\n- No file overwriting needed\n\n### Removal\n\n```go\nfunc removeBeadsHooks(settings map[string]interface{}) {\n hooks, _ := settings[\"hooks\"].(map[string]interface{})\n if hooks == nil {\n return\n }\n \n // Remove bd prime hooks from each event\n for _, event := range []string{\"SessionStart\", \"PreCompact\"} {\n removeHookCommand(hooks, event, \"bd prime\")\n }\n}\n\nfunc removeHookCommand(hooks map[string]interface{}, event, command string) {\n eventHooks, _ := hooks[event].([]interface{})\n if eventHooks == nil {\n return\n }\n \n // Filter out bd prime hooks\n var filtered []interface{}\n for _, hook := range eventHooks {\n hookMap, _ := hook.(map[string]interface{})\n commands, _ := hookMap[\"hooks\"].([]interface{})\n \n keepHook := true\n for _, cmd := range commands {\n cmdMap, _ := cmd.(map[string]interface{})\n if cmdMap[\"command\"] == command {\n keepHook = false\n break\n }\n }\n \n if keepHook {\n filtered = append(filtered, hook)\n }\n }\n \n hooks[event] = filtered\n}\n```\n\n### Files to Create\n- `cmd/bd/setup.go` - Setup command with JSON merging logic\n- `cmd/bd/setup_test.go` - Tests for JSON manipulation\n- No hook script files needed (bd prime is self-contained)","acceptance_criteria":"- `bd setup claude` installs .claude/ files\n- Idempotent (can run multiple times safely)\n- Backs up existing files\n- `bd setup claude --check` verifies installation\n- Works when .claude/ doesn't exist (skip with message)\n- Unit tests cover installation logic","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-11-11T23:28:59.374019-08:00","updated_at":"2025-11-12T08:51:23.281292-08:00","closed_at":"2025-11-12T08:51:23.281292-08:00","source_repo":".","dependencies":[{"issue_id":"bd-br8","depends_on_id":"bd-rpn","type":"blocks","created_at":"2025-11-11T23:28:59.375616-08:00","created_by":"daemon"},{"issue_id":"bd-br8","depends_on_id":"bd-90v","type":"parent-child","created_at":"2025-11-11T23:31:23.762685-08:00","created_by":"daemon"}]} +{"id":"bd-biwp","content_hash":"ece37e742d401489872e2735084fc94510f9308c3acff2659b233ab19440ebb4","title":"Support local-only git repos without remote origin","description":"Daemon crashes when working with local git repos that don't have origin remote configured. Should gracefully degrade to local-only mode: skip git pull/push operations but maintain daemon features (RPC server, auto-flush, JSONL export).","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-11-09T16:09:50.677769-08:00","updated_at":"2025-11-09T16:16:56.588548-08:00","closed_at":"2025-11-09T16:16:56.588548-08:00","external_ref":"gh#279","source_repo":"."} +{"id":"bd-br8","content_hash":"3f7413965cebb0a08803c601413ce62ea82af565c63b1747da623ca42a791316","title":"Implement `bd setup claude` command for Claude Code integration","description":"Create a `bd setup claude` command that installs Claude Code integration files (slash commands and hooks). This is idempotent and safe to run multiple times.","design":"## Implementation\n\nCreate `cmd/bd/setup.go` with subcommand `claude` that installs hooks via **JSON configuration** (Claude Code's native hook system).\n\n### Command Interface\n```bash\nbd setup claude # Install globally (default)\nbd setup claude --project # Install for this project only\nbd setup claude --check # Verify installation\nbd setup claude --remove # Remove bd hooks\n```\n\n### Claude Code Hook Architecture\n\n**Claude Code uses JSON configuration, NOT file discovery:**\n- Hooks defined in `settings.json` as arrays\n- Multiple tools coexist natively (parallel execution)\n- Configuration-based, not directory-based\n\n**Configuration files:**\n- Global: `~/.claude/settings.json`\n- Project: `./.claude/settings.json` or `./.claude/settings.local.json`\n\n### What Gets Installed\n\n**settings.json configuration only** (no script files needed):\n```json\n{\n \"hooks\": {\n \"SessionStart\": [\n {\n \"matcher\": \"\",\n \"hooks\": [\n {\n \"type\": \"command\",\n \"command\": \"bd prime\"\n }\n ]\n }\n ],\n \"PreCompact\": [\n {\n \"matcher\": \"\",\n \"hooks\": [\n {\n \"type\": \"command\",\n \"command\": \"bd prime\"\n }\n ]\n }\n ]\n }\n}\n```\n\n**Why no script files:**\n- `bd prime` is cross-platform (no shell syntax needed)\n- `bd prime` always exits 0 (no `|| true` needed)\n- `bd prime` never writes to stderr (no `2\u003e/dev/null` needed)\n- Simpler: one file to manage (settings.json), not two\n- More portable: no file permissions, no path dependencies\n\n### Installation Logic\n\n```go\nfunc setupClaude(global bool) error {\n var settingsPath string\n \n if global {\n home, _ := os.UserHomeDir()\n settingsPath = filepath.Join(home, \".claude/settings.json\")\n } else {\n settingsPath = \".claude/settings.local.json\"\n }\n \n // Update settings.json (merge with existing)\n return updateSettingsJSON(settingsPath, addBeadsHooks)\n}\n\nfunc updateSettingsJSON(path string, updateFn func(map[string]interface{})) error {\n // Create parent directory if needed\n os.MkdirAll(filepath.Dir(path), 0755)\n \n // Read existing settings (or create empty)\n var settings map[string]interface{}\n if data, err := os.ReadFile(path); err == nil {\n json.Unmarshal(data, \u0026settings)\n } else {\n settings = make(map[string]interface{})\n }\n \n // Apply updates\n updateFn(settings)\n \n // Write back atomically\n data, _ := json.MarshalIndent(settings, \"\", \" \")\n return atomicWriteFile(path, data, 0644)\n}\n\nfunc addBeadsHooks(settings map[string]interface{}) {\n hooks, _ := settings[\"hooks\"].(map[string]interface{})\n if hooks == nil {\n hooks = make(map[string]interface{})\n settings[\"hooks\"] = hooks\n }\n \n // Add SessionStart hook if not present\n addHookCommand(hooks, \"SessionStart\", \"bd prime\")\n \n // Add PreCompact hook if not present\n addHookCommand(hooks, \"PreCompact\", \"bd prime\")\n}\n\nfunc addHookCommand(hooks map[string]interface{}, event, command string) {\n // Get or create event array\n eventHooks, _ := hooks[event].([]interface{})\n if eventHooks == nil {\n eventHooks = []interface{}{}\n }\n \n // Check if bd hook already registered\n for _, hook := range eventHooks {\n hookMap, _ := hook.(map[string]interface{})\n commands, _ := hookMap[\"hooks\"].([]interface{})\n for _, cmd := range commands {\n cmdMap, _ := cmd.(map[string]interface{})\n if cmdMap[\"command\"] == command {\n fmt.Println(\"✓ Hook already registered:\", event)\n return // Already present\n }\n }\n }\n \n // Add bd hook to array\n newHook := map[string]interface{}{\n \"matcher\": \"\",\n \"hooks\": []interface{}{\n map[string]interface{}{\n \"type\": \"command\",\n \"command\": command,\n },\n },\n }\n \n eventHooks = append(eventHooks, newHook)\n hooks[event] = eventHooks\n fmt.Println(\"✓ Registered hook:\", event)\n}\n```\n\n### Slash Command (Optional)\n\n**`.claude/commands/prime_beads.md`:**\n```markdown\n---\ndescription: Load Beads workflow context\n---\n\nRun `bd prime` to refresh bd workflow understanding.\n```\n\n### Integration with `bd init`\n\nAfter git hooks:\n```go\nif isClaudeDetected() \u0026\u0026 !quietMode {\n fmt.Println(\"\\nClaude Code Integration:\")\n fmt.Println(\" Install hooks to prevent agent from forgetting bd workflow?\")\n fmt.Println(\" (Works with MCP server or CLI approach)\")\n \n choice := promptYesNo(\"Install Claude hooks globally?\")\n if choice {\n setupClaude(true) // global=true\n }\n}\n```\n\n### Safe Multi-Tool Coexistence\n\n**Why this approach is safe:**\n- JSON arrays support multiple tools natively\n- Each tool gets its own array entry\n- Parallel execution (no conflicts)\n- Removal only touches bd entries\n- No file overwriting needed\n\n### Removal\n\n```go\nfunc removeBeadsHooks(settings map[string]interface{}) {\n hooks, _ := settings[\"hooks\"].(map[string]interface{})\n if hooks == nil {\n return\n }\n \n // Remove bd prime hooks from each event\n for _, event := range []string{\"SessionStart\", \"PreCompact\"} {\n removeHookCommand(hooks, event, \"bd prime\")\n }\n}\n\nfunc removeHookCommand(hooks map[string]interface{}, event, command string) {\n eventHooks, _ := hooks[event].([]interface{})\n if eventHooks == nil {\n return\n }\n \n // Filter out bd prime hooks\n var filtered []interface{}\n for _, hook := range eventHooks {\n hookMap, _ := hook.(map[string]interface{})\n commands, _ := hookMap[\"hooks\"].([]interface{})\n \n keepHook := true\n for _, cmd := range commands {\n cmdMap, _ := cmd.(map[string]interface{})\n if cmdMap[\"command\"] == command {\n keepHook = false\n break\n }\n }\n \n if keepHook {\n filtered = append(filtered, hook)\n }\n }\n \n hooks[event] = filtered\n}\n```\n\n### Files to Create\n- `cmd/bd/setup.go` - Setup command with JSON merging logic\n- `cmd/bd/setup_test.go` - Tests for JSON manipulation\n- No hook script files needed (bd prime is self-contained)","acceptance_criteria":"- `bd setup claude` installs .claude/ files\n- Idempotent (can run multiple times safely)\n- Backs up existing files\n- `bd setup claude --check` verifies installation\n- Works when .claude/ doesn't exist (skip with message)\n- Unit tests cover installation logic","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-11-11T23:28:59.374019-08:00","updated_at":"2025-11-12T08:51:23.281292-08:00","closed_at":"2025-11-12T08:51:23.281292-08:00","source_repo":".","dependencies":[{"issue_id":"bd-br8","depends_on_id":"bd-rpn","type":"blocks","created_at":"2025-11-11T23:28:59.375616-08:00","created_by":"daemon"},{"issue_id":"bd-br8","depends_on_id":"bd-90v","type":"parent-child","created_at":"2025-11-11T23:31:23.762685-08:00","created_by":"daemon"}]} {"id":"bd-buol","content_hash":"020dc9dbbd7f3e2b40c35f01bf8a65cf32ab419c188081493ea4e541bad1442e","title":"Invert control for compact: provide tools for agent-driven compaction","description":"Currently compact requires Anthropic API key because bd calls the AI directly. This is backwards - we should provide tools (like all other bd commands) that let an AI agent perform the compaction. The agent decides what to keep/merge, not bd. Related to GH #243 complaint about API key requirement.","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-11-07T00:27:28.498069-08:00","updated_at":"2025-11-08T01:49:23.46152-08:00","closed_at":"2025-11-07T23:08:51.67473-08:00","source_repo":"."} {"id":"bd-by3x","content_hash":"80149be1ddf4ef26d5d56c444895be01ec8b59492c258c2365fa1c2619061bbd","title":"Windows binaries lack SQLite support (GH #253)","description":"Windows users installing via install.ps1 get \"sql: unknown driver sqlite\" error. Root cause: GoReleaser was building with CGO_ENABLED=0, which excludes SQLite driver.\n\nFixed by:\n1. Enabling CGO in .goreleaser.yml\n2. Installing MinGW cross-compiler in release workflow\n3. Splitting builds per platform to set correct CC for Windows\n\nNeeds new release to fix for users.","status":"closed","priority":0,"issue_type":"bug","created_at":"2025-11-07T15:54:13.134815-08:00","updated_at":"2025-11-07T15:55:07.024156-08:00","closed_at":"2025-11-07T15:55:07.024156-08:00","source_repo":"."} {"id":"bd-bzfy","content_hash":"90bbde4d90d68728a9377d5d966682dc836740f1be43a0cf80d3cc69002a560b","title":"Integrate beads-merge tool by @neongreen","description":"**Context**: @neongreen built a production-ready 3-way merge tool for JSONL files that works with both Git and Jujutsu. This is superior to our planned bd resolve-conflicts because it prevents conflicts proactively instead of resolving them after the fact.\n\n**Tool**: https://github.com/neongreen/mono/tree/main/beads-merge\n\n**What it does**:\n- 3-way merge of JSONL files (base, left, right)\n- Field-level merging (titles, status, priority, etc.)\n- Smart dependency merging (union + dedup)\n- Conflict markers for unresolvable conflicts\n- Exit code 1 for conflicts (standard)\n\n**Integration options**:\n\n1. **Recommend (minimal effort)** - Document in AGENTS.md + TROUBLESHOOTING.md\n2. **Bundle binary** - Include in releases (cross-platform builds)\n3. **Port to Go** - Reimplement in bd codebase\n4. **Auto-install hook** - During bd init, offer to install merge driver\n\n**Recommendation**: Start with option 1 (document), then option 2 (bundle) once proven.\n\n**Related**: bd-5f483051 (bd resolve-conflicts - can close as superseded)","notes":"Created GitHub issue to discuss integration approach with @neongreen: https://github.com/neongreen/mono/issues/240\n\nAwaiting their preference on:\n1. Vendor with attribution (fastest)\n2. Extract as importable module (best long-term)\n3. Keep as separate tool (current state)\n\nNext: Wait for response before proceeding with integration.\n\nUPDATE 2025-11-06: @neongreen gave permission to vendor! Quote: \"I switched from beads to my own thing (tk) so I'm very happy to give beads-merge away — feel free to move it into the beads repo and I will point mono's readme to beads\"\n\nNext: Vendor beads-merge with full attribution","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-11-05T11:31:44.906652-08:00","updated_at":"2025-11-06T18:19:16.233387-08:00","closed_at":"2025-11-06T15:38:37.052274-08:00","source_repo":"."} @@ -321,7 +321,7 @@ {"id":"bd-ce75","content_hash":"025d43c12e9cc08c6d1db0b4a97f7a086a1a9f24f07769d48a7e2666d04ea217","title":"Test parent issue","description":"","status":"closed","priority":3,"issue_type":"task","created_at":"2025-11-07T16:08:24.952167-08:00","updated_at":"2025-11-07T22:07:17.343848-08:00","closed_at":"2025-11-07T22:07:17.34385-08:00","source_repo":"."} {"id":"bd-chsc","content_hash":"ea167029efad3c506e42dfc20748a6ada0914aa93cb04caa14a48ca223386365","title":"Test lowercase p0","description":"","status":"closed","priority":0,"issue_type":"task","created_at":"2025-11-05T12:58:41.457875-08:00","updated_at":"2025-11-05T12:58:44.721486-08:00","closed_at":"2025-11-05T12:58:44.721486-08:00","source_repo":"."} {"id":"bd-cjxp","content_hash":"2a2c0aa49be01be64c5e0a6bd24ebd7b762846d31a06fd8e9360672fb476b879","title":"Bug P0","description":"","status":"closed","priority":0,"issue_type":"bug","assignee":"alice","created_at":"2025-11-07T19:00:22.536449-08:00","updated_at":"2025-11-07T22:07:17.345535-08:00","closed_at":"2025-11-07T21:55:09.429643-08:00","source_repo":"."} -{"id":"bd-ckvw","content_hash":"a4b27c0e21e3ae0a1e8fb9f64913c286164ff6746c657d70bb7cbbdbf2e365c9","title":"Add schema compatibility probe to prevent silent migration failures","description":"Issue #262 revealed a serious bug: migrations may fail silently, causing UNIQUE constraint errors later.\n\nRoot cause:\n- sqlite.New() runs migrations once on open\n- checkVersionMismatch() prints 'database will be upgraded automatically' but only updates metadata\n- If migrations fail or daemon runs older version, queries expecting new columns fail with 'no such column'\n- Import logic misinterprets this as 'not found' and tries INSERT on existing ID\n- Result: UNIQUE constraint failed: issues.id\n\nFix strategy (minimal):\n1. Add schema probe in sqlite.New() after RunMigrations\n - SELECT all expected columns from all tables with LIMIT 0\n - If fails, retry RunMigrations and probe again\n - If still fails, return fatal error with clear message\n2. Fix checkVersionMismatch to not claim 'will upgrade' unless probe passes\n3. Only update bd_version after successful migration probe\n4. Add schema verification before import operations\n5. Map 'no such column' errors to clear actionable message\n\nRelated: #262","design":"Minimal path (now includes daemon gating):\n\n1. Schema probe in sqlite.New()\n - After RunMigrations, verify all expected columns exist\n - SELECT id, title, description, created_at, updated_at, closed_at, content_hash, external_ref, source_repo, compacted_at, compacted_at_commit FROM issues LIMIT 0\n - Also probe: dependencies, labels, events, dirty_issues, export_hashes, snapshots, child_counters\n - If probe fails: retry RunMigrations once, probe again\n - If still fails: return fatal error with missing columns/tables\n\n2. Fix checkVersionMismatch()\n - Don't claim 'will be upgraded automatically' unless probe verified\n - Only update bd_version after successful probe\n\n3. Better error surfacing\n - Wrap storage errors: if 'no such column/table', return ErrSchemaIncompatible\n - Actionable message: 'Database schema is incompatible. Run bd doctor to diagnose.'\n\n4. Add 'bd doctor' command\n - Runs migrations + probe\n - Reports missing columns/tables\n - Suggests fixes (upgrade daemon, run migrations manually, etc.)\n - Exit 1 if incompatible\n\n5. Daemon version gating (REQUIRED - prevents future schema bugs)\n - On RPC connect, client/daemon exchange semver\n - If client.minor \u003e daemon.minor: refuse RPC, print 'Client vX.Y requires daemon upgrade. Run: bd daemons killall'\n - Forces users to restart daemon when bd binary is upgraded\n - Prevents stale daemon serving requests with old schema assumptions\n - Already documented best practice, now enforced\n\nEstimated effort: M-L (3-5h with daemon gating + bd doctor)","status":"closed","priority":0,"issue_type":"bug","created_at":"2025-11-08T13:23:26.934246-08:00","updated_at":"2025-11-08T13:53:29.219542-08:00","closed_at":"2025-11-08T13:53:29.219542-08:00","source_repo":"."} +{"id":"bd-ckvw","content_hash":"ca02c9be5b672a144fd2348f5b18b1ea6082e74a8de0349809785e05f9a91144","title":"Add schema compatibility probe to prevent silent migration failures","description":"Issue #262 revealed a serious bug: migrations may fail silently, causing UNIQUE constraint errors later.\n\nRoot cause:\n- sqlite.New() runs migrations once on open\n- checkVersionMismatch() prints 'database will be upgraded automatically' but only updates metadata\n- If migrations fail or daemon runs older version, queries expecting new columns fail with 'no such column'\n- Import logic misinterprets this as 'not found' and tries INSERT on existing ID\n- Result: UNIQUE constraint failed: issues.id\n\nFix strategy (minimal):\n1. Add schema probe in sqlite.New() after RunMigrations\n - SELECT all expected columns from all tables with LIMIT 0\n - If fails, retry RunMigrations and probe again\n - If still fails, return fatal error with clear message\n2. Fix checkVersionMismatch to not claim 'will upgrade' unless probe passes\n3. Only update bd_version after successful migration probe\n4. Add schema verification before import operations\n5. Map 'no such column' errors to clear actionable message\n\nRelated: #262","design":"Minimal path (now includes daemon gating):\n\n1. Schema probe in sqlite.New()\n - After RunMigrations, verify all expected columns exist\n - SELECT id, title, description, created_at, updated_at, closed_at, content_hash, external_ref, source_repo, compacted_at, compacted_at_commit FROM issues LIMIT 0\n - Also probe: dependencies, labels, events, dirty_issues, export_hashes, snapshots, child_counters\n - If probe fails: retry RunMigrations once, probe again\n - If still fails: return fatal error with missing columns/tables\n\n2. Fix checkVersionMismatch()\n - Don't claim 'will be upgraded automatically' unless probe verified\n - Only update bd_version after successful probe\n\n3. Better error surfacing\n - Wrap storage errors: if 'no such column/table', return ErrSchemaIncompatible\n - Actionable message: 'Database schema is incompatible. Run bd doctor to diagnose.'\n\n4. Add 'bd doctor' command\n - Runs migrations + probe\n - Reports missing columns/tables\n - Suggests fixes (upgrade daemon, run migrations manually, etc.)\n - Exit 1 if incompatible\n\n5. Daemon version gating (REQUIRED - prevents future schema bugs)\n - On RPC connect, client/daemon exchange semver\n - If client.minor \u003e daemon.minor: refuse RPC, print 'Client vX.Y requires daemon upgrade. Run: bd daemons killall'\n - Forces users to restart daemon when bd binary is upgraded\n - Prevents stale daemon serving requests with old schema assumptions\n - Already documented best practice, now enforced\n\nEstimated effort: M-L (3-5h with daemon gating + bd doctor)","status":"closed","priority":0,"issue_type":"bug","created_at":"2025-11-08T13:23:26.934246-08:00","updated_at":"2025-11-08T13:53:29.219542-08:00","closed_at":"2025-11-08T13:53:29.219542-08:00","source_repo":"."} {"id":"bd-csvy","content_hash":"88e2ed15c2fe9d9622b16daa530907af7069ef69e621c74dc2a2fafa1da4ac8c","title":"Add tests for merge driver auto-config in bd init","description":"Add comprehensive tests for the merge driver auto-configuration functionality in `bd init`.\n\n**Test cases needed:**\n- Auto-install in quiet mode\n- Skip with --skip-merge-driver flag\n- Detect already-installed merge driver\n- Append to existing .gitattributes\n- Interactive prompt behavior (if feasible)\n\n**File:** `cmd/bd/init_test.go`","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-05T19:27:04.133078-08:00","updated_at":"2025-11-06T18:19:16.233673-08:00","closed_at":"2025-11-06T15:56:36.014814-08:00","source_repo":".","dependencies":[{"issue_id":"bd-csvy","depends_on_id":"bd-32nm","type":"discovered-from","created_at":"2025-11-05T19:27:04.134299-08:00","created_by":"daemon"}]} {"id":"bd-d19a","content_hash":"5ff9ba5e70c3e3eeaff40887421797e30dfb75e56e97fcaaf3f3d32332f22aa2","title":"Fix import failure on missing parent issues","description":"Import process fails atomically when JSONL references deleted parent issues. Implement hybrid solution: topological sorting + parent resurrection to handle deleted parents gracefully while maintaining referential integrity. See docs/import-bug-analysis-bd-3xq.md for full analysis.","status":"closed","priority":0,"issue_type":"epic","created_at":"2025-11-04T12:31:30.994759-08:00","updated_at":"2025-11-05T00:08:42.814239-08:00","closed_at":"2025-11-05T00:08:42.814243-08:00","source_repo":"."} {"id":"bd-d33c","content_hash":"d0820d5dd6ea4ab198e013861d3d7d01da701daa8ab8ec59ad5ef855e6f83b2b","title":"Separate process/lock/PID concerns into process.go","description":"Create internal/daemonrunner/process.go with: acquireDaemonLock, PID file read/write, stopDaemon, isDaemonRunning, getPIDFilePath, socket path helpers, version check.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-01T11:41:14.871122-07:00","updated_at":"2025-11-01T23:43:55.66159-07:00","closed_at":"2025-11-01T23:43:55.66159-07:00","source_repo":"."} @@ -339,7 +339,7 @@ {"id":"bd-de0h","content_hash":"8b8b43683607e73012cf8bd7cf8631c6ae34498d0c93ca5b77d3f68944c8088d","title":"bd message: Add HTTP client timeout to prevent hangs","description":"HTTP client in `sendAgentMailRequest` uses default http.Post with no timeout.\n\n**Location:** cmd/bd/message.go:181\n\n**Problem:**\n- Can hang indefinitely if server is unresponsive\n- No way to cancel stuck requests\n- Poor UX in flaky networks\n\n**Fix:**\n```go\nclient := \u0026http.Client{Timeout: 30 * time.Second}\nresp, err := client.Post(url, \"application/json\", bytes.NewReader(reqBody))\n```\n\n**Impact:** Production reliability and security issue","status":"closed","priority":0,"issue_type":"bug","created_at":"2025-11-08T12:54:24.942645-08:00","updated_at":"2025-11-08T12:56:59.948929-08:00","closed_at":"2025-11-08T12:56:59.948929-08:00","source_repo":".","dependencies":[{"issue_id":"bd-de0h","depends_on_id":"bd-6uix","type":"parent-child","created_at":"2025-11-08T12:55:54.860847-08:00","created_by":"daemon"}]} {"id":"bd-df11","content_hash":"9d688c3fe5f4994ab29ed22c8c4ae467f2069c4cbb676a2168303b2ffcba48c4","title":"Add import metrics for external_ref matching statistics","description":"Add observability for external_ref matching behavior during imports to help debug and optimize import operations.\n\nMetrics to track:\n- Number of issues matched by external_ref\n- Number of issues matched by ID\n- Number of issues matched by content hash\n- Number of external_ref updates vs creates\n- Average import time with vs without external_ref\n\nOutput format:\n- Add to ImportResult struct\n- Include in import command output\n- Consider structured logging\n\nUse cases:\n- Debugging slow imports\n- Understanding match distribution\n- Optimizing import performance\n\nRelated: bd-1022","status":"closed","priority":4,"issue_type":"chore","created_at":"2025-11-02T15:32:46.157899-08:00","updated_at":"2025-11-08T03:54:04.856564-08:00","closed_at":"2025-11-08T02:20:01.01371-08:00","source_repo":"."} {"id":"bd-df190564","content_hash":"4966d22faf43b7de1b27315f85365d7ed896741e4e589ed01ee16f4c2f600a24","title":"bd repair-deps - Orphaned dependency cleaner","description":"Find and fix orphaned dependency references.\n\nImplementation:\n- Scan all issues for dependencies pointing to non-existent issues\n- Report orphaned refs\n- Auto-fix with --fix flag\n- Interactive mode with --interactive\n\nFiles: cmd/bd/repair_deps.go (new)","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-29T19:42:29.852745-07:00","updated_at":"2025-10-31T18:24:19.418221-07:00","closed_at":"2025-10-31T18:24:19.418221-07:00","source_repo":"."} -{"id":"bd-dxdn","content_hash":"1ad5838334d77403d884787d2b5c99b88c6fa28fb08a16014246c8db0f9f4020","title":"bd ready taking 5 seconds with 132 issues (89 closed)","description":"User reports bd ready is annoyingly slow on M2 Mac - 5 seconds for 132 issues (89 closed). Started noticing after hash-based IDs update. Need to investigate performance regression. Reported in GH #243.","notes":"Root cause identified: Not a query performance issue, but stale daemon locks causing 5s timeout delays.\n\nFixed in bd-ndyz (closed) via 5 sub-issues:\n- bd-expt: Fast-fail socket checks (200ms timeout)\n- bd-wgu4: Lock probe before RPC attempts\n- bd-1mzt: Self-heal stale artifacts\n- bd-vcg5: Panic recovery + socket cleanup\n- bd-j7e2: RPC diagnostics (BD_RPC_DEBUG)\n\nAll fixes merged. Ready for v0.22.2 release.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-07T00:26:30.359512-08:00","updated_at":"2025-11-08T02:35:47.956638-08:00","closed_at":"2025-11-08T02:35:47.956638-08:00","source_repo":"."} +{"id":"bd-dxdn","content_hash":"1165b0e3355b571db2b55d49d543b81c314d46988cb0905b0214e00baf8b4de3","title":"bd ready taking 5 seconds with 132 issues (89 closed)","description":"User reports bd ready is annoyingly slow on M2 Mac - 5 seconds for 132 issues (89 closed). Started noticing after hash-based IDs update. Need to investigate performance regression. Reported in GH #243.","notes":"Root cause identified: Not a query performance issue, but stale daemon locks causing 5s timeout delays.\n\nFixed in bd-ndyz (closed) via 5 sub-issues:\n- bd-expt: Fast-fail socket checks (200ms timeout)\n- bd-wgu4: Lock probe before RPC attempts\n- bd-1mzt: Self-heal stale artifacts\n- bd-vcg5: Panic recovery + socket cleanup\n- bd-j7e2: RPC diagnostics (BD_RPC_DEBUG)\n\nAll fixes merged. Ready for v0.22.2 release.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-07T00:26:30.359512-08:00","updated_at":"2025-11-08T02:35:47.956638-08:00","closed_at":"2025-11-08T02:35:47.956638-08:00","source_repo":"."} {"id":"bd-e044","content_hash":"8393c18d7f6edfed3d3e360a32a3075a9e0d9caa6f02d704774482aa1d9b0a7f","title":"Add mermaid output format for bd dep tree","description":"Add visual dependency graph output using Mermaid format for better visualization of issue relationships.\n\nExample usage:\n bd dep tree --format mermaid \u003cissue-id\u003e\n bd dep tree --format mermaid bd-42 \u003e graph.md\n\nThis would output Mermaid syntax that can be rendered in GitHub, documentation sites, or Mermaid live editor.\n\nImplementation notes:\n- Add --format flag to dep tree command\n- Support 'text' (default) and 'mermaid' formats\n- Mermaid graph should show issue IDs, titles, and dependency types\n- Consider using flowchart LR or graph TD syntax","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-11-03T18:10:18.978383-08:00","updated_at":"2025-11-03T20:55:06.696363-08:00","closed_at":"2025-11-03T20:55:06.69637-08:00","source_repo":"."} {"id":"bd-e05d","content_hash":"c2f4d60f5bd679d9bf609c35efc9c15e8dd52130fb9b68eacfe47bdda910ecd7","title":"Investigate and optimize test suite performance","description":"Test suite is taking very long to run (\u003e45s for cmd/bd tests, full suite timing unknown but was cancelled).\n\nThis impacts development velocity and CI/CD performance.\n\nInvestigation needed:\n- Profile which tests are slowest\n- Identify bottlenecks (disk I/O, network, excessive setup/teardown?)\n- Consider parallelization opportunities\n- Look for redundant test cases\n- Check if integration tests can be optimized","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-02T15:37:44.529955-08:00","updated_at":"2025-11-02T16:35:38.093133-08:00","closed_at":"2025-11-02T16:35:38.093137-08:00","source_repo":"."} {"id":"bd-e1085716","content_hash":"a9385e9f00bc41e5e2258fdfccd9f2cbd5a702764b5f1d036274e6026f8c3e38","title":"bd validate - Comprehensive health check","description":"Run all validation checks in one command.\n\nChecks:\n- Duplicates\n- Orphaned dependencies\n- Test pollution\n- Git conflicts\n\nSupports --fix-all for auto-repair.\n\nDepends on bd-cbed9619.1, bd-0dcea000, bd-31aab707, bd-9826b69a.\n\nFiles: cmd/bd/validate.go (new)","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-29T23:05:13.980679-07:00","updated_at":"2025-11-06T19:36:13.973071-08:00","closed_at":"2025-11-06T19:27:11.734483-08:00","source_repo":"."} @@ -358,7 +358,7 @@ {"id":"bd-ef85","content_hash":"56b7e0c048938940053b127e4f9ed578e797b99dc93d010138ec823efbe7842c","title":"Add --json flags to all bd commands for agent-friendly output","description":"","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-10-31T22:39:45.312496-07:00","updated_at":"2025-10-31T22:39:50.157022-07:00","closed_at":"2025-10-31T22:39:50.157022-07:00","source_repo":"."} {"id":"bd-eimz","content_hash":"03d818a0c6277838251b1bd67f3e88c1aedad81fa458291f27469a807a69fc13","title":"Add Agent Mail to QUICKSTART.md","description":"Mention Agent Mail as optional advanced feature in quickstart guide.\n\nFile: docs/QUICKSTART.md","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-07T22:42:51.357009-08:00","updated_at":"2025-11-08T01:51:40.35021-08:00","closed_at":"2025-11-08T01:07:11.598558-08:00","source_repo":".","dependencies":[{"issue_id":"bd-eimz","depends_on_id":"bd-xzrv","type":"blocks","created_at":"2025-11-07T23:04:09.841956-08:00","created_by":"daemon"}]} {"id":"bd-eiz9","content_hash":"0f1722abb1f24d08d2c643d9cd4109935325eb3ea994166ff88202d0a457b003","title":"Help agents understand version changes with bd info --whats-new","description":"**Problem** (from GH Discussion #239 by @maphew):\nWeekly major versions mean agents need to adapt workflows, but currently there's no efficient way to communicate \"what changed that affects you.\"\n\n**Proposed solutions:**\n\n1. **bd info --whats-new** - Show agent-actionable changes since last version\n ```\n Since v0.20.1:\n • Hash IDs eliminate collisions - remove ID coordination workarounds\n • Event-driven daemon (opt-in) - add BEADS_DAEMON_MODE=events\n • Merge driver auto-configured - conflicts rarer\n ```\n\n2. **Version-aware bd onboard** - Detect version changes and show diff of agent-relevant changes\n\n3. **AGENTS.md top section** - \"🆕 Recent Changes (Last 3 Versions)\" with workflow impacts\n\n**Why agents need this:**\n- Raw CHANGELOG is token-heavy and buried in release details\n- Full bd onboard re-run wasteful if only 2-3 things changed\n- Currently requires user to manually explain updates\n\n**Related:** https://github.com/steveyegge/beads/discussions/239","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-11-06T21:03:30.057576-08:00","updated_at":"2025-11-08T02:42:56.733731-08:00","closed_at":"2025-11-08T02:25:55.509249-08:00","source_repo":"."} -{"id":"bd-epvx","content_hash":"f0acf2bcec5857c61c542764f62c5f5a66cfa74cdafa941c1754db40dd173efc","title":"Create Go adapter library (optional)","description":"For agents written in Go, provide native adapter library instead of shelling out to curl.\n\nAcceptance Criteria:\n- agentmail.Client struct\n- HTTP client with timeout/retry logic\n- Same API as Python adapter\n- Example usage in examples/go-agent/\n- Unit tests\n\nFile: pkg/agentmail/client.go\n\nNote: Lower priority - can shell out to curl initially","status":"closed","priority":3,"issue_type":"feature","created_at":"2025-11-07T22:42:28.781577-08:00","updated_at":"2025-11-08T15:48:57.83973-08:00","closed_at":"2025-11-08T15:48:57.83973-08:00","source_repo":".","dependencies":[{"issue_id":"bd-epvx","depends_on_id":"bd-m9th","type":"blocks","created_at":"2025-11-07T23:04:01.47471-08:00","created_by":"daemon"}]} +{"id":"bd-epvx","content_hash":"abf5a06864cfb4ca280f269b00cffffa859b610eb630001e084b5c9f336831ec","title":"Create Go adapter library (optional)","description":"For agents written in Go, provide native adapter library instead of shelling out to curl.\n\nAcceptance Criteria:\n- agentmail.Client struct\n- HTTP client with timeout/retry logic\n- Same API as Python adapter\n- Example usage in examples/go-agent/\n- Unit tests\n\nFile: pkg/agentmail/client.go\n\nNote: Lower priority - can shell out to curl initially","status":"closed","priority":3,"issue_type":"feature","created_at":"2025-11-07T22:42:28.781577-08:00","updated_at":"2025-11-08T15:48:57.83973-08:00","closed_at":"2025-11-08T15:48:57.83973-08:00","source_repo":".","dependencies":[{"issue_id":"bd-epvx","depends_on_id":"bd-m9th","type":"blocks","created_at":"2025-11-07T23:04:01.47471-08:00","created_by":"daemon"}]} {"id":"bd-eqjc","content_hash":"8acc3d91ca9f9bef36d19358cb7f24eac247583a0e6701036aaff92607474c21","title":"bd init creates nested .beads directories","description":"bd init sometimes creates .beads/.beads/ nested directories, which should never happen. This occurs fairly often and can cause confusion about which .beads directory is active. Need to add validation to detect if already inside a .beads directory and either error or use the parent .beads location.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-06T22:21:22.948727-08:00","updated_at":"2025-11-06T22:22:41.04958-08:00","closed_at":"2025-11-06T22:22:41.04958-08:00","source_repo":"."} {"id":"bd-expt","content_hash":"6e14db64fb24882e4cf544ec24eaa994aba970fd0ae31c72dda2d8ea88560753","title":"RPC fast-fail: stat socket before dial, cap timeouts to 200ms","description":"Eliminate 5s delay when daemon socket is missing by:\n1. Add os.Stat(socketPath) check before dialing in TryConnect\n2. Return (nil, nil) immediately if socket doesn't exist\n3. Set default dial timeout to 200ms in TryConnect\n4. Keep TryConnectWithTimeout for explicit health/status checks (1-2s)\n\nThis prevents clients from waiting through full timeout when no daemon is running.","status":"closed","priority":0,"issue_type":"task","created_at":"2025-11-07T16:42:12.688526-08:00","updated_at":"2025-11-07T22:07:17.345918-08:00","closed_at":"2025-11-07T21:04:21.671436-08:00","source_repo":".","dependencies":[{"issue_id":"bd-expt","depends_on_id":"bd-ndyz","type":"discovered-from","created_at":"2025-11-07T16:42:12.689284-08:00","created_by":"daemon"}]} {"id":"bd-f0d9bcf2","content_hash":"00e0c7b440024e6257d1bac9c1d5af10f8a12ee1726478e4b5bab06e34bfb586","title":"Batch test 1","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-29T15:29:01.795728-07:00","updated_at":"2025-10-31T12:00:43.184078-07:00","closed_at":"2025-10-31T12:00:43.184078-07:00","source_repo":"."} @@ -378,13 +378,13 @@ {"id":"bd-f8b764c9.8","content_hash":"9acb99b9ef8844849c6b684db012f966db5766e0a7e452f9768d8611d90ad9b8","title":"Update JSONL format to use hash IDs","description":"Update JSONL import/export to use hash IDs, store aliases separately.\n\n## Current JSONL Format\n```jsonl\n{\"id\":\"bd-1c63eb84\",\"title\":\"Fix bug\",\"status\":\"open\",...}\n{\"id\":\"bd-9063acda\",\"title\":\"Add test\",\"status\":\"open\",...}\n```\n\n## New JSONL Format (Option A: Include Alias)\n```jsonl\n{\"id\":\"bd-af78e9a2\",\"alias\":1,\"title\":\"Fix bug\",\"status\":\"open\",...}\n{\"id\":\"bd-e5f6a7b8\",\"alias\":2,\"title\":\"Add test\",\"status\":\"open\",...}\n```\n\n## New JSONL Format (Option B: Hash ID Only)\n```jsonl\n{\"id\":\"bd-af78e9a2\",\"title\":\"Fix bug\",\"status\":\"open\",...}\n{\"id\":\"bd-e5f6a7b8\",\"title\":\"Add test\",\"status\":\"open\",...}\n```\n\nStore aliases in separate .beads/aliases.jsonl (local only, git-ignored):\n```jsonl\n{\"hash\":\"bd-af78e9a2\",\"alias\":1}\n{\"hash\":\"bd-e5f6a7b8\",\"alias\":2}\n```\n\n**Recommendation**: Option B (hash only in main JSONL)\n- Cleaner git diffs (no alias conflicts)\n- Aliases are workspace-local preference\n- Main JSONL is canonical, portable\n\n## Export Changes\nFile: cmd/bd/export.go\n```go\n// Export issues with hash IDs\nfor _, issue := range issues {\n json := marshalIssue(issue) // Uses issue.ID (hash)\n // Don't include alias in JSONL\n}\n\n// Separately export aliases to .beads/aliases.jsonl\nexportAliases(issues)\n```\n\n## Import Changes \nFile: cmd/bd/import.go, internal/importer/importer.go\n```go\n// Import issues by hash ID\nissue := unmarshalIssue(line)\n// Assign new alias on import (don't use incoming alias)\nissue.Alias = getNextAlias()\n\n// No collision detection needed! Hash IDs are globally unique\n```\n\n## Dependency Reference Format\nNo change needed - already uses issue IDs:\n```json\n{\"depends_on_id\":\"bd-af78e9a2\",\"type\":\"blocks\"}\n```\n\n## Files to Modify\n- cmd/bd/export.go (use hash IDs)\n- cmd/bd/import.go (import hash IDs, assign aliases)\n- internal/importer/importer.go (remove collision detection!)\n- .gitignore (add .beads/aliases.jsonl)\n\n## Testing\n- Test export produces hash IDs\n- Test import assigns new aliases\n- Test dependencies preserved with hash IDs\n- Test no collision detection triggered","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-29T21:24:47.408106-07:00","updated_at":"2025-10-31T12:32:32.609925-07:00","closed_at":"2025-10-31T12:32:32.609925-07:00","source_repo":".","dependencies":[{"issue_id":"bd-f8b764c9.8","depends_on_id":"bd-f8b764c9","type":"parent-child","created_at":"2025-10-29T21:24:47.409489-07:00","created_by":"stevey"},{"issue_id":"bd-f8b764c9.8","depends_on_id":"bd-f8b764c9.9","type":"blocks","created_at":"2025-10-29T21:24:47.409977-07:00","created_by":"stevey"},{"issue_id":"bd-f8b764c9.8","depends_on_id":"bd-f8b764c9.10","type":"blocks","created_at":"2025-10-29T21:29:45.975499-07:00","created_by":"stevey"}]} {"id":"bd-f8b764c9.9","content_hash":"f248cddca9cd0cbad13c74ee8537251e73d429d863a272259fdef786a97f53d1","title":"Implement hash ID generation in CreateIssue","description":"Replace sequential ID generation with hash-based IDs in CreateIssue function.\n\n## Current Behavior (internal/storage/sqlite/sqlite.go)\n```go\nfunc (s *SQLiteStorage) CreateIssue(ctx context.Context, issue *types.Issue) error {\n // ID comes from auto-increment counter\n // Collisions possible across clones\n}\n```\n\n## New Behavior\n```go\nfunc (s *SQLiteStorage) CreateIssue(ctx context.Context, issue *types.Issue) error {\n // Generate hash ID if not provided\n if issue.ID == \"\" {\n issue.ID = idgen.GenerateHashID(\n issue.Title,\n issue.Description,\n time.Now(),\n s.workspaceID,\n )\n }\n \n // Assign next alias\n issue.Alias = s.getNextAlias()\n \n // Insert with hash ID + alias\n // ...\n}\n```\n\n## Workspace ID Generation\nAdd to database initialization:\n```go\n// Generate stable workspace ID (persisted in .beads/workspace_id)\nworkspaceID := getOrCreateWorkspaceID()\n```\n\nOptions for workspace ID:\n1. Hostname + random suffix\n2. UUID (random)\n3. Git remote URL hash (deterministic per repo)\n\nRecommended: Option 3 (git remote hash) for reproducibility\n\n## Hash Collision Detection\n```go\n// On insert, check for collision (unlikely but possible)\nexisting, err := s.GetIssue(ctx, issue.ID)\nif err == nil {\n // Hash collision! Add random suffix and retry\n issue.ID = issue.ID + \"-\" + randomSuffix(4)\n}\n```\n\n## Files to Create/Modify\n- internal/types/id_generator.go (new)\n- internal/storage/sqlite/sqlite.go (CreateIssue)\n- internal/storage/sqlite/workspace.go (new - workspace ID management)\n- .beads/workspace_id (new file, git-ignored)\n\n## Testing\n- Test hash ID generation is deterministic\n- Test collision detection and retry\n- Test workspace ID persistence\n- Benchmark: hash generation performance (\u003c1μs)","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-29T21:24:29.412237-07:00","updated_at":"2025-10-31T12:32:32.610403-07:00","closed_at":"2025-10-31T12:32:32.610403-07:00","source_repo":".","dependencies":[{"issue_id":"bd-f8b764c9.9","depends_on_id":"bd-f8b764c9","type":"parent-child","created_at":"2025-10-29T21:24:29.413417-07:00","created_by":"stevey"},{"issue_id":"bd-f8b764c9.9","depends_on_id":"bd-f8b764c9.11","type":"blocks","created_at":"2025-10-29T21:24:29.413823-07:00","created_by":"stevey"}]} {"id":"bd-f9a1","content_hash":"97f9387b20f741a9f71ee43b0671b5d970bd594098db299dc871d0b3074c5384","title":"Add index usage verification test for external_ref lookups","description":"Currently we test that idx_issues_external_ref index exists, but we don't verify that it's actually being used by the query planner.\n\nProposed solution:\n- Add test using EXPLAIN QUERY PLAN\n- Verify that 'SEARCH TABLE issues USING INDEX idx_issues_external_ref' appears in plan\n- Ensures O(1) lookup performance is maintained\n\nRelated: bd-1022\nFiles: internal/storage/sqlite/external_ref_test.go:260","status":"closed","priority":3,"issue_type":"task","created_at":"2025-11-02T15:32:09.85419-08:00","updated_at":"2025-11-02T16:04:47.221064-08:00","closed_at":"2025-11-02T16:04:47.221064-08:00","source_repo":"."} -{"id":"bd-fasa","content_hash":"bc2c647cac7355a66fa4aefd116c82e01f536da4b4404e922b3307505413210f","title":"Prefix detection treats embedded hyphens as prefix delimiters","description":"The prefix detection logic in bd import incorrectly identifies issues like 'vc-baseline-test' and 'vc-92cl-gate-test' as having different prefixes ('vc-baseline-' and 'vc-92cl-gate-') instead of recognizing them as having the standard 'vc-' prefix with hyphenated suffixes.\n\nThis breaks import with error: 'prefix mismatch detected: database uses vc- but found issues with prefixes: [vc-92cl-gate- (1 issues) vc-baseline- (1 issues)]'\n\nThe prefix should be determined by the pattern: prefix is everything up to and including the first hyphen. The suffix can contain hyphens without being treated as part of the prefix.\n\nExample problematic IDs:\n- vc-baseline-test (detected as prefix: vc-baseline-)\n- vc-92cl-gate-test (detected as prefix: vc-92cl-gate-)\n- vc-test (correctly detected as prefix: vc-)\n\nImpact: Users cannot use descriptive multi-part IDs without triggering false prefix mismatch errors.","acceptance_criteria":"- Prefix detection only considers the first hyphen as prefix delimiter\n- IDs like 'vc-baseline-test' correctly identified as having prefix 'vc-'\n- Import succeeds without --rename-on-import for hyphenated suffixes\n- Tests added for multi-part ID suffix handling","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-09T14:27:19.046489-08:00","updated_at":"2025-11-09T14:53:53.22312-08:00","closed_at":"2025-11-09T14:53:53.22312-08:00","source_repo":"."} +{"id":"bd-fasa","content_hash":"668768c33b8abf8ec18295863bfad545b352e504736438ce87e4a630bb78d694","title":"Prefix detection treats embedded hyphens as prefix delimiters","description":"The prefix detection logic in bd import incorrectly identifies issues like 'vc-baseline-test' and 'vc-92cl-gate-test' as having different prefixes ('vc-baseline-' and 'vc-92cl-gate-') instead of recognizing them as having the standard 'vc-' prefix with hyphenated suffixes.\n\nThis breaks import with error: 'prefix mismatch detected: database uses vc- but found issues with prefixes: [vc-92cl-gate- (1 issues) vc-baseline- (1 issues)]'\n\nThe prefix should be determined by the pattern: prefix is everything up to and including the first hyphen. The suffix can contain hyphens without being treated as part of the prefix.\n\nExample problematic IDs:\n- vc-baseline-test (detected as prefix: vc-baseline-)\n- vc-92cl-gate-test (detected as prefix: vc-92cl-gate-)\n- vc-test (correctly detected as prefix: vc-)\n\nImpact: Users cannot use descriptive multi-part IDs without triggering false prefix mismatch errors.","acceptance_criteria":"- Prefix detection only considers the first hyphen as prefix delimiter\n- IDs like 'vc-baseline-test' correctly identified as having prefix 'vc-'\n- Import succeeds without --rename-on-import for hyphenated suffixes\n- Tests added for multi-part ID suffix handling","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-09T14:27:19.046489-08:00","updated_at":"2025-11-09T14:53:53.22312-08:00","closed_at":"2025-11-09T14:53:53.22312-08:00","source_repo":"."} {"id":"bd-fb05","content_hash":"1d99061e4ac1564982acc5e141674adf3bb7db789d546c12deb9108435af6450","title":"Refactor sqlite.go into focused modules","description":"Split sqlite.go (2,298 lines) into focused modules: migrations.go, ids.go, issues.go, events.go, dirty.go, db.go. This will improve maintainability and reduce cognitive load.","design":"Files to create:\n- migrations.go: Migration registry + runner\n- ids.go: ID generation/validation \n- issues.go: CRUD helpers\n- events.go: Event helpers\n- dirty.go: dirty_issues helpers\n- db.go: New/open, DSN construction\n- tx.go: Transaction helper","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-11-01T11:41:14.805895-07:00","updated_at":"2025-11-01T22:30:09.833675-07:00","closed_at":"2025-11-01T22:30:09.833675-07:00","source_repo":"."} -{"id":"bd-fb95094c","content_hash":"d30f2a45055cdb28efd6b15f97880f3fd50bee024876308440acea3f279f8920","title":"Code Health \u0026 Technical Debt Cleanup","description":"Comprehensive codebase cleanup to remove dead code, refactor monolithic files, deduplicate utilities, and improve maintainability. Based on ultrathink code health analysis conducted 2025-10-27.\n\nGoals:\n- Remove ~1,500 LOC of dead/unreachable code\n- Split 2 monolithic files (server.go 2,273 LOC, sqlite.go 2,136 LOC) into focused modules\n- Deduplicate scattered utility functions (normalizeLabels, BD_DEBUG checks)\n- Consolidate test coverage (2,019 LOC of collision tests)\n- Improve code navigation and reduce merge conflicts\n\nImpact: Reduces codebase by ~6-8%, improves maintainability, faster CI/CD\n\nEstimated Effort: 11 days across 4 phases","acceptance_criteria":"- All unreachable code identified by `deadcode` analyzer is removed\n- RPC server split into \u003c500 LOC files with clear responsibilities\n- Duplicate utility functions centralized\n- Test coverage maintained or improved\n- All tests passing\n- Documentation updated","status":"closed","priority":2,"issue_type":"epic","created_at":"2025-10-27T20:39:22.22227-07:00","updated_at":"2025-11-08T18:15:59.971899-08:00","closed_at":"2025-11-08T18:15:59.971899-08:00","source_repo":".","labels":["cleanup","epic"]} +{"id":"bd-fb95094c","content_hash":"99f456d7a5d3a4288c3f60dd65212480c54d3b0161e57d7eccffe01875d2eb5e","title":"Code Health \u0026 Technical Debt Cleanup","description":"Comprehensive codebase cleanup to remove dead code, refactor monolithic files, deduplicate utilities, and improve maintainability. Based on ultrathink code health analysis conducted 2025-10-27.\n\nGoals:\n- Remove ~1,500 LOC of dead/unreachable code\n- Split 2 monolithic files (server.go 2,273 LOC, sqlite.go 2,136 LOC) into focused modules\n- Deduplicate scattered utility functions (normalizeLabels, BD_DEBUG checks)\n- Consolidate test coverage (2,019 LOC of collision tests)\n- Improve code navigation and reduce merge conflicts\n\nImpact: Reduces codebase by ~6-8%, improves maintainability, faster CI/CD\n\nEstimated Effort: 11 days across 4 phases","acceptance_criteria":"- All unreachable code identified by `deadcode` analyzer is removed\n- RPC server split into \u003c500 LOC files with clear responsibilities\n- Duplicate utility functions centralized\n- Test coverage maintained or improved\n- All tests passing\n- Documentation updated","status":"closed","priority":2,"issue_type":"epic","created_at":"2025-10-27T20:39:22.22227-07:00","updated_at":"2025-11-08T18:15:59.971899-08:00","closed_at":"2025-11-08T18:15:59.971899-08:00","source_repo":".","labels":["cleanup","epic"]} {"id":"bd-fb95094c.1","content_hash":"8f7533da448dea49a01aa747892eab9f855127343ced4fbd6e17cb80d56419af","title":"Run final validation and cleanup checks","description":"Final validation pass to ensure all cleanup objectives met and no regressions introduced.\n\nValidation checklist:\n1. Dead code verification: `go run golang.org/x/tools/cmd/deadcode@latest -test ./...`\n2. Test coverage: `go test -cover ./...`\n3. Build verification: `go build ./cmd/bd/`\n4. Linting: `golangci-lint run`\n5. Integration tests\n6. Metrics verification\n7. Git clean check\n\nFinal metrics to report:\n- LOC removed: ~____\n- Files deleted: ____\n- Files created: ____\n- Test coverage: ____%\n- Build time: ____ (before/after)\n- Test run time: ____ (before/after)\n\nImpact: Confirms all cleanup objectives achieved successfully","acceptance_criteria":"- Zero unreachable functions per deadcode analyzer\n- All tests pass: `go test ./...`\n- Test coverage maintained or improved\n- Builds cleanly: `go build ./...`\n- Linting shows improvements\n- Integration tests all pass\n- LOC reduction target achieved (~2,500 LOC)\n- No unintended behavior changes\n- Git commit messages document all changes","notes":"Validation completed:\n- LOC: 52,372 lines total\n- Dead code: 4 functions in import_shared.go (tracked in bd-6fe4622f)\n- Build: ✓ Successful\n- Test coverage: ~20-82% across packages\n- Test failure: TestTwoCloneCollision (timeout issue)\n- Linting: errcheck warnings present (defer close, fmt errors)\n- Test time: ~20s\n\nIssues found:\n1. bd-6fe4622f: Remove unreachable import functions (renameImportedIssuePrefixes, etc)\n2. TestTwoCloneCollision: Daemon killall timeout causing test failure\n3. Linting: errcheck violations need fixing","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-27T20:32:00.14166-07:00","updated_at":"2025-10-30T17:12:58.209988-07:00","closed_at":"2025-10-28T14:11:25.218801-07:00","source_repo":".","labels":["phase-4","validation"],"dependencies":[{"issue_id":"bd-fb95094c.1","depends_on_id":"bd-fb95094c","type":"parent-child","created_at":"2025-10-27T20:32:00.144113-07:00","created_by":"daemon"}]} -{"id":"bd-fb95094c.10","content_hash":"072a2e76c3a9690c49c805351891235d488936d7a0e7b1d1334bd933f79de338","title":"Consider central serialization package for JSON handling","description":"Multiple parts of the codebase handle JSON serialization of issues with slightly different approaches. Consider creating a centralized serialization package to ensure consistency.\n\nCurrent serialization locations:\n- `cmd/bd/export.go` - JSONL export (issues to file)\n- `cmd/bd/import.go` - JSONL import (file to issues)\n- `internal/rpc/protocol.go` - RPC JSON marshaling\n- `internal/storage/memory/memory.go` - In-memory marshaling\n\nPotential benefits:\n- Single source of truth for JSON format\n- Consistent field naming\n- Easier to add new fields\n- Centralized validation\n\nNote: This is marked **optional** because:\n- Current serialization mostly works\n- May not provide enough benefit to justify refactor\n- Risk of breaking compatibility\n\nDecision point: Evaluate if benefits outweigh refactoring cost\n\nImpact: TBD based on investigation - may defer to future work","acceptance_criteria":"- Create serialization package with documented JSON format\n- Migrate export/import to use centralized serialization\n- All existing JSONL files can be read with new code\n- All tests pass: `go test ./...`\n- Export/import round-trip works perfectly\n- RPC protocol unchanged (or backwards compatible)","status":"closed","priority":3,"issue_type":"task","created_at":"2025-10-27T20:31:19.090608-07:00","updated_at":"2025-11-08T18:15:54.319047-08:00","closed_at":"2025-11-08T18:15:54.319047-08:00","source_repo":".","labels":["deduplication","optional","phase-3","refactor","serialization"],"dependencies":[{"issue_id":"bd-fb95094c.10","depends_on_id":"bd-fb95094c","type":"parent-child","created_at":"2025-10-27T20:31:19.092328-07:00","created_by":"daemon"}]} +{"id":"bd-fb95094c.10","content_hash":"0d499f79a6336ca36c7e459e3393cd7cfe471d184e5e443fa9757a22740744ab","title":"Consider central serialization package for JSON handling","description":"Multiple parts of the codebase handle JSON serialization of issues with slightly different approaches. Consider creating a centralized serialization package to ensure consistency.\n\nCurrent serialization locations:\n- `cmd/bd/export.go` - JSONL export (issues to file)\n- `cmd/bd/import.go` - JSONL import (file to issues)\n- `internal/rpc/protocol.go` - RPC JSON marshaling\n- `internal/storage/memory/memory.go` - In-memory marshaling\n\nPotential benefits:\n- Single source of truth for JSON format\n- Consistent field naming\n- Easier to add new fields\n- Centralized validation\n\nNote: This is marked **optional** because:\n- Current serialization mostly works\n- May not provide enough benefit to justify refactor\n- Risk of breaking compatibility\n\nDecision point: Evaluate if benefits outweigh refactoring cost\n\nImpact: TBD based on investigation - may defer to future work","acceptance_criteria":"- Create serialization package with documented JSON format\n- Migrate export/import to use centralized serialization\n- All existing JSONL files can be read with new code\n- All tests pass: `go test ./...`\n- Export/import round-trip works perfectly\n- RPC protocol unchanged (or backwards compatible)","status":"closed","priority":3,"issue_type":"task","created_at":"2025-10-27T20:31:19.090608-07:00","updated_at":"2025-11-08T18:15:54.319047-08:00","closed_at":"2025-11-08T18:15:54.319047-08:00","source_repo":".","labels":["deduplication","optional","phase-3","refactor","serialization"],"dependencies":[{"issue_id":"bd-fb95094c.10","depends_on_id":"bd-fb95094c","type":"parent-child","created_at":"2025-10-27T20:31:19.092328-07:00","created_by":"daemon"}]} {"id":"bd-fb95094c.2","content_hash":"685c91a6de8e1610feb5dbda18412f3eee178a37064d9ddf55511fb693dec9ba","title":"Delete skipped tests for \"old buggy behavior\"","description":"Three test functions are permanently skipped with comments indicating they test behavior that was fixed in GH#120. These tests will never run again and should be deleted.\n\nTest functions to remove:\n\n1. `cmd/bd/import_collision_test.go:228`\n ```go\n t.Skip(\"Test expects old buggy behavior - needs rewrite for GH#120 fix\")\n ```\n\n2. `cmd/bd/import_collision_test.go:505`\n ```go\n t.Skip(\"Test expects old buggy behavior - needs rewrite for GH#120 fix\")\n ```\n\n3. `internal/storage/sqlite/collision_test.go:919`\n ```go\n t.Skip(\"Test expects old buggy behavior - needs rewrite for GH#120 fix\")\n ```\n\nImpact: Removes ~150 LOC of permanently skipped tests","acceptance_criteria":"- Delete the 3 test functions entirely (~150 LOC total)\n- Update test file comments to reference GH#120 fix if needed\n- All remaining tests pass: `go test ./...`\n- No reduction in meaningful test coverage (these test fixed bugs)","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-27T20:30:19.961185-07:00","updated_at":"2025-10-30T17:12:58.196387-07:00","closed_at":"2025-10-28T14:09:21.642632-07:00","source_repo":".","labels":["cleanup","dead-code","phase-1","test-cleanup"],"dependencies":[{"issue_id":"bd-fb95094c.2","depends_on_id":"bd-fb95094c","type":"parent-child","created_at":"2025-10-27T20:30:19.962815-07:00","created_by":"daemon"}]} -{"id":"bd-fb95094c.3","content_hash":"84783b0ba6c7fc6b75167935be981a0ae52069936137ec65d79b52b54cb43f2c","title":"Update documentation after code health cleanup","description":"Update all documentation to reflect code structure changes after cleanup phases complete.\n\nDocumentation to update:\n1. **AGENTS.md** - Update file structure references\n2. **CONTRIBUTING.md** (if exists) - Update build/test instructions\n3. **Code comments** - Update any outdated references\n4. **Package documentation** - Update godoc for reorganized packages\n\nNew documentation to add:\n1. **internal/util/README.md** - Document shared utilities\n2. **internal/debug/README.md** - Document debug logging\n3. **internal/rpc/README.md** - Document new file organization\n4. **internal/storage/sqlite/migrations/README.md** - Migration system docs\n\nImpact: Keeps documentation in sync with code","acceptance_criteria":"- All documentation references to deleted files removed\n- New package READMEs written\n- Code comments updated for reorganized code\n- Migration guide for developers (if needed)\n- Architecture diagrams updated (if they exist)","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-27T20:32:00.141028-07:00","updated_at":"2025-11-08T18:15:48.644285-08:00","closed_at":"2025-11-08T18:15:48.644285-08:00","source_repo":".","labels":["documentation","phase-4"],"dependencies":[{"issue_id":"bd-fb95094c.3","depends_on_id":"bd-fb95094c","type":"parent-child","created_at":"2025-10-27T20:32:00.1423-07:00","created_by":"daemon"}]} +{"id":"bd-fb95094c.3","content_hash":"7c3b871ac8f2041b1a2f9e2096d4328d5d388728c392f18c727c6b3f39242c92","title":"Update documentation after code health cleanup","description":"Update all documentation to reflect code structure changes after cleanup phases complete.\n\nDocumentation to update:\n1. **AGENTS.md** - Update file structure references\n2. **CONTRIBUTING.md** (if exists) - Update build/test instructions\n3. **Code comments** - Update any outdated references\n4. **Package documentation** - Update godoc for reorganized packages\n\nNew documentation to add:\n1. **internal/util/README.md** - Document shared utilities\n2. **internal/debug/README.md** - Document debug logging\n3. **internal/rpc/README.md** - Document new file organization\n4. **internal/storage/sqlite/migrations/README.md** - Migration system docs\n\nImpact: Keeps documentation in sync with code","acceptance_criteria":"- All documentation references to deleted files removed\n- New package READMEs written\n- Code comments updated for reorganized code\n- Migration guide for developers (if needed)\n- Architecture diagrams updated (if they exist)","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-27T20:32:00.141028-07:00","updated_at":"2025-11-08T18:15:48.644285-08:00","closed_at":"2025-11-08T18:15:48.644285-08:00","source_repo":".","labels":["documentation","phase-4"],"dependencies":[{"issue_id":"bd-fb95094c.3","depends_on_id":"bd-fb95094c","type":"parent-child","created_at":"2025-10-27T20:32:00.1423-07:00","created_by":"daemon"}]} {"id":"bd-fb95094c.4","content_hash":"c2831a4b1f3847a8aff257d72eda7aa280b7f572a3e4e72d2283a9af367b52ea","title":"Audit and consolidate collision test coverage","description":"The codebase has 2,019 LOC of collision detection tests across 3 files. Run coverage analysis to identify redundant test cases and consolidate.\n\nTest files:\n- `cmd/bd/import_collision_test.go` - 974 LOC\n- `cmd/bd/autoimport_collision_test.go` - 750 LOC\n- `cmd/bd/import_collision_regression_test.go` - 295 LOC\n\nTotal: 2,019 LOC of collision tests\n\nAnalysis steps:\n1. Run coverage analysis\n2. Identify redundant tests\n3. Document findings\n\nConsolidation strategy:\n- Keep regression tests for critical bugs\n- Merge overlapping table-driven tests\n- Remove redundant edge case tests covered elsewhere\n- Ensure all collision scenarios still tested\n\nExpected outcome: Reduce to ~1,200 LOC (save ~800 lines) while maintaining coverage\n\nImpact: Faster test runs, easier maintenance, clearer test intent","acceptance_criteria":"- Coverage analysis completed and documented\n- Redundant tests identified (~800 LOC estimated)\n- Consolidated test suite maintains or improves coverage\n- All remaining tests pass: `go test ./cmd/bd/...`\n- Test run time unchanged or faster\n- Document which tests were removed and why\n- Coverage percentage maintained: `go test -cover ./cmd/bd/` shows same %","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-27T20:32:00.130855-07:00","updated_at":"2025-11-08T01:49:23.462872-08:00","closed_at":"2025-11-07T23:27:41.970013-08:00","source_repo":".","labels":["phase-4","test-cleanup"],"dependencies":[{"issue_id":"bd-fb95094c.4","depends_on_id":"bd-fb95094c","type":"parent-child","created_at":"2025-10-27T20:32:00.132251-07:00","created_by":"daemon"}]} {"id":"bd-fb95094c.5","content_hash":"11521fe159f640e2cefd3d138fbbbc3b8d2b4fda48c6542f39761d5a124d6154","title":"Centralize BD_DEBUG logging into debug package","description":"The codebase has 43 scattered instances of `if os.Getenv(\"BD_DEBUG\") != \"\"` debug checks across 6 files. Centralize into a debug logging package.\n\nCurrent locations:\n- `cmd/bd/main.go` - 15 checks\n- `cmd/bd/autoflush.go` - 6 checks\n- `cmd/bd/nodb.go` - 4 checks\n- `internal/rpc/server.go` - 2 checks\n- `internal/rpc/client.go` - 5 checks\n- `cmd/bd/daemon_autostart.go` - 11 checks\n\nTarget structure:\n```\ninternal/debug/\n└── debug.go\n```\n\nBenefits:\n- Centralized debug logging\n- Easier to add structured logging later\n- Testable (can mock debug output)\n- Consistent debug message format\n\nImpact: Removes 43 scattered checks, improves code clarity","acceptance_criteria":"- Create `internal/debug/debug.go` with `Enabled`, `Logf`, `Printf`\n- Add unit tests in `internal/debug/debug_test.go` (test with/without BD_DEBUG)\n- Replace all 43 instances of `os.Getenv(\"BD_DEBUG\")` checks with `debug.Logf()`\n- Verify debug output works: run with `BD_DEBUG=1 bd status`\n- All tests pass: `go test ./...`\n- No behavior change (output identical to before)","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-27T20:31:19.089078-07:00","updated_at":"2025-11-07T00:28:01.781121-08:00","closed_at":"2025-11-06T20:13:09.412212-08:00","source_repo":".","labels":["deduplication","logging","phase-3","refactor"],"dependencies":[{"issue_id":"bd-fb95094c.5","depends_on_id":"bd-fb95094c","type":"parent-child","created_at":"2025-10-27T21:48:41.542395-07:00","created_by":"stevey"}]} {"id":"bd-fb95094c.6","content_hash":"a8fe5793d281df23eb2a4856cbc4fa3fecc0a12762e75f7b80601af7d76d06da","title":"Extract normalizeLabels to shared utility package","description":"The `normalizeLabels` function appears in multiple locations with identical implementation. Extract to a shared utility package.\n\nCurrent locations:\n- `internal/rpc/server.go:37` (53 lines) - full implementation\n- `cmd/bd/list.go:50-52` - uses the server version (needs to use new shared version)\n\nFunction purpose:\n- Trims whitespace from labels\n- Removes empty strings\n- Deduplicates labels\n- Preserves order\n\nTarget structure:\n```\ninternal/util/\n├── strings.go # String utilities\n └── NormalizeLabels([]string) []string\n```\n\nImpact: DRY principle, single source of truth, easier to test","acceptance_criteria":"- Create `internal/util/strings.go` with `NormalizeLabels`\n- Add comprehensive unit tests in `internal/util/strings_test.go`\n- Update `internal/rpc/server.go` to import and use `util.NormalizeLabels`\n- Update `cmd/bd/list.go` to import and use `util.NormalizeLabels`\n- Remove duplicate implementations\n- All tests pass: `go test ./...`\n- Verify label normalization works: test `bd list --label` commands","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-27T20:31:19.078622-07:00","updated_at":"2025-11-06T20:06:49.219555-08:00","closed_at":"2025-11-06T19:58:59.467567-08:00","source_repo":".","labels":["deduplication","phase-3","refactor"],"dependencies":[{"issue_id":"bd-fb95094c.6","depends_on_id":"bd-fb95094c","type":"parent-child","created_at":"2025-10-27T20:31:19.08015-07:00","created_by":"daemon"}]} @@ -396,7 +396,7 @@ {"id":"bd-fkdw","content_hash":"aae326186151d20e26b9b5c34efa43d9261ffd0fe0d6f4de843f951e4c813886","title":"Update bash-agent example with Agent Mail integration","description":"Add Agent Mail integration to examples/bash-agent/agent.sh using curl for HTTP calls.\n\nAcceptance Criteria:\n- Health check function using curl\n- Reserve issue before claiming\n- Send notifications on status change\n- Release on completion\n- Graceful degradation if curl fails\n- No bash errors when Agent Mail unavailable\n\nFile: examples/bash-agent/agent.sh","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-11-07T22:42:28.722048-08:00","updated_at":"2025-11-08T01:51:40.350436-08:00","closed_at":"2025-11-08T01:09:25.900138-08:00","source_repo":".","dependencies":[{"issue_id":"bd-fkdw","depends_on_id":"bd-m9th","type":"blocks","created_at":"2025-11-07T23:04:01.398259-08:00","created_by":"daemon"}]} {"id":"bd-fsb1","content_hash":"a519fdd6d0ca6f70a177c2cb9441994b28d4bc2fe51a663532d4067caf126049","title":"Test issue","description":"","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-05T11:21:51.383077-08:00","updated_at":"2025-11-05T11:21:56.888913-08:00","closed_at":"2025-11-05T11:21:56.888913-08:00","source_repo":".","labels":["test","urgent"]} {"id":"bd-fzbg","content_hash":"4bf5f57a0a66a94d76882e337c25d49e807ec79257a0aeb636fb81d963493860","title":"Update python-agent example with Agent Mail integration","description":"Modify examples/python-agent/agent.py to use Agent Mail adapter at 4 integration points.\n\nAcceptance Criteria:\n- Import and initialize adapter\n- Check inbox before find_ready_work()\n- Reserve issue before claim_task()\n- Notify on status changes\n- Release reservation on complete_task()\n- Works identically when Agent Mail disabled\n- No changes required to core Beads CLI\n\nFile: examples/python-agent/agent.py","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-11-07T22:42:28.661337-08:00","updated_at":"2025-11-08T01:51:40.350671-08:00","closed_at":"2025-11-08T00:20:35.213902-08:00","source_repo":".","dependencies":[{"issue_id":"bd-fzbg","depends_on_id":"bd-m9th","type":"blocks","created_at":"2025-11-07T23:04:01.315332-08:00","created_by":"daemon"}]} -{"id":"bd-g3ey","content_hash":"e59ecb28d0ceade96c076688de71f5d0022a9b0c0676f3abb1e4e06d90f8f559","title":"bd sync --import-only doesn't update DB mtime causing bd doctor false warning","description":"","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-08T15:18:16.761052+01:00","updated_at":"2025-11-08T13:12:01.718252-08:00","closed_at":"2025-11-08T13:12:01.718252-08:00","source_repo":"."} +{"id":"bd-g3ey","content_hash":"3697da150785d4c99e125485efcf50dad02ccf01f93d3cc1a2944f652048f7ae","title":"bd sync --import-only doesn't update DB mtime causing bd doctor false warning","description":"","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-08T15:18:16.761052+01:00","updated_at":"2025-11-08T13:12:01.718252-08:00","closed_at":"2025-11-08T13:12:01.718252-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-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-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"}]} @@ -414,7 +414,7 @@ {"id":"bd-it3x","content_hash":"f31a3aae4297794bd42d7a8a8688ab5cdb4fa6c70f0ed88ffa93be93d76a2128","title":"Issue with labels","description":"","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-11-07T19:07:18.388873-08:00","updated_at":"2025-11-07T22:07:17.346541-08:00","closed_at":"2025-11-07T21:55:09.429989-08:00","source_repo":".","labels":["backend","urgent"]} {"id":"bd-iye7","content_hash":"1554b026ccacde081eb05d3889943d95ae9c75a21d3f06c346c57cbe2391dc46","title":"Add path normalization to getMultiRepoJSONLPaths()","description":"From bd-xo6b code review: getMultiRepoJSONLPaths() does not handle non-standard paths correctly.\n\nProblems:\n- No tilde expansion: ~/repos/foo treated as literal path\n- No absolute path conversion: ../other-repo breaks if working directory changes\n- No duplicate detection: If Primary=. and Additional=[.], same JSONL processed twice\n- No empty string handling: Empty paths create invalid /.beads/issues.jsonl\n\nImpact:\nConfig with tilde or relative paths will fail\n\nFix needed:\n1. Use filepath.Abs() for all paths\n2. Add tilde expansion via os.UserHomeDir()\n3. Deduplicate paths (use map to track seen paths)\n4. Filter out empty strings\n5. Validate paths exist and are readable\n\nFiles:\n- cmd/bd/deletion_tracking.go:333-358 (getMultiRepoJSONLPaths function)","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-06T19:31:51.882743-08:00","updated_at":"2025-11-06T19:35:41.246311-08:00","closed_at":"2025-11-06T19:35:41.246311-08:00","source_repo":".","dependencies":[{"issue_id":"bd-iye7","depends_on_id":"bd-xo6b","type":"discovered-from","created_at":"2025-11-06T19:32:12.267906-08:00","created_by":"daemon"}]} {"id":"bd-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-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":6,"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-12T09:55:23Z"},{"id":7,"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-12T09:55:23Z"}]} +{"id":"bd-jjua","content_hash":"1f03e105aa89285214bad40695c14bf4b5f63e85caae26c8dd326cf592002d57","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":6,"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-08T11:11:06Z"},{"id":7,"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-08T11:14:35Z"}]} {"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":"."} {"id":"bd-k58","content_hash":"cc90fb20e7bd178b52133d4d0f8781dce2debb46519674ae6356291d597fc13d","title":"Proposal workflow (propose/withdraw/accept)","description":"Implement commands and state machine for moving issues between personal planning repos and canonical upstream repos, enabling contributors to propose work without polluting PRs.","design":"Commands:\n- bd propose \u003cid\u003e [--target \u003crepo\u003e] - Move issue to target repo\n- bd withdraw \u003cid\u003e - Un-propose (move back)\n- bd accept \u003cid\u003e - Maintainer accepts proposal\n\nVisibility states:\n- local: Personal planning only\n- proposed: Staged for upstream PR\n- canonical: Accepted by upstream (default for existing)\n\nOptional visibility field (backward compatible, defaults to canonical)","acceptance_criteria":"1. bd propose moves issue from planning to primary repo\n2. bd withdraw reverses proposal\n3. bd accept (maintainer) finalizes acceptance\n4. Visibility field tracks state (local/proposed/canonical)\n5. Backward compatible - existing issues default to canonical\n6. State transitions are atomic and git-tracked","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-11-04T11:21:41.113647-08:00","updated_at":"2025-11-05T00:08:42.814698-08:00","closed_at":"2025-11-05T00:08:42.814699-08:00","source_repo":".","dependencies":[{"issue_id":"bd-k58","depends_on_id":"bd-4ms","type":"parent-child","created_at":"2025-11-04T11:22:21.811261-08:00","created_by":"daemon"}]} @@ -459,7 +459,7 @@ {"id":"bd-rb75","content_hash":"e91418eb7abda986ddb57feaee1b91867043de8c0883d71c21dc1bf4047f5824","title":"Clean up merge conflict artifacts in .beads directory","description":"After resolving merge conflicts in .beads/beads.jsonl, leftover artifacts remain as untracked files:\n- .beads/beads.base.jsonl\n- .beads/beads.left.jsonl\n\nThese appear to be temporary files created during merge conflict resolution.\n\nOptions to fix:\n1. Add these patterns to .beads/.gitignore automatically\n2. Clean up these files after successful merge resolution\n3. Document that users should delete them manually\n4. Add a check in 'bd sync' or 'bd doctor' to detect and remove stale merge artifacts\n\nPreferred solution: Add *.base.jsonl and *.left.jsonl patterns to .beads/.gitignore during 'bd init', and optionally clean them up automatically after successful import.","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-11-06T19:09:16.114274-08:00","updated_at":"2025-11-06T19:13:44.630402-08:00","closed_at":"2025-11-06T19:13:44.630402-08:00","source_repo":"."} {"id":"bd-rbxi","content_hash":"df423e4150f6f3b5a19467b8cb41a4b90475cc9ced45ed577ebbe9e3e75279f9","title":"bd-hv01: Deletion tracking production readiness","description":"Epic to track all improvements and fixes needed to make the deletion tracking implementation ([deleted:bd-hv01]) production-ready.\n\nThe core 3-way merge algorithm is sound, but there are critical issues around atomicity, error handling, and edge cases that need to be addressed before this can be safely used in production.\n\nCritical path (P1):\n- Non-atomic snapshot operations\n- Brittle JSON string comparison\n- Silent partial deletion failures\n- Race conditions in concurrent scenarios\n\nFollow-up work (P2-P3):\n- Test coverage for edge cases and multi-repo mode\n- Performance optimizations\n- Code refactoring and observability\n\nRelated commit: 708a81c","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-11-06T18:18:24.315646-08:00","updated_at":"2025-11-08T03:54:04.857449-08:00","closed_at":"2025-11-08T02:19:19.780741-08:00","source_repo":"."} {"id":"bd-ri6d","content_hash":"62b887c13232eeabf1d1b25a514b6044ff6ea7b510a06cbd5a736beabe722c43","title":"bd message: Fix inefficient client-side filtering for --unread-only","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-08T12:54:28.614867-08:00","updated_at":"2025-11-08T12:58:59.551512-08:00","closed_at":"2025-11-08T12:58:59.551512-08:00","source_repo":".","dependencies":[{"issue_id":"bd-ri6d","depends_on_id":"bd-6uix","type":"parent-child","created_at":"2025-11-08T12:55:55.012455-08:00","created_by":"daemon"}]} -{"id":"bd-rpn","content_hash":"094cb96c5740d7d206852a41cb9b100c5e3a7df32891b77eaceb7cfe56dcf1f3","title":"Implement `bd prime` command for AI context loading","description":"Create a `bd prime` command that outputs AI-optimized markdown containing essential Beads workflow context. This provides an alternative to the MCP server for token-conscious users and enables context recovery after compaction/clearing.","design":"## Implementation\n\nCreate `cmd/bd/prime.go` that outputs AI-optimized markdown with **adaptive content based on MCP detection**.\n\n## MCP-Aware Output Strategy\n\n`bd prime` detects if MCP server is active and adjusts output accordingly:\n\n**With MCP detected** (~500 tokens):\n- Workflow reminders only\n- \"Use bd MCP tools, not markdown TODOs\"\n- Session management tips\n- NO CLI command syntax (user has native MCP tools)\n\n**Without MCP** (~1-2k tokens):\n- Full workflow rules\n- Complete CLI command reference with examples\n- All command syntax and options\n\n**Why this matters:**\n- MCP users don't need CLI docs (they have native function calls)\n- Non-MCP users need full command reference\n- Same hook works for all users, adapts to their environment\n- Reduces token waste for MCP users\n\n## MCP Detection Logic\n\n```go\nfunc isMCPActive() bool {\n // Check environment variables that Claude Code sets when MCP servers are loaded\n // Options to investigate:\n // 1. Check for CLAUDE_MCP_SERVERS environment variable\n // 2. Check for specific MCP server process indicators\n // 3. Parse ~/.claude/settings.json for enabled MCP servers\n // 4. Check for MCP socket/connection availability\n \n // Fallback: assume MCP if we can't determine\n // (safer to output less and have user call with --full flag)\n return checkMCPEnvironment()\n}\n```\n\n**Alternative: Command flag for explicit control:**\n```bash\nbd prime # Auto-detect MCP\nbd prime --full # Force full output (ignore MCP detection)\nbd prime --mcp # Force MCP mode (minimal output)\n```\n\n## Discovery Logic\n\n**Skip PersistentPreRun database initialization:**\nAdd \"prime\" to noDbCommands list in main.go so it doesn't require .beads/ upfront.\n\n**Silent, cross-platform execution:**\n```go\nvar primeCmd = \u0026cobra.Command{\n Use: \"prime\",\n Short: \"Output AI-optimized workflow context\",\n Run: func(cmd *cobra.Command, args []string) {\n // Find .beads/ directory (walks up tree like bd does)\n dbPath := beads.FindDatabasePath()\n if dbPath == \"\" {\n // Not in a beads project - silent exit with success\n // CRITICAL: No stderr output, exit 0\n // This enables cross-platform hook integration\n os.Exit(0)\n }\n \n // Detect MCP mode (unless overridden by flags)\n mcpMode := isMCPActive()\n if fullFlag {\n mcpMode = false\n }\n if mcpFlag {\n mcpMode = true\n }\n \n // Output workflow context (adaptive based on MCP)\n if err := outputPrimeContext(mcpMode); err != nil {\n // Suppress all errors - silent exit with success\n // Never write to stderr (breaks Windows compatibility)\n os.Exit(0)\n }\n },\n}\n```\n\n**Why silent execution matters:**\n- **Cross-platform**: No shell-specific syntax needed (`2\u003e/dev/null`, `|| true`)\n- **Hook-friendly**: Can be called directly from JSON: `\"command\": \"bd prime\"`\n- **Windows compatible**: Works in cmd.exe, PowerShell, bash\n- **Non-beads projects**: No error noise when run outside beads projects\n\n## Output Formats\n\n### MCP Mode (~500 tokens)\n```markdown\n# Beads Workflow Context\n\n\u003e **You have native bd MCP tools available** - use them instead of markdown TODOs\n\u003e Run `bd prime --full` for complete CLI reference if needed\n\n## Core Workflow Rules\n\n**Task Tracking:**\n- Use bd MCP tools for ALL work tracking (never markdown TODOs)\n- Check available work: use `mcp__plugin_beads_beads__ready` tool\n- Create issues: use `mcp__plugin_beads_beads__create` tool\n- Update status: use `mcp__plugin_beads_beads__update` tool\n\n**Session Management:**\n- Start: Check `ready` tool for available work\n- During: Keep issues updated with `update` tool\n- End: Verify sync status, close completed issues\n\n**Git Integration:**\n- Hooks auto-sync issues with git commits\n- Run `sync` tool at session end to push to remote\n\n**Need help?** \n- Use `show` tool for issue details\n- Check AGENTS.md for complete workflow\n- Run `bd prime --full` for CLI command reference\n```\n\n### Non-MCP Mode (~1-2k tokens)\n```markdown\n# Beads Workflow Context\n\n\u003e **Context Recovery**: Run `bd prime` after compaction, clear, or new session\n\u003e Hooks auto-call this in Claude Code when .beads/ detected\n\n## Core Rules\n- Track ALL work in bd (no markdown TODOs)\n- Git workflow: hooks auto-sync, run `bd sync` at session end\n- Session management: check `bd ready` for available work\n\n## Essential Commands\n\n### Finding Work\n- `bd ready` - Show issues ready to work (no blockers)\n- `bd list --status=open` - All open issues\n- `bd list --status=in_progress` - Your active work\n- `bd show \u003cid\u003e` - Detailed issue view with dependencies\n\n### Creating \u0026 Updating\n- `bd create --title=\"...\" --type=task|bug|feature` - New issue\n- `bd update \u003cid\u003e --status=in_progress` - Claim work\n- `bd update \u003cid\u003e --assignee=username` - Assign to someone\n- `bd close \u003cid\u003e` - Mark complete\n- `bd close \u003cid\u003e --reason=\"explanation\"` - Close with reason\n\n### Dependencies \u0026 Blocking\n- `bd dep \u003cfrom\u003e \u003cto\u003e` - Add blocker dependency (from blocks to)\n- `bd blocked` - Show all blocked issues\n- `bd show \u003cid\u003e` - See what's blocking/blocked by this issue\n\n### Sync \u0026 Collaboration\n- `bd sync` - Sync with git remote (run at session end)\n- `bd sync --status` - Check sync status without syncing\n\n### Project Health\n- `bd stats` - Project statistics (open/closed/blocked counts)\n- `bd doctor` - Check for issues (sync problems, missing hooks)\n\n## Common Workflows\n\n**Starting work:**\n```bash\nbd ready # Find available work\nbd show \u003cid\u003e # Review issue details\nbd update \u003cid\u003e --status=in_progress # Claim it\n```\n\n**Completing work:**\n```bash\nbd close \u003cid\u003e # Mark done\nbd sync # Push to remote\n```\n\n**Creating dependent work:**\n```bash\nbd create --title=\"Implement feature X\" --type=feature\nbd create --title=\"Write tests for X\" --type=task\nbd dep beads-xxx beads-yyy # Feature blocks tests\n```\n\nFor complete docs: AGENTS.md, QUICKSTART.md, `bd --help`\n```\n\n## Behavior Guarantees\n\n1. **Never writes to stderr** (all errors suppressed internally)\n2. **Always exits 0** (success) even when:\n - Not in a beads project\n - .beads/ not found\n - Any internal error occurs\n3. **Cross-platform compatible** (no shell-specific syntax)\n4. **Hook-safe** (can be called directly without wrappers)\n5. **MCP-aware** (adapts output based on user's tool environment)\n\n## Files\n- `cmd/bd/prime.go` - Command implementation with MCP detection\n- `cmd/bd/prime_test.go` - Tests (including MCP mode switching)\n- Update `cmd/bd/main.go` - Add \"prime\" to noDbCommands list","acceptance_criteria":"- `bd prime` outputs markdown format\n- Output is ~1-2k tokens\n- Output includes workflow rules and command reference\n- Command has unit tests\n- Documentation updated in AGENTS.md","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-11-11T23:28:42.74124-08:00","updated_at":"2025-11-12T08:30:15.711595-08:00","closed_at":"2025-11-12T08:30:15.711595-08:00","source_repo":".","dependencies":[{"issue_id":"bd-rpn","depends_on_id":"bd-90v","type":"parent-child","created_at":"2025-11-11T23:31:20.357861-08:00","created_by":"daemon"}]} +{"id":"bd-rpn","content_hash":"4b0c8a22edcf49b95f1caba51397f5a6289bc170a69084bc3c39267a8f43d888","title":"Implement `bd prime` command for AI context loading","description":"Create a `bd prime` command that outputs AI-optimized markdown containing essential Beads workflow context. This provides an alternative to the MCP server for token-conscious users and enables context recovery after compaction/clearing.","design":"## Implementation\n\nCreate `cmd/bd/prime.go` that outputs AI-optimized markdown with **adaptive content based on MCP detection**.\n\n## MCP-Aware Output Strategy\n\n`bd prime` detects if MCP server is active and adjusts output accordingly:\n\n**With MCP detected** (~500 tokens):\n- Workflow reminders only\n- \"Use bd MCP tools, not markdown TODOs\"\n- Session management tips\n- NO CLI command syntax (user has native MCP tools)\n\n**Without MCP** (~1-2k tokens):\n- Full workflow rules\n- Complete CLI command reference with examples\n- All command syntax and options\n\n**Why this matters:**\n- MCP users don't need CLI docs (they have native function calls)\n- Non-MCP users need full command reference\n- Same hook works for all users, adapts to their environment\n- Reduces token waste for MCP users\n\n## MCP Detection Logic\n\n```go\nfunc isMCPActive() bool {\n // Check environment variables that Claude Code sets when MCP servers are loaded\n // Options to investigate:\n // 1. Check for CLAUDE_MCP_SERVERS environment variable\n // 2. Check for specific MCP server process indicators\n // 3. Parse ~/.claude/settings.json for enabled MCP servers\n // 4. Check for MCP socket/connection availability\n \n // Fallback: assume MCP if we can't determine\n // (safer to output less and have user call with --full flag)\n return checkMCPEnvironment()\n}\n```\n\n**Alternative: Command flag for explicit control:**\n```bash\nbd prime # Auto-detect MCP\nbd prime --full # Force full output (ignore MCP detection)\nbd prime --mcp # Force MCP mode (minimal output)\n```\n\n## Discovery Logic\n\n**Skip PersistentPreRun database initialization:**\nAdd \"prime\" to noDbCommands list in main.go so it doesn't require .beads/ upfront.\n\n**Silent, cross-platform execution:**\n```go\nvar primeCmd = \u0026cobra.Command{\n Use: \"prime\",\n Short: \"Output AI-optimized workflow context\",\n Run: func(cmd *cobra.Command, args []string) {\n // Find .beads/ directory (walks up tree like bd does)\n dbPath := beads.FindDatabasePath()\n if dbPath == \"\" {\n // Not in a beads project - silent exit with success\n // CRITICAL: No stderr output, exit 0\n // This enables cross-platform hook integration\n os.Exit(0)\n }\n \n // Detect MCP mode (unless overridden by flags)\n mcpMode := isMCPActive()\n if fullFlag {\n mcpMode = false\n }\n if mcpFlag {\n mcpMode = true\n }\n \n // Output workflow context (adaptive based on MCP)\n if err := outputPrimeContext(mcpMode); err != nil {\n // Suppress all errors - silent exit with success\n // Never write to stderr (breaks Windows compatibility)\n os.Exit(0)\n }\n },\n}\n```\n\n**Why silent execution matters:**\n- **Cross-platform**: No shell-specific syntax needed (`2\u003e/dev/null`, `|| true`)\n- **Hook-friendly**: Can be called directly from JSON: `\"command\": \"bd prime\"`\n- **Windows compatible**: Works in cmd.exe, PowerShell, bash\n- **Non-beads projects**: No error noise when run outside beads projects\n\n## Output Formats\n\n### MCP Mode (~500 tokens)\n```markdown\n# Beads Workflow Context\n\n\u003e **You have native bd MCP tools available** - use them instead of markdown TODOs\n\u003e Run `bd prime --full` for complete CLI reference if needed\n\n## Core Workflow Rules\n\n**Task Tracking:**\n- Use bd MCP tools for ALL work tracking (never markdown TODOs)\n- Check available work: use `mcp__plugin_beads_beads__ready` tool\n- Create issues: use `mcp__plugin_beads_beads__create` tool\n- Update status: use `mcp__plugin_beads_beads__update` tool\n\n**Session Management:**\n- Start: Check `ready` tool for available work\n- During: Keep issues updated with `update` tool\n- End: Verify sync status, close completed issues\n\n**Git Integration:**\n- Hooks auto-sync issues with git commits\n- Run `sync` tool at session end to push to remote\n\n**Need help?** \n- Use `show` tool for issue details\n- Check AGENTS.md for complete workflow\n- Run `bd prime --full` for CLI command reference\n```\n\n### Non-MCP Mode (~1-2k tokens)\n```markdown\n# Beads Workflow Context\n\n\u003e **Context Recovery**: Run `bd prime` after compaction, clear, or new session\n\u003e Hooks auto-call this in Claude Code when .beads/ detected\n\n## Core Rules\n- Track ALL work in bd (no markdown TODOs)\n- Git workflow: hooks auto-sync, run `bd sync` at session end\n- Session management: check `bd ready` for available work\n\n## Essential Commands\n\n### Finding Work\n- `bd ready` - Show issues ready to work (no blockers)\n- `bd list --status=open` - All open issues\n- `bd list --status=in_progress` - Your active work\n- `bd show \u003cid\u003e` - Detailed issue view with dependencies\n\n### Creating \u0026 Updating\n- `bd create --title=\"...\" --type=task|bug|feature` - New issue\n- `bd update \u003cid\u003e --status=in_progress` - Claim work\n- `bd update \u003cid\u003e --assignee=username` - Assign to someone\n- `bd close \u003cid\u003e` - Mark complete\n- `bd close \u003cid\u003e --reason=\"explanation\"` - Close with reason\n\n### Dependencies \u0026 Blocking\n- `bd dep \u003cfrom\u003e \u003cto\u003e` - Add blocker dependency (from blocks to)\n- `bd blocked` - Show all blocked issues\n- `bd show \u003cid\u003e` - See what's blocking/blocked by this issue\n\n### Sync \u0026 Collaboration\n- `bd sync` - Sync with git remote (run at session end)\n- `bd sync --status` - Check sync status without syncing\n\n### Project Health\n- `bd stats` - Project statistics (open/closed/blocked counts)\n- `bd doctor` - Check for issues (sync problems, missing hooks)\n\n## Common Workflows\n\n**Starting work:**\n```bash\nbd ready # Find available work\nbd show \u003cid\u003e # Review issue details\nbd update \u003cid\u003e --status=in_progress # Claim it\n```\n\n**Completing work:**\n```bash\nbd close \u003cid\u003e # Mark done\nbd sync # Push to remote\n```\n\n**Creating dependent work:**\n```bash\nbd create --title=\"Implement feature X\" --type=feature\nbd create --title=\"Write tests for X\" --type=task\nbd dep beads-xxx beads-yyy # Feature blocks tests\n```\n\nFor complete docs: AGENTS.md, QUICKSTART.md, `bd --help`\n```\n\n## Behavior Guarantees\n\n1. **Never writes to stderr** (all errors suppressed internally)\n2. **Always exits 0** (success) even when:\n - Not in a beads project\n - .beads/ not found\n - Any internal error occurs\n3. **Cross-platform compatible** (no shell-specific syntax)\n4. **Hook-safe** (can be called directly without wrappers)\n5. **MCP-aware** (adapts output based on user's tool environment)\n\n## Files\n- `cmd/bd/prime.go` - Command implementation with MCP detection\n- `cmd/bd/prime_test.go` - Tests (including MCP mode switching)\n- Update `cmd/bd/main.go` - Add \"prime\" to noDbCommands list","acceptance_criteria":"- `bd prime` outputs markdown format\n- Output is ~1-2k tokens\n- Output includes workflow rules and command reference\n- Command has unit tests\n- Documentation updated in AGENTS.md","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-11-11T23:28:42.74124-08:00","updated_at":"2025-11-12T08:30:15.711595-08:00","closed_at":"2025-11-12T08:30:15.711595-08:00","source_repo":".","dependencies":[{"issue_id":"bd-rpn","depends_on_id":"bd-90v","type":"parent-child","created_at":"2025-11-11T23:31:20.357861-08:00","created_by":"daemon"}]} {"id":"bd-ry1u","content_hash":"013464efc3cf53d47c2a170040c66099ce77b13d3d1b34c3729e6a5208122799","title":"Publish official devcontainer configuration","description":"","design":"Problem: GH issue #229 shows git hooks aren't available in devcontainers because bd CLI isn't installed. Solution: Provide official .devcontainer/devcontainer.json that installs Go, builds bd from source, runs bd init --quiet, and installs hooks automatically. Benefits: New contributors start immediately, AI assistants work out-of-box, no manual setup. Implementation: Create .devcontainer/devcontainer.json with Go feature, postCreateCommand to build bd and install hooks, environment variables. Acceptance: Container builds with bd installed, hooks functional, documentation updated, tested with Codespaces and VSCode.","notes":"Devcontainer configuration implemented. Manual testing required in actual devcontainer environment (Codespaces or VSCode Remote Containers). All code changes complete, tests pass, linting clean.","status":"closed","priority":2,"issue_type":"epic","created_at":"2025-11-05T15:02:21.783666-08:00","updated_at":"2025-11-05T17:46:42.70998-08:00","closed_at":"2025-11-05T17:46:42.70998-08:00","source_repo":"."} {"id":"bd-s02","content_hash":"911d456e4dabae028dd615b643c99058ef12e55ea523cb81cc933783c7b13546","title":"Manual task","description":"","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-03T20:15:10.022202-08:00","updated_at":"2025-11-03T20:15:10.022202-08:00","source_repo":"."} {"id":"bd-s1xn","content_hash":"0207827e9eec2a520f16f53a2cdaf50a06483dc53736aa5158e1ff971b88acc6","title":"bd message: Refactor duplicated error messages","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-08T12:54:27.624981-08:00","updated_at":"2025-11-08T12:58:59.542795-08:00","closed_at":"2025-11-08T12:58:59.542795-08:00","source_repo":".","dependencies":[{"issue_id":"bd-s1xn","depends_on_id":"bd-6uix","type":"parent-child","created_at":"2025-11-08T12:55:54.96063-08:00","created_by":"daemon"}]} @@ -470,12 +470,13 @@ {"id":"bd-tmdx","content_hash":"0976d6529458902f06108d5d316fda3bf6ed299eaa684501aada481d9e4b10a5","title":"Investigate database pollution - unexpected issue count increases","description":"Two repositories showing unexpected issue counts:\n- ~/src/beads: 280 issues (expected ~209-220)\n- ~/src/dave/beads: 895 issues (675 open, 149 closed)\n\nThis suggests database pollution - issues from one repository leaking into another. Need to investigate:\n1. Run bd detect-pollution on both repos\n2. Check for cross-repo contamination\n3. Identify source of pollution (daemon? multi-repo config? import issues?)\n4. Clean up polluted databases\n5. Prevent future pollution","status":"closed","priority":0,"issue_type":"bug","created_at":"2025-11-06T22:50:16.957689-08:00","updated_at":"2025-11-07T00:05:38.994405-08:00","closed_at":"2025-11-07T00:05:38.994405-08:00","source_repo":"."} {"id":"bd-tne","content_hash":"2a6596980450714800bddc88e106026743a1a131e96f09198eb7dc2a16d75ca4","title":"Add Claude setup tip with dynamic priority","description":"Add a predefined tip that suggests running `bd setup claude` when Claude Code is detected but not configured. This tip should have higher priority (shown more frequently) until the setup is complete.","design":"## Implementation\n\nAdd to tip registry in `cmd/bd/tips.go`:\n\n```go\n{\n ID: \"claude_setup\",\n Condition: func() bool {\n return isClaudeDetected() \u0026\u0026 !isClaudeSetupComplete()\n },\n Message: \"Run 'bd setup claude' to enable automatic context recovery in Claude Code\",\n Frequency: 24 * time.Hour, // Daily minimum gap\n Priority: 100, // Highest priority\n Probability: 0.6, // 60% chance when eligible\n}\n```\n\n## Detection Logic\n\n```go\nfunc isClaudeDetected() bool {\n // Check environment variables\n if os.Getenv(\"CLAUDE_CODE\") != \"\" || os.Getenv(\"ANTHROPIC_CLI\") != \"\" {\n return true\n }\n // Check if .claude/ directory exists\n if _, err := os.Stat(filepath.Join(os.Getenv(\"HOME\"), \".claude\")); err == nil {\n return true\n }\n return false\n}\n\nfunc isClaudeSetupComplete() bool {\n // Check for global installation\n home, err := os.UserHomeDir()\n if err == nil {\n _, err1 := os.Stat(filepath.Join(home, \".claude/commands/prime_beads.md\"))\n _, err2 := os.Stat(filepath.Join(home, \".claude/hooks/sessionstart\"))\n if err1 == nil \u0026\u0026 err2 == nil {\n return true // Global hooks installed\n }\n }\n \n // Check for project installation\n _, err1 := os.Stat(\".claude/commands/prime_beads.md\")\n _, err2 := os.Stat(\".claude/hooks/sessionstart\")\n return err1 == nil \u0026\u0026 err2 == nil\n}\n```\n\n## Priority and Probability Behavior\n\n**Why 60% probability?**\n- Important message (priority 100) but not critical\n- Daily frequency + 60% = shows ~4 times per week\n- Avoids spam while staying visible\n- Balances persistence with user experience\n\n**Comparison with other probabilities:**\n- 100% probability: Shows EVERY day (annoying)\n- 80% probability: Shows ~6 days per week (too frequent)\n- 60% probability: Shows ~4 days per week (balanced)\n- 40% probability: Shows ~3 days per week (might be missed)\n\n**Auto-stops when setup complete:**\n- Condition becomes false after `bd setup claude`\n- No manual dismissal needed\n- Tip naturally disappears from rotation","acceptance_criteria":"- Claude setup tip added to registry\n- isClaudeDetected() checks environment and filesystem\n- isClaudeSetupComplete() verifies hook installation\n- Tip shows daily until setup complete\n- Tip stops showing after setup\n- Unit tests for detection functions","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-11T23:29:29.871324-08:00","updated_at":"2025-11-11T23:50:29.756454-08:00","source_repo":".","dependencies":[{"issue_id":"bd-tne","depends_on_id":"bd-d4i","type":"blocks","created_at":"2025-11-11T23:29:29.872081-08:00","created_by":"daemon"},{"issue_id":"bd-tne","depends_on_id":"bd-br8","type":"blocks","created_at":"2025-11-11T23:29:29.87252-08:00","created_by":"daemon"}]} {"id":"bd-tru","content_hash":"0de12031088519a3dcd27968d6bf17eb3a92d1853264e5a0dceef3310b3a2b04","title":"Update documentation for bd prime and Claude integration","description":"Update AGENTS.md, README.md, and QUICKSTART.md to document the new `bd prime` command, `bd setup claude` command, and tip system.","design":"## Documentation Updates\n\n### AGENTS.md\nAdd new section \"Context Recovery\":\n```markdown\n## Context Recovery\n\n### The Problem\nAfter context compaction or clearing conversation, AI agents may forget to use Beads and revert to markdown TODOs. Claude Code hooks solve this.\n\n### bd prime Command\nThe `bd prime` command outputs essential Beads workflow context in AI-optimized markdown format (~1-2k tokens).\n\n**When to use:**\n- After context compaction\n- After clearing conversation\n- Starting new session\n- When agent seems to forget bd workflow\n- Manual context refresh\n\n**Usage:**\n```bash\nbd prime # Output workflow context\n```\n\n### Automatic Integration (Recommended)\n\nRun `bd setup claude` to install hooks that auto-refresh bd context:\n- **SessionStart hook**: Loads context in new sessions\n- **PreCompact hook**: Refreshes context before compaction (survives better)\n- **Works with MCP**: Hooks complement MCP server (not replace)\n- **Works without MCP**: bd prime provides workflow via CLI\n\n**Why hooks matter even with MCP:**\n- MCP provides native tools, but agent may forget to use them\n- Hooks keep \"use bd, not markdown\" fresh in context\n- PreCompact refreshes workflow before compaction\n\n### MCP Server vs bd prime\n\n**Not an either/or choice** - they solve different problems:\n\n| Aspect | MCP Server | bd prime | Both |\n|--------|-----------|----------|------|\n| **Purpose** | Native bd tools | Workflow context | Best of both |\n| **Tokens** | 10.5k always loaded | ~1-2k when called | 10.5k + ~2k |\n| **Tool access** | Function calls | CLI via Bash | Function calls |\n| **Context memory** | Can fade after compaction | Hooks keep fresh | Hooks + tools |\n| **Recommended** | Heavy usage | Token optimization | Best experience |\n\n**Setup options:**\n```bash\nbd setup claude # Install hooks (works with or without MCP)\nbd setup claude --local # Per-project only\nbd setup claude --remove # Remove hooks\n```\n```\n\n### README.md\nAdd to \"Getting Started\" section:\n```markdown\n### AI Agent Integration\n\n**Claude Code users:** Run `bd setup claude` to install automatic context recovery hooks.\n\nHooks work with both MCP server and CLI approaches, preventing agents from forgetting bd workflow after compaction.\n\n**MCP vs bd prime:**\n- **With MCP server**: Hooks keep agent using bd tools (prevents markdown TODO reversion)\n- **Without MCP server**: Hooks provide workflow context via `bd prime` (~1-2k tokens)\n```\n\n### QUICKSTART.md\nAdd section on agent integration:\n```markdown\n## For AI Agents\n\n**Context loading:**\n```bash\nbd prime # Load workflow context (~1-2k tokens)\n```\n\n**Automatic setup (Claude Code):**\n```bash\nbd setup claude # Install hooks for automatic context recovery\n```\n\nHooks prevent agents from forgetting bd workflow after compaction.\n```","acceptance_criteria":"- AGENTS.md has Context Recovery section\n- README.md mentions bd setup claude\n- QUICKSTART.md mentions bd prime\n- Examples show when to use bd prime vs MCP\n- Clear comparison of trade-offs","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-11T23:30:22.77349-08:00","updated_at":"2025-11-11T23:45:23.242658-08:00","source_repo":".","dependencies":[{"issue_id":"bd-tru","depends_on_id":"bd-rpn","type":"blocks","created_at":"2025-11-11T23:30:22.774216-08:00","created_by":"daemon"},{"issue_id":"bd-tru","depends_on_id":"bd-br8","type":"blocks","created_at":"2025-11-11T23:30:22.774622-08:00","created_by":"daemon"},{"issue_id":"bd-tru","depends_on_id":"bd-90v","type":"parent-child","created_at":"2025-11-11T23:31:35.277819-08:00","created_by":"daemon"}]} +{"id":"bd-ts0c","content_hash":"46989179f15aa0faaeb9b0d839e71c6ea5002d6d850a8015dfaa5ea6e8308b0b","title":"Merge PR #300: gitignore upgrade feature","description":"PR #300 is ready to merge but has rebase conflicts with main.\n\n**Context:**\n- PR implements 3 mechanisms for .beads/.gitignore upgrade (bd doctor --fix, daemon auto-upgrade, bd init idempotent)\n- Conflicts resolved locally but diverged branches make push difficult\n- All fixes applied: removed merge artifact, applied new gitignore template\n- Clean scope: only 6 files changed (+194/-42)\n\n**Next steps:**\n1. Option A: Merge via GitHub UI (resolve conflicts in web interface)\n2. Option B: Fresh rebase on main and force push\n3. Verify CI passes\n4. Squash and merge\n\nPR URL: https://github.com/steveyegge/beads/pull/300\nFixes: #274","status":"open","priority":1,"issue_type":"task","created_at":"2025-11-12T11:56:22.778982-08:00","updated_at":"2025-11-12T11:56:22.778982-08:00","source_repo":"."} {"id":"bd-tuqd","content_hash":"06ac95944f03d871a6f58d2cd63796828873e92ef7c9b897eb639d28860a458e","title":"bd init overwrites existing git hooks without detection or chaining","description":"GH #254: bd init silently overwrites existing git hooks (like pre-commit framework) without detecting them, backing them up, or offering to chain. This breaks workflows and can result in committed code with failing tests.\n\nFix: Detect existing hooks, prompt user with options to chain/overwrite/skip.","status":"closed","priority":0,"issue_type":"bug","created_at":"2025-11-07T15:51:17.582882-08:00","updated_at":"2025-11-07T15:55:01.330531-08:00","closed_at":"2025-11-07T15:55:01.330531-08:00","source_repo":"."} {"id":"bd-twlr","content_hash":"e0fe5d5f0cac3bb24ae6c12bdcac79ba0dac61f2e85568e9def8b809b7d038b6","title":"Add bd init --team wizard","description":"Interactive wizard for team workflow setup. Guides user through: branch workflow configuration, shared repo setup, team member onboarding, examples of team collaboration patterns.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-05T18:04:30.013645-08:00","updated_at":"2025-11-05T19:27:33.075826-08:00","closed_at":"2025-11-05T18:56:03.004161-08:00","source_repo":".","dependencies":[{"issue_id":"bd-twlr","depends_on_id":"bd-8rd","type":"parent-child","created_at":"2025-11-05T18:04:39.164445-08:00","created_by":"daemon"}]} {"id":"bd-u4f5","content_hash":"89c6ae8745a842541c9a2025222c2c2e67e17b4fc33e0e56e58a37f0c5935939","title":"bd import silently succeeds when database matches working tree but not git HEAD","description":"**Critical**: bd import reports '0 created, 0 updated' when database matches working tree JSONL, even when working tree is ahead of git HEAD. This gives false confidence that everything is synced with the source of truth.\n\n## Reproduction\n\n1. Start with database synced to working tree .beads/issues.jsonl (376 issues)\n2. Git HEAD has older version of .beads/issues.jsonl (354 issues)\n3. Run: bd import .beads/issues.jsonl\n4. Output: 'Import complete: 0 created, 0 updated'\n\n## Problem\n\nUser expects 'bd import' after 'git pull' to sync database with committed state, but:\n- Command silently succeeds because DB already matches working tree\n- No warning that working tree has uncommitted changes\n- User falsely believes everything is synced with git\n- Violates 'JSONL in git is source of truth' principle\n\n## Expected Behavior\n\nWhen .beads/issues.jsonl differs from git HEAD, bd import should:\n1. Detect uncommitted changes: git diff --quiet HEAD .beads/issues.jsonl\n2. Warn user: 'Warning: .beads/issues.jsonl has uncommitted changes (376 lines vs 354 in HEAD)'\n3. Clarify status: 'Import complete: 0 created, 0 updated (already synced with working tree)'\n4. Recommend: 'Run git diff .beads/issues.jsonl to review uncommitted work'\n\n## Impact\n\n- Users can't trust 'bd import' status messages\n- Silent data loss risk if user assumes synced and runs git checkout\n- Breaks mental model of 'JSONL in git = source of truth'\n- Critical for VC's landing-the-plane workflow","acceptance_criteria":"1. bd import detects when working tree differs from git HEAD\n2. Warning emitted if JSONL has uncommitted changes \n3. Status message clarifies 'synced with working tree' vs 'synced with git'\n4. Optional flag to suppress warning (e.g., --working-tree mode)\n5. Documentation updated to explain import behavior with uncommitted changes\n6. Test case: import with dirty working tree shows warning","status":"closed","priority":0,"issue_type":"bug","created_at":"2025-11-07T23:51:28.536822-08:00","updated_at":"2025-11-07T23:58:34.482313-08:00","closed_at":"2025-11-07T23:58:34.482313-08:00","source_repo":".","labels":["data-integrity"]} {"id":"bd-u8j","content_hash":"91f39bbd4f2394592407c77917682b2c7c3a0b6415a3572eb75a49b0486a17fe","title":"Clarify exclusive lock protocol compatibility with multi-repo","description":"The contributor-workflow-analysis.md proposes per-repo file locking (Decision #7) using flock on JSONL files. However, VC (a downstream library consumer) uses an exclusive lock protocol (vc-195, requires Beads v0.17.3+) that allows bd daemon and VC executor to coexist.\n\nNeed to clarify:\n- Does the proposed per-repo file locking work with VC's existing exclusive lock protocol?\n- Do library consumers like VC need to adapt their locking logic?\n- Can multiple repos be locked atomically for cross-repo operations?\n\nContext: contributor-workflow-analysis.md lines 662-681","acceptance_criteria":"- Documentation explicitly states compatibility or incompatibility with existing lock protocols\n- If incompatible, migration path is documented for library consumers\n- If compatible, example showing coexistence is provided","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-03T20:24:08.257493-08:00","updated_at":"2025-11-05T14:15:01.506885-08:00","closed_at":"2025-11-05T14:15:01.506885-08:00","source_repo":"."} {"id":"bd-uiae","content_hash":"5c184901daaa674a0f1224a29ab789019b53da6d5b5b4d6ac943e7d5d4846b3e","title":"Update documentation for beads-merge integration","description":"Document the integrated merge functionality.\n\n**Updates needed**:\n- AGENTS.md: Replace \"use external beads-merge\" with \"bd merge\"\n- README.md: Add git merge driver section\n- TROUBLESHOOTING.md: Update merge conflict resolution\n- ADVANCED.md: Document 3-way merge algorithm\n- Create CREDITS.md or ATTRIBUTION.md for @neongreen\n\n**Highlight**: Deletion sync fix (bd-hv01)","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-05T18:42:20.488998-08:00","updated_at":"2025-11-06T18:19:16.234758-08:00","closed_at":"2025-11-06T15:40:27.830475-08:00","source_repo":".","dependencies":[{"issue_id":"bd-uiae","depends_on_id":"bd-qqvw","type":"parent-child","created_at":"2025-11-05T18:42:28.752447-08:00","created_by":"daemon"}]} -{"id":"bd-urob","content_hash":"fc0e79260f5f6860fa8884859c4b33b18f9cc2dad361c1c1abb9bdeb412479b5","title":"bd-hv01: Refactor snapshot management into dedicated module","description":"Problem: Snapshot logic is scattered across deletion_tracking.go. Would benefit from abstraction with SnapshotManager type.\n\nBenefits: cleaner separation of concerns, easier to test in isolation, better encapsulation, could add observability/metrics.\n\nSuggested improvements: add magic constants, track merge statistics, better error messages.\n\nFiles: cmd/bd/deletion_tracking.go (refactor into new snapshot_manager.go)","status":"closed","priority":3,"issue_type":"chore","created_at":"2025-11-06T18:16:27.943666-08:00","updated_at":"2025-11-08T02:19:14.152412-08:00","closed_at":"2025-11-08T02:19:14.152412-08:00","source_repo":".","dependencies":[{"issue_id":"bd-urob","depends_on_id":"bd-rbxi","type":"parent-child","created_at":"2025-11-06T18:19:15.192447-08:00","created_by":"daemon"}]} +{"id":"bd-urob","content_hash":"de6cf45a2ad9d6b7f5e02a197196834b091f5b2f19ed9a8f4af367d9a319e1f2","title":"bd-hv01: Refactor snapshot management into dedicated module","description":"Problem: Snapshot logic is scattered across deletion_tracking.go. Would benefit from abstraction with SnapshotManager type.\n\nBenefits: cleaner separation of concerns, easier to test in isolation, better encapsulation, could add observability/metrics.\n\nSuggested improvements: add magic constants, track merge statistics, better error messages.\n\nFiles: cmd/bd/deletion_tracking.go (refactor into new snapshot_manager.go)","status":"closed","priority":3,"issue_type":"chore","created_at":"2025-11-06T18:16:27.943666-08:00","updated_at":"2025-11-08T02:19:14.152412-08:00","closed_at":"2025-11-08T02:19:14.152412-08:00","source_repo":".","dependencies":[{"issue_id":"bd-urob","depends_on_id":"bd-rbxi","type":"parent-child","created_at":"2025-11-06T18:19:15.192447-08:00","created_by":"daemon"}]} {"id":"bd-vcg5","content_hash":"82933ce7e0add2ee5b5830b343785c3585151453c5c06243af2b1f2b934e72b2","title":"Daemon crash recovery: panic handler + socket cleanup","description":"Improve daemon cleanup on unexpected exit:\n1. Add top-level recover() in runDaemonLoop to capture panics\n2. Write daemon-error file with stack trace on panic\n3. Prefer return over os.Exit where possible (so defers run)\n4. In stopDaemon forced-kill path, also remove stale socket if present\n\nThis ensures better diagnostics and cleaner state after crashes.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-07T16:42:12.733219-08:00","updated_at":"2025-11-07T22:07:17.347728-08:00","closed_at":"2025-11-07T21:17:15.94117-08:00","source_repo":".","dependencies":[{"issue_id":"bd-vcg5","depends_on_id":"bd-ndyz","type":"discovered-from","created_at":"2025-11-07T16:42:12.733889-08:00","created_by":"daemon"}]} {"id":"bd-vxdr","content_hash":"d188358987c7a7d444f9144a4a6cc5164eccd35b16325edba51dad104ab2a7f2","title":"Investigate database pollution - issue count anomalies","description":"Multiple repos showing inflated issue counts suggesting cross-repo pollution:\n- ~/src/dave/beads: 895 issues (675 open) - clearly polluted\n- ~/src/stevey/src/beads: 280 issues (expected ~209-220) - possibly polluted\n\nNeed to investigate:\n1. Source of pollution (multi-repo sync issues?)\n2. How many duplicate/foreign issues exist\n3. Whether recent sync operations caused cross-contamination\n4. How to clean up and prevent future pollution","notes":"Investigation findings:\n\n**Root cause identified:**\n- NOT cross-repo contamination\n- NOT automated test leakage (tests properly use t.TempDir())\n- Manual testing during template feature development (Nov 2-4)\n- Commit ba325a2: \"test issues were accidentally committed during template feature development\"\n\n**Database growth timeline:**\n- Nov 3: 19 issues (baseline)\n- Nov 2-5: +244 issues (massive development spike)\n- Nov 6-7: +40 issues (continued growth)\n- Current: 291 issues → 270 after cleanup\n\n**Test pollution breakdown:**\n- 21 issues matching \"Test \" prefix pattern\n- Most created Nov 2-5 during feature development\n- Pollution from manual `./bd create \"Test issue\"` commands in production workspace\n- All automated tests properly isolated with t.TempDir()\n\n**Cleanup completed:**\n- Ran scripts/cleanup-test-pollution.sh successfully\n- Removed 21 test issues\n- Database reduced from 291 → 270 issues (7.2% cleanup)\n- JSONL synced to git\n\n**Prevention strategy:**\n- Filed follow-up issue for prevention mechanisms\n- Script can be deleted once prevention is in place\n- Tests are already properly isolated - no code changes needed there","status":"closed","priority":0,"issue_type":"bug","created_at":"2025-11-06T22:34:40.137483-08:00","updated_at":"2025-11-07T16:07:28.274136-08:00","closed_at":"2025-11-07T16:04:02.199807-08:00","source_repo":"."} {"id":"bd-wcl","content_hash":"c08d62ce3627a49126c63f6a630a08c1666e5b1b8d9148ae0c72d7d06611b2a9","title":"Document CLI + hooks as recommended approach over MCP","description":"Update documentation to position CLI + bd prime hooks as the primary recommended approach over MCP server, explaining why minimizing context matters even with large context windows (compute cost, energy, environment, latency).","design":"## Goals\n\nPosition CLI + `bd prime` hooks as the **primary recommended approach** for AI agent integration, with MCP server as a legacy/fallback option.\n\nExplore **hybrid mode** - if certain commands benefit from MCP (UX/DX advantages like no approval prompts), minimize MCP surface area to only those commands.\n\nThis requires production validation first - only update docs after CLI mode is proven reliable.\n\n## Why Minimize Context (Even With Large Windows)\n\n**Context window size ≠ free resource**\n\nLarge context windows (100k+, 200k+) don't mean we should fill them wastefully. Every token in context has real costs:\n\n### Compute Cost\n- **Processing overhead**: Larger context = more GPU/CPU cycles per request\n- **Memory usage**: 10.5k tokens consume significant RAM/VRAM\n- **Scaling impact**: Multiplied across all users, all sessions, all requests\n\n### Energy \u0026 Environment\n- **Electricity**: More compute = more power consumption\n- **Carbon footprint**: Data centers running on grid power (not all renewable)\n- **Sustainability**: Unnecessary token usage contributes to AI's environmental impact\n- **Responsibility**: Efficient tools are better for the planet\n\n### User Experience\n- **Latency**: Larger context = slower processing (noticeable at 10k+ tokens)\n- **Cost**: Many AI services charge per token (input + output)\n- **Rate limits**: Context counts against API quotas\n\n### Engineering Excellence\n- **Efficiency**: Good engineering minimizes resource usage\n- **Scalability**: Efficient tools scale better\n- **Best practices**: Optimize for the common case\n\n**The comparison:**\n\n| Approach | Standing Context | Efficiency | User Cost | Environmental Impact |\n|----------|-----------------|------------|-----------|---------------------|\n| **CLI + hooks** | ~1-2k tokens | 80-90% reduction | Lower | Sustainable ✓ |\n| **MCP minimal** | ~2-4k tokens | 60-80% reduction | Medium | Better ✓ |\n| **MCP full** | ~10.5k tokens | Baseline | Higher | Wasteful ✗ |\n\n**Functional equivalence:**\n- CLI via Bash tool works just as well as MCP native calls\n- Same features, same reliability\n- No downside except initial learning curve\n\n## Hybrid Mode: Minimal MCP Surface Area\n\n**Philosophy:** MCP server doesn't have to expose everything.\n\nIf certain commands have legitimate UX/DX benefits from MCP (e.g., no approval prompts, cleaner syntax), we can expose ONLY those commands via MCP while using CLI for everything else.\n\n### Potential MCP-Only Candidates (TBD)\n\nCommands that might benefit from MCP native calls:\n- `ready` - frequently checked, no side effects, approval prompt annoying\n- `show` - read-only, frequently used, approval slows workflow\n- `list` - read-only, no risk, approval adds friction\n\nCommands that work fine via CLI:\n- `create` - complex parameters, benefits from explicit confirmation\n- `update` - state changes, good to see command explicitly\n- `close` - state changes, explicit is better\n- `dep` - relationships, good to see what's being linked\n- `sync` - git operations, definitely want visibility\n\n### Token Budget\n\n**Full MCP** (current): ~10.5k tokens\n- All ~20+ bd commands exposed\n- All parameter schemas\n- All descriptions and examples\n\n**Minimal MCP** (proposed): ~2-4k tokens\n- 3-5 high-frequency read commands only\n- Simplified schemas\n- Minimal descriptions\n- Everything else via CLI\n\n**Pure CLI**: ~1-2k tokens (only on SessionStart/PreCompact)\n- No MCP tools loaded\n- All commands via Bash\n\n### Investigation Required\n\nBefore implementing hybrid mode, validate:\n\n1. **Do MCP calls actually skip approval prompts?**\n - Test with Claude Code approval settings\n - Compare MCP tool calls vs Bash tool calls\n - Measure UX difference in real usage\n\n2. **What's the actual token breakdown per command?**\n - Measure individual command schemas\n - Calculate token savings for minimal vs full\n\n3. **Is approval prompt the only benefit?**\n - Are there other UX advantages to MCP?\n - Does native syntax actually improve experience?\n - User testing with both approaches\n\n4. **Can we dynamically load MCP tools?**\n - Only load MCP when certain commands needed?\n - Hot-swap between CLI and MCP?\n - Probably not - MCP loads at startup\n\n### Hybrid Mode Documentation (If Validated)\n\n```markdown\n## Choosing Your Integration Approach\n\nBeads supports three AI agent integration approaches:\n\n### CLI + Hooks (Recommended - Most Efficient)\n\n**Setup:** `bd setup claude`\n\nUses Claude Code hooks to inject workflow context via `bd prime` command. Agent uses bd via Bash tool.\n\n**Tokens:** ~1-2k (on SessionStart/PreCompact only)\n\n**Pros:**\n- Maximum efficiency (80-90% reduction vs full MCP)\n- Lowest compute/energy usage\n- Same functionality as MCP\n\n**Cons:**\n- Bash tool calls may require approval prompts\n- Slightly more verbose in conversation\n\n### Minimal MCP + Hooks (Balanced)\n\n**Setup:** Install minimal MCP server (read-only commands) + `bd setup claude`\n\nExposes only high-frequency read commands via MCP (ready, show, list). Everything else via CLI.\n\n**Tokens:** ~2-4k MCP + ~1-2k hooks\n\n**Pros:**\n- 60-80% reduction vs full MCP\n- No approval prompts for common queries\n- Cleaner syntax for frequent operations\n- Still efficient\n\n**Cons:**\n- Requires MCP server (additional setup)\n- Mixed interface (some MCP, some CLI)\n\n### Full MCP + Hooks (Legacy)\n\n**Setup:** Install full MCP server + `bd setup claude`\n\n**Tokens:** ~10.5k MCP + hooks\n\n**Pros:**\n- All commands as native function calls\n- Consistent interface\n\n**Cons:**\n- Highest token usage (worst for compute/energy/cost)\n- Slowest processing\n- Less sustainable\n\n### Recommendation\n\n1. **Start with CLI + hooks** - most efficient, works great\n2. **Try minimal MCP** if approval prompts become annoying\n3. **Avoid full MCP** - wasteful with no significant benefit\n```\n\n## Production Validation Checklist\n\nBefore making these documentation changes, validate CLI approach works reliably:\n\n### Phase 1: Pure CLI Validation\n- [ ] `bd prime` implemented and tested\n- [ ] Hooks installed and working in Claude Code\n- [ ] Real-world usage by at least 2-3 developers for 1+ weeks\n- [ ] No significant usability issues reported\n- [ ] Agent successfully uses bd via Bash tool\n- [ ] Document which commands (if any) have approval prompt issues\n\n### Phase 2: Hybrid Mode Investigation (Optional)\n- [ ] Test if MCP calls skip approval prompts vs Bash calls\n- [ ] Measure token cost per MCP command\n- [ ] Identify minimal set of commands worth exposing via MCP\n- [ ] Build minimal MCP server variant\n- [ ] Validate token savings (should be 60-80% vs full MCP)\n- [ ] User testing shows actual UX improvement\n\n### Phase 3: Documentation Update\n- [ ] Update based on validation results\n- [ ] Include measured token counts (not estimates)\n- [ ] Provide clear migration paths\n- [ ] Update `bd doctor` recommendations\n\n## Migration Guide (Optional)\n\nFor users currently using MCP:\n\n```markdown\n### Migrating from Full MCP to CLI + Hooks\n\nAlready using full MCP server? You can switch to the more efficient CLI approach:\n\n1. Install hooks: `bd setup claude`\n2. Test it works (hooks inject context, agent uses Bash tool)\n3. Remove MCP server from `~/.claude/settings.json`\n4. Restart Claude Code\n\nYou'll get the same functionality with 80-90% less token usage.\n\n### Migrating to Minimal MCP (If Available)\n\nIf you find approval prompts annoying for certain commands:\n\n1. Replace full MCP with minimal MCP in `~/.claude/settings.json`\n2. Restart Claude Code\n3. Verify high-frequency commands (ready, show, list) work via MCP\n4. Everything else automatically uses CLI\n\nYou'll get 60-80% token reduction vs full MCP while keeping the UX benefits.\n```\n\n## Files to Update\n\n- `README.md` - Add recommendation in AI Integration section\n- `AGENTS.md` - Add \"Choosing Your Integration Approach\" section early\n- `QUICKSTART.md` - Update AI integration section\n- `docs/` - Any other AI integration docs if they exist\n- `mcp-server/` - Create minimal variant if hybrid validated\n\n## Future: Update `bd init`\n\nOnce validated, update `bd init` to:\n- Default to recommending `bd setup claude` (hooks only)\n- Mention minimal MCP as option for UX improvement\n- Detect existing full MCP and suggest migration\n- Provide token usage estimates for each approach\n\n## MCP Server Architecture Note\n\n**Key insight:** MCP server doesn't have to expose all bd functionality.\n\nCurrent design exposes ~20+ commands (all bd subcommands). This is over-engineered.\n\n**Better design:**\n- **Minimal MCP**: 3-5 read-only commands (~2-4k tokens)\n- **CLI**: Everything else via Bash tool\n- **Hooks**: Context injection via `bd prime`\n\nThis achieves best of both worlds:\n- Low token usage (efficient)\n- No approval prompts for common queries (UX)\n- Explicit visibility for state changes (safety)\n\nIf validation shows NO meaningful benefit to MCP (even minimal), skip hybrid mode entirely and recommend pure CLI.","acceptance_criteria":"- Documentation explains CLI + hooks as recommended approach\n- Explains why context size matters (compute/energy/cost/latency)\n- Token comparison table shows 80-90% reduction\n- Migration guide for existing MCP users\n- Only deployed AFTER production validation\n- Clear that both approaches are supported","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-12T00:15:25.923025-08:00","updated_at":"2025-11-12T00:18:16.786857-08:00","source_repo":"."} diff --git a/cmd/bd/daemon.go b/cmd/bd/daemon.go index 2083aa22..6c67d14d 100644 --- a/cmd/bd/daemon.go +++ b/cmd/bd/daemon.go @@ -10,6 +10,7 @@ import ( "time" "github.com/spf13/cobra" + "github.com/steveyegge/beads/cmd/bd/doctor" "github.com/steveyegge/beads/internal/beads" "github.com/steveyegge/beads/internal/daemon" "github.com/steveyegge/beads/internal/rpc" @@ -308,6 +309,17 @@ func runDaemonLoop(interval time.Duration, autoCommit, autoPush bool, logPath, p defer func() { _ = store.Close() }() log.log("Database opened: %s", daemonDBPath) + // Auto-upgrade .beads/.gitignore if outdated + gitignoreCheck := doctor.CheckGitignore() + if gitignoreCheck.Status == "warning" || gitignoreCheck.Status == "error" { + log.log("Upgrading .beads/.gitignore...") + if err := doctor.FixGitignore(); err != nil { + log.log("Warning: failed to upgrade .gitignore: %v", err) + } else { + log.log("Successfully upgraded .beads/.gitignore") + } + } + // Hydrate from multi-repo if configured hydrateCtx := context.Background() if results, err := store.HydrateFromMultiRepo(hydrateCtx); err != nil { diff --git a/cmd/bd/doctor.go b/cmd/bd/doctor.go index c782f366..51793984 100644 --- a/cmd/bd/doctor.go +++ b/cmd/bd/doctor.go @@ -44,6 +44,10 @@ type doctorResult struct { CLIVersion string `json:"cli_version"` } +var ( + doctorFix bool +) + var doctorCmd = &cobra.Command{ Use: "doctor [path]", Short: "Check beads installation health", @@ -62,11 +66,13 @@ This command checks: - File permissions - Circular dependencies - Git hooks (pre-commit, post-merge, pre-push) + - .beads/.gitignore up to date Examples: bd doctor # Check current directory bd doctor /path/to/repo # Check specific repository - bd doctor --json # Machine-readable output`, + bd doctor --json # Machine-readable output + bd doctor --fix # Automatically fix issues`, Run: func(cmd *cobra.Command, args []string) { // Use global jsonOutput set by PersistentPreRun @@ -86,6 +92,13 @@ Examples: // Run diagnostics result := runDiagnostics(absPath) + // Apply fixes if requested + if doctorFix { + applyFixes(result) + // Re-run diagnostics to show results + result = runDiagnostics(absPath) + } + // Output results if jsonOutput { outputJSON(result) @@ -100,7 +113,27 @@ Examples: }, } -func runDiagnostics(path string) doctorResult { +func init() { + doctorCmd.Flags().BoolVar(&doctorFix, "fix", false, "Automatically fix issues where possible") +} + +func applyFixes(result doctorResult) { + for _, check := range result.Checks { + if check.Status == statusWarning || check.Status == statusError { + switch check.Name { + case "Gitignore": + fmt.Println("Fixing .beads/.gitignore...") + if err := doctor.FixGitignore(); err != nil { + fmt.Fprintf(os.Stderr, " Error: %v\n", err) + } else { + fmt.Println(" ✓ Updated .beads/.gitignore") + } + } + } + } +} + +func runDiagnostics(path string) doctorResult{ result := doctorResult{ Path: path, CLIVersion: Version, @@ -202,6 +235,11 @@ func runDiagnostics(path string) doctorResult { result.Checks = append(result.Checks, legacyDocsCheck) // Don't fail overall check for legacy docs, just warn + // Check 13: Gitignore up to date + gitignoreCheck := convertDoctorCheck(doctor.CheckGitignore()) + result.Checks = append(result.Checks, gitignoreCheck) + // Don't fail overall check for gitignore, just warn + return result } diff --git a/cmd/bd/doctor/gitignore.go b/cmd/bd/doctor/gitignore.go new file mode 100644 index 00000000..9d13286c --- /dev/null +++ b/cmd/bd/doctor/gitignore.go @@ -0,0 +1,104 @@ +package doctor + +import ( + "os" + "path/filepath" + "strings" +) + +// GitignoreTemplate is the canonical .beads/.gitignore content +const GitignoreTemplate = `# SQLite databases +*.db +*.db?* +*.db-journal +*.db-wal +*.db-shm + +# Daemon runtime files +daemon.lock +daemon.log +daemon.pid +bd.sock + +# Legacy database files +db.sqlite +bd.db + +# Merge artifacts (temporary files from 3-way merge) +beads.base.jsonl +beads.base.meta.json +beads.left.jsonl +beads.left.meta.json +beads.right.jsonl +beads.right.meta.json + +# Keep JSONL exports and config (source of truth for git) +!issues.jsonl +!metadata.json +!config.json +` + +// requiredPatterns are patterns that MUST be in .beads/.gitignore +var requiredPatterns = []string{ + "beads.base.jsonl", + "beads.left.jsonl", + "beads.right.jsonl", + "beads.base.meta.json", + "beads.left.meta.json", + "beads.right.meta.json", + "*.db?*", +} + +// CheckGitignore checks if .beads/.gitignore is up to date +func CheckGitignore() DoctorCheck { + gitignorePath := filepath.Join(".beads", ".gitignore") + + // Check if file exists + content, err := os.ReadFile(gitignorePath) // #nosec G304 -- path is hardcoded + if err != nil { + return DoctorCheck{ + Name: "Gitignore", + Status: "warning", + Message: ".beads/.gitignore not found", + Fix: "Run: bd init (safe to re-run) or bd doctor --fix", + } + } + + // Check for required patterns + contentStr := string(content) + var missing []string + for _, pattern := range requiredPatterns { + if !strings.Contains(contentStr, pattern) { + missing = append(missing, pattern) + } + } + + if len(missing) > 0 { + return DoctorCheck{ + Name: "Gitignore", + Status: "warning", + Message: "Outdated .beads/.gitignore (missing merge artifact patterns)", + Detail: "Missing: " + strings.Join(missing, ", "), + Fix: "Run: bd doctor --fix or bd init (safe to re-run)", + } + } + + return DoctorCheck{ + Name: "Gitignore", + Status: "ok", + Message: "Up to date", + } +} + +// FixGitignore updates .beads/.gitignore to the current template +func FixGitignore() error { + gitignorePath := filepath.Join(".beads", ".gitignore") + + // Write canonical template + // #nosec G306 -- 0600 is appropriate for gitignore + if err := os.WriteFile(gitignorePath, []byte(GitignoreTemplate), 0600); err != nil { + return err + } + + return nil +} diff --git a/cmd/bd/init.go b/cmd/bd/init.go index cd87d4af..9def0f77 100644 --- a/cmd/bd/init.go +++ b/cmd/bd/init.go @@ -13,6 +13,7 @@ import ( "github.com/fatih/color" "github.com/spf13/cobra" + "github.com/steveyegge/beads/cmd/bd/doctor" "github.com/steveyegge/beads/internal/beads" "github.com/steveyegge/beads/internal/config" "github.com/steveyegge/beads/internal/configfile" @@ -175,43 +176,13 @@ With --no-db: creates .beads/ directory and issues.jsonl file instead of SQLite return } - // Create .gitignore in .beads directory + // Create/update .gitignore in .beads directory (idempotent - always update to latest) gitignorePath := filepath.Join(localBeadsDir, ".gitignore") - gitignoreContent := `# SQLite databases -*.db -*.db?* -*.db-journal -*.db-wal -*.db-shm - -# Daemon runtime files -daemon.lock -daemon.log -daemon.pid -bd.sock - -# Legacy database files -db.sqlite -bd.db - -# Merge artifacts (temporary files from 3-way merge) -beads.base.jsonl -beads.base.meta.json -beads.left.jsonl -beads.left.meta.json -beads.right.jsonl -beads.right.meta.json - -# Keep JSONL exports and config (source of truth for git) -!issues.jsonl -!metadata.json -!config.json -` - if err := os.WriteFile(gitignorePath, []byte(gitignoreContent), 0600); err != nil { - fmt.Fprintf(os.Stderr, "Warning: failed to create .gitignore: %v\n", err) - // Non-fatal - continue anyway - } + if err := os.WriteFile(gitignorePath, []byte(doctor.GitignoreTemplate), 0600); err != nil { + fmt.Fprintf(os.Stderr, "Warning: failed to create/update .gitignore: %v\n", err) + // Non-fatal - continue anyway } + } // Ensure parent directory exists for the database if err := os.MkdirAll(initDBDir, 0750); err != nil {