diff --git a/.beads/bd.jsonl b/.beads/bd.jsonl index 13efba51..4140203b 100644 --- a/.beads/bd.jsonl +++ b/.beads/bd.jsonl @@ -2,7 +2,7 @@ {"id":"bd-10","title":"Make beads reusable as a Go library for external projects like vc","description":"Currently beads is only usable as a CLI tool. We want to use beads as a library in other Go projects like ~/src/vc so they can programmatically manage issues without shelling out to the bd CLI.\n\nGoals:\n- Export public API from internal packages\n- Document Go package usage\n- Provide examples of programmatic usage\n- Ensure vc can import and use beads storage layer directly\n\nUse case: The vc project needs issue tracking and wants to use beads as an embedded library rather than as a separate CLI tool.","notes":"UnderlyingDB() method implemented and tested. Core functionality complete. Still needs documentation updates (bd-17) and lifecycle safety enhancements (bd-16).","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-10-22T12:27:30.35968-07:00","updated_at":"2025-10-25T23:15:33.517762-07:00","closed_at":"2025-10-22T19:46:09.362533-07:00"} {"id":"bd-100","title":"GH#146: No color showing in terminal for some users","description":"User reports color not working in macOS (Taho 26.0.1) with iTerm 3.6.4 and Terminal.app, despite color working elsewhere in terminal. Python rich and printf escape codes work.\n\nNeed to investigate:\n- Is NO_COLOR env var set?\n- Terminal type detection?\n- fatih/color library configuration\n- Does bd list show colors? bd ready? bd init?\n- What's the output of: echo $TERM, echo $NO_COLOR","status":"open","priority":2,"issue_type":"bug","created_at":"2025-10-24T22:26:36.22163-07:00","updated_at":"2025-10-25T23:15:33.508654-07:00","external_ref":"github:146"} {"id":"bd-101","title":"Fix nil pointer crash in bd reopen command","description":"bd reopen crashes with SIGSEGV at reopen.go:30. Nil pointer dereference when trying to reopen an issue.","notes":"Fixed by adding daemon RPC support to reopen command. Pattern: check daemonClient != nil first, use RPC UpdateArgs with Status=open, fall back to direct store if daemon unavailable.","status":"closed","priority":0,"issue_type":"bug","created_at":"2025-10-25T10:30:31.602438-07:00","updated_at":"2025-10-25T23:15:33.50884-07:00","closed_at":"2025-10-25T10:33:39.016623-07:00"} -{"id":"bd-102","title":"Address gosec security warnings (102 issues)","description":"Security linter warnings: file permissions (0755 should be 0750), G304 file inclusion via variable, G204 subprocess launches. Many are false positives but should be reviewed.","design":"Review each gosec warning. Add exclusions for legitimate cases to .golangci.yml. Fix real security issues (overly permissive file modes).","notes":"**Resolution Summary:**\n\nAll 20 gosec security warnings have been addressed:\n\n**Fixed Issues (improved security):**\n- G301/G306: Changed directory/file permissions from 0755/0644 to 0750/0600 (5 locations)\n- G302: Added #nosec comment for intentionally secure 0700 socket directory permission\n\n**Safe Cases (added #nosec comments with justifications):**\n- G204: Subprocess launches with safe commands (git show, bd daemon) - 5 locations\n- G304: File inclusions with controlled paths - 20+ locations\n- G201: SQL formatting with controlled column names - 4 locations\n- G115: Integer overflow conversions with controlled values - 2 locations\n\n**Changes Made:**\n1. Tightened file/directory permissions for better security\n2. Enabled gosec linter in .golangci.yml\n3. Added #nosec comments for legitimate cases with clear justifications\n4. All tests pass (pre-existing failures in export_test.go are unrelated)\n\nZero gosec warnings remain.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-25T13:47:10.719134-07:00","updated_at":"2025-10-26T22:47:53.848709-07:00","closed_at":"2025-10-26T22:47:53.848709-07:00"} +{"id":"bd-102","title":"Address gosec security warnings (102 issues)","description":"Security linter warnings: file permissions (0755 should be 0750), G304 file inclusion via variable, G204 subprocess launches. Many are false positives but should be reviewed.","design":"Review each gosec warning. Add exclusions for legitimate cases to .golangci.yml. Fix real security issues (overly permissive file modes).","status":"open","priority":2,"issue_type":"task","created_at":"2025-10-25T13:47:10.719134-07:00","updated_at":"2025-10-25T23:15:33.50904-07:00"} {"id":"bd-103","title":"Multi-project MCP context switching (GH#145)","description":"Enable MCP server to manage multiple beads projects in a single session with per-request workspace_root parameter.\n\nCurrent bug: set_context(workspace_root) doesn't actually switch sockets - all operations hit first initialized socket.\n\nUse case: Managing tasks across multiple organizations with different permission models (internal, partners, open source).\n\nArchitecture: Connection pool keyed by workspace_root, each maintaining its own daemon socket connection. Request-scoped routing using ContextVar to avoid global state races.\n\nSee GH#145 for full requirements and user context.","design":"✅ APPROVED WITH MODIFICATIONS by architectural review (2025-10-25)\n\nLSP-style model is correct: Single MCP server → per-project daemons → isolated databases.\n\nCRITICAL CHANGES from review:\n1. **Simplify connection pool**: No LRU eviction initially (typical user: 2-5 projects)\n2. **Add asyncio.Lock**: Prevent race conditions in pool access\n3. **Defer health checks**: Only retry on failure, not preemptive pings\n4. **Handle submodules**: Check local .beads BEFORE git toplevel\n5. **Path canonicalization**: realpath + git toplevel with caching\n\nRISKS MITIGATED:\n- Global _client bug: Replace with connection pool keyed by canonical path\n- Race conditions: Add asyncio.Lock for pool mutations\n- Submodule edge case: Check .beads directory first\n- Stale sockets: Retry once on connection failure\n\nEstimated effort: 2.5-3.5 days (simplified from 2.5-4.5 days)\nConfidence: 8/10","acceptance_criteria":"- Multiple projects can be accessed in single MCP session\n- Per-request workspace_root parameter works on all tools\n- No cross-project data leakage\n- Concurrent calls to different projects work correctly\n- Stale sockets auto-reconnect with retry/backoff\n- Integration tests verify isolation across 2+ temp repos\n- set_context() still works as default fallback","notes":"Review doc: docs/bd-103-architectural-review.md\n\nImplementation order:\n1. bd-108 (connection manager) - Foundation with pool + lock\n2. bd-104 (ContextVar routing) - Per-request workspace\n3. bd-106 (require_context) - Validation\n4. bd-105 (tests) - Concurrency + edge cases\n5. bd-109 (docs) - Usage guide\n6. [deleted:bd-142] (health checks) - DEFERRED to Phase 2","status":"closed","priority":1,"issue_type":"epic","assignee":"amp","created_at":"2025-10-25T13:59:57.231937-07:00","updated_at":"2025-10-25T23:15:33.522558-07:00","closed_at":"2025-10-25T14:36:02.046142-07:00"} {"id":"bd-104","title":"Implement request-scoped routing with ContextVar","description":"Add ContextVar-based routing to avoid global state races during concurrent multi-project calls.\n\nApproach:\n- Define current_workspace: ContextVar[str|None] in server.py\n- Add @with_workspace decorator that resolves workspace_root (via _resolve_workspace_root + realpath)\n- Set ContextVar for duration of tool call, reset after\n- Falls back to set_context default (BEADS_WORKING_DIR) if workspace_root not provided\n- beads_mcp.tools.get_client() reads current_workspace from ContextVar\n\nBlocks: bd-103 (connection manager must exist first)","design":"Decorator pattern with ContextVar for request-scoped workspace routing.\n\n@with_workspace decorator:\n- Extract workspace_root parameter from tool call\n- Resolve via _resolve_workspace_root + realpath\n- Set current_workspace ContextVar for request duration\n- Falls back to BEADS_WORKING_DIR if workspace_root not provided\n- Reset ContextVar after tool completes\n\nApplied to all tools in server.py. _get_client() reads current_workspace.\n\n⚠️ CONCURRENCY GOTCHA (from architectural review):\n- ContextVar doesn't propagate to asyncio.create_task() spawned tasks\n- SOLUTION: Keep tool calls synchronous, no background task spawning\n- If background tasks needed: use contextvars.copy_context()\n\nDocument this limitation in bd-109.","notes":"Blocks on bd-108 (connection pool must exist first).\n\nCRITICAL: Do NOT spawn background tasks within tool implementations.\nContextVar propagation to spawned tasks is unreliable.","status":"closed","priority":1,"issue_type":"task","assignee":"amp","created_at":"2025-10-25T14:00:27.895512-07:00","updated_at":"2025-10-25T23:15:33.522814-07:00","closed_at":"2025-10-25T14:32:36.531658-07:00","dependencies":[{"issue_id":"bd-104","depends_on_id":"bd-103","type":"parent-child","created_at":"2025-10-25T14:00:27.896366-07:00","created_by":"daemon"}]} {"id":"bd-105","title":"Add integration tests for multi-project MCP switching","description":"Comprehensive tests to verify multi-project isolation, concurrency, and edge cases.\n\nEXPANDED TEST COVERAGE (per architectural review):\n\n**Concurrency tests (CRITICAL):**\n- asyncio.gather() with calls to different workspace_root values\n- Verify no cross-project data leakage\n- Verify pool lock prevents race conditions\n\n**Edge case tests:**\n- Submodule handling: Parent repo vs submodule with own .beads\n- Symlink deduplication: Same physical path via different symlinks\n- Stale socket recovery: Kill daemon, verify retry on failure\n- Missing .beads directory handling\n\n**Isolation tests:**\n- Create 2+ temp repos with bd init\n- Verify operations in project A don't affect project B\n- Stress test: many parallel calls across 3-5 repos\n\nEstimated effort: M (1-2 days) including fixtures for temp repos and daemon process management","design":"Test structure:\n\n1. test_concurrent_multi_project.py:\n - asyncio.gather with 2+ projects\n - Verify pool lock prevents corruption\n \n2. test_path_canonicalization.py:\n - Submodule edge case (check .beads first)\n - Symlink deduplication (realpath normalization)\n \n3. test_stale_socket_recovery.py:\n - Kill daemon mid-session\n - Verify retry-on-failure works\n \n4. test_cross_project_isolation.py:\n - Create issues in project A\n - List from project B, verify empty\n - No data leakage\n\nUse pytest fixtures for temp repos and daemon lifecycle.","acceptance_criteria":"- All concurrency tests pass with asyncio.gather\n- Submodule edge case handled correctly\n- Symlinks deduplicated to same connection\n- Stale socket retry works\n- No cross-project data leakage in stress tests","status":"closed","priority":1,"issue_type":"task","assignee":"amp","created_at":"2025-10-25T14:00:27.896623-07:00","updated_at":"2025-10-25T23:15:33.509737-07:00","closed_at":"2025-10-25T14:35:13.09686-07:00","dependencies":[{"issue_id":"bd-105","depends_on_id":"bd-103","type":"parent-child","created_at":"2025-10-25T14:00:27.90028-07:00","created_by":"daemon"}]} @@ -28,14 +28,14 @@ {"id":"bd-123","title":"Add staleness check to non-daemon mode","description":"Extend staleness detection to non-daemon mode (--no-daemon).\n\nImplementation:\n- On database open, check if .beads/issues.jsonl exists\n- If JSONL exists and is newer than .db file: auto-import\n- Compare JSONL mtime vs .db mtime (both os.Stat)\n- Log: \"Auto-importing from .beads/issues.jsonl (newer than database)\"\n\nThis ensures both daemon and non-daemon modes handle git pull correctly.","notes":"INVESTIGATION COMPLETE:\n\nThe requested feature is already implemented in ensureStoreActive() (cmd/bd/direct_mode.go:79-81) which calls autoImportIfNewer() on every database open in non-daemon mode.\n\nThe implementation uses hash-based staleness detection via autoimport.AutoImportIfNewer() instead of mtime-based, which is BETTER because:\n1. Avoids unnecessary imports when file is merely touched\n2. Detects actual content changes reliably \n3. Works correctly after git pull\n\nVerified working with BD_DEBUG=1:\n```\nBD_DEBUG=1 ./bd --no-daemon stats\nDebug: auto-import skipped, JSONL unchanged (hash match)\n```\n\nThe issue description requested mtime-based approach like daemon mode, but hash-based is superior for non-daemon usage. Both modes now have auto-import after git pull.","status":"closed","priority":0,"issue_type":"task","created_at":"2025-10-25T22:46:44.664917-07:00","updated_at":"2025-10-26T12:23:13.349472-07:00","closed_at":"2025-10-26T12:23:13.349472-07:00"} {"id":"bd-124","title":"Add 'bd sync' command for explicit synchronization","description":"Add explicit `bd sync` command as fallback for manual synchronization after git pull.\n\nBehavior:\n- Import from .beads/issues.jsonl\n- If daemon mode: send RPC command to daemon to re-import\n- If non-daemon: directly import to local db\n- Show summary: \"Imported N issues, updated M issues\"\n\nUsage:\n```bash\ngit pull\nbd sync # Force immediate sync\n```\n\nThis complements auto-detection but gives users manual control.","notes":"IMPLEMENTED:\n\nAdded `bd sync --import-only` flag that:\n- Imports from .beads/issues.jsonl automatically (no need to specify path)\n- Works in both daemon and non-daemon modes\n- Shows summary: \"Import complete: X created, Y updated, Z unchanged, N remapped\"\n- Handles collisions automatically with --resolve-collisions\n\nUsage:\n```bash\ngit pull\nbd sync --import-only # Force immediate sync\n```\n\nThe existing `bd sync` command does full git workflow (export, commit, pull, import, push). The new --import-only flag complements --flush-only for granular control.\n\nImplementation in cmd/bd/sync.go","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-25T22:46:52.139434-07:00","updated_at":"2025-10-26T12:27:40.539108-07:00","closed_at":"2025-10-26T12:27:40.539108-07:00"} {"id":"bd-125","title":"Add integration test for git pull sync scenario","description":"Add integration test simulating the git pull sync issue.\n\nTest scenario:\n1. Create temp git repo with beads initialized\n2. Clone 1: Create and close issue, export, commit, push\n3. Clone 2: Start daemon, git pull\n4. Clone 2: Verify bd show \u003cissue\u003e reflects closed status immediately\n5. Verify no manual import or daemon restart needed\n\nAlso test:\n- Non-daemon mode (--no-daemon) handles git pull correctly\n- bd sync command works in both modes\n- Performance: staleness check adds \u003c10ms overhead\n\nDepends on staleness detection implementation.","status":"closed","priority":0,"issue_type":"task","created_at":"2025-10-25T22:47:01.101808-07:00","updated_at":"2025-10-26T12:32:34.054034-07:00","closed_at":"2025-10-26T12:32:34.054034-07:00","dependencies":[{"issue_id":"bd-125","depends_on_id":"bd-123","type":"blocks","created_at":"2025-10-25T22:47:05.615638-07:00","created_by":"daemon"}]} -{"id":"bd-126","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-10-26T22:37:41.210402-07:00","closed_at":"2025-10-26T22:37:41.210402-07:00","dependencies":[{"issue_id":"bd-126","depends_on_id":"bd-124","type":"blocks","created_at":"2025-10-25T22:47:16.949519-07:00","created_by":"daemon"}]} +{"id":"bd-126","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":"open","priority":2,"issue_type":"task","created_at":"2025-10-25T22:47:14.668842-07:00","updated_at":"2025-10-25T23:15:33.515404-07:00","dependencies":[{"issue_id":"bd-126","depends_on_id":"bd-124","type":"blocks","created_at":"2025-10-25T22:47:16.949519-07:00","created_by":"daemon"}]} {"id":"bd-127","title":"Update documentation for auto-sync behavior","description":"Update documentation to explain auto-sync after git pull.\n\nFiles to update:\n1. README.md - Add section on git workflow and auto-sync\n2. AGENTS.md - Note that bd auto-detects JSONL changes after git pull\n3. WORKFLOW.md - Update git pull workflow to remove manual import step\n4. FAQ.md - Add Q\u0026A about sync behavior and staleness\n\nKey points:\n- bd automatically detects when JSONL is newer than database\n- No manual import needed after git pull\n- bd sync command available for manual control\n- Optional git hook for guaranteed sync","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-25T22:47:24.618649-07:00","updated_at":"2025-10-26T12:44:33.996187-07:00","closed_at":"2025-10-26T12:44:33.996187-07:00"} {"id":"bd-128","title":"Refactor autoImportIfNewer to be callable from daemon","description":"The staleness check in [deleted:bd-160] detects when JSONL is newer than last import, but can't trigger the actual import because autoImportIfNewer() is in cmd/bd and uses global variables.\n\nNeed to:\n1. Extract core import logic from autoImportIfNewer() into importable function\n2. Move to internal/autoimport or similar package\n3. Make it callable from daemon (no global state dependency)\n4. Update staleness check in server.go to call actual import instead of just logging\n\nThis completes the auto-sync feature - daemon will truly auto-import after git pull.","status":"closed","priority":0,"issue_type":"task","created_at":"2025-10-25T23:10:41.392416-07:00","updated_at":"2025-10-25T23:51:09.811006-07:00","closed_at":"2025-10-25T23:51:09.811006-07:00"} {"id":"bd-129","title":"Enforce daemon singleton per workspace with file locking","description":"Agent in ~/src/wyvern discovered 4 simultaneous daemon processes running, causing infinite directory recursion (.beads/.beads/.beads/...). Each daemon used relative paths and created nested .beads/ directories.\n\nRoot cause: No singleton enforcement. Multiple `bd daemon` processes can start in same workspace.\n\nExpected: One daemon per workspace (each workspace = separate .beads/ dir with bd.sock)\nActual: Multiple daemons can run simultaneously in same workspace\n\nNote: Separate git clones = separate workspaces = separate daemons (correct). Git worktrees share .beads/ and have known limitations (documented, use --no-daemon).","design":"Use flock (file locking) on daemon socket or database file to enforce singleton:\n\n1. On daemon start, attempt exclusive lock on .beads/bd.sock or .beads/daemon.lock\n2. If lock held by another process, refuse to start (exit with clear error)\n3. Hold lock for lifetime of daemon process\n4. Release lock on daemon shutdown\n\nAlternative: Use PID file with stale detection (check if PID is still running)\n\nImplementation location: Daemon startup code in cmd/bd/ or internal/daemon/","acceptance_criteria":"1. Starting second daemon process in same workspace fails with clear error\n2. Test: Start daemon, attempt second start, verify failure\n3. Killing daemon releases lock, allowing new daemon to start\n4. No infinite .beads/ directory recursion possible\n5. Works correctly with auto-start mechanism","status":"in_progress","priority":0,"issue_type":"bug","created_at":"2025-10-25T23:13:12.269549-07:00","updated_at":"2025-10-25T23:15:33.516072-07:00"} {"id":"bd-13","title":"Phase 2: Implement VCStorage Wrapper","description":"Create VCStorage wrapper that embeds beads.Storage and adds VC-specific operations.\n\n**Goal:** Build clean abstraction layer where VC extends Beads without modifying Beads library.\n\n**Architecture:**\n- VCStorage embeds beads.Storage (delegates core operations)\n- VCStorage adds VC-specific methods (executor instances, events)\n- Same database, separate table namespaces (Beads tables + VC tables)\n- Zero changes to Beads library code\n\n**Key Tasks:**\n1. Create VCStorage struct that embeds beads.Storage\n2. Implement VC-specific methods: CreateExecutorInstance(), GetStaleExecutors(), LogEvent(), UpdateExecutionState()\n3. Create VC table schemas (executor_instances, issue_execution_state, agent_events)\n4. Verify type compatibility between VC types.Issue and Beads Issue\n5. Create MockVCStorage for testing\n6. Write unit tests for VC-specific methods\n7. Write integration tests (end-to-end with Beads)\n8. Benchmark performance vs current SQLite\n9. Verify NO changes needed to Beads library\n\n**Acceptance Criteria:**\n- VCStorage successfully wraps Beads storage (embedding works)\n- VC-specific tables created and accessible via foreign keys to Beads tables\n- VC-specific methods work (executor instances, events)\n- Core operations delegate to Beads correctly\n- Tests pass with \u003e90% coverage\n- Performance benchmark shows no regression\n- Beads library remains unmodified and standalone\n\n**Technical Details:**\n- Use beadsStore.DB() to get underlying database connection\n- Create VC tables with FOREIGN KEY references to Beads issues table\n- Schema separation: Beads owns (issues, dependencies, labels), VC owns (executor_instances, agent_events)\n- Testing: Embed MockBeadsStorage in MockVCStorage\n\n**Dependencies:**\n- Blocked by Phase 1 (need Beads library imported)\n\n**Estimated Effort:** 1.5 sprints","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-22T14:04:36.674165-07:00","updated_at":"2025-10-25T23:15:33.472658-07:00","closed_at":"2025-10-22T21:37:48.747033-07:00","dependencies":[{"issue_id":"bd-13","depends_on_id":"bd-11","type":"parent-child","created_at":"2025-10-24T13:17:40.321936-07:00","created_by":"renumber"},{"issue_id":"bd-13","depends_on_id":"bd-12","type":"blocks","created_at":"2025-10-24T13:17:40.322171-07:00","created_by":"renumber"}]} {"id":"bd-130","title":"Track last JSONL import timestamp in daemon state","description":"Add state tracking to daemon to record when .beads/issues.jsonl was last imported.\n\nImplementation:\n- Add lastImportTime field to daemon state (time.Time)\n- Update timestamp after successful import\n- Persist across RPC requests (in-memory state)\n- Initialize on daemon startup\n\nNeeded for staleness detection to compare against JSONL mtime.","status":"closed","priority":0,"issue_type":"task","created_at":"2025-10-25T23:13:12.270048-07:00","updated_at":"2025-10-25T23:15:33.516267-07:00","closed_at":"2025-10-25T23:04:33.056154-07:00"} {"id":"bd-131","title":"Implement staleness check before serving daemon requests","description":"Add staleness detection to daemon RPC handler that checks if JSONL is newer than last import.\n\nLogic:\n1. Before processing any RPC request (show, list, ready, etc.)\n2. Get .beads/issues.jsonl mtime (os.Stat)\n3. Compare with lastImportTime\n4. If JSONL mtime \u003e lastImportTime: auto-import before processing request\n5. If import fails: log error but continue with existing data\n\nPerformance: mtime check is fast (\u003c1ms). Only imports if needed.\n\nDepends on lastImportTime tracking.","status":"closed","priority":0,"issue_type":"task","created_at":"2025-10-25T23:13:12.270392-07:00","updated_at":"2025-10-25T23:15:33.516457-07:00","closed_at":"2025-10-25T23:04:33.056796-07:00"} -{"id":"bd-132","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":"**Implementation Complete + Code Review (2025-10-27):**\n\n✅ **Phase 1: Initial Implementation**\n- Created internal/importer package with all import logic\n- Implemented real daemon importFunc\n- Updated cmd/bd to use importer as thin wrapper\n- Fixed memory storage interface\n\n✅ **Phase 2: Oracle Code Review Improvements**\n1. **Single-flight concurrency guard**: TryLock pattern prevents parallel imports\n2. **Fast mtime check**: \u003c0.1ms overhead on 99% of requests (vs 1-10ms hashing)\n3. **Correct import options**: RenameOnImport=true (not SkipPrefixValidation)\n4. **Export after remap**: Prevents collision loops by updating JSONL\n5. **Track last import time**: Enables future throttling optimizations\n\n**Performance:**\n- Every request: Check mtime (~0.01ms)\n- Only if stale: Hash + import (~10-100ms)\n- Throughput: 4300+ issues/sec maintained\n- Concurrency: Single-flight eliminates duplicate work\n\n**Testing:**\n- RPC tests pass (64s)\n- Performance tests pass\n- No regressions\n\n**See CODE_REVIEW_BD132.md for full analysis.**","status":"closed","priority":0,"issue_type":"epic","created_at":"2025-10-25T23:13:12.270766-07:00","updated_at":"2025-10-27T15:29:51.972417-07:00","closed_at":"2025-10-27T15:22:57.205504-07:00"} +{"id":"bd-132","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":"**Current Status (2025-10-26):**\n\n✅ **Completed (bd-128):**\n- Created internal/autoimport package with staleness detection\n- Daemon can detect when JSONL is newer than last import\n- Infrastructure exists to call import logic\n\n❌ **Remaining Work:**\nThe daemon's importFunc in server.go (line 2096-2102) is a stub that just logs a notice. It needs to actually import the issues.\n\n**Problem:** \n- importIssuesCore is in cmd/bd package, not accessible from internal/rpc\n- daemon's handleImport() returns 'not yet implemented' error\n\n**Two approaches:**\n1. Move importIssuesCore to internal/import package (shares with daemon)\n2. Use storage layer directly in daemon (create/update issues via Storage interface)\n\n**Blocker:** \nThis is the critical bug causing data corruption:\n- Agent A pushes changes\n- Agent B does git pull\n- Agent B's daemon serves stale SQLite data\n- Agent B exports stale data back to JSONL, overwriting Agent A's changes\n- Agent B pushes, losing Agent A's work\n\n**Next Steps:**\n1. Choose approach (probably #1 - move importIssuesCore to internal/import)\n2. Implement real importFunc in daemon's checkAndAutoImportIfStale()\n3. Test with two-repo scenario (push from A, pull in B, verify B sees changes)\n4. Ensure no data corruption in multi-agent workflows","status":"in_progress","priority":0,"issue_type":"epic","created_at":"2025-10-25T23:13:12.270766-07:00","updated_at":"2025-10-26T12:11:20.217716-07:00"} {"id":"bd-133","title":"Enforce daemon singleton per workspace with file locking","description":"Agent in ~/src/wyvern discovered 4 simultaneous daemon processes running, causing infinite directory recursion (.beads/.beads/.beads/...). Each daemon used relative paths and created nested .beads/ directories.\n\nRoot cause: No singleton enforcement. Multiple `bd daemon` processes can start in same workspace.\n\nExpected: One daemon per workspace (each workspace = separate .beads/ dir with bd.sock)\nActual: Multiple daemons can run simultaneously in same workspace\n\nNote: Separate git clones = separate workspaces = separate daemons (correct). Git worktrees share .beads/ and have known limitations (documented, use --no-daemon).","design":"Use flock (file locking) on daemon socket or database file to enforce singleton:\n\n1. On daemon start, attempt exclusive lock on .beads/bd.sock or .beads/daemon.lock\n2. If lock held by another process, refuse to start (exit with clear error)\n3. Hold lock for lifetime of daemon process\n4. Release lock on daemon shutdown\n\nAlternative: Use PID file with stale detection (check if PID is still running)\n\nImplementation location: Daemon startup code in cmd/bd/ or internal/daemon/","acceptance_criteria":"1. Starting second daemon process in same workspace fails with clear error\n2. Test: Start daemon, attempt second start, verify failure\n3. Killing daemon releases lock, allowing new daemon to start\n4. No infinite .beads/ directory recursion possible\n5. Works correctly with auto-start mechanism","status":"closed","priority":0,"issue_type":"bug","created_at":"2025-10-25T23:15:14.418051-07:00","updated_at":"2025-10-26T12:28:21.145649-07:00","closed_at":"2025-10-26T12:28:21.145649-07:00"} {"id":"bd-134","title":"Track last JSONL import timestamp in daemon state","description":"Add state tracking to daemon to record when .beads/issues.jsonl was last imported.\n\nImplementation:\n- Add lastImportTime field to daemon state (time.Time)\n- Update timestamp after successful import\n- Persist across RPC requests (in-memory state)\n- Initialize on daemon startup\n\nNeeded for staleness detection to compare against JSONL mtime.","status":"closed","priority":0,"issue_type":"task","created_at":"2025-10-25T23:15:14.4184-07:00","updated_at":"2025-10-25T23:15:33.517097-07:00","closed_at":"2025-10-25T23:04:33.056154-07:00"} {"id":"bd-135","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","status":"closed","priority":0,"issue_type":"epic","created_at":"2025-10-25T23:15:14.418651-07:00","updated_at":"2025-10-26T11:59:31.178532-07:00","closed_at":"2025-10-26T11:59:31.178532-07:00"} @@ -49,50 +49,46 @@ {"id":"bd-142","title":"Local testing of bd init --quiet and auto-sync improvements","description":"Before doing official version bump, test the new changes locally across multiple agent projects:\n\n**Changes to test:**\n- bd init --quiet (non-interactive for agents)\n- Auto-sync documentation updates\n- Git hooks auto-install in quiet mode\n\n**Test scenarios:**\n1. Fresh repo clone with existing .beads/issues.jsonl (bd init --quiet)\n2. Agent setting up new project (bd init --quiet)\n3. Verify git hooks install automatically in quiet mode\n4. Test auto-import after git pull\n5. Verify no daemon conflicts across projects\n\n**Projects/agents to test:**\n- ~/src/vc (waiting on exclusive lock protocol)\n- Other agent projects with fresh clones\n- Multiple agents on same machine","design":"From RELEASING.md, for local testing:\n\n1. Build local binary: `go build -o bd ./cmd/bd`\n2. Use `./bd` directly (don't install via brew yet)\n3. Optional: `alias bd=\"$PWD/bd\"` to test across projects\n4. Kill all daemons first: `pkill -f \"bd.*daemon\"`\n\n**Testing workflow:**\n- Build latest bd binary in ~/src/beads\n- Create alias: `alias bd=\"$HOME/src/beads/bd\"`\n- Test with multiple agents in different repos\n- Verify version: `bd version` shows latest\n- Check daemon compatibility after restart","notes":"Found and fixed bug: bd init --quiet was returning before hooks installation.\n\nFixed by:\n1. Moving hooks check/install before quiet mode return\n2. Embedding hooks inline instead of using external install.sh\n3. This makes bd init --quiet fully self-contained\n\nTested successfully in /tmp/bd-test-quiet - hooks installed correctly.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-26T12:56:04.960569-07:00","updated_at":"2025-10-26T13:19:22.400117-07:00","closed_at":"2025-10-26T13:19:22.400117-07:00"} {"id":"bd-143","title":"Review and respond to new GitHub PRs","description":"Check for new pull requests on GitHub and review/respond to them.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-26T13:19:22.407693-07:00","updated_at":"2025-10-26T13:22:33.395599-07:00","closed_at":"2025-10-26T13:22:33.395599-07:00"} {"id":"bd-144","title":"Document bd edit command and verify MCP exclusion","description":"Follow-up from PR #152:\n1. Add \"bd edit\" to AGENTS.md with \"Humans only\" note\n2. Verify MCP server doesn't expose bd edit command\n3. Consider adding test for command registration","status":"open","priority":2,"issue_type":"task","created_at":"2025-10-26T13:23:47.982295-07:00","updated_at":"2025-10-26T13:23:47.982295-07:00","dependencies":[{"issue_id":"bd-144","depends_on_id":"bd-143","type":"discovered-from","created_at":"2025-10-26T13:23:47.983557-07:00","created_by":"daemon"}]} -{"id":"bd-145","title":"Add \"bd daemons\" command for multi-daemon management","description":"Add a new \"bd daemons\" command with subcommands to manage daemon processes across all beads repositories/worktrees. Should show all running daemons with metadata (version, workspace, uptime, last sync), allow stopping/restarting individual daemons, auto-clean stale processes, view logs, and show exclusive lock status.","design":"Subcommands:\n- list: Show all running daemons with metadata (workspace, PID, version, socket path, uptime, last activity, exclusive lock status)\n- stop \u003cpath|pid\u003e: Gracefully stop a specific daemon\n- restart \u003cpath|pid\u003e: Stop and restart daemon\n- killall: Emergency stop all daemons\n- health: Verify each daemon responds to ping\n- logs \u003cpath\u003e: View daemon logs\n\nFeatures:\n- Auto-clean stale sockets/dead processes\n- Discovery: Scan for .beads/bd.sock files + running processes\n- Communication: Use existing socket protocol, add GET /status endpoint for metadata","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-10-26T16:53:40.970042-07:00","updated_at":"2025-10-26T19:26:29.045738-07:00","closed_at":"2025-10-26T19:26:29.045738-07:00"} -{"id":"bd-146","title":"Implement daemon discovery mechanism","description":"Build the core discovery logic to find all running bd daemons. Scan filesystem for .beads/bd.sock files, check if processes are alive, and collect metadata.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-26T16:54:00.22163-07:00","updated_at":"2025-10-26T19:26:29.048756-07:00","closed_at":"2025-10-26T19:26:29.048756-07:00","dependencies":[{"issue_id":"bd-146","depends_on_id":"bd-145","type":"parent-child","created_at":"2025-10-26T16:54:00.222398-07:00","created_by":"daemon"}]} -{"id":"bd-147","title":"Implement \"bd daemons list\" subcommand","description":"Create the \"bd daemons list\" command that displays all running daemons in a table with: workspace path, PID, version, socket path, uptime, last activity, exclusive lock status. Include --json flag.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-26T16:54:00.232956-07:00","updated_at":"2025-10-26T19:26:29.061768-07:00","closed_at":"2025-10-26T19:26:29.061768-07:00"} -{"id":"bd-148","title":"Add GET /status endpoint to daemon HTTP server","description":"Add a new HTTP endpoint that returns daemon metadata: version, workspace path, PID, uptime, last activity timestamp, exclusive lock status.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-26T16:54:00.233084-07:00","updated_at":"2025-10-26T19:26:29.070048-07:00","closed_at":"2025-10-26T19:26:29.070048-07:00","dependencies":[{"issue_id":"bd-148","depends_on_id":"bd-145","type":"parent-child","created_at":"2025-10-26T16:54:00.238293-07:00","created_by":"daemon"}]} -{"id":"bd-149","title":"Add auto-cleanup of stale sockets and dead processes","description":"When discovering daemons, automatically detect and clean up stale socket files (where process is dead) and orphaned PID files. Should be safe and only remove confirmed-dead processes.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-26T16:54:00.246629-07:00","updated_at":"2025-10-26T19:26:29.077686-07:00","closed_at":"2025-10-26T19:26:29.077686-07:00","dependencies":[{"issue_id":"bd-149","depends_on_id":"bd-145","type":"parent-child","created_at":"2025-10-26T16:54:00.247788-07:00","created_by":"daemon"}]} +{"id":"bd-145","title":"Add \"bd daemons\" command for multi-daemon management","description":"Add a new \"bd daemons\" command with subcommands to manage daemon processes across all beads repositories/worktrees. Should show all running daemons with metadata (version, workspace, uptime, last sync), allow stopping/restarting individual daemons, auto-clean stale processes, view logs, and show exclusive lock status.","design":"Subcommands:\n- list: Show all running daemons with metadata (workspace, PID, version, socket path, uptime, last activity, exclusive lock status)\n- stop \u003cpath|pid\u003e: Gracefully stop a specific daemon\n- restart \u003cpath|pid\u003e: Stop and restart daemon\n- killall: Emergency stop all daemons\n- health: Verify each daemon responds to ping\n- logs \u003cpath\u003e: View daemon logs\n\nFeatures:\n- Auto-clean stale sockets/dead processes\n- Discovery: Scan for .beads/bd.sock files + running processes\n- Communication: Use existing socket protocol, add GET /status endpoint for metadata","status":"in_progress","priority":1,"issue_type":"epic","created_at":"2025-10-26T16:53:40.970042-07:00","updated_at":"2025-10-26T18:11:11.077613-07:00"} +{"id":"bd-146","title":"Implement daemon discovery mechanism","description":"Build the core discovery logic to find all running bd daemons. Scan filesystem for .beads/bd.sock files, check if processes are alive, and collect metadata.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-26T16:54:00.22163-07:00","updated_at":"2025-10-26T18:05:22.257361-07:00","closed_at":"2025-10-26T18:05:22.257361-07:00","dependencies":[{"issue_id":"bd-146","depends_on_id":"bd-145","type":"parent-child","created_at":"2025-10-26T16:54:00.222398-07:00","created_by":"daemon"}]} +{"id":"bd-147","title":"Implement \"bd daemons list\" subcommand","description":"Create the \"bd daemons list\" command that displays all running daemons in a table with: workspace path, PID, version, socket path, uptime, last activity, exclusive lock status. Include --json flag.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-26T16:54:00.232956-07:00","updated_at":"2025-10-26T18:10:24.905516-07:00","closed_at":"2025-10-26T18:10:24.905516-07:00","dependencies":[{"issue_id":"bd-147","depends_on_id":"bd-145","type":"parent-child","created_at":"2025-10-26T17:47:47.922208-07:00","created_by":"stevey"}]} +{"id":"bd-148","title":"Add GET /status endpoint to daemon HTTP server","description":"Add a new HTTP endpoint that returns daemon metadata: version, workspace path, PID, uptime, last activity timestamp, exclusive lock status.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-26T16:54:00.233084-07:00","updated_at":"2025-10-26T17:55:32.40399-07:00","closed_at":"2025-10-26T17:55:32.40399-07:00","dependencies":[{"issue_id":"bd-148","depends_on_id":"bd-145","type":"parent-child","created_at":"2025-10-26T16:54:00.238293-07:00","created_by":"daemon"}]} +{"id":"bd-149","title":"Add auto-cleanup of stale sockets and dead processes","description":"When discovering daemons, automatically detect and clean up stale socket files (where process is dead) and orphaned PID files. Should be safe and only remove confirmed-dead processes.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-26T16:54:00.246629-07:00","updated_at":"2025-10-26T18:17:18.560526-07:00","closed_at":"2025-10-26T18:17:18.560526-07:00","dependencies":[{"issue_id":"bd-149","depends_on_id":"bd-145","type":"parent-child","created_at":"2025-10-26T16:54:00.247788-07:00","created_by":"daemon"}]} {"id":"bd-15","title":"Phase 4: Gradual Cutover \u0026 Production Rollout","description":"Replace SQLite implementation with Beads library in production and remove legacy code.\n\n**Goal:** Complete transition to Beads library, deprecate and remove custom SQLite implementation.\n\n**Key Tasks:**\n1. Run VC executor with Beads library in CI\n2. Dogfood: Use Beads library for VC's own development\n3. Monitor for regressions and performance issues\n4. Flip feature flag: VC_USE_BEADS_LIBRARY=true by default\n5. Monitor production logs for errors\n6. Collect user feedback\n7. Add deprecation notice to CLAUDE.md\n8. Provide migration guide for users\n9. Remove legacy code: internal/storage/sqlite/sqlite.go (~1500 lines)\n10. Remove migration framework: internal/storage/migrations/\n11. Remove manual transaction management code\n12. Update all documentation\n\n**Acceptance Criteria:**\n- Beads library enabled by default in production\n- Zero production incidents related to migration\n- Performance meets or exceeds SQLite implementation\n- All tests passing with Beads library\n- Legacy SQLite code removed\n- Documentation updated\n- Celebration documented 🎉\n\n**Rollout Strategy:**\n1. Week 1: Enable for CI/testing environments\n2. Week 2: Dogfood on VC development\n3. Week 3: Enable for 50% of production (canary)\n4. Week 4: Enable for 100% of production\n5. Week 5: Remove legacy code\n\n**Monitoring:**\n- Track error rates before/after cutover\n- Monitor database query performance\n- Track issue creation/update latency\n- Monitor executor claim performance\n\n**Rollback Plan:**\n- Keep VC_FORCE_SQLITE=true escape hatch for 2 weeks post-cutover\n- Keep legacy code for 1 sprint after cutover\n- Document rollback procedure\n\n**Success Metrics:**\n- Zero data loss\n- No performance regression (\u003c 5% latency increase acceptable)\n- Reduced maintenance burden (code LOC reduction)\n- Positive developer feedback\n\n**Dependencies:**\n- Blocked by Phase 3 (need migration tooling)\n\n**Estimated Effort:** 1 sprint","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-22T14:05:07.755107-07:00","updated_at":"2025-10-25T23:15:33.474948-07:00","closed_at":"2025-10-22T21:37:48.748919-07:00","dependencies":[{"issue_id":"bd-15","depends_on_id":"bd-11","type":"parent-child","created_at":"2025-10-24T13:17:40.324637-07:00","created_by":"renumber"},{"issue_id":"bd-15","depends_on_id":"bd-14","type":"blocks","created_at":"2025-10-24T13:17:40.324851-07:00","created_by":"renumber"}]} -{"id":"bd-150","title":"Update AGENTS.md and README.md with \"bd daemons\" documentation","description":"Document the new \"bd daemons\" command and all subcommands in AGENTS.md and README.md. Include examples and troubleshooting guidance.","status":"open","priority":2,"issue_type":"task","created_at":"2025-10-26T16:54:00.254006-07:00","updated_at":"2025-10-26T16:54:00.254006-07:00","dependencies":[{"issue_id":"bd-150","depends_on_id":"bd-145","type":"parent-child","created_at":"2025-10-26T16:54:00.254862-07:00","created_by":"daemon"}]} -{"id":"bd-151","title":"Implement \"bd daemons health\" subcommand","description":"Add health check command that pings each daemon and reports responsiveness. Should detect and report stale sockets, version mismatches, unresponsive daemons.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-26T16:54:00.255444-07:00","updated_at":"2025-10-26T19:26:29.085111-07:00","closed_at":"2025-10-26T19:26:29.085111-07:00"} -{"id":"bd-152","title":"Implement \"bd daemons logs\" subcommand","description":"Add command to view daemon logs for a specific workspace. Requires daemon logging to file (may need separate issue for log infrastructure).","status":"open","priority":2,"issue_type":"task","created_at":"2025-10-26T16:54:00.256037-07:00","updated_at":"2025-10-26T16:54:00.256037-07:00","dependencies":[{"issue_id":"bd-152","depends_on_id":"bd-145","type":"parent-child","created_at":"2025-10-26T16:54:00.256797-07:00","created_by":"daemon"}]} -{"id":"bd-153","title":"Implement \"bd daemons killall\" subcommand","description":"Add emergency command to stop all running bd daemons. Should discover all daemons and stop them gracefully (with timeout fallback to SIGKILL).","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-26T16:54:00.258822-07:00","updated_at":"2025-10-26T19:26:29.086026-07:00","closed_at":"2025-10-26T19:26:29.086026-07:00","dependencies":[{"issue_id":"bd-153","depends_on_id":"bd-145","type":"parent-child","created_at":"2025-10-26T16:54:00.259421-07:00","created_by":"daemon"}]} -{"id":"bd-154","title":"Implement \"bd daemons stop\" and \"bd daemons restart\" subcommands","description":"Add commands to stop and restart individual daemons by path or PID. Should send graceful shutdown signal via socket, with fallback to SIGTERM.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-26T16:54:00.259875-07:00","updated_at":"2025-10-26T19:26:29.091742-07:00","closed_at":"2025-10-26T19:26:29.091742-07:00","dependencies":[{"issue_id":"bd-154","depends_on_id":"bd-145","type":"parent-child","created_at":"2025-10-26T16:54:00.260433-07:00","created_by":"daemon"}]} +{"id":"bd-150","title":"Update AGENTS.md and README.md with \"bd daemons\" documentation","description":"Document the new \"bd daemons\" command and all subcommands in AGENTS.md and README.md. Include examples and troubleshooting guidance.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-26T16:54:00.254006-07:00","updated_at":"2025-10-26T19:03:21.93015-07:00","closed_at":"2025-10-26T19:03:21.93015-07:00","dependencies":[{"issue_id":"bd-150","depends_on_id":"bd-145","type":"parent-child","created_at":"2025-10-26T16:54:00.254862-07:00","created_by":"daemon"}]} +{"id":"bd-151","title":"Implement \"bd daemons health\" subcommand","description":"Add health check command that pings each daemon and reports responsiveness. Should detect and report stale sockets, version mismatches, unresponsive daemons.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-26T16:54:00.255444-07:00","updated_at":"2025-10-26T18:21:59.75853-07:00","closed_at":"2025-10-26T18:21:59.75853-07:00","dependencies":[{"issue_id":"bd-151","depends_on_id":"bd-145","type":"parent-child","created_at":"2025-10-26T17:47:47.949848-07:00","created_by":"stevey"}]} +{"id":"bd-152","title":"Implement \"bd daemons logs\" subcommand","description":"Add command to view daemon logs for a specific workspace. Requires daemon logging to file (may need separate issue for log infrastructure).","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-26T16:54:00.256037-07:00","updated_at":"2025-10-26T19:03:21.929414-07:00","closed_at":"2025-10-26T19:03:21.929414-07:00","dependencies":[{"issue_id":"bd-152","depends_on_id":"bd-145","type":"parent-child","created_at":"2025-10-26T16:54:00.256797-07:00","created_by":"daemon"}]} +{"id":"bd-153","title":"Implement \"bd daemons killall\" subcommand","description":"Add emergency command to stop all running bd daemons. Should discover all daemons and stop them gracefully (with timeout fallback to SIGKILL).","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-26T16:54:00.258822-07:00","updated_at":"2025-10-26T19:03:21.928597-07:00","closed_at":"2025-10-26T19:03:21.928597-07:00","dependencies":[{"issue_id":"bd-153","depends_on_id":"bd-145","type":"parent-child","created_at":"2025-10-26T16:54:00.259421-07:00","created_by":"daemon"}]} +{"id":"bd-154","title":"Implement \"bd daemons stop\" and \"bd daemons restart\" subcommands","description":"Add commands to stop and restart individual daemons by path or PID. Should send graceful shutdown signal via socket, with fallback to SIGTERM.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-26T16:54:00.259875-07:00","updated_at":"2025-10-26T18:35:28.407904-07:00","closed_at":"2025-10-26T18:35:28.407904-07:00","dependencies":[{"issue_id":"bd-154","depends_on_id":"bd-145","type":"parent-child","created_at":"2025-10-26T16:54:00.260433-07:00","created_by":"daemon"}]} {"id":"bd-155","title":"Daemon auto-import creates race condition with deletions","description":"When a user deletes an issue while the daemon is running, the daemon's periodic import from JSONL can immediately re-add the deleted issue before the deletion is flushed to the JSONL file.\n\n## Steps to reproduce:\n1. Start daemon: bd daemon --interval 30s --auto-commit --auto-push\n2. Delete an issue: bd delete wy-XX --force\n3. Wait for daemon sync cycle (observe daemon log showing \"Imported from JSONL\")\n4. Run bd show wy-XX - issue still exists despite successful deletion\n\n## Expected behavior:\nThe deletion should be immediately flushed to JSONL before the next import cycle, or imports should respect deletions in the database.\n\n## Actual behavior:\nThe daemon imports from JSONL and re-adds the deleted issue, overwriting the deletion. The user sees \"✓ Deleted wy-XX\" but the issue persists.\n\n## Workaround:\n1. Stop daemon: bd daemon --stop\n2. Delete issue: bd delete wy-XX --force\n3. Export to JSONL: bd export -o .beads/issues.jsonl\n4. Commit and push manually\n5. Restart daemon\n\n## Suggested fixes:\n1. Flush pending changes to JSONL before each import cycle\n2. Track deletions separately and don't re-import deleted issues\n3. Make delete operation immediately flush to JSONL when daemon is running\n4. Add a \"dirty\" flag that prevents import if there are pending exports","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-10-26T17:02:30.576489-07:00","updated_at":"2025-10-26T17:07:10.34777-07:00","closed_at":"2025-10-26T17:07:10.34777-07:00","labels":["daemon","data-integrity","race-condition"]} {"id":"bd-156","title":"bd create files issues in wrong project when multiple beads databases exist","description":"When working in a directory with a beads database (e.g., /Users/stevey/src/wyvern/.beads/wy.db), bd create can file issues in a different project's database instead of the current directory's database.\n\n## Steps to reproduce:\n1. Have multiple beads projects (e.g., ~/src/wyvern with wy.db, ~/vibecoder with vc.db)\n2. cd ~/src/wyvern\n3. Run bd create --title \"Test\" --type bug\n4. Observe issue created with wrong prefix (e.g., vc-1 instead of wy-1)\n\n## Expected behavior:\nbd create should respect the current working directory and use the beads database in that directory (.beads/ folder).\n\n## Actual behavior:\nbd create appears to use a different project's database, possibly the last accessed or a global default.\n\n## Impact:\nThis can cause issues to be filed in completely wrong projects, polluting unrelated issue trackers.\n\n## Suggested fix:\n- Always check for .beads/ directory in current working directory first\n- Add --project flag to explicitly specify which database to use\n- Show which project/database is being used in command output\n- Add validation/confirmation when creating issues if current directory doesn't match database project","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-10-26T17:02:30.578817-07:00","updated_at":"2025-10-26T17:08:43.009159-07:00","closed_at":"2025-10-26T17:08:43.009159-07:00","labels":["cli","project-context"]} -{"id":"bd-157","title":"Implement \"bd daemons health\" subcommand","description":"Add health check command that pings each daemon and reports responsiveness. Should detect and report stale sockets, version mismatches, unresponsive daemons.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-26T17:09:51.138682-07:00","updated_at":"2025-10-26T19:26:29.101216-07:00","closed_at":"2025-10-26T19:26:29.101216-07:00","dependencies":[{"issue_id":"bd-157","depends_on_id":"bd-145","type":"parent-child","created_at":"2025-10-26T17:09:51.140111-07:00","created_by":"daemon"}]} -{"id":"bd-158","title":"Implement \"bd daemons list\" subcommand","description":"Create the \"bd daemons list\" command that displays all running daemons in a table with: workspace path, PID, version, socket path, uptime, last activity, exclusive lock status. Include --json flag.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-26T17:09:51.140442-07:00","updated_at":"2025-10-26T19:26:29.10179-07:00","closed_at":"2025-10-26T19:26:29.10179-07:00","dependencies":[{"issue_id":"bd-158","depends_on_id":"bd-145","type":"parent-child","created_at":"2025-10-26T17:09:51.150077-07:00","created_by":"daemon"}]} -{"id":"bd-159","title":"Improve database naming and version management robustness","description":"Make beads architecture more robust to prevent issues like accidental vc.db usage after version upgrades.\n\nKey improvements:\n\n1. **Canonical database name enforcement**\n - Always use beads.db, never auto-detect from multiple .db files\n - bd init migrates/renames any old databases (vc.db → beads.db, bd.db → beads.db)\n - Daemon refuses to start if multiple .db files exist (ambiguity error)\n\n2. **Database schema versioning**\n - Store beads version in SQLite (PRAGMA user_version or metadata table)\n - Daemon checks on startup: validate schema version matches\n - Auto-migrate or fail with clear instructions on version mismatch\n\n3. **Config file with database path**\n - .beads/config.json specifies {\"database\": \"beads.db\", \"version\": \"0.17.5\"}\n - Daemon and clients read config first (single source of truth)\n - No ambiguity about which file is active\n\n4. **Stricter daemon lock validation**\n - daemon.lock includes database path and beads version (JSON)\n - Client validates: lock says beads.db but I expect bd.db → hard error\n - Already partially implemented, make it stricter\n\n5. **Migration tooling**\n - bd init --migrate or auto-run on first command after upgrade\n - Detects old databases, prompts to migrate/clean up\n - Could be part of daemon auto-start logic\n\n**IMPORTANT**: Allow issues.jsonl to be renamed (users cycle through new names to avoid polluted git history). Only enforce database naming, not JSONL naming.","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-10-26T18:01:42.356175-07:00","updated_at":"2025-10-26T19:04:07.843634-07:00","closed_at":"2025-10-26T19:04:07.843634-07:00"} +{"id":"bd-157","title":"Implement \"bd daemons health\" subcommand","description":"Add health check command that pings each daemon and reports responsiveness. Should detect and report stale sockets, version mismatches, unresponsive daemons.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-26T17:09:51.138682-07:00","updated_at":"2025-10-26T17:47:47.958834-07:00","closed_at":"2025-10-26T17:47:47.958834-07:00","dependencies":[{"issue_id":"bd-157","depends_on_id":"bd-145","type":"parent-child","created_at":"2025-10-26T17:09:51.140111-07:00","created_by":"daemon"}]} +{"id":"bd-158","title":"Implement \"bd daemons list\" subcommand","description":"Create the \"bd daemons list\" command that displays all running daemons in a table with: workspace path, PID, version, socket path, uptime, last activity, exclusive lock status. Include --json flag.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-26T17:09:51.140442-07:00","updated_at":"2025-10-26T17:47:47.929666-07:00","closed_at":"2025-10-26T17:47:47.929666-07:00","dependencies":[{"issue_id":"bd-158","depends_on_id":"bd-145","type":"parent-child","created_at":"2025-10-26T17:09:51.150077-07:00","created_by":"daemon"}]} +{"id":"bd-159","title":"Timestamp-only changes still being exported despite dedup logic","description":"User observed timestamp-only changes in .beads/beads.jsonl causing dirty working tree. Example: bd-128's updated_at changed from 2025-10-25T23:51:09.811006-07:00 to 2025-10-26T14:12:45.207573-07:00 with no other field changes.\n\nThis should have been prevented by the export deduplication logic that's supposed to skip timestamp-only updates.\n\nNeed to investigate why timestamp-only changes are still being exported and fix the dedup logic.","status":"open","priority":1,"issue_type":"bug","created_at":"2025-10-26T17:58:15.41007-07:00","updated_at":"2025-10-26T17:58:15.41007-07:00"} {"id":"bd-16","title":"Add lifecycle safety docs and tests for UnderlyingDB() method","description":"The new UnderlyingDB() method exposes the raw *sql.DB connection for extensions like VC to create their own tables. While database/sql is concurrency-safe, there are lifecycle and misuse risks that need documentation and testing.\n\n**What needs to be done:**\n\n1. **Enhanced documentation** - Expand UnderlyingDB() comments to warn:\n - Callers MUST NOT call Close() on returned DB\n - Do NOT change pool/driver settings (SetMaxOpenConns, SetConnMaxIdleTime)\n - Do NOT modify SQLite PRAGMAs (WAL mode, journal, etc.)\n - Expect errors after Storage.Close() - use contexts\n - Keep write transactions short to avoid blocking core storage\n\n2. **Add lifecycle tracking** - Implement closed flag:\n - Add atomic.Bool closed field to SQLiteStorage\n - Set flag in Close(), clear in New()\n - Optional: Add IsClosed() bool method\n\n3. **Add safety tests** (run with -race):\n - TestUnderlyingDB_ConcurrentAccess - N goroutines using UnderlyingDB() during normal storage ops\n - TestUnderlyingDB_AfterClose - Verify operations fail cleanly after storage closed\n - TestUnderlyingDB_CreateExtensionTables - Create VC table with FK to issues, verify FK enforcement\n - TestUnderlyingDB_LongTxDoesNotCorrupt - Ensure long read tx doesn't block writes indefinitely\n\n**Why this matters:**\nVC will use this to create tables in the same database. Need to ensure production-ready safety without over-engineering.\n\n**Estimated effort:** S+S+S = M total (1-3h)","design":"Oracle recommends \"simple path\": enhanced docs + minimal guardrails + focused tests. See oracle output for detailed rationale on concurrency safety, lifecycle risks, and when to consider advanced path (wrapping interface).","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-22T17:07:56.812983-07:00","updated_at":"2025-10-25T23:15:33.476053-07:00","closed_at":"2025-10-22T20:10:52.636372-07:00"} -{"id":"bd-160","title":"Add database schema versioning","description":"Store beads version in SQLite database for version compatibility checking.\n\nImplementation:\n- Add metadata table with schema_version field (or use PRAGMA user_version)\n- Set on database creation (bd init)\n- Daemon validates on startup: schema version matches daemon version\n- Fail with clear error if mismatch: \"Database schema v0.17.5 but daemon is v0.18.0\"\n- Provide migration guidance in error message\n\nSchema version format:\n- Use semver (0.17.5)\n- Store in metadata table: CREATE TABLE metadata (key TEXT PRIMARY KEY, value TEXT)\n- Alternative: PRAGMA user_version (integer only)\n\nBenefits:\n- Detect version mismatches before corruption\n- Enable auto-migration in future\n- Clear error messages for users","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-26T18:06:07.568054-07:00","updated_at":"2025-10-26T18:27:48.294001-07:00","closed_at":"2025-10-26T18:27:48.294001-07:00","dependencies":[{"issue_id":"bd-160","depends_on_id":"bd-159","type":"parent-child","created_at":"2025-10-26T18:06:07.569191-07:00","created_by":"daemon"}]} -{"id":"bd-161","title":"Stricter daemon lock file validation","description":"Enhance daemon.lock to include database path and version, validate on client connection.\n\nCurrent: daemon.lock has PID\nProposed: JSON format with database path and version\n\nLock file format:\n{\n \"pid\": 12345,\n \"database\": \"/full/path/to/.beads/beads.db\",\n \"version\": \"0.17.5\",\n \"started_at\": \"2025-10-26T18:00:00Z\"\n}\n\nImplementation:\n- Daemon writes enhanced lock on startup\n- Client reads lock and validates:\n - Database path matches expected\n - Version compatible\n - Fail hard (not just warn) on mismatch\n- Update existing lock validation code (already partially implemented)\n\nBenefits:\n- Catch daemon/database mismatches early\n- Better error messages\n- More robust multi-workspace scenarios","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-26T18:06:07.570081-07:00","updated_at":"2025-10-26T18:36:09.975648-07:00","closed_at":"2025-10-26T18:36:09.975648-07:00","dependencies":[{"issue_id":"bd-161","depends_on_id":"bd-159","type":"parent-child","created_at":"2025-10-26T18:06:07.570687-07:00","created_by":"daemon"}]} -{"id":"bd-162","title":"Enforce canonical database name (beads.db)","description":"Always use beads.db as the canonical database name. Never auto-detect from multiple .db files.\n\nImplementation:\n- bd init always creates/uses beads.db\n- bd init detects and migrates old databases (vc.db → beads.db, bd.db → beads.db)\n- Daemon refuses to start if multiple .db files exist in .beads/ (exit with ambiguity error)\n- Update database discovery logic to prefer beads.db, error on ambiguity\n\nBenefits:\n- Prevents accidental use of stale databases\n- Clear single source of truth\n- Migration path for existing users","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-26T18:06:07.571076-07:00","updated_at":"2025-10-26T18:16:56.23769-07:00","closed_at":"2025-10-26T18:16:56.23769-07:00"} -{"id":"bd-163","title":"Add .beads/config.json for database path configuration","description":"Create config file to eliminate ambiguity about which database is active.\n\nConfig file format (.beads/config.json):\n{\n \"database\": \"beads.db\",\n \"version\": \"0.17.5\",\n \"jsonl_export\": \"beads.jsonl\" // Allow user to rename\n}\n\nImplementation:\n- bd init creates config.json\n- Daemon and clients read config first (single source of truth)\n- Fall back to beads.db if config missing (backward compat)\n- bd init --jsonl-name allows customizing export filename\n- Gitignore: do NOT ignore config.json (part of repo state)\n\nBenefits:\n- Explicit configuration over convention\n- Allows JSONL renaming for git history hygiene\n- Single source of truth for file paths","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-26T18:06:07.571909-07:00","updated_at":"2025-10-26T18:44:16.133085-07:00","closed_at":"2025-10-26T18:44:16.133085-07:00","dependencies":[{"issue_id":"bd-163","depends_on_id":"bd-159","type":"parent-child","created_at":"2025-10-26T18:06:07.572636-07:00","created_by":"daemon"}]} -{"id":"bd-164","title":"Add migration tooling for database upgrades","description":"Create bd migrate command and auto-migration logic for version upgrades.\n\nImplementation:\n- bd migrate command (or bd init --migrate)\n- Auto-run on first command after daemon version upgrade\n- Detection logic:\n - Find all .db files in .beads/\n - Check schema version in each\n - Prompt to migrate/rename/delete\n- Migration operations:\n - Rename old database to beads.db\n - Update schema version metadata\n - Remove stale databases (with confirmation)\n- Could be part of daemon auto-start logic\n\nUser experience:\n$ bd ready\nDatabase schema mismatch detected.\n Found: vc.db (schema v0.16.0)\n Expected: beads.db (schema v0.17.5)\n \nRun 'bd migrate' to migrate automatically.\n\nBenefits:\n- Smooth upgrade path\n- Prevents confusion on version changes\n- Clean up stale databases\n\nDepends on:\n- Canonical naming (bd-160)\n- Schema versioning (bd-161)","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-26T18:06:07.571855-07:00","updated_at":"2025-10-26T19:04:02.023089-07:00","closed_at":"2025-10-26T19:04:02.023089-07:00","dependencies":[{"issue_id":"bd-164","depends_on_id":"bd-159","type":"parent-child","created_at":"2025-10-26T18:06:07.573546-07:00","created_by":"daemon"},{"issue_id":"bd-164","depends_on_id":"bd-162","type":"blocks","created_at":"2025-10-26T18:06:17.327717-07:00","created_by":"daemon"},{"issue_id":"bd-164","depends_on_id":"bd-160","type":"blocks","created_at":"2025-10-26T18:06:17.351768-07:00","created_by":"daemon"}]} -{"id":"bd-165","title":"Enforce canonical database name (beads.db)","description":"Always use beads.db as the canonical database name. Never auto-detect from multiple .db files.\n\nImplementation:\n- bd init always creates/uses beads.db\n- bd init detects and migrates old databases (vc.db → beads.db, bd.db → beads.db)\n- Daemon refuses to start if multiple .db files exist in .beads/ (exit with ambiguity error)\n- Update database discovery logic to prefer beads.db, error on ambiguity\n\nBenefits:\n- Prevents accidental use of stale databases\n- Clear single source of truth\n- Migration path for existing users","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-26T18:06:18.33827-07:00","updated_at":"2025-10-26T18:10:34.132537-07:00","closed_at":"2025-10-26T18:10:34.132537-07:00","dependencies":[{"issue_id":"bd-165","depends_on_id":"bd-159","type":"parent-child","created_at":"2025-10-26T18:06:18.339465-07:00","created_by":"daemon"}]} -{"id":"bd-166","title":"bd import/sync created 173 duplicate issues with wrong prefix","description":"## What Happened\nDuring corruption recovery investigation (beads-173), discovered the database contained 338 issues instead of expected 165:\n- 165 issues with correct `bd-` prefix \n- 173 duplicate issues with `beads-` prefix (bd-1 → beads-1, etc.)\n- Database config was set to `beads` prefix instead of `bd`\n\n## Root Cause\nSome bd operation (likely import or sync) created duplicate issues with the wrong prefix. The database should have rejected or warned about prefix mismatch, but instead:\n1. Silently created duplicates with wrong prefix\n2. Changed database prefix config from `bd` to `beads`\n\n## Impact\n- **Data integrity violation**: Duplicate issues with different IDs\n- **Silent corruption**: No error or warning during creation \n- **Wrong prefix**: Database config changed without user consent\n- **Confusion**: Users see double the issues, dependencies broken\n\n## Recovery \nHad to manually fix the `issue_prefix` config key (not `prefix` as initially thought):\n```bash\nsqlite3 .beads/beads.db \"UPDATE config SET value = 'bd' WHERE key = 'issue_prefix';\"\nsqlite3 .beads/beads.db \"DELETE FROM issues WHERE id LIKE 'beads-%';\"\n```\n\n## What Should Happen\n1. **Reject prefix mismatch**: If importing issues with different prefix than configured, error or require `--rename-on-import`\n2. **Never auto-change prefix**: Database prefix should only change via explicit `bd rename-prefix` command \n3. **Validate on import**: Check imported issue IDs match configured prefix before creating\n4. **Warn on duplicate IDs**: Even with different prefixes, detect potential duplicates\n\n## Related\n- Discovered during beads-173 (database corruption investigation)\n- Similar to existing prefix validation in `bd sync` (bd-21)","notes":"## Root Cause Analysis\n\nFound the smoking gun! The bug is a combination of three factors:\n\n**1. Database filename-based prefix fallback (sqlite.go:577-589)**\n```go\nfunc derivePrefixFromPath(dbPath string) string {\n dbFileName := filepath.Base(dbPath)\n dbFileName = strings.TrimSuffix(dbFileName, \".db\")\n prefix := strings.TrimSuffix(dbFileName, \"-\")\n if prefix == \"\" {\n prefix = \"bd\"\n }\n return prefix\n}\n```\nWhen `issue_prefix` config is missing, CreateIssue uses database filename (beads.db → \"beads\" prefix).\n\n**2. Auto-import skips prefix validation (autoimport.go:175)**\n```go\nopts := ImportOptions{\n ResolveCollisions: true,\n SkipPrefixValidation: true, // Auto-import is lenient about prefixes\n}\n```\nThis allows importing bd- issues without error even when config says \"beads\".\n\n**3. Missing issue_prefix config**\nSomehow the database lost its `issue_prefix = 'bd'` config (should be set by `bd init --prefix bd`), triggering the fallback.\n\n**Timeline:**\n1. Database exists with bd- issues\n2. `issue_prefix` config gets lost (corruption? manual deletion? reinit?)\n3. Auto-import brings in bd- issues from git (SkipPrefixValidation allows this)\n4. New issue creation falls back to filename → uses \"beads\" prefix\n5. Result: 165 bd- issues + 173 beads- duplicates\n\n**Fixes implemented:**\n1. ✅ Removed derivePrefixFromPath - never derive prefix from filename\n2. ✅ CreateIssue now REJECTS operations if issue_prefix is missing (hard error)\n3. ✅ Auto-import now SETS issue_prefix from first imported issue if missing\n4. ✅ Updated all test helpers to set issue_prefix during database initialization\n\nThis prevents silent corruption - if issue_prefix is missing, operations fail loudly instead of creating duplicate issues.","status":"closed","priority":0,"issue_type":"bug","created_at":"2025-10-26T21:38:39.096165-07:00","updated_at":"2025-10-26T21:51:44.171474-07:00","closed_at":"2025-10-26T21:51:44.171474-07:00"} -{"id":"bd-167","title":"Complete test fixes for bd-166 (missing issue_prefix)","description":"Several test files still fail with \"database not initialized: issue_prefix config is missing\" error:\n\n- cmd/bd/comments_test.go\n- cmd/bd/export_test.go \n- cmd/bd/git_sync_test.go\n- cmd/bd/label_test.go\n- cmd/bd/list_test.go\n- cmd/bd/reopen_test.go\n- cmd/bd/direct_mode_test.go\n\nAll need to either:\n1. Use the new `newTestStore(t, dbPath)` helper, or\n2. Call `store.SetConfig(ctx, \"issue_prefix\", \"bd\")` after `sqlite.New()`\n\nPattern to fix:\n```go\n// Old:\nstore, err := sqlite.New(dbPath)\n\n// New:\nstore := newTestStore(t, dbPath)\n```","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-26T21:54:36.625952-07:00","updated_at":"2025-10-26T22:07:15.853197-07:00","closed_at":"2025-10-26T22:07:15.853197-07:00","dependencies":[{"issue_id":"bd-167","depends_on_id":"bd-166","type":"discovered-from","created_at":"2025-10-26T21:54:41.993277-07:00","created_by":"daemon"}]} -{"id":"bd-168","title":"Add bd doctor command to detect/fix missing issue_prefix","description":"Create a `bd doctor` command that validates database health and offers to fix common issues.\n\n**Phase 1: Detect missing issue_prefix**\n```bash\nbd doctor\n# Output:\n# ✗ issue_prefix not configured\n# Database has 165 issues with prefix \"bd\"\n# Run: bd doctor --fix-prefix bd\n```\n\n**Phase 2: Auto-fix**\n```bash\nbd doctor --fix-prefix bd\n# Sets issue_prefix config to \"bd\"\n# Or derive from existing issues if --fix-prefix not specified\n```\n\n**Phase 3: Other checks (future)**\n- Orphaned dependencies\n- Counter mismatches \n- Corrupted timestamps\n- Duplicate issues with different prefixes\n\nThis helps users recover from bd-166 corruption without manual SQL.","status":"open","priority":2,"issue_type":"feature","created_at":"2025-10-26T21:54:36.634246-07:00","updated_at":"2025-10-26T21:54:36.634246-07:00","dependencies":[{"issue_id":"bd-168","depends_on_id":"bd-166","type":"discovered-from","created_at":"2025-10-26T21:54:41.994194-07:00","created_by":"daemon"}]} -{"id":"bd-169","title":"Add test for CreateIssue with missing issue_prefix","description":"Add explicit test case that verifies CreateIssue fails correctly when issue_prefix config is missing.\n\n**Test:**\n```go\nfunc TestCreateIssue_MissingPrefix(t *testing.T) {\n store, cleanup := setupTestDB(t)\n defer cleanup()\n \n ctx := context.Background()\n \n // Clear the issue_prefix config\n err := store.SetConfig(ctx, \"issue_prefix\", \"\")\n require.NoError(t, err)\n \n // Attempt to create issue should fail\n issue := \u0026types.Issue{\n Title: \"Test issue\",\n Status: types.StatusOpen,\n Priority: 1,\n IssueType: types.TypeTask,\n }\n \n err = store.CreateIssue(ctx, issue, \"test\")\n require.Error(t, err)\n assert.Contains(t, err.Error(), \"database not initialized\")\n assert.Contains(t, err.Error(), \"issue_prefix config is missing\")\n}\n```\n\nThis ensures the fix for bd-166 doesn't regress.","status":"open","priority":3,"issue_type":"task","created_at":"2025-10-26T21:54:36.63521-07:00","updated_at":"2025-10-26T21:54:36.63521-07:00","dependencies":[{"issue_id":"bd-169","depends_on_id":"bd-166","type":"discovered-from","created_at":"2025-10-26T21:54:41.995525-07:00","created_by":"daemon"}]} +{"id":"bd-160","title":"Add database schema versioning","description":"Store beads version in SQLite database for version compatibility checking.\n\nImplementation:\n- Add metadata table with schema_version field (or use PRAGMA user_version)\n- Set on database creation (bd init)\n- Daemon validates on startup: schema version matches daemon version\n- Fail with clear error if mismatch: \"Database schema v0.17.5 but daemon is v0.18.0\"\n- Provide migration guidance in error message\n\nSchema version format:\n- Use semver (0.17.5)\n- Store in metadata table: CREATE TABLE metadata (key TEXT PRIMARY KEY, value TEXT)\n- Alternative: PRAGMA user_version (integer only)\n\nBenefits:\n- Detect version mismatches before corruption\n- Enable auto-migration in future\n- Clear error messages for users","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-26T19:41:11.098628-07:00","updated_at":"2025-10-26T19:41:11.115761-07:00","closed_at":"2025-10-26T19:04:07.843634-07:00","dependencies":[{"issue_id":"bd-160","depends_on_id":"bd-159","type":"parent-child","created_at":"2025-10-26T18:06:07.569191-07:00","created_by":"daemon"}]} +{"id":"bd-161","title":"Update AGENTS.md and README.md with \"bd daemons\" documentation","description":"Document the new \"bd daemons\" command and all subcommands in AGENTS.md and README.md. Include examples and troubleshooting guidance.","status":"open","priority":2,"issue_type":"task","created_at":"2025-10-26T19:41:11.099254-07:00","updated_at":"2025-10-26T19:41:11.099254-07:00","dependencies":[{"issue_id":"bd-161","depends_on_id":"bd-159","type":"parent-child","created_at":"2025-10-26T18:06:07.570687-07:00","created_by":"daemon"}]} +{"id":"bd-162","title":"Implement \"bd daemons logs\" subcommand","description":"Add command to view daemon logs for a specific workspace. Requires daemon logging to file (may need separate issue for log infrastructure).","status":"open","priority":2,"issue_type":"task","created_at":"2025-10-26T19:41:11.099659-07:00","updated_at":"2025-10-26T19:41:11.099659-07:00"} +{"id":"bd-163","title":"Refactor high complexity functions (gocyclo)","description":"11 functions exceed cyclomatic complexity threshold (\u003e30): runDaemonLoop (42), importIssuesCore (71), TestLabelCommands (67), issueDataChanged (39), etc.","design":"Break down complex functions into smaller, testable units. Extract validation, error handling, and business logic into separate functions.","notes":"Refactored issueDataChanged from complexity 39 → 11 by extracting into fieldComparator struct with methods for each comparison type.\n\nRefactored runDaemonLoop from complexity 42 → 7 by extracting:\n- setupDaemonLogger: Logger initialization logic\n- setupDaemonLock: Lock and PID file management\n- startRPCServer: RPC server startup with error handling\n- runGlobalDaemon: Global daemon mode handling\n- createSyncFunc: Sync cycle logic (export, commit, pull, import, push)\n- runEventLoop: Signal handling and main event loop\n\nCode review fixes:\n- Fixed sync overlap: Changed initial sync from `go doSync()` to synchronous `doSync()` to prevent race with ticker\n- Fixed resource cleanup: Replaced `os.Exit(1)` with `return` after acquiring locks to ensure defers run and clean up PID files/locks\n- Added signal.Stop(sigChan) in runEventLoop and runGlobalDaemon to prevent lingering notifications\n- Added server.Stop() in serverErrChan case for consistent cleanup\n\nRefactored TestLabelCom\u0001\u0004\u0013\u0000\u0004\u0013\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000�\u000eA\u000b\u0000_\u001b\u0019�I�E\u00003temp-bad6eeef-f902-459�jA\u000b\u0000\u0017\u001b\u0019�I�E\u00003bd-13updateddaemon{\"id\":\"bd-51\",\"title\":\"Auto-flush writes test pollution and session work to git-tracked issues.jsonl\",\"description\":\"Auto-flush exports ALL issues from DB to issues.jsonl every 5 seconds, including:\\n- Test issues (bd-4053 through bd-4059 were version test junk)\\n- Issues created during debugging sessions\\n- Test pollution from stress tests\\n- Temporary diagnostic issues\\n\\nThis pollutes the git-tracked issues.jsonl with garbage that shouldn't be committed.\\n\\nExample from today:\\n- Git had 49 clean issues\\n- Our DB grew to 100+ with test junk and session work\\n- Auto-flush wrote all 100+ to issues.jsonl\\n- Git status showed modified issues.jsonl with 50+ unwanted issues\\n\\nImpact:\\n- Pollutes git history with test/debug garbage\\n- Makes code review difficult (noise in diffs)\\n- Can't distinguish real work from session artifacts\\n- Other team members pull polluted issues\\n\\nSolutions to consider:\\n1. Disable auto-flush by default (require explicit --enable-auto-flush)\\n2. Add .beadsignore to exclude issue ID patterns\\n3. Make auto-flush only export 'real' issues (exclude test-*)\\n4. Require manual 'bd sync' for git commit\\n5. Auto-flush to separate file (.beads/session.jsonl vs issues.jsonl)\\n\\nRelated: bd-49 (test pollution), isolation_test.go (test DB separation)\",\"status\":\"in_progress\",\"priority\":1,\"issue_type\":\"bug\",\"created_at\":\"2025-10-21T23:54:57.369511-07:00\",\"updated_at\":\"2025-10-22T00:04:09.389477-07:00\"}{\"design\":\"## Analysis\\n\\nConfirmed the issue exists - bd-52 through bd-58 are test pollution in the git-tracked issues.jsonl.\\n\\n### Solution Evaluation:\\n\\n**Option 1: Disable auto-flush by default** ❌\\n- Breaks the auto-sync workflow that users rely on\\n- Requires manual intervention which defeats the purpose\\n- Not recommended\\n\\n**Option 2: Add .beadsignore** ⚠️\\n- Complex to implement (pattern matching, configuration)\\n- Doesn't solve root cause: test issues in production DB\\n- Better to prevent pollution at source\\n\\n**Option 3: Filter on export** ❌\\n- Doesn't solve root cause\\n- Test issues still pollute production DB\\n- Complicates export logic\\n\\n**Option 4: Manual 'bd sync'** ❌\\n- Same issues as Option 1\\n- Breaks automated workflow\\n\\n**Option 5: Separate session file** ❌\\n- Splits issue tracking across files\\n- Confusing for users\\n- Import/export complexity\\n\\n### RECOMMENDED SOLUTION:\\n\\n**Fix the root cause: Tests should NEVER touch the production database**\\n\\nThe real problem is that Go tests ARE properly isolated (they use temp DBs), but someone must be manually creating test issues in the production DB during development/debugging.\\n\\n**Best fix:**\\n1. Document that production DB is for real work only\\n2. Add a convenience command: `bd test-create` that uses a separate test database\\n3. Clean up the existing test pollution: bd-52 through bd-58\\n4. Consider adding a git pre-commit hook to warn about suspicious issues\\n\\nTh","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-26T19:41:11.100062-07:00","updated_at":"2025-10-26T19:41:11.100062-07:00","closed_at":"2025-10-25T13:16:42.865768-07:00","dependencies":[{"issue_id":"bd-163","depends_on_id":"bd-159","type":"parent-child","created_at":"2025-10-26T18:06:07.572636-07:00","created_by":"daemon"}]} +{"id":"bd-164","title":"Add \"bd daemons\" command for multi-daemon management","description":"Add a new \"bd daemons\" command with subcommands to manage daemon processes across all beads repositories/worktrees. Should show all running daemons with metadata (version, workspace, uptime, last sync), allow stopping/restarting individual daemons, auto-clean stale processes, view logs, and show exclusive lock status.","design":"Subcommands:\n- list: Show all running daemons with metadata (workspace, PID, version, socket path, uptime, last activity, exclusive lock status)\n- stop \u003cpath|pid\u003e: Gracefully stop a specific daemon\n- restart \u003cpath|pid\u003e: Stop and restart daemon\n- killall: Emergency stop all daemons\n- health: Verify each daemon responds to ping\n- logs \u003cpath\u003e: View daemon logs\n\nFeatures:\n- Auto-clean stale sockets/dead processes\n- Discovery: Scan for .beads/bd.sock files + running processes\n- Communication: Use existing socket protocol, add GET /status endpoint for metadata","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-10-26T19:41:11.100511-07:00","updated_at":"2025-10-26T19:41:11.100511-07:00","closed_at":"2025-10-26T19:26:29.045738-07:00","dependencies":[{"issue_id":"bd-164","depends_on_id":"bd-162","type":"blocks","created_at":"2025-10-26T18:06:17.327717-07:00","created_by":"daemon"},{"issue_id":"bd-164","depends_on_id":"bd-160","type":"blocks","created_at":"2025-10-26T18:06:17.351768-07:00","created_by":"daemon"}]} +{"id":"bd-165","title":"Enforce canonical database name (beads.db)","description":"Always use beads.db as the canonical database name. Never auto-detect from multiple .db files.\n\nImplementation:\n- bd init always creates/uses beads.db\n- bd init detects and migrates old databases (vc.db → beads.db, bd.db → beads.db)\n- Daemon refuses to start if multiple .db files exist in .beads/ (exit with ambiguity error)\n- Update database discovery logic to prefer beads.db, error on ambiguity\n\nBenefits:\n- Prevents accidental use of stale databases\n- Clear single source of truth\n- Migration path for existing users","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-27T17:37:34.389764-07:00","updated_at":"2025-10-27T17:37:34.416718-07:00","closed_at":"2025-10-26T19:04:07.843634-07:00","dependencies":[{"issue_id":"bd-165","depends_on_id":"bd-159","type":"parent-child","created_at":"2025-10-26T18:06:18.339465-07:00","created_by":"daemon"}]} +{"id":"bd-166","title":"Stricter daemon lock file validation","description":"Enhance daemon.lock to include database path and version, validate on client connection.\n\nCurrent: daemon.lock has PID\nProposed: JSON format with database path and version\n\nLock file format:\n{\n \"pid\": 12345,\n \"database\": \"/full/path/to/.beads/beads.db\",\n \"version\": \"0.17.5\",\n \"started_at\": \"2025-10-26T18:00:00Z\"\n}\n\nImplementation:\n- Daemon writes enhanced lock on startup\n- Client reads lock and validates:\n - Database path matches expected\n - Version compatible\n - Fail hard (not just warn) on mismatch\n- Update existing lock validation code (already partially implemented)\n\nBenefits:\n- Catch daemon/database mismatches early\n- Better error messages\n- More robust multi-workspace scenarios","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-27T17:37:34.391114-07:00","updated_at":"2025-10-27T17:37:34.391114-07:00","closed_at":"2025-10-26T18:36:09.975648-07:00"} +{"id":"bd-167","title":"Enforce canonical database name (beads.db)","description":"Always use beads.db as the canonical database name. Never auto-detect from multiple .db files.\n\nImplementation:\n- bd init always creates/uses beads.db\n- bd init detects and migrates old databases (vc.db → beads.db, bd.db → beads.db)\n- Daemon refuses to start if multiple .db files exist in .beads/ (exit with ambiguity error)\n- Update database discovery logic to prefer beads.db, error on ambiguity\n\nBenefits:\n- Prevents accidental use of stale databases\n- Clear single source of truth\n- Migration path for existing users","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-27T17:37:34.391778-07:00","updated_at":"2025-10-27T17:37:34.391778-07:00","closed_at":"2025-10-26T18:16:56.23769-07:00"} +{"id":"bd-168","title":"Add .beads/config.json for database path configuration","description":"Create config file to eliminate ambiguity about which database is active.\n\nConfig file format (.beads/config.json):\n{\n \"database\": \"beads.db\",\n \"version\": \"0.17.5\",\n \"jsonl_export\": \"beads.jsonl\" // Allow user to rename\n}\n\nImplementation:\n- bd init creates config.json\n- Daemon and clients read config first (single source of truth)\n- Fall back to beads.db if config missing (backward compat)\n- bd init --jsonl-name allows customizing export filename\n- Gitignore: do NOT ignore config.json (part of repo state)\n\nBenefits:\n- Explicit configuration over convention\n- Allows JSONL renaming for git history hygiene\n- Single source of truth for file paths","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-27T17:37:34.392142-07:00","updated_at":"2025-10-27T17:37:34.392142-07:00","closed_at":"2025-10-26T18:44:16.133085-07:00"} +{"id":"bd-169","title":"Add migration tooling for database upgrades","description":"Create bd migrate command and auto-migration logic for version upgrades.\n\nImplementation:\n- bd migrate command (or bd init --migrate)\n- Auto-run on first command after daemon version upgrade\n- Detection logic:\n - Find all .db files in .beads/\n - Check schema version in each\n - Prompt to migrate/rename/delete\n- Migration operations:\n - Rename old database to beads.db\n - Update schema version metadata\n - Remove stale databases (with confirmation)\n- Could be part of daemon auto-start logic\n\nUser experience:\n$ bd ready\nDatabase schema mismatch detected.\n Found: vc.db (schema v0.16.0)\n Expected: beads.db (schema v0.17.5)\n \nRun 'bd migrate' to migrate automatically.\n\nBenefits:\n- Smooth upgrade path\n- Prevents confusion on version changes\n- Clean up stale databases\n\nDepends on:\n- Canonical naming (bd-160)\n- Schema versioning (bd-177)","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-27T17:37:34.392486-07:00","updated_at":"2025-10-27T17:38:38.074606-07:00","closed_at":"2025-10-26T19:04:02.023089-07:00"} {"id":"bd-17","title":"Update EXTENDING.md with UnderlyingDB() usage and best practices","description":"EXTENDING.md currently shows how to use direct sql.Open() to access the database, but doesn't mention the new UnderlyingDB() method that's the recommended way for extensions.\n\n**Update needed:**\n1. Add section showing UnderlyingDB() usage:\n ```go\n store, err := beads.NewSQLiteStorage(dbPath)\n db := store.UnderlyingDB()\n // Create extension tables using db\n ```\n\n2. Document when to use UnderlyingDB() vs direct sql.Open():\n - Use UnderlyingDB() when you want to share the storage connection\n - Use sql.Open() when you need independent connection management\n\n3. Add safety warnings (cross-reference from UnderlyingDB() docs):\n - Don't close the DB\n - Don't modify pool settings\n - Keep transactions short\n\n4. Update the VC example to show UnderlyingDB() pattern\n\n5. Explain beads.Storage.UnderlyingDB() in the API section","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-22T17:07:56.820056-07:00","updated_at":"2025-10-25T23:15:33.478579-07:00","closed_at":"2025-10-22T19:41:19.895847-07:00","dependencies":[{"issue_id":"bd-17","depends_on_id":"bd-10","type":"discovered-from","created_at":"2025-10-24T13:17:40.32522-07:00","created_by":"renumber"}]} -{"id":"bd-170","title":"Clean up beads-* duplicate issues and review corrupt backup for missing issues","description":"## Current State\n- Database has 3 duplicate beads-* issues (beads-2, beads-3, beads-4) that should be deleted\n- Have corrupt backup: `.beads/beads.db.corrupt-backup` (4.4MB) from bd-166 corruption incident\n- Current clean DB has 172 issues (155 closed, 14 open, 3 in_progress)\n\n## Tasks\n1. **Delete beads-* duplicates** - these are corrupted duplicates from bd-166\n ```bash\n sqlite3 .beads/beads.db \"DELETE FROM issues WHERE id LIKE 'beads-%';\"\n ```\n\n2. **Review corrupt backup for missing issues**\n - Open corrupt backup: `sqlite3 .beads/beads.db.corrupt-backup`\n - Compare issue counts: backup had ~338 issues (165 bd- + 173 beads- duplicates)\n - Check if any ~8 issues exist in backup that are NOT in current DB\n - Cherry-pick any legitimate issues that were lost during cleanup\n\n3. **Verification**\n - Compare issue IDs between corrupt backup and current DB\n - Identify any missing issues worth recovering\n - Document findings\n\n## Why P0\nThis blocks clean database state and may contain lost work from the corruption incident.","status":"closed","priority":0,"issue_type":"task","created_at":"2025-10-26T22:30:00.126524-07:00","updated_at":"2025-10-26T22:30:35.01995-07:00","closed_at":"2025-10-26T22:30:35.01995-07:00"} -{"id":"bd-171","title":"Address gosec security warnings (102 issues)","description":"Security linter warnings: file permissions (0755 should be 0750), G304 file inclusion via variable, G204 subprocess launches. Many are false positives but should be reviewed.","design":"Review each gosec warning. Add exclusions for legitimate cases to .golangci.yml. Fix real security issues (overly permissive file modes).","status":"open","priority":2,"issue_type":"task","created_at":"2025-10-26T23:54:06.320626-07:00","updated_at":"2025-10-26T23:54:06.320626-07:00"} -{"id":"bd-172","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":"open","priority":2,"issue_type":"task","created_at":"2025-10-26T23:54:06.321545-07:00","updated_at":"2025-10-26T23:54:06.321545-07:00"} -{"id":"bd-173","title":"Address gosec security warnings (102 issues)","description":"Security linter warnings: file permissions (0755 should be 0750), G304 file inclusion via variable, G204 subprocess launches. Many are false positives but should be reviewed.","design":"Review each gosec warning. Add exclusions for legitimate cases to .golangci.yml. Fix real security issues (overly permissive file modes).","status":"open","priority":2,"issue_type":"task","created_at":"2025-10-26T23:55:58.5422-07:00","updated_at":"2025-10-26T23:55:58.5422-07:00"} -{"id":"bd-174","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":"open","priority":2,"issue_type":"task","created_at":"2025-10-26T23:55:58.542616-07:00","updated_at":"2025-10-26T23:55:58.542616-07:00"} -{"id":"bd-175","title":"Add test coverage for internal/storage/memory backend","description":"","design":"Create internal/storage/memory/memory_test.go with test coverage similar to internal/storage/sqlite tests.\n\nTest areas:\n1. Basic CRUD: CreateIssue, GetIssue, UpdateIssue, DeleteIssue\n2. Bulk operations: CreateIssues, ListIssues with filters\n3. Dependencies: AddDependency, GetDependencies, RemoveDependency\n4. Labels: AddLabel, RemoveLabel, ListLabels\n5. Comments: AddComment, GetComments\n6. ID generation: Prefix handling, counter management\n7. LoadFromIssues: Proper initialization from JSONL data\n8. Thread safety: Concurrent operations with go test -race","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-27T10:45:33.145874-07:00","updated_at":"2025-10-27T11:26:02.515421-07:00","closed_at":"2025-10-27T11:26:02.515421-07:00"} -{"id":"bd-176","title":"Document distinction between corruption prevention and collision resolution","description":"Clarify that the hash/fingerprint/collision architecture solves logical consistency (wrong prefixes, ID collisions) but NOT physical SQLite corruption. --no-db mode is still needed for multi-process/container scenarios.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-27T10:45:46.872233-07:00","updated_at":"2025-10-27T11:27:15.6189-07:00","closed_at":"2025-10-27T11:27:15.6189-07:00"} -{"id":"bd-177","title":"Add prefix validation in SQLite mode to fail fast on mismatches","description":"The new hash/collision architecture prevents logical consistency issues, but doesn't prevent wrong-prefix bugs. Add validation to reject writes with mismatched prefixes.","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-10-27T10:45:46.87772-07:00","updated_at":"2025-10-27T11:28:52.800581-07:00","closed_at":"2025-10-27T11:28:52.800581-07:00"} -{"id":"bd-178","title":"Address gosec security warnings (102 issues)","description":"Security linter warnings: file permissions (0755 should be 0750), G304 file inclusion via variable, G204 subprocess launches. Many are false positives but should be reviewed.","design":"Review each gosec warning. Add exclusions for legitimate cases to .golangci.yml. Fix real security issues (overly permissive file modes).","status":"open","priority":2,"issue_type":"task","created_at":"2025-10-27T12:51:52.033528-07:00","updated_at":"2025-10-27T12:51:52.033528-07:00"} -{"id":"bd-179","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":"open","priority":2,"issue_type":"task","created_at":"2025-10-27T12:51:52.034442-07:00","updated_at":"2025-10-27T12:51:52.034442-07:00"} +{"id":"bd-170","title":"Update AGENTS.md and README.md with \"bd daemons\" documentation","description":"Document the new \"bd daemons\" command and all subcommands in AGENTS.md and README.md. Include examples and troubleshooting guidance.","status":"open","priority":2,"issue_type":"task","created_at":"2025-10-27T17:37:34.392799-07:00","updated_at":"2025-10-27T17:37:34.392799-07:00"} +{"id":"bd-171","title":"Implement \"bd daemons logs\" subcommand","description":"Add command to view daemon logs for a specific workspace. Requires daemon logging to file (may need separate issue for log infrastructure).","status":"open","priority":2,"issue_type":"task","created_at":"2025-10-27T17:37:34.393072-07:00","updated_at":"2025-10-27T17:37:34.393072-07:00"} +{"id":"bd-172","title":"Add \"bd daemons\" command for multi-daemon management","description":"Add a new \"bd daemons\" command with subcommands to manage daemon processes across all beads repositories/worktrees. Should show all running daemons with metadata (version, workspace, uptime, last sync), allow stopping/restarting individual daemons, auto-clean stale processes, view logs, and show exclusive lock status.","design":"Subcommands:\n- list: Show all running daemons with metadata (workspace, PID, version, socket path, uptime, last activity, exclusive lock status)\n- stop \u003cpath|pid\u003e: Gracefully stop a specific daemon\n- restart \u003cpath|pid\u003e: Stop and restart daemon\n- killall: Emergency stop all daemons\n- health: Verify each daemon responds to ping\n- logs \u003cpath\u003e: View daemon logs\n\nFeatures:\n- Auto-clean stale sockets/dead processes\n- Discovery: Scan for .beads/bd.sock files + running processes\n- Communication: Use existing socket protocol, add GET /status endpoint for metadata","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-10-27T17:37:34.393355-07:00","updated_at":"2025-10-27T17:37:34.393355-07:00","closed_at":"2025-10-26T19:26:29.045738-07:00"} +{"id":"bd-173","title":"Update AGENTS.md and README.md with \"bd daemons\" documentation","description":"Document the new \"bd daemons\" command and all subcommands in AGENTS.md and README.md. Include examples and troubleshooting guidance.","status":"open","priority":2,"issue_type":"task","created_at":"2025-10-27T17:38:38.054891-07:00","updated_at":"2025-10-27T17:38:38.054891-07:00"} +{"id":"bd-174","title":"Implement \"bd daemons logs\" subcommand","description":"Add command to view daemon logs for a specific workspace. Requires daemon logging to file (may need separate issue for log infrastructure).","status":"open","priority":2,"issue_type":"task","created_at":"2025-10-27T17:38:38.05581-07:00","updated_at":"2025-10-27T17:38:38.05581-07:00"} +{"id":"bd-175","title":"Enforce canonical database name (beads.db)","description":"Always use beads.db as the canonical database name. Never auto-detect from multiple .db files.\n\nImplementation:\n- bd init always creates/uses beads.db\n- bd init detects and migrates old databases (vc.db → beads.db, bd.db → beads.db)\n- Daemon refuses to start if multiple .db files exist in .beads/ (exit with ambiguity error)\n- Update database discovery logic to prefer beads.db, error on ambiguity\n\nBenefits:\n- Prevents accidental use of stale databases\n- Clear single source of truth\n- Migration path for existing users","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-27T17:38:38.05621-07:00","updated_at":"2025-10-27T17:38:38.05621-07:00","closed_at":"2025-10-26T18:16:56.23769-07:00"} +{"id":"bd-176","title":"Add .beads/config.json for database path configuration","description":"Create config file to eliminate ambiguity about which database is active.\n\nConfig file format (.beads/config.json):\n{\n \"database\": \"beads.db\",\n \"version\": \"0.17.5\",\n \"jsonl_export\": \"beads.jsonl\" // Allow user to rename\n}\n\nImplementation:\n- bd init creates config.json\n- Daemon and clients read config first (single source of truth)\n- Fall back to beads.db if config missing (backward compat)\n- bd init --jsonl-name allows customizing export filename\n- Gitignore: do NOT ignore config.json (part of repo state)\n\nBenefits:\n- Explicit configuration over convention\n- Allows JSONL renaming for git history hygiene\n- Single source of truth for file paths","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-27T17:38:38.056524-07:00","updated_at":"2025-10-27T17:38:38.056524-07:00","closed_at":"2025-10-26T18:44:16.133085-07:00"} +{"id":"bd-177","title":"Stricter daemon lock file validation","description":"Enhance daemon.lock to include database path and version, validate on client connection.\n\nCurrent: daemon.lock has PID\nProposed: JSON format with database path and version\n\nLock file format:\n{\n \"pid\": 12345,\n \"database\": \"/full/path/to/.beads/beads.db\",\n \"version\": \"0.17.5\",\n \"started_at\": \"2025-10-26T18:00:00Z\"\n}\n\nImplementation:\n- Daemon writes enhanced lock on startup\n- Client reads lock and validates:\n - Database path matches expected\n - Version compatible\n - Fail hard (not just warn) on mismatch\n- Update existing lock validation code (already partially implemented)\n\nBenefits:\n- Catch daemon/database mismatches early\n- Better error messages\n- More robust multi-workspace scenarios","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-27T17:38:38.056822-07:00","updated_at":"2025-10-27T17:38:38.056822-07:00","closed_at":"2025-10-26T18:36:09.975648-07:00"} +{"id":"bd-178","title":"Add migration tooling for database upgrades","description":"Create bd migrate command and auto-migration logic for version upgrades.\n\nImplementation:\n- bd migrate command (or bd init --migrate)\n- Auto-run on first command after daemon version upgrade\n- Detection logic:\n - Find all .db files in .beads/\n - Check schema version in each\n - Prompt to migrate/rename/delete\n- Migration operations:\n - Rename old database to beads.db\n - Update schema version metadata\n - Remove stale databases (with confirmation)\n- Could be part of daemon auto-start logic\n\nUser experience:\n$ bd ready\nDatabase schema mismatch detected.\n Found: vc.db (schema v0.16.0)\n Expected: beads.db (schema v0.17.5)\n \nRun 'bd migrate' to migrate automatically.\n\nBenefits:\n- Smooth upgrade path\n- Prevents confusion on version changes\n- Clean up stale databases\n\nDepends on:\n- Canonical naming (bd-160)\n- Schema versioning (bd-161)","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-27T17:38:38.057188-07:00","updated_at":"2025-10-27T17:38:38.086406-07:00","closed_at":"2025-10-26T19:04:02.023089-07:00"} +{"id":"bd-179","title":"Improve database naming and version management robustness","description":"Make beads architecture more robust to prevent issues like accidental vc.db usage after version upgrades.\n\nKey improvements:\n\n1. **Canonical database name enforcement**\n - Always use beads.db, never auto-detect from multiple .db files\n - bd init migrates/renames any old databases (vc.db → beads.db, bd.db → beads.db)\n - Daemon refuses to start if multiple .db files exist (ambiguity error)\n\n2. **Database schema versioning**\n - Store beads version in SQLite (PRAGMA user_version or metadata table)\n - Daemon checks on startup: validate schema version matches\n - Auto-migrate or fail with clear instructions on version mismatch\n\n3. **Config file with database path**\n - .beads/config.json specifies {\"database\": \"beads.db\", \"version\": \"0.17.5\"}\n - Daemon and clients read config first (single source of truth)\n - No ambiguity about which file is active\n\n4. **Stricter daemon lock validation**\n - daemon.lock includes database path and beads version (JSON)\n - Client validates: lock says beads.db but I expect bd.db → hard error\n - Already partially implemented, make it stricter\n\n5. **Migration tooling**\n - bd init --migrate or auto-run on first command after upgrade\n - Detects old databases, prompts to migrate/clean up\n - Could be part of daemon auto-start logic\n\n**IMPORTANT**: Allow issues.jsonl to be renamed (users cycle through new names to avoid polluted git history). Only enforce database naming, not JSONL naming.","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-10-27T17:38:38.057563-07:00","updated_at":"2025-10-27T17:38:38.057563-07:00","closed_at":"2025-10-26T19:04:07.843634-07:00"} {"id":"bd-18","title":"Consider adding UnderlyingConn(ctx) for safer scoped DB access","description":"Currently UnderlyingDB() returns *sql.DB which is correct for most uses, but for extension migrations/DDL, a scoped connection might be safer.\n\n**Proposal:** Add optional UnderlyingConn(ctx) (*sql.Conn, error) method that:\n- Returns a scoped connection via s.db.Conn(ctx)\n- Encourages lifetime-bounded usage\n- Reduces temptation to tune global pool settings\n- Better for one-time DDL operations like CREATE TABLE\n\n**Implementation:**\n```go\n// UnderlyingConn returns a single connection from the pool for scoped use\n// Useful for migrations and DDL. Close the connection when done.\nfunc (s *SQLiteStorage) UnderlyingConn(ctx context.Context) (*sql.Conn, error) {\n return s.db.Conn(ctx)\n}\n```\n\n**Benefits:**\n- Safer for migrations (explicit scope)\n- Complements UnderlyingDB() for different use cases\n- Low implementation cost\n\n**Trade-off:** Adds another method to maintain, but Oracle considers this balanced compromise between safety and flexibility.\n\n**Decision:** This is optional - evaluate based on VC's actual usage patterns.","status":"closed","priority":3,"issue_type":"feature","created_at":"2025-10-22T17:07:56.832638-07:00","updated_at":"2025-10-25T23:15:33.479496-07:00","closed_at":"2025-10-22T22:02:18.479512-07:00","dependencies":[{"issue_id":"bd-18","depends_on_id":"bd-10","type":"related","created_at":"2025-10-24T13:17:40.325463-07:00","created_by":"renumber"}]} -{"id":"bd-180","title":"Address gosec security warnings (102 issues)","description":"Security linter warnings: file permissions (0755 should be 0750), G304 file inclusion via variable, G204 subprocess launches. Many are false positives but should be reviewed.","design":"Review each gosec warning. Add exclusions for legitimate cases to .golangci.yml. Fix real security issues (overly permissive file modes).","status":"open","priority":2,"issue_type":"task","created_at":"2025-10-27T13:08:48.798508-07:00","updated_at":"2025-10-27T13:08:48.798508-07:00"} -{"id":"bd-181","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":"open","priority":2,"issue_type":"task","created_at":"2025-10-27T13:08:48.799037-07:00","updated_at":"2025-10-27T13:08:48.799037-07:00"} -{"id":"bd-182","title":"Remove duplicate code from cmd/bd/import_shared.go","description":"Clean up cmd/bd/import_shared.go to remove code duplication with internal/importer.\n\nAfter bd-132, we have duplicate implementations of:\n- Field comparators (issueDataChanged, fieldComparator)\n- ID renaming logic (renameImportedIssuePrefixes, replaceIDReferences, replaceBoundaryAware)\n\nThese should be thin wrappers calling internal/importer to avoid drift.","design":"1. Keep only ImportOptions and ImportResult type definitions in import_shared.go\n2. Remove duplicate comparator/rename functions\n3. Ensure all cmd/bd code calls internal/importer functions\n4. Verify all tests still pass","status":"open","priority":3,"issue_type":"chore","created_at":"2025-10-27T16:28:53.186639-07:00","updated_at":"2025-10-27T16:28:53.186639-07:00"} -{"id":"bd-183","title":"Add unit tests for internal/importer package","description":"Add comprehensive unit tests for the new internal/importer package created in bd-132.\n\nCurrently the package has no tests, relying on cmd/bd integration tests.\n\nTest coverage needed:\n- Prefix mismatch cases (rename on import, validation)\n- Collision cases (resolve vs error)\n- Upsert logic (unchanged, updated, duplicates)\n- Deps/labels/comments deduplication","status":"open","priority":2,"issue_type":"task","created_at":"2025-10-27T16:29:17.67769-07:00","updated_at":"2025-10-27T16:29:17.67769-07:00"} -{"id":"bd-184","title":"Add integration tests for daemon auto-import","description":"Add integration tests for daemon auto-import behavior after bd-132 implementation.\n\nCurrent RPC tests don't specifically test the auto-import flow.\n\nTest scenarios needed:\n- Mtime gate fast path (no import when unchanged)\n- Hash change triggers import\n- Concurrency single-flight pattern\n- ID remap triggers export to JSONL","status":"open","priority":2,"issue_type":"task","created_at":"2025-10-27T16:29:17.68737-07:00","updated_at":"2025-10-27T16:29:17.68737-07:00"} +{"id":"bd-180","title":"Add \"bd daemons\" command for multi-daemon management","description":"Add a new \"bd daemons\" command with subcommands to manage daemon processes across all beads repositories/worktrees. Should show all running daemons with metadata (version, workspace, uptime, last sync), allow stopping/restarting individual daemons, auto-clean stale processes, view logs, and show exclusive lock status.","design":"Subcommands:\n- list: Show all running daemons with metadata (workspace, PID, version, socket path, uptime, last activity, exclusive lock status)\n- stop \u003cpath|pid\u003e: Gracefully stop a specific daemon\n- restart \u003cpath|pid\u003e: Stop and restart daemon\n- killall: Emergency stop all daemons\n- health: Verify each daemon responds to ping\n- logs \u003cpath\u003e: View daemon logs\n\nFeatures:\n- Auto-clean stale sockets/dead processes\n- Discovery: Scan for .beads/bd.sock files + running processes\n- Communication: Use existing socket protocol, add GET /status endpoint for metadata","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-10-27T17:38:38.057858-07:00","updated_at":"2025-10-27T17:38:38.057858-07:00","closed_at":"2025-10-26T19:26:29.045738-07:00"} {"id":"bd-19","title":"MCP close tool method signature error - takes 1 positional argument but 2 were given","description":"The close approval routing fix in beads-mcp v0.11.0 works correctly and successfully routes update(status=\"closed\") calls to close() tool. However, the close() tool has a Python method signature bug that prevents execution.\n\nImpact: All MCP-based close operations are broken. Workaround: Use bd CLI directly.\n\nError: BdDaemonClient.close() takes 1 positional argument but 2 were given\n\nRoot cause: BdDaemonClient.close() only accepts self, but MCP tool passes issue_id and reason.\n\nAdditional issue: CLI close has FOREIGN KEY constraint error when recording reason parameter.\n\nSee GitHub issue #107 for full details.","status":"closed","priority":0,"issue_type":"bug","created_at":"2025-10-22T17:25:34.67056-07:00","updated_at":"2025-10-25T23:15:33.480292-07:00","closed_at":"2025-10-22T17:36:55.463445-07:00"} {"id":"bd-2","title":"Improve error handling in dependency removal during remapping","description":"In updateDependencyReferences(), RemoveDependency errors are caught and ignored with continue (line 392). Comment says 'if dependency doesn't exist' but this catches ALL errors including real failures. Should check error type with errors.Is(err, ErrDependencyNotFound) and only ignore not-found errors, returning other errors properly.","status":"closed","priority":3,"issue_type":"bug","created_at":"2025-10-21T23:53:44.31362-07:00","updated_at":"2025-10-25T23:15:33.462194-07:00","closed_at":"2025-10-18T09:41:18.209717-07:00"} {"id":"bd-20","title":"Fix pre-existing MCP test failures - show/update return arrays not dicts","description":"9 tests fail in beads-mcp because bd CLI commands return arrays but MCP client expects dicts:\n\nFailing tests:\n- test_create_and_show_issue: show returns array, expects dict\n- test_update_issue: update returns array, expects dict \n- test_add_dependency: show returns array, expects dict\n- test_invalid_issue_id: show returns empty dict instead of error\n- test_dependency_types: show returns array, expects dict\n- test_show_issue_tool: show returns array, expects dict\n- test_update_issue_tool: update returns array, expects dict\n- test_update_partial_fields: update returns array, expects dict\n- test_client_lazy_initialization: BdClient import issue\n\nRoot cause: bd CLI commands like 'bd show' and 'bd update' output JSON arrays, but BdCliClient.show() and BdCliClient.update() expect single dict objects.\n\nExample:\n```bash\nbd show test-1 --json\n[{\"id\":\"test-1\",...}] # Array, not dict\n```\n\nFix needed: Update bd_client.py to handle array responses and extract first element, or change CLI to return single object for single-ID operations.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-10-22T17:43:23.29302-07:00","updated_at":"2025-10-25T23:15:33.481154-07:00","closed_at":"2025-10-22T20:05:49.3826-07:00"}