diff --git a/.beads/beads.jsonl b/.beads/beads.jsonl index 7c204855..1dc2380c 100644 --- a/.beads/beads.jsonl +++ b/.beads/beads.jsonl @@ -1,122 +1,74 @@ -{"id":"bd-0a43","content_hash":"36ff43c769f6b0d227c892b20c3af9b1092b38e06cc0f31c0d7c313528be716e","title":"Split monolithic sqlite.go into focused files","description":"internal/storage/sqlite/sqlite.go is 1050 lines containing initialization, 20+ CRUD methods, query building, and schema management.\n\nSplit into:\n- store.go: Store struct \u0026 initialization (150 lines)\n- bead_queries.go: Bead CRUD (300 lines)\n- work_queries.go: Work queries (200 lines) \n- stats_queries.go: Statistics (150 lines)\n- schema.go: Schema \u0026 migrations (150 lines)\n- helpers.go: Common utilities (100 lines)\n\nImpact: Impossible to understand at a glance; hard to find specific functionality; high cognitive load\n\nEffort: 6-8 hours","status":"open","priority":0,"issue_type":"task","created_at":"2025-11-16T14:51:16.520465-08:00","updated_at":"2025-11-16T14:51:16.520465-08:00","source_repo":"."} -{"id":"bd-0fvq","content_hash":"6fb6e394efe3010fd5d9213669417e5f6376017de4187988d5a6fd0d36c80b40","title":"bd doctor should recommend bd prime migration for existing repos","description":"bd doctor should detect old beads integration patterns and recommend migrating to bd prime approach.\n\n## Current behavior\n- bd doctor checks if Claude hooks are installed globally\n- Doesn't check project-level integration (AGENTS.md, CLAUDE.md)\n- Doesn't recommend migration for repos using old patterns\n\n## Desired behavior\nbd doctor should detect and suggest:\n\n1. **Old slash command pattern detected**\n - Check for /beads:* references in AGENTS.md, CLAUDE.md\n - Suggest: These slash commands are deprecated, use bd prime hooks instead\n \n2. **No agent documentation**\n - Check if AGENTS.md or CLAUDE.md exists\n - Suggest: Run 'bd onboard' or 'bd setup claude' to document workflow\n \n3. **Old MCP-only pattern**\n - Check for instructions to use MCP tools but no bd prime hooks\n - Suggest: Add bd prime hooks for better token efficiency\n\n4. **Migration path**\n - Show: 'Run bd setup claude to add SessionStart/PreCompact hooks'\n - Show: 'Update AGENTS.md to reference bd prime instead of slash commands'\n\n## Example output\n\n⚠ Warning: Old beads integration detected in CLAUDE.md\n Found: /beads:* slash command references (deprecated)\n Recommend: Migrate to bd prime hooks for better token efficiency\n Fix: Run 'bd setup claude' and update CLAUDE.md\n\nπŸ’‘ Tip: bd prime + hooks reduces token usage by 80-99% vs slash commands\n MCP mode: ~50 tokens vs ~10.5k for full MCP scan\n CLI mode: ~1-2k tokens with automatic context recovery\n\n## Benefits\n- Helps existing repos adopt new best practices\n- Clear migration path for users\n- Better token efficiency messaging","status":"open","priority":2,"issue_type":"feature","created_at":"2025-11-12T03:20:25.567748-08:00","updated_at":"2025-11-12T03:20:25.567748-08:00","source_repo":"."} -{"id":"bd-0l5n","content_hash":"00fc853350d8dbf1a0cdfe3b7212d312d8c6afe1c29432dce2ada42d306b01be","title":"SECURITY: No authorization check - any agent can deregister others","description":"In deregister_agent (app.py:2882), there is no authorization check to verify the calling agent has permission to deregister another agent. Any agent or external caller can deregister any other agent in a project, allowing malicious or buggy agents to disrupt legitimate agents. Recommendation: Restrict to self-deregistration, add caller_agent verification, or require admin approval.","status":"open","priority":0,"issue_type":"bug","created_at":"2025-11-24T17:13:46.378191-08:00","updated_at":"2025-11-24T17:13:46.378191-08:00","source_repo":".","labels":["mcp-agent-mail","security"]} -{"id":"bd-13gm","content_hash":"690c7a4421984b863d40b35af9623fc40c5b8d4af7e829cfacb57fcd389941ff","title":"Add explicit cache validation tests for blocked_issues_cache","description":"The blocked_issues_cache optimization works correctly but lacks explicit tests that verify cache invalidation behavior.\n\n## What to test\n\n1. **Cache invalidation on dependency add**\n - Add a blocking dependency\n - Verify blocked issue appears in cache\n \n2. **Cache invalidation on dependency remove**\n - Remove a blocking dependency\n - Verify blocked issue removed from cache\n \n3. **Cache invalidation on status change**\n - Close a blocker issue\n - Verify dependent issue removed from cache\n - Reopen blocker\n - Verify dependent issue added back to cache\n\n4. **Cache consistency across operations**\n - Multiple dependency changes in sequence\n - Verify cache stays consistent with actual blocking state\n\n5. **Parent-child transitive blocking**\n - Create epic with child tasks\n - Add blocking dependency to epic\n - Verify all children appear in cache\n\n## Implementation\n\nAdd tests to internal/storage/sqlite/blocked_cache_test.go (new file) with direct cache queries:\n\n```go\nfunc TestBlockedCacheInvalidation(t *testing.T) {\n // Verify cache updates correctly on dependency changes\n}\n\nfunc TestBlockedCacheConsistency(t *testing.T) {\n // Verify cache matches actual blocking state\n}\n```\n\n## Why this matters\n\n- Current tests verify behavior but not implementation\n- Explicit cache tests catch cache-specific bugs\n- Makes cache correctness visible in test output\n- Easier debugging if cache gets out of sync\n\n## Related\n\n- [deleted:[deleted:[deleted:[deleted:[deleted:[deleted:bd-5qim]]]]]]: GetReadyWork performance optimization (implemented cache)\n- internal/storage/sqlite/blocked_cache.go\n- internal/storage/sqlite/ready_test.go (behavior tests)","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-23T20:06:55.736412-08:00","updated_at":"2025-11-24T00:01:27.55236-08:00","closed_at":"2025-11-23T23:22:04.177645-08:00","source_repo":"."} -{"id":"bd-19er","content_hash":"17f69b5bb6b1d48e99ea46d79ffc6fd025207ae3ca15472caa947835194ca38c","title":"Create backup and restore procedures","description":"Disaster recovery procedures for Agent Mail data.\n\nAcceptance Criteria:\n- Automated daily snapshots (GCP persistent disk)\n- SQLite backup script\n- Git repository backup\n- Restore procedure documentation\n- Test restore from backup\n\nFile: deployment/agent-mail/backup.sh","status":"closed","priority":3,"issue_type":"task","created_at":"2025-11-07T22:43:43.417403-08:00","updated_at":"2025-11-24T00:01:27.553156-08:00","closed_at":"2025-11-23T23:39:00.061047-08:00","source_repo":".","dependencies":[{"issue_id":"bd-19er","depends_on_id":"bd-z3s3","type":"blocks","created_at":"2025-11-07T23:04:28.122501-08:00","created_by":"daemon"}]} -{"id":"bd-1a6j","content_hash":"2eaf57cb617922924aadb6b04366a3ef058d386752c65e8471f2704b512ea30a","title":"Test issue 2","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-07T19:07:12.24632-08:00","updated_at":"2025-11-24T23:43:39.129454-08:00","closed_at":"2025-11-23T23:35:04.068982-08:00","source_repo":"."} -{"id":"bd-1pj6","content_hash":"de1c1195b29d9a70c88b5f2b05ca1c3497469d1802f9c0be415d5a44b0575deb","title":"Proposal: Custom status states via config","description":"Proposal to add 'custom status states' via `bd config`.\nUsers could define an optional issue status enum (e.g., awaiting_review, review_in_progress) in the config.\nThis would enable multi-step pipelines to process issues where each step correlates to a specific status.\n\nExamples:\n- awaiting_verification\n- awaiting_docs\n- awaiting_testing\n","status":"open","priority":3,"issue_type":"feature","created_at":"2025-11-20T18:55:48.670499-05:00","updated_at":"2025-11-20T18:55:48.670499-05:00","source_repo":"."} -{"id":"bd-1qwo","content_hash":"21b58f84acf275fe99617aec1aaabd687a34220e3603c8b2a9cecad7c186163a","title":"Audit and enforce consistent error handling patterns across codebase","description":"**Background:** Error handling patterns are now documented in docs/ERROR_HANDLING.md (bd-9lwr). We have three established patterns:\n- Pattern A: Exit immediately (os.Exit) for fatal errors\n- Pattern B: Warn and continue for optional operations\n- Pattern C: Silent ignore for cleanup/best-effort\n\n**Goal:** Systematically review all error handling in cmd/bd to ensure each instance uses the appropriate pattern according to the guidelines.\n\n**Scope:** \n- Review all files in cmd/bd/*.go\n- Focus on files with high usage: create.go, init.go, sync.go, daemon_sync.go, export.go, import.go\n- Identify outliers where similar operations use different patterns\n- Refactor to use consistent patterns\n\n**Acceptance Criteria:**\n- Similar operations (e.g., all metadata updates) use the same pattern\n- Critical operations always use Pattern A\n- Auxiliary operations use Pattern B or C appropriately\n- No mixed patterns for identical operation types\n\n**References:**\n- docs/ERROR_HANDLING.md - Guidelines and decision tree\n- bd-9lwr - Documentation task\n- bd-bwk2 - Related storage layer error handling work","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-23T21:53:25.687087-08:00","updated_at":"2025-11-24T01:08:18.294375-08:00","closed_at":"2025-11-24T00:28:58.356196-08:00","source_repo":"."} -{"id":"bd-1rh","content_hash":"94302659c93aea0ed8458da6499ddfd97f2ed2a3a33a0af9131eca51d3e8bc72","title":"cmd/bd test suite is absurdly slow - 279 tests taking 8+ minutes","description":"# Problem\n\nThe cmd/bd test suite is painfully slow:\n- **279 tests** in cmd/bd alone\n- Full suite takes **8+ minutes** to run\n- Even with the 16 slowest integration tests now tagged with `integration` build tag, the remaining tests still take forever\n\nThis makes the development loop unusable. We can't wait 8+ minutes every time we want to run tests.\n\n# Root Cause Analysis\n\n## 1. Sheer Volume\n279 tests is too many for a single package. Even at 0.1s per test, that's 28 seconds minimum just for cmd/bd.\n\n## 2. Each Test Creates Full Database + Temp Directories\nEvery test does heavy setup:\n- Creates temp directory (`t.TempDir()` or `os.MkdirTemp`)\n- Initializes SQLite database\n- Sets up git repo in many cases\n- Creates full storage layer\n\nExample from the tests:\n```go\nfunc setupCLITestDB(t *testing.T) string {\n tmpDir := createTempDirWithCleanup(t)\n runBDInProcess(t, tmpDir, \"init\", \"--prefix\", \"test\", \"--quiet\")\n return tmpDir\n}\n```\n\nThis happens 279 times!\n\n## 3. Tests Are Not Properly Categorized\nWe have three types of tests mixed together:\n- **Unit tests** - should be fast, test single functions\n- **Integration tests** - test full workflows, need DB/git\n- **End-to-end tests** - test entire CLI commands\n\nThey're all lumped together in cmd/bd, all running every time.\n\n# What We've Already Fixed\n\nAdded `integration` build tags to 16 obviously-slow test files:\n- import_profile_test.go (performance benchmarking tests)\n- export_mtime_test.go (tests with time.Sleep calls)\n- cli_fast_test.go (full CLI integration tests)\n- delete_test.go, import_uncommitted_test.go, sync_local_only_test.go (git integration)\n- And 10 more in internal/ packages\n\nThese are now excluded from the default `go test ./...` run.\n\n# Proposed Solutions\n\n## Option 1: Shared Test Fixtures (Quick Win)\nCreate a shared test database that multiple tests can use:\n```go\nvar testDB *sqlite.SQLiteStorage\nvar testDBOnce sync.Once\n\nfunc getSharedTestDB(t *testing.T) storage.Storage {\n testDBOnce.Do(func() {\n // Create one DB for all tests\n })\n return testDB\n}\n```\n\n**Pros**: Easy to implement, immediate speedup\n**Cons**: Tests become less isolated, harder to debug failures\n\n## Option 2: Table-Driven Tests (Medium Win)\nCollapse similar tests into table-driven tests:\n```go\nfunc TestCreate(t *testing.T) {\n tests := []struct{\n name string\n args []string\n want string\n }{\n {\"basic issue\", []string{\"create\", \"Test\"}, \"created\"},\n {\"with description\", []string{\"create\", \"Test\", \"-d\", \"desc\"}, \"created\"},\n // ... 50 more cases\n }\n \n db := setupOnce(t) // Setup once, not 50 times\n for _, tt := range tests {\n t.Run(tt.name, func(t *testing.T) {\n // test using shared db\n })\n }\n}\n```\n\n**Pros**: Dramatically reduces setup overhead, tests run in parallel\n**Cons**: Requires refactoring, tests share more state\n\n## Option 3: Split cmd/bd Tests Into Packages (Big Win)\nMove tests into focused packages:\n- `cmd/bd/internal/clitests` - CLI integration tests (mark with integration tag)\n- `cmd/bd/internal/unittests` - Fast unit tests\n- Keep only essential tests in cmd/bd\n\n**Pros**: Clean separation, easy to run just fast tests\n**Cons**: Requires significant refactoring\n\n## Option 4: Parallel Execution (Quick Win)\nAdd `t.Parallel()` to independent tests:\n```go\nfunc TestSomething(t *testing.T) {\n t.Parallel() // Run this test concurrently with others\n // ...\n}\n```\n\n**Pros**: Easy to add, can cut time in half on multi-core machines\n**Cons**: Doesn't reduce actual test work, just parallelizes it\n\n## Option 5: In-Memory Databases (Medium Win)\nUse `:memory:` SQLite databases instead of file-based:\n```go\nstore, err := sqlite.New(ctx, \":memory:\")\n```\n\n**Pros**: Faster than disk I/O, easier cleanup\n**Cons**: Some tests need actual file-based DBs (export/import tests)\n\n# Recommended Approach\n\n**Short-term (this week)**:\n1. Add `t.Parallel()` to all independent tests in cmd/bd\n2. Use `:memory:` databases where possible\n3. Create table-driven tests for similar test cases\n\n**Medium-term (next sprint)**:\n4. Split cmd/bd tests into focused packages\n5. Mark more integration tests appropriately\n\n**Long-term (backlog)**:\n6. Consider shared test fixtures with proper isolation\n\n# Current Status\n\nWe've tagged 16 files with `integration` build tag, but the remaining 279 tests in cmd/bd still take 8+ minutes. This issue tracks fixing the cmd/bd test performance specifically.\n\n# Target\n\nGet `go test ./...` (without `-short` or `-tags=integration`) down to **under 30 seconds**.\n\n\n# THE REAL ROOT CAUSE (Updated Analysis)\n\nAfter examining the actual test code, the problem is clear:\n\n## Every Test Creates Its Own Database From Scratch\n\nLook at `create_test.go`:\n```go\nfunc TestCreate_BasicIssue(t *testing.T) {\n tmpDir := t.TempDir() // ← Creates temp dir\n testDB := filepath.Join(tmpDir, \".beads\", \"beads.db\")\n s := newTestStore(t, testDB) // ← Opens NEW SQLite connection\n // ← Runs migrations\n // ← Sets config\n // ... actual test (3 lines)\n}\n\nfunc TestCreate_WithDescription(t *testing.T) {\n tmpDir := t.TempDir() // ← Creates ANOTHER temp dir\n testDB := filepath.Join(tmpDir, \".beads\", \"beads.db\")\n s := newTestStore(t, testDB) // ← Opens ANOTHER SQLite connection\n // ... actual test (3 lines)\n}\n```\n\n**This happens 279 times!**\n\n## These Tests Don't Need Isolation!\n\nMost tests are just checking:\n- \"Can I create an issue with a title?\"\n- \"Can I create an issue with a description?\"\n- \"Can I add labels?\"\n\nThey don't conflict with each other. They could all share ONE database!\n\n## The Fix: Test Suites with Shared Setup\n\nInstead of:\n```go\nfunc TestCreate_BasicIssue(t *testing.T) {\n s := newTestStore(t, t.TempDir()+\"/db\") // ← Expensive!\n // test\n}\n\nfunc TestCreate_WithDesc(t *testing.T) {\n s := newTestStore(t, t.TempDir()+\"/db\") // ← Expensive!\n // test\n}\n```\n\nDo this:\n```go\nfunc TestCreate(t *testing.T) {\n // ONE setup for all subtests\n s := newTestStore(t, t.TempDir()+\"/db\")\n \n t.Run(\"basic_issue\", func(t *testing.T) {\n t.Parallel() // Can run concurrently - tests don't conflict\n // test using shared `s`\n })\n \n t.Run(\"with_description\", func(t *testing.T) {\n t.Parallel()\n // test using shared `s`\n })\n \n // ... 50 more subtests, all using same DB\n}\n```\n\n**Result**: 50 tests β†’ 1 database setup instead of 50!\n\n## Why This Works\n\nSQLite is fine with concurrent reads and isolated transactions. These tests:\n- βœ… Create different issues (no ID conflicts)\n- βœ… Just read back what they created\n- βœ… Don't depend on database state from other tests\n\nThey SHOULD share a database!\n\n## Real Numbers\n\nCurrent:\n- 279 tests Γ— (create dir + init SQLite + migrations) = **8 minutes**\n\nAfter fix:\n- 10 test suites Γ— (create dir + init SQLite + migrations) = **30 seconds**\n- 279 subtests running in parallel using those 10 DBs = **5 seconds**\n\n**Total: ~35 seconds instead of 8 minutes!**\n\n## Implementation Plan\n\n1. **Group related tests** into suites (Create, List, Update, Delete, etc.)\n2. **One setup per suite** instead of per test\n3. **Use t.Run() for subtests** with t.Parallel()\n4. **Keep tests that actually need isolation** separate (export/import tests, git operations)\n\nThis is way better than shuffling tests into folders!","notes":"## Progress Update (2025-11-21)\n\nβœ… **Completed**:\n- Audited all 280 tests, created TEST_SUITE_AUDIT.md ([deleted:[deleted:[deleted:[deleted:[deleted:[deleted:[deleted:bd-c49]]]]]]])\n- Refactored create_test.go to shared DB pattern ([deleted:[deleted:[deleted:[deleted:[deleted:[deleted:[deleted:bd-y6d]]]]]]])\n- Proven the pattern works: 11 tests now run in 0.04s with 1 DB instead of 11\n\n❌ **Current Reality**:\n- Overall test suite: Still 8+ minutes (no meaningful change)\n- Only 1 of 76 test files refactored\n- Saved ~10 DB initializations out of 280\n\n## Acceptance Criteria (REALISTIC)\n\nThis task is NOT complete until:\n- [ ] All P1 files refactored (create βœ…, dep, stale, comments, list, ready)\n- [ ] Test suite runs in \u003c 2 minutes\n- [ ] Measured and verified actual speedup\n\n## Next Steps\n\n1. Refactor remaining 5 P1 files: dep_test.go, stale_test.go, comments_test.go, list_test.go, ready_test.go\n2. Measure actual time improvement after each file\n3. Continue with P2 files if needed to hit \u003c2min target","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-21T11:37:47.886207-05:00","updated_at":"2025-11-24T00:01:27.554109-08:00","closed_at":"2025-11-23T23:38:54.185364-08:00","source_repo":"."} -{"id":"bd-1w6i","content_hash":"399a7154894933424ced51b60af7486c17befc2b4b7ea25583dd8fcb8b71f891","title":"Document blocked_issues_cache architecture and behavior","description":"Add comprehensive documentation about the blocked_issues_cache optimization to help future maintainers understand the design.\n\n## What to document\n\n1. **Architecture overview**\n - Why cache exists (performance: 752ms -\u003e 29ms)\n - When cache is used (GetReadyWork queries)\n - How cache is maintained (invalidation triggers)\n\n2. **Cache invalidation rules**\n - Invalidated on: dependency add/remove (blocks/parent-child only)\n - Invalidated on: any status change\n - Invalidated on: issue close\n - NOT invalidated on: related/discovered-from dependencies\n\n3. **Transaction safety**\n - All invalidations happen within transactions\n - Cache can use tx or direct db connection\n - Rebuild is atomic (DELETE + INSERT in same tx)\n\n4. **Performance characteristics**\n - Full rebuild on every invalidation\n - Rebuild is fast (\u003c50ms on 10K database)\n - Write complexity traded for read speed\n - Dependency changes are rare vs reads\n\n5. **Edge cases**\n - Parent-child transitive blocking\n - Closed issues don't block\n - Foreign key CASCADE handles deletions\n\n## Where to document\n\nAdd to these locations:\n\n1. **blocked_cache.go** - Add detailed package comment:\n```go\n// Package blocked_cache implements the blocked_issues_cache optimization.\n// \n// Performance: GetReadyWork originally used recursive CTE (752ms on 10K db).\n// With cache: Simple NOT EXISTS query (29ms on 10K db).\n//\n// Cache Maintenance:\n// - Rebuild triggered on dependency changes (blocks/parent-child only)\n// - Rebuild triggered on status changes \n// - Full rebuild (DELETE + INSERT) is fast enough for all cases\n// ...\n```\n\n2. **ARCHITECTURE.md** or **PERFORMANCE.md** (new file) - High-level overview\n\n3. **ready.go** - Update comment at line 84-85 with more detail\n\n## Related\n\n- [deleted:[deleted:[deleted:[deleted:[deleted:[deleted:bd-5qim]]]]]]: GetReadyWork optimization (implemented)\n- bd-13gm: Cache validation tests\n- [deleted:[deleted:[deleted:[deleted:bd-obdc]]]]: Cache rebuild command","status":"closed","priority":3,"issue_type":"task","created_at":"2025-11-23T20:07:23.467296-08:00","updated_at":"2025-11-24T01:17:35.451953-08:00","closed_at":"2025-11-24T01:14:27.162122-08:00","source_repo":"."} -{"id":"bd-28db","content_hash":"d5e519475ac57322f0ebe7a1f2499af199621f7cab7f7efcf5c4397845702766","title":"Add 'bd status' command for issue database overview","description":"Implement a bd status command that provides a quick snapshot of the issue database state, similar to how git status shows working tree state.\n\nExpected output: Show summary including counts by state (open, in-progress, blocked, closed), recent activity (last 7 days), and quick overview without needing multiple queries.\n\nExample output showing issue counts, recent activity stats, and pointer to bd list for details.\n\nProposed options: --all (show all issues), --assigned (show issues assigned to current user), --json (JSON format output)\n\nUse cases: Quick project health check, onboarding for new contributors, integration with shell prompts or CI/CD, daily standup reference","status":"open","priority":2,"issue_type":"feature","created_at":"2025-11-02T17:25:59.203549-08:00","updated_at":"2025-11-02T17:25:59.203549-08:00","source_repo":"."} -{"id":"bd-2q6d","content_hash":"d593b18be7696f1b6447d41a2b6988ee2e993169a183bec16e4df86607f288d1","title":"Beads commands operate on stale database without warning","description":"All beads read operations should validate database is in sync with JSONL before proceeding.\n\n**Current Behavior:**\n- Commands can query/read from stale database\n- Only mutation operations (like 'bd sync') check if JSONL is newer\n- User gets incorrect results without realizing database is out of sync\n\n**Expected Behavior:**\n- All beads commands should have pre-flight check for database freshness\n- If JSONL is newer than database, refuse to operate with error: \"Database out of sync. Run 'bd import' first.\"\n- Same safety check that exists for 'bd sync' should apply to ALL operations\n\n**Impact:**\n- Users make decisions based on incomplete/outdated data\n- Silent failures lead to confusion (e.g., thinking issues don't exist when they do)\n- Similar to running git commands on stale repo without being warned to pull\n\n**Example:**\n- Searched for bd-g9eu issue file: not found\n- Issue exists in .beads/issues.jsonl (in git)\n- Database was stale, but no warning was given\n- Led to incorrect conclusion that issue was already closed/deleted","notes":"## Implementation Complete\n\n**Phase 1: Created staleness check (cmd/bd/staleness.go)**\n- ensureDatabaseFresh() function checks JSONL mtime vs last_import_time\n- Returns error with helpful message when database is stale\n- Auto-skips in daemon mode (daemon has auto-import)\n\n**Phase 2: Added to all read commands**\n- list, show, ready, status, stale, info, duplicates, validate\n- Check runs before database queries in direct mode\n- Daemon mode already protected via checkAndAutoImportIfStale()\n\n**Phase 3: Code Review Findings**\nSee follow-up issues:\n- bd-XXXX: Add warning when staleness check errors\n- bd-YYYY: Improve CheckStaleness error handling\n- bd-ZZZZ: Refactor redundant daemon checks (low priority)\n\n**Testing:**\n- Build successful: go build ./cmd/bd\n- Binary works: ./bd --version\n- Ready for manual testing\n\n**Next Steps:**\n1. Test with stale database scenario\n2. Implement review improvements\n3. Close issue when tests pass","status":"open","priority":1,"issue_type":"bug","created_at":"2025-11-20T19:33:40.019297-05:00","updated_at":"2025-11-21T23:13:03.801202-08:00","source_repo":".","comments":[{"id":47,"issue_id":"bd-2q6d","author":"stevey","text":"# Updated Analysis\n\n## Root Cause\n\nThe bug has multiple contributing factors:\n\n1. **Daemon mode bypasses auto-import**: When running in daemon mode (most common), the `PersistentPreRun` returns early (main.go:332) before reaching auto-import logic (main.go:451-467)\n\n2. **No staleness validation on reads**: Read operations (list, show, search) don't verify database is fresh before returning results\n\n3. **Auto-import can be disabled**: Users with `--no-auto-import` can unknowingly operate on stale data\n\n## Current Auto-Import Behavior\n\nAuto-import DOES exist and uses SHA256 hash comparison:\n- Location: `autoflush.go:autoImportIfNewer()`\n- Stores last import hash in DB metadata: `last_import_hash`\n- Runs in `PersistentPreRun` for direct mode only\n- Skipped for: import, delete, sync --dry-run commands\n\n## Proposed Solution\n\nAdd lightweight hash-based staleness check to all read operations:\n\n### Implementation Points:\n1. **Before ANY database read** (list, show, search, ready, etc.):\n ```go\n func ensureDatabaseFresh(ctx context.Context) error {\n // Get stored import hash from DB\n storedHash, _ := store.GetMetadata(ctx, \"last_import_hash\")\n \n // Compute current JSONL hash\n currentHash := computeJSONLHash(findJSONLPath())\n \n if currentHash != storedHash {\n if autoImportEnabled {\n // Try auto-import\n autoImportIfNewer()\n // Re-check - fail if still stale\n } else {\n return fmt.Errorf(\"database out of sync with JSONL. Run 'bd import' or enable auto-import\")\n }\n }\n return nil\n }\n ```\n\n2. **Add to daemon RPC handlers** - daemon mode currently has NO staleness checking\n\n3. **Make check fast** - hash comparison is O(1) if JSONL hash is cached\n\n### Benefits:\n- Works in both daemon and direct mode\n- Minimal performance overhead (just hash comparison)\n- Catches all staleness cases\n- Clear error messages guide users to fix\n- Defense in depth - doesn't rely solely on auto-import\n\n### Alternatives Considered:\n- **mtime comparison**: Unreliable after git operations\n- **Block all reads when stale**: Too aggressive, breaks workflows \n- **Only check on mutations**: Current bug - reads return stale data\n- **Only rely on auto-import**: Fails in daemon mode and when disabled\n\n## Files to Modify:\n- `cmd/bd/list.go` - add check before SearchIssues\n- `cmd/bd/show.go` - add check before GetIssue\n- `cmd/bd/ready.go` - add check before GetReadyWork\n- `internal/rpc/server.go` - add check in daemon RPC handlers\n- Create `cmd/bd/staleness.go` - shared staleness check function","created_at":"2025-11-25T04:19:56Z"},{"id":48,"issue_id":"bd-2q6d","author":"stevey","text":"## Implementation Tasks\n\n### Phase 1: Core Infrastructure\n- [ ] Create `cmd/bd/staleness.go` with `ensureDatabaseFresh()` function\n- [ ] Add unit tests for staleness detection\n- [ ] Handle edge cases (missing JSONL, missing hash, etc.)\n\n### Phase 2: Direct Mode Read Commands\n- [ ] Add check to `cmd/bd/list.go`\n- [ ] Add check to `cmd/bd/show.go`\n- [ ] Add check to `cmd/bd/ready.go`\n- [ ] Add check to `cmd/bd/blocked.go`\n- [ ] Add check to `cmd/bd/stale.go`\n- [ ] Integration tests for direct mode\n\n### Phase 3: Daemon Mode\n- [ ] Add staleness check to daemon RPC handlers in `internal/rpc/server.go`\n- [ ] Ensure daemon can access JSONL path\n- [ ] Integration tests for daemon mode\n\n### Phase 4: Polish\n- [ ] Performance testing (check should be \u003c10ms)\n- [ ] Error message clarity\n- [ ] Documentation updates","created_at":"2025-11-25T04:19:56Z"}]} -{"id":"bd-379","content_hash":"f0b4cbd9a790732abc38ecc0941943d7ba28d094ddbbf2b6cc24ff8e371f54fc","title":"Implement `bd setup cursor` for Cursor IDE integration","description":"Create a `bd setup cursor` command that integrates Beads workflow into Cursor IDE via .cursorrules file. Unlike Claude Code (which has hooks), Cursor uses a static rules file to provide context to its AI.","status":"open","priority":3,"issue_type":"feature","created_at":"2025-11-11T23:32:22.170083-08:00","updated_at":"2025-11-11T23:32:22.170083-08:00","source_repo":"."} -{"id":"bd-3852","content_hash":"f5a2177b54d9b6c02e134f5e563006bfa065093c05a93cedd50201e3b0eea23e","title":"Add orphan detection migration","description":"Create migration to detect orphaned children in existing databases. Query: SELECT id FROM issues WHERE id LIKE '%.%' AND substr(id, 1, instr(id || '.', '.') - 1) NOT IN (SELECT id FROM issues). Log results, let user decide action (delete orphans or convert to top-level).","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-04T12:32:30.727044-08:00","updated_at":"2025-11-24T01:08:18.295118-08:00","closed_at":"2025-11-24T00:31:16.479343-08:00","source_repo":"."} -{"id":"bd-39o","content_hash":"36d58121cc9218718d262a1991ee84695af722d2823cf9c8415c2dfdd44fb390","title":"Rename last_import_hash metadata key to jsonl_content_hash","description":"The metadata key 'last_import_hash' is misleading because it's updated on both import AND export (sync.go:614, import.go:320).\n\nBetter names:\n- jsonl_content_hash (more accurate)\n- last_sync_hash (clearer intent)\n\nThis is a breaking change requiring migration of existing metadata values.","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-20T21:31:07.568739-05:00","updated_at":"2025-11-20T21:31:07.568739-05:00","source_repo":"."} -{"id":"bd-3gc","content_hash":"83684e0e79d016a9569ccd04adda44cc072a662ee09556c156bf54e0603c5b6a","title":"Audit remaining cmd/bd files for error handling consistency","description":"Extend ERROR_HANDLING_AUDIT.md to cover: daemon_sync.go, update.go, list.go, show.go, close.go, reopen.go, dep.go, label.go, comments.go, delete.go, compact.go, config.go, validate.go and other high-usage command files","status":"open","priority":3,"issue_type":"task","created_at":"2025-11-24T00:28:55.890991-08:00","updated_at":"2025-11-24T00:28:55.890991-08:00","source_repo":".","dependencies":[{"issue_id":"bd-3gc","depends_on_id":"bd-1qwo","type":"blocks","created_at":"2025-11-24T00:28:55.891827-08:00","created_by":"daemon"}]} -{"id":"bd-3sz0","content_hash":"50d2315d5561c2b89acaa7c6ad84e7b2b0f5155f796bbbeeb862818c4b331423","title":"Auto-repair stale merge driver configs with invalid placeholders","description":"Old bd versions (\u003c0.24.0) installed merge driver with invalid placeholders %L %R instead of %A %B. Add detection to bd doctor --fix: check if git config merge.beads.driver contains %L or %R, auto-repair to 'bd merge %A %O %A %B'. One-time migration for users who initialized with old versions.","status":"open","priority":2,"issue_type":"feature","created_at":"2025-11-21T23:16:10.762808-08:00","updated_at":"2025-11-21T23:16:28.892655-08:00","source_repo":".","dependencies":[{"issue_id":"bd-3sz0","depends_on_id":"bd-tbz3","type":"parent-child","created_at":"2025-11-21T23:16:10.763612-08:00","created_by":"daemon"}]} -{"id":"bd-49kw","content_hash":"738d97a0ac6a43b7810415b6824abd481415358568899c48e7d5d20cf8708ceb","title":"Workaround for FastMCP outputSchema bug in Claude Code","description":"The beads MCP server (v0.23.1) successfully connects to Claude Code, but all tools fail to load with a schema validation error due to a bug in FastMCP 2.13.1.\n\nError: \"Invalid literal value, expected \\\"object\\\"\" in outputSchema.\n\nRoot Cause: FastMCP generates outputSchema with $ref at root level without \"type\": \"object\" for self-referential models (Issue).\n\nWorkaround: Use slash commands (/beads:ready) or wait for FastMCP fix.\n","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-20T18:55:39.041831-05:00","updated_at":"2025-11-24T00:01:27.554672-08:00","closed_at":"2025-11-23T23:22:49.789004-08:00","source_repo":"."} -{"id":"bd-4aao","content_hash":"67e1bab2ec59b16ea0daf6220b137588a6704793584663d1cf6d58765d41437e","title":"Fix failing integration tests in beads-mcp","description":"The `beads-mcp` test suite has failures in `tests/test_bd_client_integration.py` (assertion error in `test_init_creates_beads_directory`) and errors in `tests/test_worktree_separate_dbs.py` (setup failures finding database). These need to be investigated and fixed to ensure a reliable CI baseline.","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-20T18:53:28.4803-05:00","updated_at":"2025-11-20T18:53:28.4803-05:00","source_repo":"."} -{"id":"bd-4h3","content_hash":"c31e267da6b7885e45562d6b1d9176a4ea8603de218f7ffd361226e7268d283e","title":"Add test coverage for internal/git package","description":"","design":"Git package has 1 test file. Critical package needs comprehensive testing. Target: 70% coverage","acceptance_criteria":"- At least 4 test files\n- Package coverage \u003e= 70%\n- Tests cover git commands, error handling","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-20T21:21:23.497486-05:00","updated_at":"2025-11-20T21:21:23.497486-05:00","source_repo":".","dependencies":[{"issue_id":"bd-4h3","depends_on_id":"bd-ge7","type":"blocks","created_at":"2025-11-20T21:21:31.277639-05:00","created_by":"daemon"}]} -{"id":"bd-4ri","content_hash":"d2d8749ed02a35e0207ec699b3936fccf86f80073774800e40bfe69c49bc6f39","title":"Fix TestFallbackToDirectModeEnablesFlush deadlock causing 10min test timeout","description":"## Problem\n\nTestFallbackToDirectModeEnablesFlush in direct_mode_test.go deadlocks for 9m59s before timing out, causing the entire test suite to take 10+ minutes instead of \u003c10 seconds.\n\n## Root Cause\n\nDatabase lock contention between test cleanup and flushToJSONL():\n- Test cleanup (line 36) tries to close DB via defer\n- flushToJSONL() (line 132) is still accessing DB\n- Results in deadlock: database/sql.(*DB).Close() waits for mutex while GetJSONLFileHash() holds it\n\n## Stack Trace Evidence\n\n```\ngoroutine 512 [sync.Mutex.Lock, 9 minutes]:\ndatabase/sql.(*DB).Close(0x14000643790)\n .../database/sql/sql.go:927 +0x84\ngithub.com/steveyegge/beads/cmd/bd.TestFallbackToDirectModeEnablesFlush.func1()\n .../direct_mode_test.go:36 +0xf4\n\nWhile goroutine running flushToJSONL() holds DB connection via GetJSONLFileHash()\n```\n\n## Impact\n\n- Test suite: 10+ minutes β†’ should be \u003c10 seconds\n- ALL other tests pass in ~4 seconds\n- This ONE test accounts for 99.9% of test runtime\n\n## Related\n\nThis is the EXACT same issue documented in MAIN_TEST_REFACTOR_NOTES.md for why main_test.go refactoring was deferred - global state manipulation + DB cleanup = deadlock.\n\n## Fix Approaches\n\n1. **Add proper cleanup sequencing** - stop flush goroutines BEFORE closing DB\n2. **Use test-specific DB lifecycle** - ensure flush completes before cleanup\n3. **Mock the flush mechanism** - avoid real DB for testing this code path \n4. **Add explicit timeout handling** - fail fast with clear error instead of hanging\n\n## Files\n\n- cmd/bd/direct_mode_test.go:36-132\n- cmd/bd/autoflush.go:353 (validateJSONLIntegrity)\n- cmd/bd/autoflush.go:508 (flushToJSONLWithState)\n\n## Acceptance\n\n- Test passes without timeout\n- Test suite completes in \u003c10 seconds\n- No deadlock between cleanup and flush operations","status":"open","priority":1,"issue_type":"bug","created_at":"2025-11-21T20:09:00.794372-05:00","updated_at":"2025-11-21T20:09:00.794372-05:00","source_repo":"."} -{"id":"bd-581b80b3","content_hash":"f32f7d8f0b07aaaeb9d07d8a1d000eef8fc79cf864e8aa20ebb899f6e359ebda","title":"bd find-duplicates - AI-powered duplicate detection","description":"Find semantically duplicate issues.\n\nApproaches:\n1. Mechanical: Exact title/description matching\n2. Embeddings: Cosine similarity (cheap, scalable)\n3. AI: LLM-based semantic comparison (expensive, accurate)\n\nUses embeddings by default for \u003e100 issues.\n\nFiles: cmd/bd/find_duplicates.go (new)","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-29T20:49:49.126801-07:00","updated_at":"2025-11-24T23:43:39.129879-08:00","closed_at":"2025-11-23T23:20:41.046092-08:00","source_repo":"."} -{"id":"bd-5a90","content_hash":"025d43c12e9cc08c6d1db0b4a97f7a086a1a9f24f07769d48a7e2666d04ea217","title":"Test parent issue","description":"","status":"closed","priority":3,"issue_type":"task","created_at":"2025-11-02T11:50:35.85367-08:00","updated_at":"2025-11-24T23:43:39.131049-08:00","closed_at":"2025-11-23T23:35:06.724333-08:00","source_repo":"."} -{"id":"bd-5b6e","content_hash":"307c8a329ac65471b45d05e66ed8353670ea99732039a0897156589223422ccb","title":"Add tests for helper functions (GetDirtyIssueHash, GetAllDependencyRecords, export hashes)","description":"Several utility functions have 0% coverage:\n- GetDirtyIssueHash (dirty.go)\n- GetAllDependencyRecords (dependencies.go)\n- GetExportHash, SetExportHash, ClearAllExportHashes (hash.go)\n\nThese are lower priority but should have basic coverage.","status":"closed","priority":4,"issue_type":"task","created_at":"2025-11-01T22:40:58.989976-07:00","updated_at":"2025-11-24T00:01:27.555906-08:00","closed_at":"2025-11-23T23:39:01.556131-08:00","source_repo":"."} -{"id":"bd-5ibn","content_hash":"ad2cfd0d4c3889f1aede7b4c86f42b84474a4689563d7c850ef20010dec886ca","title":"Latency test 1","description":"","notes":"Resetting stale in_progress status from old executor run (yesterday)","status":"closed","priority":3,"issue_type":"task","created_at":"2025-11-20T12:16:30.703754-05:00","updated_at":"2025-11-24T00:01:27.556337-08:00","closed_at":"2025-11-23T23:35:05.255017-08:00","source_repo":"."} -{"id":"bd-5qim","content_hash":"5117e87c5a56b5b8254402d982e85bea1478c1961f05654a50cf2df11e7ad6bf","title":"Optimize GetReadyWork performance - 752ms on 10K database (target: \u003c50ms)","description":"","notes":"# Performance Analysis (10K Issue Database)\n\nAnalyzed using CPU profiles from benchmark suite on Apple M2 Pro.\n\n## Operation Performance\n\n| Operation | Time | Allocations | Memory |\n|----------------------------------|---------|-------------|--------|\n| bd ready (GetReadyWork) | ~752ms | 167,466 | 16MB |\n| bd list (SearchIssues no filter) | ~11.6ms | 89,214 | 5.8MB |\n| bd list (SearchIssues filtered) | ~9.2ms | 62,365 | 3.5MB |\n| bd create (CreateIssue) | ~2.6ms | 146 | 8.6KB |\n| bd update (UpdateIssue) | ~0.32ms | 364 | 15KB |\n| bd close (UpdateIssue) | ~0.32ms | 364 | 15KB |\n\n**Target: \u003c50ms for all operations on 10K database**\n\n**Current issue: GetReadyWork is 15x over target (752ms vs 50ms)**\n\n## Root Cause\n\nGetReadyWork (internal/storage/sqlite/ready.go:90-128) uses recursive CTE to propagate blocking:\n- 65x slower than SearchIssues\n- Recalculates entire blocked issue tree on every call\n- Algorithm:\n 1. Find directly blocked issues via 'blocks' dependencies\n 2. Recursively propagate blockage to descendants (max depth: 50)\n 3. Exclude all blocked issues from results\n\n## CPU Profile Analysis\n\n- Database syscalls (pthread_cond_signal, syscall6): ~75%\n- SQLite engine overhead: inherent to recursive CTE\n- Application code (query construction): \u003c1%\n\n**Bottleneck is the recursive CTE query execution, not application code.**\n\n## Optimization Recommendations\n\n### High Impact (Likely to achieve \u003c50ms target)\n\n1. **Cache blocked issue calculation**\n - Add `blocked_issues` table updated on dependency changes\n - Trade write complexity for read speed (ready called \u003e\u003e dependency changes)\n - Eliminates recursive CTE on every read\n\n2. **Add/verify database indexes**\n ```sql\n CREATE INDEX IF NOT EXISTS idx_dependencies_blocked \n ON dependencies(issue_id, type, depends_on_id);\n CREATE INDEX IF NOT EXISTS idx_issues_status \n ON issues(status);\n ```\n\n### Medium Impact\n\n3. **Reduce allocations** (167K allocations for GetReadyWork)\n - Profile `scanIssues()` for object pooling opportunities\n - Reuse slice capacity for repeated calls\n\n### Low Impact (Not recommended)\n- Query optimization for CRUD operations (already \u003c3ms)\n- Connection pooling tuning (not showing in profiles)\n\n## Verification\n\nRun benchmarks to validate optimization:\n```bash\nmake bench-quick\ngo tool pprof -http=:8080 internal/storage/sqlite/bench-cpu-*.prof\n```\n\nProfile files automatically generated in `internal/storage/sqlite/`.","status":"open","priority":0,"issue_type":"bug","created_at":"2025-11-14T09:02:46.507526-08:00","updated_at":"2025-11-14T09:03:44.073236-08:00","source_repo":"."} -{"id":"bd-61tg","content_hash":"ee733093dc6eba2a3b6dbd3f8858a264e09d86b9b0f296fe817b95433114b10c","title":"Add test for cross-project contact with deregistered agent","description":"Test coverage for agent deregistration is missing cross-project scenarios. Add tests for: 1) Agent A in Project X tries to contact deregistered Agent B in Project Y, 2) Agent in Project X is deregistered - verify cleanup of cross-project links.","status":"open","priority":3,"issue_type":"task","created_at":"2025-11-24T17:14:17.358681-08:00","updated_at":"2025-11-24T17:14:17.358681-08:00","source_repo":".","labels":["mcp-agent-mail","testing"]} -{"id":"bd-6pul","content_hash":"438d1300af1d2c9073daaef3327785dd0ce5d4e412ed91fa849673ab7f35602c","title":"Epic: Transaction Support for Atomic Operations","description":"Add RunInTransaction API to enable atomic multi-operation workflows.\n\nThis epic implements transaction support in the Beads storage layer, allowing clients (like VC) to execute multiple storage operations atomically. Without this, operations like plan approval that create issues, dependencies, and labels cannot guarantee all-or-nothing semantics.\n\n## Problem\n- Each storage method manages its own transaction\n- External callers cannot coordinate multiple operations atomically\n- Attempting to use BeginTx externally causes deadlocks (methods try to acquire separate connections)\n\n## Solution\nAdd `RunInTransaction(func(tx Transaction) error)` API where Transaction interface exposes key storage methods that execute within a single database transaction.\n\n## Success Criteria\n- WHEN multiple issues created in transaction THEN all succeed or all rollback\n- WHEN transaction commits THEN all changes are durable\n- WHEN transaction rolls back THEN no partial state remains\n- WHEN concurrent transactions compete THEN proper serialization via IMMEDIATE mode\n\nSee bd-9dbq for detailed design notes.","design":"Architecture:\n1. Add Transaction interface to storage/storage.go\n2. Add RunInTransaction to Storage interface \n3. Implement sqliteTxStorage in sqlite package\n4. Refactor internal helpers to accept *sql.Conn\n\nKey design decisions:\n- Use BEGIN IMMEDIATE for write lock acquisition\n- Dedicated connection per transaction (prevents pool contention)\n- Transaction interface mirrors Storage methods (subset)\n- Panic-safe with deferred rollback","status":"open","priority":1,"issue_type":"epic","created_at":"2025-11-24T11:36:18.525875-08:00","updated_at":"2025-11-24T11:36:18.525875-08:00","source_repo":"."} -{"id":"bd-6pxx","content_hash":"539078ccb50c33192672c949c94ecfd001f87bc251a149db879243c3ba4c1275","title":"_get_agent_by_id does not check deregistration status","description":"In app.py:2270-2281, _get_agent_by_id does not filter deregistered agents. Used in reply_to_message (line 3958) and message resource (line 7083). May leak deregistered agent info or allow operations on their behalf. Recommendation: Add include_deregistered=False parameter and audit call sites.","status":"open","priority":1,"issue_type":"bug","created_at":"2025-11-24T17:13:47.497579-08:00","updated_at":"2025-11-24T17:13:47.497579-08:00","source_repo":".","labels":["mcp-agent-mail"]} -{"id":"bd-736d","content_hash":"4743b1f41ff07fee3daa63240f0d5f7ac3f876e928b22c4ce0bee2cdf544e53a","title":"Refactor path canonicalization into helper function","description":"The path canonicalization logic (filepath.Abs + EvalSymlinks) is duplicated in 3 places:\n- beads.go:131-137 (BEADS_DIR handling)\n- cmd/bd/main.go:446-451 (--no-db cleanup)\n- cmd/bd/nodb.go:26-31 (--no-db initialization)\n\nRefactoring suggestion:\nExtract to a helper function like:\n func canonicalizePath(path string) string\n\nThis would:\n- Reduce code duplication\n- Make the logic easier to maintain\n- Ensure consistent behavior across all path handling\n\nRelated to bd-e16b implementation.","status":"open","priority":3,"issue_type":"chore","created_at":"2025-11-02T18:33:47.727443-08:00","updated_at":"2025-11-02T18:33:47.727443-08:00","source_repo":"."} -{"id":"bd-77gm","content_hash":"3072888f4e983c3038332d0d01ffd486c9510bb36c4419129821c1366f24e55a","title":"Import reports misleading '0 created, 0 updated' when actually importing all issues","description":"When running 'bd import' on a fresh database (no existing issues), the command reports 'Import complete: 0 created, 0 updated' even though it successfully imported all issues from the JSONL file.\n\n**Steps to reproduce:**\n1. Delete .beads/beads.db\n2. Run: bd import .beads/issues.jsonl\n3. Observe output: 'Import complete: 0 created, 0 updated'\n4. Run: bd list\n5. Confirm: All issues are actually present in the database\n\n**Expected behavior:**\nReport the actual number of issues imported, e.g., 'Import complete: 523 created, 0 updated'\n\n**Actual behavior:**\n'Import complete: 0 created, 0 updated' (misleading - makes user think import failed)\n\n**Impact:**\n- Users think import failed when it succeeded\n- Confusing during database sync operations (e.g., after git pull)\n- Makes debugging harder (can't tell if import actually worked)\n\n**Context:**\nDiscovered during VC session when syncing database after git pull. The misleading message caused confusion about whether the database was properly synced with the canonical JSONL file.","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-11-09T16:20:13.191156-08:00","updated_at":"2025-11-24T01:25:15.917451-08:00","closed_at":"2025-11-24T01:25:15.917451-08:00","source_repo":"."} -{"id":"bd-7kg","content_hash":"4e40027d49dd5a3d17e033df8962021409cf46777153ed24fdba2810f4c191dd","title":"Document error handling audit findings","description":"Comprehensive audit document showing all error handling inconsistencies found across cmd/bd/*.go files, with specific examples and recommended refactorings","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-24T00:26:59.45249-08:00","updated_at":"2025-11-24T00:28:51.788141-08:00","closed_at":"2025-11-24T00:28:51.788141-08:00","source_repo":"."} -{"id":"bd-7st7","content_hash":"c7abece823288799ecb47eee93a87d9d25ab600abcb4fcd44c5440849ede7bd0","title":"Silent exception swallowing in deregister_agent cleanup","description":"In app.py:3019-3020 and 3027-3028, exceptions are silently swallowed with 'pass' and no logging. This makes debugging difficult when build slot or archive operations fail. Recommendation: Add logger.warning() calls to log the errors.","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-24T17:14:02.644981-08:00","updated_at":"2025-11-24T17:14:02.644981-08:00","source_repo":".","labels":["mcp-agent-mail","observability"]} -{"id":"bd-7yg","content_hash":"a421df3d78f39edb93e421f18e042ad113f6d26c91439d1f732d3df7c80eee62","title":"Git merge driver uses invalid placeholders (%L, %R instead of %A, %B)","description":"## Problem\n\nThe beads git merge driver is configured with invalid Git placeholders:\n\n```\ngit config merge.beads.driver \"bd merge %A %O %L %R\"\n```\n\nGit doesn't recognize `%L` or `%R` as valid merge driver placeholders. The valid placeholders are:\n- `%O` = base (common ancestor)\n- `%A` = current version (ours)\n- `%B` = other version (theirs)\n\n## Impact\n\n- Affects ALL users when they have `.beads/beads.jsonl` merge conflicts\n- Automatic JSONL merge fails with error: \"error reading left file: failed to open file: open 7: no such file or directory\"\n- Users must manually resolve conflicts instead of getting automatic merge\n\n## Root Cause\n\nThe `bd init` command (or wherever the merge driver is configured) is using non-standard placeholders. When Git encounters `%L` and `%R`, it either passes them literally or interprets them incorrectly.\n\n## Fix\n\nUpdate the merge driver configuration to:\n```\ngit config merge.beads.driver \"bd merge %A %O %A %B\"\n```\n\nWhere:\n- 1st `%A` = output file (current file, will be overwritten)\n- `%O` = base (common ancestor)\n- 2nd `%A` = left/current version\n- `%B` = right/other version\n\n## Action Items\n\n1. Fix `bd init` (or equivalent setup command) to use correct placeholders\n2. Add migration/warning for existing users with misconfigured merge driver\n3. Update documentation with correct merge driver setup\n4. Consider adding validation when `bd init` is run","status":"open","priority":1,"issue_type":"bug","created_at":"2025-11-21T19:51:55.747608-05:00","updated_at":"2025-11-21T19:51:55.747608-05:00","source_repo":"."} -{"id":"bd-81a","content_hash":"9177d5018975629174d1e4a531fedb1f3cbcf908ae740a80f224ebfb02e3b000","title":"Add programmatic tip injection API","description":"Allow tips to be programmatically injected at runtime based on detected conditions. This enables dynamic tips (not just pre-defined ones) to be shown with custom priority and frequency.","status":"open","priority":2,"issue_type":"feature","created_at":"2025-11-11T23:29:46.645583-08:00","updated_at":"2025-11-11T23:50:12.209135-08:00","source_repo":".","dependencies":[{"issue_id":"bd-81a","depends_on_id":"bd-d4i","type":"blocks","created_at":"2025-11-11T23:29:46.646327-08:00","created_by":"daemon"}]} -{"id":"bd-853a","content_hash":"df6de1f6a58a995d979a7be59c2fb38800e81b96e8fa0bd39980f8bf9f1a4f37","title":"bd resolve-conflicts - Git merge conflict resolver","description":"Automatically resolve JSONL merge conflicts.\n\nModes:\n- Mechanical: ID remapping (no AI)\n- AI-assisted: Smart merge/keep decisions\n- Interactive: Review each conflict\n\nHandles \u003c\u003c\u003c\u003c\u003c\u003c\u003c conflict markers in .beads/beads.jsonl\n\nFiles: cmd/bd/resolve_conflicts.go (new)","status":"open","priority":1,"issue_type":"task","created_at":"2025-11-24T17:04:47.303547-08:00","updated_at":"2025-11-24T17:04:47.303547-08:00","source_repo":"."} -{"id":"bd-8wa","content_hash":"4dbf9e3e653a748751b14d4c338643d60a8c6b8703a62bd88962602f9ad14b00","title":"Code Review Sweep: thorough","description":"Perform thorough code review sweep based on accumulated activity.\n\n**AI Reasoning:**\nSignificant code volume added (150,273 lines) across multiple critical areas, including cmd/bd, internal/storage/sqlite, and internal/rpc. High file change count (616) indicates substantial refactoring or new functionality. The metrics suggest potential for subtle architectural or implementation issues that warrant review.\n\n**Scope:** thorough\n**Target Areas:** cmd/bd, internal/storage/sqlite, internal/rpc\n**Estimated Files:** 12\n**Estimated Cost:** $5\n\n**Task:**\nReview files for non-obvious issues that agents miss during focused work:\n- Inefficiencies (algorithmic, resource usage)\n- Subtle bugs (race conditions, off-by-one, copy-paste)\n- Poor patterns (coupling, complexity, duplication)\n- Missing best practices (error handling, docs, tests)\n- Unnamed anti-patterns\n\nFile discovered issues with detailed reasoning and suggestions.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-21T10:25:37.081296-05:00","updated_at":"2025-11-24T01:08:18.29555-08:00","closed_at":"2025-11-23T23:24:19.821439-08:00","source_repo":"."} -{"id":"bd-98c4e1fa.1","content_hash":"18da5da06505d025d219d9de2e9fe9b7b538725e935efe58ff9463eb11bd1e01","title":"Update AGENTS.md with event-driven mode","description":"Document BEADS_DAEMON_MODE env var. Explain opt-in during Phase 1. Add troubleshooting for watcher failures.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-29T23:05:13.986452-07:00","updated_at":"2025-11-24T23:43:39.128776-08:00","closed_at":"2025-11-23T23:20:42.790628-08:00","source_repo":"."} -{"id":"bd-9cdc","content_hash":"361f598170b06de5743a2bcaade92866135f2d1019cfde4f04daf16e8d817864","title":"Update docs for import bug fix","description":"Update AGENTS.md, README.md, TROUBLESHOOTING.md with import.orphan_handling config documentation. Document resurrection behavior, tombstones, config modes. Add troubleshooting section for import failures with deleted parents.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-04T12:32:30.770415-08:00","updated_at":"2025-11-24T01:20:17.196828-08:00","closed_at":"2025-11-24T01:20:17.196828-08:00","source_repo":"."} -{"id":"bd-9dbq","content_hash":"3c462046931ba97960701c8b73ccbbbfbe74379b9e982b62b37a58d04354da4b","title":"Add transaction support for atomic issue creation","description":"Use Beads transaction API to create all issues atomically\n\nDesign:\nAdd a transaction-aware API to Beads Storage interface.\n\nApproach 1 (Recommended): RunInTransaction wrapper\n```go\n// In beads/storage.go\ntype Storage interface {\n // ... existing methods ...\n \n // RunInTransaction executes fn in a transaction\n // If fn returns error, transaction is rolled back\n // If fn returns nil, transaction is committed\n RunInTransaction(ctx context.Context, fn func(tx Transaction) error) error\n}\n\ntype Transaction interface {\n // Same methods as Storage, but use underlying *sql.Tx\n CreateIssue(ctx context.Context, issue *Issue, actor string) error\n AddLabel(ctx context.Context, issueID, label, actor string) error\n AddDependency(ctx context.Context, dep *Dependency, actor string) error\n UpdateIssue(ctx context.Context, id string, updates map[string]interface{}, actor string) error\n // ... etc\n}\n```\n\nImplementation in sqlite/sqlite.go:\n```go\nfunc (s *SQLiteStorage) RunInTransaction(ctx context.Context, fn func(tx Transaction) error) error {\n tx, err := s.db.BeginTx(ctx, nil)\n if err != nil {\n return err\n }\n defer tx.Rollback() // Safe to call even after commit\n \n txStorage := \u0026transactionStorage{tx: tx, storage: s}\n if err := fn(txStorage); err != nil {\n return err\n }\n \n return tx.Commit()\n}\n\ntype transactionStorage struct {\n tx *sql.Tx\n storage *SQLiteStorage\n}\n\nfunc (t *transactionStorage) CreateIssue(ctx context.Context, issue *Issue, actor string) error {\n // Same logic as storage.CreateIssue but use t.tx instead of s.db\n // ...\n}\n```\n\nApproach 2 (Alternative): Optional tx parameter\n```go\n// More invasive - requires changing all method signatures\nCreateIssue(ctx context.Context, issue *Issue, actor string, tx ...*sql.Tx) error\n```\n\nPrefer Approach 1 - cleaner API and explicit transaction scope.\n\nNotes:\nContext from VC implementation (vc-apx8):\n\nThe VC plan approval code (internal/planning/approval.go) needs to create multiple issues atomically:\n1. Phase issues (chores)\n2. Task issues \n3. Dependencies between them\n4. Labels\n5. Mission metadata updates\n6. Plan deletion\n\nCurrent problem:\n- Each operation uses storage methods that get their own DB connections\n- Starting a transaction (db.BeginTx) and then calling storage methods causes deadlock\n- Storage methods try to acquire connections while transaction holds a lock\n\nWhat Beads needs:\n1. A transaction-aware API, either:\n - RunInTransaction(func(tx) error) pattern (preferred)\n - OR: All storage methods accept optional *sql.Tx parameter\n\n2. Example usage:\n err := store.RunInTransaction(ctx, func(tx Transaction) error {\n // All operations use tx instead of separate connections\n issue := \u0026Issue{...}\n if err := tx.CreateIssue(ctx, issue, actor); err != nil {\n return err // Triggers rollback\n }\n if err := tx.AddLabel(ctx, issue.ID, \"label\", actor); err != nil {\n return err // Triggers rollback\n }\n return nil // Triggers commit\n })\n\n3. The Transaction interface should expose same methods as Storage:\n - CreateIssue\n - AddLabel\n - AddDependency\n - UpdateMission\n - DeletePlan\n - etc.\n\nReference implementation:\n- See internal/storage/beads/wrapper.go for existing transaction examples\n- Lines 146, 236, 305 show BeginTx usage for migrations\n- But these are DDL operations, not issue CRUD\n\nAcceptance Criteria:\n- WHEN creating issues in transaction THEN all succeed or all rollback\n- WHEN transaction commits THEN all issues exist in Beads\n- WHEN transaction rolls back THEN no issues exist","status":"open","priority":1,"issue_type":"task","created_at":"2025-11-24T11:32:52.877111-08:00","updated_at":"2025-11-24T11:32:52.877111-08:00","source_repo":".","dependencies":[{"issue_id":"bd-9dbq","depends_on_id":"bd-6pul","type":"related","created_at":"2025-11-24T11:37:44.948422-08:00","created_by":"daemon"}]} -{"id":"bd-9e23","content_hash":"fa94af8126d5d8c816a6f83d5ad191ebdb954687abb87ce30e4f67eee4f1a9ce","title":"Optimize Memory backend GetIssueByExternalRef with index","description":"Currently GetIssueByExternalRef in Memory storage uses O(n) linear search through all issues.\n\nCurrent code (memory.go:282-308):\nfor _, issue := range m.issues {\n if issue.ExternalRef != nil \u0026\u0026 *issue.ExternalRef == externalRef {\n return \u0026issueCopy, nil\n }\n}\n\nProposed optimization:\n- Add externalRefToID map[string]string to MemoryStorage\n- Maintain it in CreateIssue, UpdateIssue, DeleteIssue\n- Achieve O(1) lookup like SQLite's index\n\nImpact: Low (--no-db mode typically has smaller datasets)\nRelated: bd-1022","status":"open","priority":4,"issue_type":"chore","created_at":"2025-11-02T15:32:30.242357-08:00","updated_at":"2025-11-02T15:32:30.242357-08:00","source_repo":"."} -{"id":"bd-9li4","content_hash":"7ae7b885e82a2de333584c01f690dbc3ecb924603f18e316f5c91cc44e2256f8","title":"Create Docker image for Agent Mail","description":"Containerize Agent Mail server for easy deployment.\n\nAcceptance Criteria:\n- Dockerfile with Python 3.14\n- Health check endpoint\n- Volume mount for storage\n- Environment variable configuration\n- Multi-arch builds (amd64, arm64)\n\nFile: deployment/agent-mail/Dockerfile","status":"open","priority":3,"issue_type":"task","created_at":"2025-11-07T22:43:43.231964-08:00","updated_at":"2025-11-07T22:43:43.231964-08:00","source_repo":"."} -{"id":"bd-9lwr","content_hash":"8b609156ce481ad87d3da436cb59f1e8a4a979c28cc67d5f06beb5f3720d5125","title":"Document inconsistent error handling strategy across codebase","description":"**Scope:** Cross-cutting pattern across cmd/bd (create.go, init.go, sync.go, daemon_sync.go)\n\n**Issue:** Three different error handling patterns used inconsistently:\n\n**Pattern A: Exit immediately**\n```go\nif err := store.CreateIssue(...) {\n fmt.Fprintf(os.Stderr, \"Error: %v\\n\", err)\n os.Exit(1)\n}\n```\n\n**Pattern B: Warn and continue**\n```go\nif err := createConfigYaml(...) {\n fmt.Fprintf(os.Stderr, \"Warning: %v\\n\", err)\n // Non-fatal - continue anyway\n}\n```\n\n**Pattern C: Silent ignore**\n```go\n_ = store.Close()\n```\n\n**Impact:**\n- Makes error handling non-deterministic\n- Hard to test error paths\n- Inconsistent user experience\n\n**Task:**\n1. Document when each pattern should be used\n2. Add decision tree/flowchart to developer docs\n3. Consider creating error handling helpers to enforce consistency\n4. Audit codebase and refactor outliers","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-23T19:46:52.861673-08:00","updated_at":"2025-11-24T01:08:18.297709-08:00","closed_at":"2025-11-24T00:06:37.086708-08:00","source_repo":"."} -{"id":"bd-9msn","content_hash":"22e4a8227a7caf2577820ea8ac0f10754ac28c15af389cb01e55e5132052adb3","title":"Add monitoring and alerting","description":"Observability for production Agent Mail server.\n\nAcceptance Criteria:\n- Health check endpoint (/health)\n- Prometheus metrics export\n- Grafana dashboard\n- Alerts for server downtime\n- Alerts for high error rate\n- Log aggregation config\n\nFile: deployment/agent-mail/monitoring/","status":"closed","priority":3,"issue_type":"task","created_at":"2025-11-07T22:43:43.354117-08:00","updated_at":"2025-11-24T00:01:27.557683-08:00","closed_at":"2025-11-23T23:38:56.81073-08:00","source_repo":".","dependencies":[{"issue_id":"bd-9msn","depends_on_id":"bd-z3s3","type":"blocks","created_at":"2025-11-07T23:04:28.050074-08:00","created_by":"daemon"}]} -{"id":"bd-afd","content_hash":"fbd5cfa6509144a3650092f743b61f5301926f4086962879290a8478f8dcbcc0","title":"bd doctor --fix should auto-fix metadata.json jsonl_export mismatch","description":"## Root Cause\n\nThe version tracking code (cmd/bd/version_tracking.go:33-38) auto-recreates metadata.json using DefaultConfig() if it doesn't exist. DefaultConfig() hardcodes jsonl_export to 'issues.jsonl', but many repos (including beads itself) use 'beads.jsonl'.\n\nWhen metadata.json goes missing (git clean, merge conflict, rebase, etc.), the next bd command recreates it with the wrong filename, causing a mismatch with the actual JSONL file.\n\n## Impact\n\nThis affects ANY user whose metadata.json gets deleted and who uses a non-default JSONL filename. Normal git operations can trigger this.\n\n## Fix Requirements\n\n1. bd doctor --fix should auto-detect and fix the mismatch (check which .jsonl file exists, update metadata.json)\n2. Version tracking should detect actual JSONL file instead of using hardcoded default\n3. DefaultConfig() should scan for existing .jsonl files before defaulting\n4. Daemon should auto-detect config changes without restart\n\n## Related Code\n\n- internal/configfile/configfile.go:18-23 (DefaultConfig hardcodes issues.jsonl)\n- cmd/bd/version_tracking.go:33-38 (auto-creates config with default) \n- internal/beads/beads.go:245-246 (FindJSONLPath defaults to issues.jsonl)","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-11-23T22:57:34.03414-08:00","updated_at":"2025-11-23T23:11:15.270911-08:00","closed_at":"2025-11-23T23:11:15.270911-08:00","source_repo":"."} -{"id":"bd-au0","content_hash":"755c63ab5b27bc77ee20034d16cc63614a0b3f10a81728f1bde5503cf6615813","title":"Command Set Standardization \u0026 Flag Consistency","description":"Comprehensive improvements to bd command set based on 2025 audit findings.\n\n## Background\nSee docs/command-audit-2025.md for detailed analysis.\n\n## Goals\n1. Standardize flag naming and behavior across all commands\n2. Add missing flags for feature parity\n3. Fix naming confusion\n4. Improve consistency in JSON output\n\n## Success Criteria\n- All mutating commands support --dry-run (no --preview variants)\n- bd update supports label operations\n- bd search has filter parity with bd list\n- Priority flags accept both int and P0-P4 format everywhere\n- JSON output is consistent across all commands","status":"open","priority":2,"issue_type":"epic","created_at":"2025-11-21T21:05:55.672749-05:00","updated_at":"2025-11-21T21:05:55.672749-05:00","source_repo":"."} -{"id":"bd-au0.10","content_hash":"50d18ebce621f3e83c512a74dcb66d98a6d7f67d6632d872a4278f0e46e4bb7a","title":"Add global verbosity flags (--verbose, --quiet)","description":"Add consistent verbosity controls across all commands.\n\n**Current state:**\n- bd init has --quiet flag\n- No other commands have verbosity controls\n- Debug output controlled by BD_VERBOSE env var\n\n**Proposal:**\nAdd persistent flags:\n- --verbose / -v: Enable debug output\n- --quiet / -q: Suppress non-essential output\n\n**Implementation:**\n- Add to rootCmd.PersistentFlags()\n- Replace BD_VERBOSE checks with flag checks\n- Standardize output levels:\n * Quiet: Errors only\n * Normal: Errors + success messages\n * Verbose: Errors + success + debug info\n\n**Files to modify:**\n- cmd/bd/main.go (add flags)\n- internal/debug/debug.go (respect flags)\n- Update all commands to respect quiet mode\n\n**Testing:**\n- Verify --verbose shows debug output\n- Verify --quiet suppresses normal output\n- Ensure errors always show regardless of mode","status":"open","priority":3,"issue_type":"task","created_at":"2025-11-21T21:08:21.600209-05:00","updated_at":"2025-11-21T21:08:21.600209-05:00","source_repo":".","dependencies":[{"issue_id":"bd-au0.10","depends_on_id":"bd-au0","type":"parent-child","created_at":"2025-11-21T21:08:21.602557-05:00","created_by":"daemon"}]} -{"id":"bd-au0.5","content_hash":"add9038348d0512c29c42aaec387bee31f0657a5271fb10542fccd6f906d2339","title":"Add date and priority filters to bd search","description":"Add filter parity with bd list for consistent querying.\n\n**Missing filters to add:**\n- --priority, --priority-min, --priority-max\n- --created-after, --created-before\n- --updated-after, --updated-before\n- --closed-after, --closed-before\n- --empty-description, --no-assignee, --no-labels\n- --desc-contains, --notes-contains\n\n**Files to modify:**\n- cmd/bd/search.go\n- internal/rpc/protocol.go (SearchArgs)\n- internal/storage/storage.go (Search method)\n\n**Testing:**\n- All filter combinations\n- Date format parsing\n- Daemon and direct mode","status":"open","priority":1,"issue_type":"task","created_at":"2025-11-21T21:07:05.496726-05:00","updated_at":"2025-11-21T21:07:05.496726-05:00","source_repo":".","dependencies":[{"issue_id":"bd-au0.5","depends_on_id":"bd-au0","type":"parent-child","created_at":"2025-11-21T21:07:05.497762-05:00","created_by":"daemon"}]} -{"id":"bd-au0.6","content_hash":"90eda170769f9e2355b4e86c0a072ea8f6a2ca46c20d14db410b0a9b2e2049e7","title":"Add comprehensive filters to bd export","description":"Enhance bd export with filtering options for selective exports.\n\n**Currently only has:**\n- --status\n\n**Add filters:**\n- --label, --label-any\n- --assignee\n- --type\n- --priority, --priority-min, --priority-max\n- --created-after, --created-before\n- --updated-after, --updated-before\n\n**Use case:**\n- Export only open issues: bd export --status open\n- Export high-priority bugs: bd export --type bug --priority-max 1\n- Export recent issues: bd export --created-after 2025-01-01\n\n**Files to modify:**\n- cmd/bd/export.go\n- Reuse filter logic from list.go","status":"open","priority":1,"issue_type":"task","created_at":"2025-11-21T21:07:19.431307-05:00","updated_at":"2025-11-21T21:07:19.431307-05:00","source_repo":".","dependencies":[{"issue_id":"bd-au0.6","depends_on_id":"bd-au0","type":"parent-child","created_at":"2025-11-21T21:07:19.432983-05:00","created_by":"daemon"}]} -{"id":"bd-au0.7","content_hash":"38cf025be27a35266601cc65faa97464ec05db76591388d55372c1ec6d26c68a","title":"Audit and standardize JSON output across all commands","description":"Ensure consistent JSON format and error handling when --json flag is used.\n\n**Scope:**\n1. Verify all commands respect --json flag\n2. Standardize success response format\n3. Standardize error response format\n4. Document JSON schemas\n\n**Commands to audit:**\n- Core CRUD: create, update, delete, show, list, search βœ“\n- Queries: ready, blocked, stale, count, stats, status\n- Deps: dep add/remove/tree/cycles\n- Labels: label commands\n- Comments: comments add/list/delete\n- Epics: epic status/close-eligible\n- Export/import: already support --json βœ“\n\n**Testing:**\n- Success cases return valid JSON\n- Error cases return valid JSON (not plain text)\n- Consistent field naming (snake_case vs camelCase)\n- Array vs object wrapping consistency","status":"open","priority":1,"issue_type":"task","created_at":"2025-11-21T21:07:35.304424-05:00","updated_at":"2025-11-21T21:07:35.304424-05:00","source_repo":".","dependencies":[{"issue_id":"bd-au0.7","depends_on_id":"bd-au0","type":"parent-child","created_at":"2025-11-21T21:07:35.305663-05:00","created_by":"daemon"}]} -{"id":"bd-au0.8","content_hash":"3a2fa758b811136e939b5cbb12041106901daab5251effed7ed6f4a6078babd2","title":"Improve clean vs cleanup command naming/documentation","description":"Clarify the difference between bd clean and bd cleanup to reduce user confusion.\n\n**Current state:**\n- bd clean: Remove temporary artifacts (.beads/bd.sock, logs, etc.)\n- bd cleanup: Delete old closed issues from database\n\n**Options:**\n1. Rename for clarity:\n - bd clean β†’ bd clean-temp\n - bd cleanup β†’ bd cleanup-issues\n \n2. Keep names but improve help text and documentation\n\n3. Add prominent warnings in help output\n\n**Preferred approach:** Option 2 (improve documentation)\n- Update short/long descriptions in commands\n- Add examples to help text\n- Update README.md\n- Add cross-references in help output\n\n**Files to modify:**\n- cmd/bd/clean.go\n- cmd/bd/cleanup.go\n- README.md or ADVANCED.md","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-21T21:07:49.960534-05:00","updated_at":"2025-11-21T21:07:49.960534-05:00","source_repo":".","dependencies":[{"issue_id":"bd-au0.8","depends_on_id":"bd-au0","type":"parent-child","created_at":"2025-11-21T21:07:49.962743-05:00","created_by":"daemon"}]} -{"id":"bd-au0.9","content_hash":"825794959c7b81e7d19cc6028b7d098c707627319b9c53a2477e062ced1d03f4","title":"Review and document rarely-used commands","description":"Document use cases or consider deprecation for infrequently-used commands.\n\n**Commands to review:**\n1. bd rename-prefix - How often is this used? Document use cases\n2. bd detect-pollution - Consider integrating into bd validate\n3. bd migrate-hash-ids - One-time migration, keep but document as legacy\n\n**For each command:**\n- Document typical use cases\n- Add examples to help text\n- Consider if it should be a subcommand instead\n- Add deprecation warning if appropriate\n\n**Not changing:**\n- duplicates βœ“ (useful for data quality)\n- repair-deps βœ“ (useful for fixing broken refs)\n- restore βœ“ (critical for compacted issues)\n- compact βœ“ (performance feature)\n\n**Deliverable:**\n- Updated help text\n- Documentation in ADVANCED.md\n- Deprecation plan if needed","status":"open","priority":3,"issue_type":"task","created_at":"2025-11-21T21:08:05.588275-05:00","updated_at":"2025-11-21T21:08:05.588275-05:00","source_repo":".","dependencies":[{"issue_id":"bd-au0.9","depends_on_id":"bd-au0","type":"parent-child","created_at":"2025-11-21T21:08:05.59003-05:00","created_by":"daemon"}]} -{"id":"bd-b0c8","content_hash":"a838027a450cdeb33a415d882ca96e1de37bc70d446a0c99f0be0d50c53669c8","title":"Research hooks/skills approach for enforcing issue descriptions","description":"## Solution: Hooks/Skills (mentioned in discussion)\n\nResearch the hooks/skills system mentioned by riordanpawley in discussion #366:\nhttps://www.reddit.com/r/ClaudeAI/s/wrn2tjkMHX\n\n## Investigation Tasks\n\n1. Review the Reddit post to understand the approach\n2. Determine if beads hooks can enforce validation\n3. Check if Claude Code skills/hooks can intercept MCP calls\n4. Assess feasibility and user burden\n\n## Notes\n\nFrom discussion #366:\n\u003e I'm using a skills/hooks system to get Claude to do that kind of thing right similar to https://www.reddit.com/r/ClaudeAI/s/wrn2tjkMHX\n\nThis might be a client-side solution rather than server-side.\n\n## Deliverable\n\nDocument findings in issue notes, with recommendation on whether to pursue this approach.","status":"closed","priority":3,"issue_type":"task","created_at":"2025-11-23T14:01:01.57079-08:00","updated_at":"2025-11-24T01:25:22.237007-08:00","closed_at":"2025-11-24T01:15:03.961995-08:00","source_repo":"."} -{"id":"bd-b2c","content_hash":"9ee2cd9b36a4c158840f9adb4cf56afbc00affafc20a4971b5d5884e5b24a992","title":"Clarify metadata handling in init.go (config vs tracking)","description":"Review init.go:207-228 to ensure configuration metadata (issue_prefix, sync.branch) uses Pattern A consistently, while tracking metadata (bd_version, repo_id, etc.) uses Pattern B. Add comments explaining the distinction.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-24T00:28:53.199481-08:00","updated_at":"2025-11-24T00:33:24.654007-08:00","closed_at":"2025-11-24T00:33:24.654007-08:00","source_repo":".","dependencies":[{"issue_id":"bd-b2c","depends_on_id":"bd-1qwo","type":"blocks","created_at":"2025-11-24T00:28:53.200299-08:00","created_by":"daemon"}]} -{"id":"bd-b55e2ac2","content_hash":"dbcecb8b95f9f2939d97c61bd8cbe331bea866f47600bded213d3122e311c356","title":"Fix autoimport tests for content-hash collision scoring","description":"## Overview\nThree autoimport tests are failing after bd-cbed9619.4 because they expect behavior based on the old reference-counting collision resolution, but the system now uses deterministic content-hash scoring.\n\n## Failing Tests\n1. `TestAutoImportMultipleCollisionsRemapped` - expects local versions preserved\n2. `TestAutoImportAllCollisionsRemapped` - expects local versions preserved \n3. `TestAutoImportCollisionRemapMultipleFields` - expects specific collision resolution behavior\n\n## Root Cause\nThese tests were written when ScoreCollisions used reference counting to determine which version to keep. Now it uses content-hash comparison (introduced in commit 2e87329), which produces different but deterministic results.\n\n## Example\nOld behavior: Issue with more references would be kept\nNew behavior: Issue with lexicographically lower content hash is kept\n\n## Solution\nUpdate each test to:\n1. Verify the new content-hash based behavior is correct\n2. Check that the remapped issue (not necessarily local/remote) has the expected content\n3. Ensure dependencies are preserved on the correct remapped issue\n\n## Acceptance Criteria\n- All three autoimport tests pass\n- Tests verify content-hash determinism (same collision always resolves the same way)\n- Tests check dependency preservation on remapped issues\n- Test documentation explains content-hash scoring expectations\n\n## Files to Modify\n- `cmd/bd/autoimport_collision_test.go`\n\n## Testing\nRun: `go test ./cmd/bd -run \"TestAutoImport.*Collision\" -v`","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-28T19:17:28.358028-07:00","updated_at":"2025-11-24T00:01:27.558153-08:00","closed_at":"2025-11-23T23:20:43.995595-08:00","source_repo":"."} -{"id":"bd-bp17","content_hash":"650d8d3aa6e4afcb308da0d52aba48d26fae049979d0e0742b389c187f449469","title":"Race condition: double commit in deregister_agent","description":"In app.py:2958-2994, deregister_agent commits twice within the same session: line 2962 after setting deregistered_ts, and line 2994 after cleanup operations. If second operation fails, agent is marked deregistered but cleanup is incomplete. Fix: Use single transaction or handle partial failure explicitly.","status":"open","priority":1,"issue_type":"bug","created_at":"2025-11-24T17:13:48.054719-08:00","updated_at":"2025-11-24T17:13:48.054719-08:00","source_repo":".","labels":["mcp-agent-mail"]} -{"id":"bd-bt6y","content_hash":"462f08aa379cf2f196b4c0ca096271fa47ab5e1a18c5663c28d2d86fd02115cf","title":"Improve compact/daemon/merge documentation and UX","description":"Multiple documentation and UX issues encountered:\n1. \"bd compact --analyze\" fails with misleading \"requires SQLite storage\" error when daemon is running. Needs --no-daemon or better error.\n2. \"bd merge\" help text is outdated (refers to 3-way merge instead of issue merging).\n3. Daemon mode purpose isn't clear to local-only users.\n4. Compact/cleanup commands are hard to discover.\n\nProposed fixes:\n- Fix compact+daemon interaction or error message.\n- Update \"bd merge\" help text.\n- Add \"when to use daemon\" section to docs.\n- Add maintenance section to quickstart.\n","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-20T18:55:43.637047-05:00","updated_at":"2025-11-20T18:55:43.637047-05:00","source_repo":"."} -{"id":"bd-bwk2","content_hash":"c34c5f6281f61bd3298a0cfdaf11594a91e95decf680d655edf35854d1c94fe2","title":"Centralize error handling patterns in storage layer","description":"80+ instances of inconsistent error handling across sqlite.go with mix of %w, %v, and no wrapping.\n\nLocation: internal/storage/sqlite/sqlite.go (throughout)\n\nProblem:\n- Some use fmt.Errorf(\"op failed: %w\", err) - correct wrapping\n- Some use fmt.Errorf(\"op failed: %v\", err) - loses error chain\n- Some return err directly - no context\n- Hard to debug production issues\n- Can't distinguish error types\n\nSolution: Create internal/storage/sqlite/errors.go:\n- Define sentinel errors (ErrNotFound, ErrInvalidID, etc.)\n- Create wrapDBError(op string, err error) helper\n- Convert sql.ErrNoRows to ErrNotFound\n- Always wrap with operation context\n\nImpact: Lost error context; inconsistent messages; hard to debug\n\nEffort: 5-7 hours","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-16T14:51:54.974909-08:00","updated_at":"2025-11-24T01:08:18.298536-08:00","closed_at":"2025-11-24T00:57:47.359519-08:00","source_repo":".","dependencies":[{"issue_id":"bd-bwk2","depends_on_id":"bd-vfe","type":"blocks","created_at":"2025-11-24T00:53:28.831021-08:00","created_by":"daemon"},{"issue_id":"bd-bwk2","depends_on_id":"bd-z8z","type":"blocks","created_at":"2025-11-24T00:53:28.897593-08:00","created_by":"daemon"},{"issue_id":"bd-bwk2","depends_on_id":"bd-w8h","type":"blocks","created_at":"2025-11-24T00:53:28.957487-08:00","created_by":"daemon"},{"issue_id":"bd-bwk2","depends_on_id":"bd-r71","type":"blocks","created_at":"2025-11-24T00:53:29.023262-08:00","created_by":"daemon"}]} -{"id":"bd-bxha","content_hash":"c2ecc8ebb17f47bbb4b23bfc6d283f91fa45bdbe48076082b0397616de197b81","title":"Default to YES for git hooks and merge driver installation","description":"Currently bd init prompts user to install git hooks and merge driver, but setup is incomplete if user declines. Change to install by default unless --skip-hooks or --skip-merge-driver flags are passed. Better safe defaults. If installation fails, warn user and suggest bd doctor --fix.","status":"open","priority":1,"issue_type":"feature","created_at":"2025-11-21T23:16:10.172238-08:00","updated_at":"2025-11-21T23:16:28.369137-08:00","source_repo":".","dependencies":[{"issue_id":"bd-bxha","depends_on_id":"bd-tbz3","type":"parent-child","created_at":"2025-11-21T23:16:10.173034-08:00","created_by":"daemon"}]} -{"id":"bd-c362","content_hash":"92c47f92d3650f8bcf7f858c8e9c3c130978b06629cf1f6aa50ddb32bd871c7c","title":"Extract database search logic into helper function","description":"The logic for finding a database in a beads directory is duplicated:\n- FindDatabasePath() BEADS_DIR section (beads.go:141-169)\n- findDatabaseInTree() (beads.go:248-280)\n\nBoth implement the same search order:\n1. Check config.json first (single source of truth)\n2. Fall back to canonical beads.db\n3. Search for *.db files, filtering backups and vc.db\n\nRefactoring suggestion:\nExtract to a helper function like:\n func findDatabaseInBeadsDir(beadsDir string) string\n\nBenefits:\n- Single source of truth for database search logic\n- Easier to maintain and update search order\n- Reduces code duplication\n\nRelated to [deleted:[deleted:[deleted:[deleted:[deleted:[deleted:[deleted:[deleted:[deleted:[deleted:[deleted:[deleted:bd-e16b]]]]]]]]]]]] implementation.","status":"open","priority":3,"issue_type":"chore","created_at":"2025-11-02T18:34:02.831543-08:00","updated_at":"2025-11-24T23:41:22.67267-08:00","source_repo":"."} -{"id":"bd-c4rq","content_hash":"4c096e1d84c3ba5b5b4e107692b990a99166b4c99a4262fd26ec08297fb81046","title":"Refactor: Move staleness check inside daemon branch","description":"## Problem\n\nCurrently ensureDatabaseFresh() is called before the daemon mode check, but it checks daemonClient != nil internally and returns early. This is redundant.\n\n**Location:** All read commands (list.go:196, show.go:27, ready.go:102, status.go:80, etc.)\n\n## Current Pattern\n\nCall happens before daemon check, function checks daemonClient internally.\n\n## Better Pattern\n\nMove staleness check to direct mode branch only, after daemon check.\n\n## Impact\nLow - minor performance improvement (avoids one function call per command in daemon mode)\n\n## Effort\nMedium - requires refactoring 8 command files\n\n## Priority\nLow - can defer to future cleanup PR","status":"open","priority":3,"issue_type":"chore","created_at":"2025-11-20T20:17:45.119583-05:00","updated_at":"2025-11-20T20:17:45.119583-05:00","source_repo":"."} -{"id":"bd-cb2f","content_hash":"99b9c1c19d5e9f38308d78f09763426777797f133d4c86edd579419e7ba4043f","title":"Week 1 task","description":"","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-03T19:11:59.358093-08:00","updated_at":"2025-11-03T19:11:59.358093-08:00","source_repo":".","labels":["frontend","week2"]} -{"id":"bd-d4i","content_hash":"34836b77273a27caf94ed9785729212f108246f0f5d3e3780e62ecb9472ac528","title":"Create tip system infrastructure for contextual hints","description":"Implement a tip/hint system that shows helpful contextual messages after successful commands. This is different from the existing error-path \"Hint:\" messages - tips appear on success paths to educate users about features they might not know about.","status":"open","priority":2,"issue_type":"feature","created_at":"2025-11-11T23:29:15.693956-08:00","updated_at":"2025-11-11T23:49:50.812933-08:00","source_repo":"."} -{"id":"bd-dow9","content_hash":"5fa420f7eb64396bcd8a58626ae82209d9d75da474a03847d4fbaba76a953846","title":"Improve CheckStaleness error handling","description":"## Problem\n\nCheckStaleness returns 'false' (not stale) for multiple error conditions instead of returning errors. This masks problems.\n\n**Location:** internal/autoimport/autoimport.go:253-285\n\n## Edge Cases That Return False\n\n1. **Invalid last_import_time format** (line 259-262)\n - Corrupted metadata returns 'not stale'\n - Could show stale data\n\n2. **No JSONL file found** (line 267-277)\n - If glob fails, falls back to 'issues.jsonl'\n - If that's empty, returns 'not stale'\n\n3. **JSONL stat fails** (line 279-282)\n - Permission denied, file missing\n - Returns 'not stale' even though can't verify\n\n## Current Code\n\n```go\nlastImportTime, err := time.Parse(time.RFC3339, lastImportStr)\nif err \\!= nil {\n return false, nil // ← Should return error\n}\n\n// ...\n\nif jsonlPath == \"\" {\n return false, nil // ← Should return error\n}\n\nstat, err := os.Stat(jsonlPath)\nif err \\!= nil {\n return false, nil // ← Should return error\n}\n```\n\n## Fix\n\n```go\nlastImportTime, err := time.Parse(time.RFC3339, lastImportStr)\nif err \\!= nil {\n return false, fmt.Errorf(\"corrupted last_import_time: %w\", err)\n}\n\n// ...\n\nif jsonlPath == \"\" {\n return false, fmt.Errorf(\"no JSONL file found\")\n}\n\nstat, err := os.Stat(jsonlPath)\nif err \\!= nil {\n return false, fmt.Errorf(\"cannot stat JSONL: %w\", err)\n}\n```\n\n## Impact\nMedium - edge cases are rare but should be handled\n\n## Effort \n30 minutes - requires updating callers in RPC server\n\n## Dependencies\nRequires: bd-n4td (warning on errors)","status":"open","priority":2,"issue_type":"bug","created_at":"2025-11-20T20:16:45.658965-05:00","updated_at":"2025-11-20T20:16:45.658965-05:00","source_repo":"."} -{"id":"bd-e1085716","content_hash":"a9385e9f00bc41e5e2258fdfccd9f2cbd5a702764b5f1d036274e6026f8c3e38","title":"bd validate - Comprehensive health check","description":"Run all validation checks in one command.\n\nChecks:\n- Duplicates\n- Orphaned dependencies\n- Test pollution\n- Git conflicts\n\nSupports --fix-all for auto-repair.\n\nDepends on bd-cbed9619.1, bd-0dcea000, bd-31aab707, bd-9826b69a.\n\nFiles: cmd/bd/validate.go (new)","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-29T23:05:13.980679-07:00","updated_at":"2025-11-24T23:43:39.1303-08:00","closed_at":"2025-11-23T23:20:39.694984-08:00","source_repo":"."} -{"id":"bd-e166","content_hash":"000f4f9d069ffedceae13894d967ec30fa4a89e318bfcac4847f3c3b16d44a89","title":"Improve timestamp comparison readability in import","description":"The timestamp comparison logic uses double-negative which can be confusing:\n\nCurrent code:\nif !incoming.UpdatedAt.After(existing.UpdatedAt) {\n // skip update\n}\n\nMore readable:\nif incoming.UpdatedAt.After(existing.UpdatedAt) {\n // perform update\n} else {\n // skip (local is newer)\n}\n\nThis is a minor refactor for code clarity.\n\nRelated: bd-1022\nFiles: internal/importer/importer.go:411, 488","status":"open","priority":4,"issue_type":"chore","created_at":"2025-11-02T15:32:12.27108-08:00","updated_at":"2025-11-02T15:32:12.27108-08:00","source_repo":"."} -{"id":"bd-e92","content_hash":"12073b3293b06f99051bc9c00188aeb520cd2e4792cf4694f1fa4b784e625e54","title":"Add test coverage for internal/autoimport package","description":"","design":"The autoimport package has only 1 test file. Need comprehensive tests. Target: 70% coverage","acceptance_criteria":"- At least 3 test files\n- Package coverage \u003e= 70%\n- Tests cover main functionality, error paths, edge cases","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-20T21:21:22.338577-05:00","updated_at":"2025-11-20T21:21:22.338577-05:00","source_repo":".","dependencies":[{"issue_id":"bd-e92","depends_on_id":"bd-ge7","type":"blocks","created_at":"2025-11-20T21:21:31.128625-05:00","created_by":"daemon"}]} -{"id":"bd-ee1","content_hash":"4bda9d2227e9b454883dd36bf2fa21d7ff3a96b58cb9ab7848bf9093ba466505","title":"Add security tests for WriteFile permissions in doctor command","description":"Test coverage gap identified by automated analysis (vc-217).\n\n**Original Issue:** [deleted:[deleted:[deleted:[deleted:[deleted:bd-da96-baseline-lint]]]]]\n\nIn cmd/bd/doctor/gitignore.go:98, os.WriteFile uses 0644 permissions, flagged by gosec G306 as potentially too permissive.\n\nAdd tests to verify:\n- File is created with appropriate permissions (0600 or less)\n- Existing file permissions are not loosened\n- File ownership is correct\n- Sensitive data handling if .gitignore contains secrets\n\nThis ensures .gitignore files are created with secure permissions to prevent unauthorized access.\n\n_This issue was automatically created by AI test coverage analysis._","status":"open","priority":1,"issue_type":"task","created_at":"2025-11-21T10:25:33.529153-05:00","updated_at":"2025-11-24T23:41:22.57494-08:00","source_repo":".","labels":["discovered:supervisor"]} -{"id":"bd-fw7c","content_hash":"57378e8271933f7717413faf976baef28afc1317f94ba48c2d72c8cd894490a9","title":"No database index on Agent.deregistered_ts field","description":"In models.py:58, deregistered_ts field has no index. Every agent query now filters on this field, which will slow down as the agents table grows. Fix: Add index=True to the field definition.","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-24T17:14:01.530402-08:00","updated_at":"2025-11-24T17:14:01.530402-08:00","source_repo":".","labels":["mcp-agent-mail","performance"]} -{"id":"bd-g9eu","content_hash":"4c5542fdd6422092607cca0f8d5f82a41bd366c348a97a604299d6dc75970b3a","title":"Investigate TestRoutingIntegration failure","description":"TestRoutingIntegration/maintainer_with_SSH_remote failed during pre-commit check with \"expected role maintainer, got contributor\".\nThis occurred while running `go test -short ./...` on darwin/arm64.\nThe failure appears unrelated to storage/sqlite changes.\nNeed to investigate if this is a flaky test or environmental issue.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-20T15:55:19.337094-08:00","updated_at":"2025-11-24T00:01:27.559057-08:00","closed_at":"2025-11-23T23:38:55.477369-08:00","source_repo":"."} -{"id":"bd-ge7","content_hash":"84248781654b9924e1f4284058f141b73d761dead05ef9a3d1cc9b9f8cd4b60d","title":"Improve Beads test coverage from 46% to 80%","description":"","design":"Currently at 46% test coverage. Need to systematically improve coverage across all subsystems, focusing first on packages with minimal or no tests.\n\nTarget: 80% overall coverage\n\nApproach:\n- Break down by subsystem (internal/* packages)\n- Prioritize packages with 0-1 test files\n- Each child issue targets specific coverage goals\n- Focus on unit tests for core logic, error paths, and edge cases\n\nThis epic will be executed by the VC executor to test its ability to handle sustained multi-issue work.","acceptance_criteria":"- Overall test coverage reaches 80% or higher\n- All internal/* packages have at least 60% coverage\n- All packages with only 1 test file now have at least 3 test files\n- Quality gates (go test, golangci-lint) pass\n- Tests are maintainable and test actual behavior, not implementation details","status":"open","priority":1,"issue_type":"epic","created_at":"2025-11-20T21:21:03.700271-05:00","updated_at":"2025-11-20T21:21:03.700271-05:00","source_repo":"."} -{"id":"bd-gfu","content_hash":"5777a82b6480e3a730fad9f813830238582276d42bb95f7a73e6cbcbb272438f","title":"Add --start flag to bd daemon, show help with no args","description":"Currently `bd daemon` with no args immediately starts the daemon. This is inconsistent with other daemon management commands like `--stop`, `--status`, etc.\n\n## Proposed Changes\n\n1. Add `--start` flag to explicitly start daemon\n2. With no args or flags, print help text showing available options\n3. Maintain backward compatibility where feasible\n\n## Current Consumers\n\n- **Auto-start logic** (`daemon_autostart.go:106, 270`): Calls `bd daemon` programmatically - needs update\n- **MCP docs** (SETUP_DAEMON.md:111): Already incorrectly shows `bd daemon start` - will be fixed by this change\n- **Python daemon client**: Suggests `bd daemon` in error messages - needs doc update\n\n## Implementation Notes\n\n- Default behavior (no args/flags) should show help\n- `--start` should start daemon (current no-args behavior)\n- Auto-start code needs to pass `--start` flag explicitly\n- Update all documentation to use `bd daemon --start`\n- Ensure backward compat doesn't break existing workflows","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-11-23T23:54:49.906553-08:00","updated_at":"2025-11-24T00:03:15.231345-08:00","closed_at":"2025-11-24T00:03:15.231345-08:00","source_repo":"."} -{"id":"bd-gqo","content_hash":"21642505de8036d9501f8593b78de7b761f05869f9d8d11758278e9c0b33c9c3","title":"Implement health checks in daemon event loop","description":"Add health checks to checkDaemonHealth() function in daemon_event_loop.go:170:\n- Database integrity check\n- Disk space check\n- Memory usage check\n\nCurrently it's just a no-op placeholder.","status":"open","priority":3,"issue_type":"feature","created_at":"2025-11-21T18:55:07.534304-05:00","updated_at":"2025-11-21T18:55:07.534304-05:00","source_repo":"."} -{"id":"bd-hdt","content_hash":"8e6cf1653ef2ea583b39a421b3d708763ab7c042d6cd494e77202a92af0a7398","title":"Implement auto-merge functionality in duplicates command","description":"The duplicates.go file has a TODO at line 95 to implement the performMerge function for automatic duplicate merging. Currently it just prints a warning message. This would automate the merge process instead of just suggesting commands.","status":"open","priority":2,"issue_type":"feature","created_at":"2025-11-21T18:55:02.828619-05:00","updated_at":"2025-11-21T18:55:02.828619-05:00","source_repo":"."} -{"id":"bd-hy9p","content_hash":"338c8d09c267dbca4b25d2ee0c5e6f130d94360a59597c3ecb4f1b64308d208b","title":"Add --body-file flag to bd create for reading descriptions from files","description":"## Problem\n\nCreating issues with long/complex descriptions via CLI requires shell escaping gymnastics:\n\n```bash\n# Current workaround - awkward heredoc quoting\nbd create --title=\"...\" --description=\"$(cat \u003c\u003c'EOF'\n...markdown...\nEOF\n)\"\n\n# Often fails with quote escaping errors in eval context\n# Agents resort to writing temp files then reading them\n```\n\n## Proposed Solution\n\nAdd `--body-file` and `--description-file` flags to read description from a file, matching `gh` CLI pattern.\n\n```bash\n# Natural pattern that aligns with training data\ncat \u003e /tmp/desc.md \u003c\u003c 'EOF'\n...markdown content...\nEOF\n\nbd create --title=\"...\" --body-file=/tmp/desc.md\n```\n\n## Implementation\n\n### 1. Add new flags to `bd create`\n\n```go\ncreateCmd.Flags().String(\"body-file\", \"\", \"Read description from file (use - for stdin)\")\ncreateCmd.Flags().String(\"description-file\", \"\", \"Alias for --body-file\")\n```\n\n### 2. Flag precedence\n\n- If `--body-file` or `--description-file` is provided, read from file\n- If value is `-`, read from stdin\n- Otherwise fall back to `--body` or `--description` flag\n- If neither provided, description is empty (current behavior)\n\n### 3. Error handling\n\n- File doesn't exist β†’ clear error message\n- File not readable β†’ clear error message\n- stdin specified but not available β†’ clear error message\n\n## Benefits\n\nβœ… **Matches training data**: `gh issue create --body-file file.txt` is a common pattern\nβœ… **No shell escaping issues**: File content is read directly\nβœ… **Works with any content**: Markdown, special characters, quotes, etc.\nβœ… **Agent-friendly**: Agents already write complex content to temp files\nβœ… **User-friendly**: Easier for humans too when pasting long descriptions\n\n## Related Commands\n\nConsider adding similar support to:\n- `bd update --body-file` (for updating descriptions)\n- `bd comment --body-file` (if/when we add comments)\n\n## Examples\n\n```bash\n# From file\nbd create --title=\"Add new feature\" --body-file=feature.md\n\n# From stdin\necho \"Quick description\" | bd create --title=\"Bug fix\" --body-file=-\n\n# With other flags\nbd create \\\n --title=\"Security issue\" \\\n --type=bug \\\n --priority=0 \\\n --body-file=security-report.md \\\n --label=security\n```\n\n## Testing\n\n- Test with normal files\n- Test with stdin (`-`)\n- Test with non-existent files (error handling)\n- Test with binary files (should handle gracefully)\n- Test with empty files (valid - empty description)\n- Test that `--description-file` and `--body-file` are equivalent aliases","status":"open","priority":1,"issue_type":"feature","created_at":"2025-11-22T00:02:08.762684-08:00","updated_at":"2025-11-22T00:02:08.762684-08:00","source_repo":"."} -{"id":"bd-iq7n","content_hash":"e6058e742c029c684d63f91a13f2a1e4a95bb461d82f765b652f5a97cf236c6a","title":"Audit and fix JSONL filename mismatches across all repo clones","description":"## Problem\n\nMultiple clones of repos are configured with different JSONL filenames (issues.jsonl vs beads.jsonl), causing:\n1. JSONL files to be resurrected after deletion (one clone pushes issues.jsonl, another pushes beads.jsonl)\n2. Agents unable to see issues filed by other agents after sync\n3. Merge conflicts and data inconsistencies\n\n## Root Cause\n\nWhen repos were \"bd doctored\" or initialized at different times, some got issues.jsonl (old default) and others got beads.jsonl (Beads repo specific). These clones push their respective files, creating duplicates.\n\n## Task\n\nScan all repo clones under ~/src/ (1-2 levels deep) and standardize their JSONL configuration.\n\n### Step 1: Find all beads-enabled repos\n\n```bash\n# Find all directories named 'beads' at levels 1-2 under ~/src/\nfind ~/src -maxdepth 2 -type d -name beads\n```\n\n### Step 2: For each repo found, check configuration\n\nFor each directory from Step 1, check:\n- Does `.beads/metadata.json` exist?\n- What is the `jsonl_export` value?\n- What JSONL files actually exist in `.beads/`?\n- Are there multiple JSONL files (problem!)?\n\n### Step 3: Create audit report\n\nGenerate a report showing:\n```\nRepo Path | Config | Actual Files | Status\n----------------------------------- | ------------- | ---------------------- | --------\n~/src/beads | beads.jsonl | beads.jsonl | OK\n~/src/dave/beads | issues.jsonl | issues.jsonl | MISMATCH\n~/src/emma/beads | issues.jsonl | issues.jsonl, beads.jsonl | DUPLICATE!\n```\n\n### Step 4: Determine canonical name for each repo\n\nFor repos that are the SAME git repository (check `git remote -v`):\n- Group them together\n- Determine which JSONL filename should be canonical (majority wins, or beads.jsonl for the beads repo itself)\n- List which clones need to be updated\n\n### Step 5: Generate fix script\n\nCreate a script that for each mismatched clone:\n1. Updates `.beads/metadata.json` to use the canonical name\n2. If JSONL file needs renaming: `git mv .beads/old.jsonl .beads/new.jsonl`\n3. Removes any duplicate JSONL files: `git rm .beads/duplicate.jsonl`\n4. Commits the change\n5. Syncs: `bd sync`\n\n### Expected Output\n\n1. Audit report showing all repos and their config status\n2. List of repos grouped by git remote (same repository)\n3. Fix script or manual instructions for standardizing each repo\n4. Verification that after fixes, all clones of the same repo use the same JSONL filename\n\n### Edge Cases\n\n- Handle repos without metadata.json (use default discovery)\n- Handle repos with no git remote (standalone/local)\n- Handle repos that are not git repositories\n- Don't modify repos with uncommitted changes (warn instead)\n\n### Success Criteria\n\n- All clones of the same git repository use the same JSONL filename\n- No duplicate JSONL files in any repo\n- All configurations documented in metadata.json\n- bd doctor passes on all repos","status":"open","priority":0,"issue_type":"task","created_at":"2025-11-21T23:58:35.044762-08:00","updated_at":"2025-11-21T23:58:35.044762-08:00","source_repo":"."} -{"id":"bd-j3zt","content_hash":"531ad51101f41375a93d66b8d22105ce7c4913261db78b662bb759e802bc01e2","title":"Fix mypy errors in beads-mcp","description":"Running `mypy .` in `integrations/beads-mcp` reports 287 errors. These should be addressed to improve type safety and code quality.","status":"open","priority":3,"issue_type":"task","created_at":"2025-11-20T18:53:28.557708-05:00","updated_at":"2025-11-20T18:53:28.557708-05:00","source_repo":"."} -{"id":"bd-jgxi","content_hash":"9af80db7f04944bbc55f2d77e3576028c553c936e9d40266ccbf169eec47eb9f","title":"Auto-migrate database on CLI version bump","description":"When CLI is upgraded (e.g., 0.24.0 β†’ 0.24.1), database version becomes stale. Add auto-migration in PersistentPreRun or daemon startup. Check dbVersion != CLIVersion and run bd migrate automatically. Fixes recurring UX issue where bd doctor shows version mismatch after every CLI upgrade.","status":"open","priority":0,"issue_type":"feature","created_at":"2025-11-21T23:16:09.004619-08:00","updated_at":"2025-11-21T23:16:27.229388-08:00","source_repo":".","dependencies":[{"issue_id":"bd-jgxi","depends_on_id":"bd-tbz3","type":"parent-child","created_at":"2025-11-21T23:16:09.005513-08:00","created_by":"daemon"}]} -{"id":"bd-koab","content_hash":"f09900dfd63312833816a4feae0d3b6e751306b611173d57c23722b7709e54a2","title":"Import should continue on FOREIGN KEY constraint violations from deletions","description":"# Problem\n\nWhen importing JSONL after a merge that includes deletions, we may encounter FOREIGN KEY constraint violations if:\n- Issue A was deleted in one branch\n- Issue B (that depends on A) was modified in another branch \n- The merge keeps the deletion of A and the modification of B\n- Import tries to import B with a dependency/reference to deleted A\n\nCurrently import fails completely on such constraint violations, requiring manual intervention.\n\n# Solution\n\nAdd IsForeignKeyConstraintError() helper similar to IsUniqueConstraintError()\n\nUpdate import code to:\n1. Detect FOREIGN KEY constraint violations\n2. Log a warning with the issue ID and constraint\n3. Continue importing remaining issues\n4. Report summary of skipped issues at the end\n\n# Implementation Notes\n\n- Add to internal/storage/sqlite/util.go\n- Pattern: strings.Contains(err.Error(), \"FOREIGN KEY constraint failed\")\n- Update importer to handle these errors gracefully\n- Keep track of skipped issues for summary reporting","notes":"## Implementation Complete\n\nAdded FOREIGN KEY constraint violation handling to the importer:\n\n**Changes made:**\n\n1. **internal/importer/importer.go**\n - Added SkippedDependencies field to Result struct\n - Updated importDependencies() to accept result parameter\n - Added FK constraint detection using sqlite.IsForeignKeyConstraintError()\n - Log warning for each skipped dependency\n - Track skipped dependencies in result\n\n2. **cmd/bd/import_shared.go**\n - Added SkippedDependencies field to ImportResult struct\n - Updated result conversion to include skipped dependencies\n\n3. **cmd/bd/import.go**\n - Added summary reporting for skipped dependencies\n - Displays warning with list of skipped dependencies and helpful context\n\n**Behavior:**\n- When a FOREIGN KEY constraint violation is encountered during dependency import:\n - A warning is logged: 'Warning: Skipping dependency due to missing reference: issue-a β†’ issue-b (blocks)'\n - The dependency is tracked in result.SkippedDependencies\n - Import continues with remaining dependencies\n - Summary at end lists all skipped dependencies with context message\n\n**Testing:**\n- All existing importer tests pass\n- Build succeeds\n- Ready for real-world testing when FK constraint violations are encountered","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-11-23T21:37:02.811665-08:00","updated_at":"2025-11-24T00:01:27.559495-08:00","closed_at":"2025-11-23T23:31:04.325337-08:00","source_repo":"."} -{"id":"bd-ktng","content_hash":"16c10a49a20bf911b3e2643b6bd7ef19d139d991c22407165df68a531d1ce221","title":"Optimize CLI test suite - eliminate redundant git init calls","description":"Current: Each of 13 CLI tests calls git init (31s total). Solution: Use single test binary built once in init(), skip git operations where possible, or use mock filesystem.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-04T11:23:13.660276-08:00","updated_at":"2025-11-23T23:01:49.003046-08:00","closed_at":"2025-11-23T22:55:32.103839-08:00","source_repo":"."} -{"id":"bd-l0r","content_hash":"ee68006dadd763375e8e5e6e4fb3d84cabb4b55407d834314a40bdffe89ebdd1","title":"CRITICAL: bd sync pushes stale DB state instead of trusting JSONL truth on pull","description":"When a clone has stale DB (688 issues) and pulls fresh JSONL (62 issues), bd sync detects 1009.7% divergence but proceeds to re-export the stale DB and push it, overwriting the correct JSONL state. \n\nRepro:\n1. Clone has 688 issues in DB (628 closed)\n2. git pull brings JSONL with 62 issues (cleanup applied)\n3. bd sync warns about divergence but exports DBβ†’JSONL\n4. Pushes 688 issues back to remote, undoing cleanup\n\nExpected: JSONL is source of truth after pull. DB should be wiped and reimported.\nActual: DB overwrites JSONL, pushing stale state upstream.\n\nImpact: Breaks multi-clone coordination. Cleanup work gets undone.","status":"in_progress","priority":0,"issue_type":"bug","created_at":"2025-11-23T22:29:37.668882-08:00","updated_at":"2025-11-23T22:30:11.405611-08:00","source_repo":"."} -{"id":"bd-l954","content_hash":"263dd2111cf0353b307f2e47489aa42ecf607e49b1316b54a6497cad9d3722b0","title":"Performance Testing Framework","description":"Add comprehensive performance testing for beads focusing on optimization guidance and validating 10K+ database scale. Uses standard Go tooling, follows existing patterns, minimal complexity.\n\nComponents:\n- Benchmark suite for critical operations at 10K-20K scale\n- Fixture generator for realistic test data (epic hierarchies, cross-links)\n- User diagnostics via bd doctor --perf\n- Always-on profiling integration\n\nGoals:\n- Identify bottlenecks for optimization work\n- Validate performance at 10K+ issue scale\n- Enable users to collect diagnostics for bug reports\n- Support both SQLite and JSONL import paths","status":"open","priority":2,"issue_type":"epic","created_at":"2025-11-13T22:22:11.203467-08:00","updated_at":"2025-11-13T22:22:11.203467-08:00","source_repo":"."} -{"id":"bd-m0w","content_hash":"e8641e225f1d4cf13fbd97c4a83046e3597df180d3ee134125e4a35abc6941cd","title":"Add test coverage for internal/validation package","description":"","design":"Validation package has 1 test file. Critical for data integrity. Target: 80% coverage","acceptance_criteria":"- At least 4 test files\n- Package coverage \u003e= 80%\n- Tests cover all validation rules","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-20T21:21:24.129559-05:00","updated_at":"2025-11-20T21:21:24.129559-05:00","source_repo":".","dependencies":[{"issue_id":"bd-m0w","depends_on_id":"bd-ge7","type":"blocks","created_at":"2025-11-20T21:21:31.350477-05:00","created_by":"daemon"}]} -{"id":"bd-m7ge","content_hash":"bb08f2bcbbdd2e392733d92bff2e46a51000337ac019d306dd6a2983916873c4","title":"Add .beads/README.md during 'bd init' for project documentation and promotion","description":"When 'bd init' is run, automatically generate a .beads/README.md file that:\n\n1. Briefly explains what Beads is (AI-native issue tracking that lives in your repo)\n2. Links to the main repository: https://github.com/steveyegge/beads\n3. Provides a quick reference of essential commands:\n - bd create: Create new issues\n - bd list: View all issues\n - bd update: Modify issue status/details\n - bd show: View issue details\n - bd sync: Sync with git remote\n4. Highlights key benefits for AI coding agents and developers\n5. Encourages developers to try it out\n\nThe README should be enthusiastic and compelling to get open source contributors excited about using Beads for their AI-assisted development workflows.","status":"open","priority":2,"issue_type":"feature","created_at":"2025-11-16T22:32:50.478681-08:00","updated_at":"2025-11-16T22:32:58.492868-08:00","source_repo":"."} -{"id":"bd-mexx","content_hash":"8fef16c6c30727dda57cbabc54e315e45cedf6c9cff4f87e768729db288ce2e9","title":"Add test for concurrent deregistration race condition","description":"No test verifies behavior when two concurrent deregistration calls race. Add a test that calls deregister_agent twice concurrently to verify idempotency holds under race conditions.","status":"open","priority":3,"issue_type":"task","created_at":"2025-11-24T17:14:17.901397-08:00","updated_at":"2025-11-24T17:14:17.901397-08:00","source_repo":".","labels":["mcp-agent-mail","testing"]} -{"id":"bd-mnap","content_hash":"c15d3c631656fe6d21291f127fc545af93e712b5f3f94cce028513fb743a4fdb","title":"Investigate performance issues in VS Code Copilot (Windows)","description":"Beads unusable in Windows 11 VS Code Copilot chat with Sonnet 4.5.\nSummary event happens every 3-4 turns, taking 3 minutes.\nCopilot summarizes after ~125k tokens despite model supporting 1M.\nLarge context size of beads might be triggering aggressive summarization.\nNeed workaround or optimization for context size.\n","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-20T18:56:30.124918-05:00","updated_at":"2025-11-20T18:56:30.124918-05:00","source_repo":"."} -{"id":"bd-n4gu","content_hash":"0d06c2ec9303bf472c239b1a95e1b857bfb08f630e8016920aa49fff63716947","title":"Build slot cleanup uses synchronous file I/O in async function","description":"In app.py:2996-3020, deregister_agent uses synchronous file I/O (iterdir, glob, read_text, write_text) in an async function. This can cause latency spikes with many build slot files. Recommendation: Use anyio or aiofiles for async file operations, or run in thread pool.","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-24T17:14:02.06723-08:00","updated_at":"2025-11-24T17:14:02.06723-08:00","source_repo":".","labels":["mcp-agent-mail","performance"]} -{"id":"bd-n4td","content_hash":"1a5222748ad9badd0cdfdcfbe831f96c532deeb41909f9729e111dcbaa119d0d","title":"Add warning when staleness check errors","description":"## Problem\n\nWhen ensureDatabaseFresh() calls CheckStaleness() and it errors (corrupted metadata, permission issues, etc.), we silently proceed with potentially stale data.\n\n**Location:** cmd/bd/staleness.go:27-32\n\n**Scenarios:**\n- Corrupted metadata table\n- Database locked by another process \n- Permission issues reading JSONL file\n- Invalid last_import_time format in DB\n\n## Current Code\n\n```go\nisStale, err := autoimport.CheckStaleness(ctx, store, dbPath)\nif err \\!= nil {\n // If we can't determine staleness, allow operation to proceed\n // (better to show potentially stale data than block user)\n return nil\n}\n```\n\n## Fix\n\n```go\nisStale, err := autoimport.CheckStaleness(ctx, store, dbPath)\nif err \\!= nil {\n fmt.Fprintf(os.Stderr, \"Warning: Could not verify database freshness: %v\\n\", err)\n fmt.Fprintf(os.Stderr, \"Proceeding anyway. Data may be stale.\\n\\n\")\n return nil\n}\n```\n\n## Impact\nMedium - users should know when staleness check fails\n\n## Effort\nEasy - 5 minutes","status":"open","priority":2,"issue_type":"bug","created_at":"2025-11-20T20:16:34.889997-05:00","updated_at":"2025-11-20T20:16:34.889997-05:00","source_repo":".","dependencies":[{"issue_id":"bd-n4td","depends_on_id":"bd-2q6d","type":"blocks","created_at":"2025-11-20T20:18:20.154723-05:00","created_by":"stevey"}]} -{"id":"bd-nq41","content_hash":"33f9cfe6a0ef5200dcd5016317b43b1568ff9dc7303537d956bdab02029f6c63","title":"Fix Homebrew warning about Ruby file location","description":"Homebrew warning: Found Ruby file outside steveyegge/beads tap formula directory.\nWarning points to: /opt/homebrew/Library/Taps/steveyegge/homebrew-beads/bd.rb\nIt should likely be inside a Formula/ directory or similar structure expected by Homebrew taps.\n","status":"open","priority":2,"issue_type":"chore","created_at":"2025-11-20T18:56:21.226579-05:00","updated_at":"2025-11-20T18:56:21.226579-05:00","source_repo":"."} -{"id":"bd-o4qy","content_hash":"28304d9e414cbc475b89dc2d1474f110d8f9d90d50fdbdca8f15961db540806b","title":"Improve CheckStaleness error handling","description":"## Problem\n\nCheckStaleness returns 'false' (not stale) for multiple error conditions instead of returning errors. This masks problems.\n\n**Location:** internal/autoimport/autoimport.go:253-285\n\n## Edge Cases That Return False\n\n1. **Invalid last_import_time format** (line 259-262)\n2. **No JSONL file found** (line 267-277) \n3. **JSONL stat fails** (line 279-282)\n\n## Fix\n\nReturn errors for abnormal conditions:\n\n```go\nlastImportTime, err := time.Parse(time.RFC3339, lastImportStr)\nif err != nil {\n return false, fmt.Errorf(\"corrupted last_import_time: %w\", err)\n}\n\nif jsonlPath == \"\" {\n return false, fmt.Errorf(\"no JSONL file found\")\n}\n\nstat, err := os.Stat(jsonlPath)\nif err != nil {\n return false, fmt.Errorf(\"cannot stat JSONL: %w\", err)\n}\n```\n\n## Impact\nMedium - edge cases are rare but should be handled\n\n## Effort \n30 minutes - requires updating callers in RPC server","status":"open","priority":2,"issue_type":"bug","created_at":"2025-11-20T20:17:27.606219-05:00","updated_at":"2025-11-20T20:17:27.606219-05:00","source_repo":".","dependencies":[{"issue_id":"bd-o4qy","depends_on_id":"bd-2q6d","type":"blocks","created_at":"2025-11-20T20:18:26.81065-05:00","created_by":"stevey"}]} -{"id":"bd-ola6","content_hash":"d34a1caa5be1a46beafb798388403b1118adbd335f43e0c610a8ec50bd322eca","title":"Implement transaction retry logic for SQLITE_BUSY","description":"BEGIN IMMEDIATE fails immediately on SQLITE_BUSY instead of retrying with exponential backoff.\n\nLocation: internal/storage/sqlite/sqlite.go:223-225\n\nProblem:\n- Under concurrent write load, BEGIN IMMEDIATE can fail with SQLITE_BUSY\n- Current implementation fails immediately instead of retrying\n- Results in spurious failures under normal concurrent usage\n\nSolution: Implement exponential backoff retry:\n- Retry up to N times (e.g., 5)\n- Backoff: 10ms, 20ms, 40ms, 80ms, 160ms\n- Check for context cancellation between retries\n- Only retry on SQLITE_BUSY/database locked errors\n\nImpact: Spurious failures under concurrent write load\n\nEffort: 3 hours","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-11-16T14:51:31.247147-08:00","updated_at":"2025-11-24T01:17:35.455245-08:00","closed_at":"2025-11-24T01:08:59.54254-08:00","source_repo":"."} -{"id":"bd-p6vp","content_hash":"1df6d3b9b438cdcdbc618c24fea48769c1f22e8a8701af4e742531d4433ca7ea","title":"Clarify .beads/.gitattributes handling in Protected Branches docs","description":"Protected Branches docs quick start leaves untracked `.beads` directory and `.gitattributes`.\nQuestion: Are these changes meant to be checked into the protected branch?\nNeed to clarify if these should be ignored or committed, or if the instructions are missing a step.\n","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-20T18:56:25.79407-05:00","updated_at":"2025-11-20T18:56:25.79407-05:00","source_repo":"."} -{"id":"bd-pp3","content_hash":"f9cb8f8d8d9390c4c6c00bb1752bfc9d939735ab63b961aee507331ac0fed4bd","title":"Add metadata distinction guidelines to ERROR_HANDLING.md","description":"Update ERROR_HANDLING.md with clear guidelines distinguishing configuration metadata (Pattern A) from tracking metadata (Pattern B). Include examples from init.go and sync.go.","status":"closed","priority":3,"issue_type":"task","created_at":"2025-11-24T00:28:54.559851-08:00","updated_at":"2025-11-24T00:34:13.980602-08:00","closed_at":"2025-11-24T00:34:13.980602-08:00","source_repo":".","dependencies":[{"issue_id":"bd-pp3","depends_on_id":"bd-1qwo","type":"blocks","created_at":"2025-11-24T00:28:54.560699-08:00","created_by":"daemon"}]} -{"id":"bd-r46","content_hash":"4107332c80d234a2f3b5a65117745853947ea3e6c2eabb66bab4088a45f18ae1","title":"Support --reason flag in daemon mode for reopen command","description":"The reopen.go command has a TODO at line 61 to add reason as a comment once RPC supports AddComment. Currently --reason flag is ignored in daemon mode with a warning.","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-11-21T18:55:10.773626-05:00","updated_at":"2025-11-24T01:08:58.570375-08:00","closed_at":"2025-11-24T01:08:58.570375-08:00","source_repo":"."} -{"id":"bd-r71","content_hash":"88067b1a1aaad4cf0fe63e795ee581eebc2dda5b45ea4d6a5a7e357eb17ffeee","title":"Add tests for error wrapping behavior","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-24T00:53:16.906291-08:00","updated_at":"2025-11-24T00:57:46.21316-08:00","closed_at":"2025-11-24T00:57:46.21316-08:00","source_repo":"."} -{"id":"bd-rmo8","content_hash":"f1a088c8ab180770d6459f6ec54afe1f282093adde6a8b175eb5125732049de9","title":"resource://project/{slug} does not filter deregistered agents","description":"In app.py:6859, the project_resource retrieves ALL agents without filtering deregistered ones, while resource://agents/{project_key} correctly filters at line 6921-6923. This causes inconsistent behavior between discovery endpoints. Fix: Add Agent.deregistered_ts.is_(None) filter to line 6859.","status":"open","priority":1,"issue_type":"bug","created_at":"2025-11-24T17:13:46.949705-08:00","updated_at":"2025-11-24T17:13:46.949705-08:00","source_repo":".","labels":["mcp-agent-mail"]} -{"id":"bd-s02","content_hash":"911d456e4dabae028dd615b643c99058ef12e55ea523cb81cc933783c7b13546","title":"Manual task","description":"","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-03T20:15:10.022202-08:00","updated_at":"2025-11-03T20:15:10.022202-08:00","source_repo":"."} -{"id":"bd-s0z","content_hash":"b69df0c8664737b3c04b10e3137652e3c8c3d782de0ecd02bfcd648919f8d944","title":"Consider extracting error handling helpers","description":"Evaluate creating FatalError() and WarnError() helpers as suggested in ERROR_HANDLING.md to reduce boilerplate and enforce consistency. Prototype in a few files first to validate the approach.","status":"open","priority":4,"issue_type":"task","created_at":"2025-11-24T00:28:57.248959-08:00","updated_at":"2025-11-24T00:28:57.248959-08:00","source_repo":".","dependencies":[{"issue_id":"bd-s0z","depends_on_id":"bd-1qwo","type":"blocks","created_at":"2025-11-24T00:28:57.249945-08:00","created_by":"daemon"}]} -{"id":"bd-sqgq","content_hash":"2b77b5e987b58e2bd3ed5f3bb07ec314c6a4a4b79122f13eafde59089e86ecef","title":"Block version bumps/releases when CI is failing","description":"The bump-version.sh script and release process should verify that CI is passing before creating version tags and releases.\n\n## Problem\nCurrently we can cut releases even when CI tests are failing, which could ship broken code to users.\n\n## Proposed Solution\nAdd a CI status check to:\n1. scripts/bump-version.sh - Check CI status before tagging\n2. Potentially add a GitHub branch protection rule requiring CI to pass before tags can be pushed\n\n## Implementation Ideas\n- Use `gh run list --branch main --limit 1` to check latest CI status\n- Add `--force` flag to override the check if needed\n- Consider GitHub Actions workflow that validates CI before release\n\n## Benefits\n- Prevents shipping broken releases\n- Catches test failures before they reach users\n- Maintains quality standards in distribution channels","status":"open","priority":2,"issue_type":"feature","created_at":"2025-11-22T00:10:31.48266-08:00","updated_at":"2025-11-22T00:10:31.48266-08:00","source_repo":"."} -{"id":"bd-t3b","content_hash":"c32a3a0f2f836148033fb330e209ac22e06dbecf18894153c15e2036f5afae1c","title":"Add test coverage for internal/config package","description":"","design":"Config package has 1 test file. Need comprehensive tests. Target: 70% coverage","acceptance_criteria":"- At least 3 test files\n- Package coverage \u003e= 70%","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-20T21:21:22.91657-05:00","updated_at":"2025-11-20T21:21:22.91657-05:00","source_repo":".","dependencies":[{"issue_id":"bd-t3b","depends_on_id":"bd-ge7","type":"blocks","created_at":"2025-11-20T21:21:31.201036-05:00","created_by":"daemon"}]} -{"id":"bd-t4u1","content_hash":"c119816ca9a3fada73b24b145cbc9407560dd72207aa79390d93f9e588810552","title":"False positive detection by Kaspersky Antivirus (Trojan)","description":"Kaspersky Antivirus falsely detects beads (bd.exe v0.23.1) as a Trojan (PDM:Trojan.Win32.Generic) and removes it.\nEvent: Malicious object detected\nComponent: System Watcher\nObject name: bd.exe\n","notes":"## Completed Actions\n\n1. **Root cause analysis**: Documented that this is a known false positive with Go binaries\n2. **Created comprehensive user documentation**: docs/ANTIVIRUS.md with:\n - Explanation of why Go binaries trigger false positives\n - Instructions for adding exclusions (Kaspersky, Windows Defender, etc.)\n - File integrity verification steps\n - False positive reporting procedures\n - FAQ section\n3. **Updated TROUBLESHOOTING.md**: Added quick reference section with link to detailed guide\n\n## Next Steps (Follow-up Issues)\n\nThe following actions require external processes or future releases:\n\n1. **Submit false positive to Kaspersky**: Need to access bd.exe v0.23.1 Windows binary and submit to https://opentip.kaspersky.com/\n2. **Code signing for Windows**: Requires purchasing certificate and configuring GoReleaser (medium-term)\n3. **Apply for Kaspersky whitelist**: Long-term relationship building with vendor\n\n## Current Status\n\nUsers affected by this issue now have:\n- Clear documentation explaining the false positive\n- Step-by-step instructions to work around it\n- Ways to verify file integrity\n- Process to report to their antivirus vendor\n\nBuild configuration already includes recommended optimizations (-s -w flags).","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-20T18:56:12.498187-05:00","updated_at":"2025-11-24T01:17:35.4543-08:00","closed_at":"2025-11-24T01:03:39.166915-08:00","source_repo":"."} -{"id":"bd-tbz3","content_hash":"ac416dd2c873a4abb653dfbb689464834000b0c11410c09adf0efb2396a33c48","title":"bd init UX Improvements","description":"bd init leaves users with incomplete setup, requiring manual bd doctor --fix. Issues found: (1) git hooks not installed if user declines prompt, (2) no auto-migration when CLI is upgraded, (3) stale merge driver configs from old versions. Fix by making bd init more robust with better defaults and auto-migration.","status":"open","priority":1,"issue_type":"epic","created_at":"2025-11-21T23:16:00.333543-08:00","updated_at":"2025-11-21T23:16:37.811233-08:00","source_repo":"."} -{"id":"bd-tne","content_hash":"499d308e9cf12752247dbd13adcd633ce0190f72f8a56f7074c44805d6cb396f","title":"Add Claude setup tip with dynamic priority","description":"Add a predefined tip that suggests running `bd setup claude` when Claude Code is detected but not configured. This tip should have higher priority (shown more frequently) until the setup is complete.","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-11T23:29:29.871324-08:00","updated_at":"2025-11-11T23:50:29.756454-08:00","source_repo":".","dependencies":[{"issue_id":"bd-tne","depends_on_id":"bd-d4i","type":"blocks","created_at":"2025-11-11T23:29:29.872081-08:00","created_by":"daemon"}]} -{"id":"bd-tonp","content_hash":"19bc3a248ffffd0e36808609a0cbb9e22ee73d51c616a62fa3c669a9b60e7fe5","title":"Consider adding preserve_metadata option on agent reactivation","description":"Currently reactivation always overwrites agent metadata (program, model, task_description). Some use cases might prefer preserving original inception_ts or other historical data. Suggestion: Add preserve_metadata: bool = False parameter for flexibility.","status":"open","priority":3,"issue_type":"feature","created_at":"2025-11-24T17:14:18.480198-08:00","updated_at":"2025-11-24T17:14:18.480198-08:00","source_repo":".","labels":["enhancement","mcp-agent-mail"]} -{"id":"bd-tru","content_hash":"0de12031088519a3dcd27968d6bf17eb3a92d1853264e5a0dceef3310b3a2b04","title":"Update documentation for bd prime and Claude integration","description":"Update AGENTS.md, README.md, and QUICKSTART.md to document the new `bd prime` command, `bd setup claude` command, and tip system.","design":"## Documentation Updates\n\n### AGENTS.md\nAdd new section \"Context Recovery\":\n```markdown\n## Context Recovery\n\n### The Problem\nAfter context compaction or clearing conversation, AI agents may forget to use Beads and revert to markdown TODOs. Claude Code hooks solve this.\n\n### bd prime Command\nThe `bd prime` command outputs essential Beads workflow context in AI-optimized markdown format (~1-2k tokens).\n\n**When to use:**\n- After context compaction\n- After clearing conversation\n- Starting new session\n- When agent seems to forget bd workflow\n- Manual context refresh\n\n**Usage:**\n```bash\nbd prime # Output workflow context\n```\n\n### Automatic Integration (Recommended)\n\nRun `bd setup claude` to install hooks that auto-refresh bd context:\n- **SessionStart hook**: Loads context in new sessions\n- **PreCompact hook**: Refreshes context before compaction (survives better)\n- **Works with MCP**: Hooks complement MCP server (not replace)\n- **Works without MCP**: bd prime provides workflow via CLI\n\n**Why hooks matter even with MCP:**\n- MCP provides native tools, but agent may forget to use them\n- Hooks keep \"use bd, not markdown\" fresh in context\n- PreCompact refreshes workflow before compaction\n\n### MCP Server vs bd prime\n\n**Not an either/or choice** - they solve different problems:\n\n| Aspect | MCP Server | bd prime | Both |\n|--------|-----------|----------|------|\n| **Purpose** | Native bd tools | Workflow context | Best of both |\n| **Tokens** | 10.5k always loaded | ~1-2k when called | 10.5k + ~2k |\n| **Tool access** | Function calls | CLI via Bash | Function calls |\n| **Context memory** | Can fade after compaction | Hooks keep fresh | Hooks + tools |\n| **Recommended** | Heavy usage | Token optimization | Best experience |\n\n**Setup options:**\n```bash\nbd setup claude # Install hooks (works with or without MCP)\nbd setup claude --local # Per-project only\nbd setup claude --remove # Remove hooks\n```\n```\n\n### README.md\nAdd to \"Getting Started\" section:\n```markdown\n### AI Agent Integration\n\n**Claude Code users:** Run `bd setup claude` to install automatic context recovery hooks.\n\nHooks work with both MCP server and CLI approaches, preventing agents from forgetting bd workflow after compaction.\n\n**MCP vs bd prime:**\n- **With MCP server**: Hooks keep agent using bd tools (prevents markdown TODO reversion)\n- **Without MCP server**: Hooks provide workflow context via `bd prime` (~1-2k tokens)\n```\n\n### QUICKSTART.md\nAdd section on agent integration:\n```markdown\n## For AI Agents\n\n**Context loading:**\n```bash\nbd prime # Load workflow context (~1-2k tokens)\n```\n\n**Automatic setup (Claude Code):**\n```bash\nbd setup claude # Install hooks for automatic context recovery\n```\n\nHooks prevent agents from forgetting bd workflow after compaction.\n```","acceptance_criteria":"- AGENTS.md has Context Recovery section\n- README.md mentions bd setup claude\n- QUICKSTART.md mentions bd prime\n- Examples show when to use bd prime vs MCP\n- Clear comparison of trade-offs","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-11T23:30:22.77349-08:00","updated_at":"2025-11-11T23:45:23.242658-08:00","source_repo":"."} -{"id":"bd-ufny","content_hash":"e91676db7930ad2f04145ce7bb6d438d2ade056750d78974c55577a4cc0409b7","title":"First-class git worktree support","description":"## Motivation\n\nBeads should be a first-class citizen in git worktree environments like gastown/town, where multiple worktrees share the same repository but work on different branches simultaneously.\n\nCurrent state: Worktrees trigger a warning suggesting --no-daemon, but this is a bandaid, not a solution. MCP integration requires daemon mode, so worktree users are second-class citizens.\n\n## The Core Problem\n\nGit worktrees create a fundamental mismatch:\n- Multiple checkouts share one .beads/ directory (tracked in git)\n- One SQLite database (gitignored local cache)\n- One daemon per .beads/ path\n- Daemon doesn't know which worktree is calling it\n- Sync commits can go to the wrong branch\n\n## Use Cases\n\n1. **Gastown/Town Pattern**: One project, multiple named worktrees (polecats), all sharing issues\n2. **Solo Developer**: Main + feature branch worktrees, issues visible across all\n3. **Team**: Multiple developers using worktrees, syncing via git\n\n## Key Insight\n\nIssues are PROJECT-level, not BRANCH-level. An issue created in BlackRoad worktree is still relevant to RedTanker. The JSONL is shared via git. The database is just a local cache.\n\n## Proposed Solution: Per-Worktree Daemon with Shared Database\n\n### 1. Auto-Detect Worktree Environment\n```go\nfunc DetectWorktreeMode() WorktreeMode {\n gitDir := exec(\"git rev-parse --git-dir\")\n commonDir := exec(\"git rev-parse --git-common-dir\")\n if gitDir != commonDir {\n return WorktreeModeDetected\n }\n return WorktreeModeNormal\n}\n```\n\n### 2. Worktree Identity in Daemon\n- Socket path includes worktree name: `.beads/bd-{worktree-name}.sock`\n- Each worktree gets its own daemon process\n- All daemons share SQLite with proper WAL-mode locking\n- Each daemon knows its worktree's current branch\n\n### 3. Auto-Initialize on First Access\nWhen bd runs in worktree without local database:\n1. Detect worktree mode\n2. Find shared .beads/issues.jsonl\n3. Create/update local SQLite cache\n4. Auto-detect prefix from existing JSONL issues\n5. Start worktree-aware daemon\n6. No \"bd init\" ceremony needed\n\n### 4. Worktree-Aware Sync\nOptions (configurable):\n- **Per-branch**: Each daemon commits to its worktree's current branch\n- **Unified**: All daemons commit to a shared \"beads-sync\" branch\n\n### 5. Graceful Degradation\nIf worktree complexity detected and daemon can't handle it:\n- Warn once (not every command)\n- Auto-fallback to no-daemon mode\n- Fully functional, just no auto-sync\n\n## Implementation Phases\n\n### Phase 1: Better Detection \u0026 Auto-Fallback\n- Improved worktree detection\n- Single clear warning with actionable advice\n- Auto-set BEADS_NO_DAEMON in worktrees by default\n- Add --worktree-mode flag to override\n\n### Phase 2: Auto-Init\n- When JSONL exists but no DB, auto-initialize\n- Infer prefix from existing issues (already works in bd init)\n- Eliminate \"bd init\" requirement for fresh worktree clones\n\n### Phase 3: Per-Worktree Daemons\n- Socket/lock naming with worktree identity\n- Daemon startup detects and records worktree context\n- Proper WAL-mode locking for concurrent DB access\n- RPC includes worktree context\n\n### Phase 4: Worktree-Aware Sync\n- Config option: sync-mode: per-branch | unified\n- Branch-aware commit routing\n- Handle merge conflicts gracefully\n- Test with gastown multi-polecat setup\n\n## Files to Modify\n\n- `cmd/bd/main.go`: Database discovery, worktree detection\n- `cmd/bd/daemon.go`: Socket path generation with worktree ID\n- `cmd/bd/daemon_sync_branch.go`: Branch routing per worktree\n- `cmd/bd/worktree.go`: Enhanced detection, auto-fallback logic\n- `cmd/bd/init.go`: Auto-init when JSONL exists\n- `internal/daemon/discovery.go`: Find daemons per worktree\n- `internal/beads/discover.go`: Worktree-aware DB discovery\n\n## Success Criteria\n\n1. Running `bd list` in a fresh gastown worktree \"just works\" (no bd init needed)\n2. Multiple worktrees can run daemons simultaneously without conflict\n3. MCP integration works in worktree environments\n4. Sync commits go to correct branch (or configured sync branch)\n5. No scary warnings for supported worktree configurations\n\n## References\n\n- gastown issue: gt-t8q (Support git worktree environments natively)\n- Current worktree warning: cmd/bd/worktree.go warnWorktreeDaemon()\n- Existing WorktreeManager: internal/git/worktree.go","status":"open","priority":1,"issue_type":"feature","created_at":"2025-11-24T16:27:31.381177-08:00","updated_at":"2025-11-24T16:27:31.381177-08:00","source_repo":"."} -{"id":"bd-ut5","content_hash":"d9b4ee9c7748c28dc2cd436911b1bee39e68e82df99b718ebe57a246f72a6bcb","title":"Test label update feature","description":"","status":"open","priority":3,"issue_type":"task","created_at":"2025-11-21T22:07:25.488849-05:00","updated_at":"2025-11-21T22:07:25.488849-05:00","source_repo":".","labels":["test-direct"]} -{"id":"bd-v0y","content_hash":"72d91011884bc9e20ac1c18b67f66489dcf49f3fec6da4d9b4dbbe1832d8b72f","title":"Critical: bd sync overwrites git-pulled JSONL instead of importing it","description":"## Problem\n\nWhen a user runs `git pull` (which updates .beads/beads.jsonl) followed by `bd sync`, the sync command fails to detect that the JSONL changed and exports the local database, **overwriting the pulled JSONL** instead of importing it first.\n\nThis causes cleaned-up issues (removed via `bd cleanup` in another repo) to be resurrected and pushed back to the remote.\n\n## Root Cause\n\n`hasJSONLChanged()` in cmd/bd/integrity.go incorrectly returns FALSE when it should return TRUE after git pull updates the JSONL file.\n\nThe function has two code paths:\n1. **Fast-path (line 128-129)**: If mtime unchanged, return false\n2. **Slow-path (line 135-151)**: Compute hash and compare\n\nSuspected issue: The mtime-based fast-path may incorrectly return false if:\n- Git preserves mtime when checking out files, OR\n- The mtime check logic has a race condition, OR\n- The stored last_import_mtime is stale/incorrect\n\n## Reproduction\n\n**Setup:**\n1. Repo A: Has 686 issues (including 630 closed)\n2. Run `bd cleanup -f` in Repo A (removes 630 closed issues β†’ 56 issues remain)\n3. Push to remote\n4. Repo B: Still has 686 issues in database\n\n**Trigger:**\n1. In Repo B: `git pull` (JSONL now has 56 issues)\n2. In Repo B: `bd sync`\n\n**Expected behavior:**\n- hasJSONLChanged() returns TRUE\n- Auto-imports 56-issue JSONL\n- Database updated to 56 issues\n- Exports (no-op, DB and JSONL match)\n- Pushes\n\n**Actual behavior:**\n- hasJSONLChanged() returns FALSE ❌\n- Skips auto-import\n- Exports 686 issues from DB to JSONL\n- Commits and pushes the 686-issue JSONL\n- **Undoes the cleanup from Repo A**\n\n## Evidence\n\nFrom actual session (2025-11-23):\n- Commit 8bc8611 in cino/beads shows: `+640, -14 lines` after bd sync\n- No \"Auto-import complete\" message in output\n- Database had 686 issues, JSONL was pulled with 56 issues\n- Sync exported DB β†’ JSONL instead of importing JSONL β†’ DB\n\n## Impact\n\n**Critical:** This breaks multi-device sync and causes:\n- Lost work (cleanup operations undone)\n- Data resurrection (deleted issues come back)\n- Confusing merge conflicts\n- User trust issues (\"Why does sync keep bringing back deleted issues?\")\n\n## Proposed Solutions\n\n### Option 1: Remove mtime fast-path (safest)\nAlways compute and compare hashes. Eliminates false negatives from mtime issues.\n\n**Pros:** Guaranteed correctness\n**Cons:** Slightly slower (hash computation on every sync)\n\n### Option 2: Fix mtime comparison logic\nInvestigate why mtime check fails and fix it properly.\n\n**Areas to check:**\n- Does git preserve mtime on checkout? (may vary by git version/config)\n- Is last_import_mtime updated correctly after all operations?\n- Race condition between git pull and mtime check?\n\n### Option 3: Add hash-based validation\nKeep mtime fast-path but add hash validation as backup:\n- If mtime unchanged, still spot-check hash occasionally (e.g., 10% of the time)\n- Log warnings when mtime and hash disagree\n- This would catch the bug while maintaining performance\n\n### Option 4: Add `--force-import` flag to bd sync\nShort-term workaround: Allow users to force import even if hasJSONLChanged() returns false.\n\n## Workaround\n\nUntil fixed, after `git pull`:\n```bash\nbd import --force # Force import the pulled JSONL\nbd sync # Then sync normally\n```\n\nOr manually run bd cleanup in affected repos.\n\n## Files\n\n- cmd/bd/integrity.go:101-152 (hasJSONLChanged function)\n- cmd/bd/sync.go:130-143 (auto-import logic)\n- cmd/bd/autoflush.go:698 (export updates last_import_hash)\n\n## Related Issues\n\n- bd-77gm: Import reports misleading counts\n- bd-khnb: Content-based staleness detection (original implementation of hash checking)\n","notes":"## Fix Implemented (Option 1)\n\n**Root Cause Confirmed:**\nGit does NOT update mtime when checking out files. Testing confirmed that after `git checkout HEAD~1`, the file mtime remains unchanged even though content differs.\n\n**Solution:**\nRemoved the mtime-based fast-path in `hasJSONLChanged()`. Now always computes content hash for comparison.\n\n**Changes Made:**\n1. **cmd/bd/integrity.go:107-116** - Removed mtime fast-path, always compute hash\n2. **cmd/bd/sync.go:752** - Removed mtime storage after import\n3. **cmd/bd/import.go:340** - Removed mtime storage after import\n4. **cmd/bd/daemon_sync.go:280-301** - Removed mtime storage and updated comments\n5. **cmd/bd/daemon_sync_test.go:479,607,628** - Removed mtime assertions from tests\n\n**Performance Impact:**\nMinimal. Hash computation takes ~10-50ms even for large databases, which is acceptable for sync operations.\n\n**Testing:**\n- All existing tests pass\n- Test \"mtime changed but content same - git operation scenario\" verifies the fix\n- Full test suite passes (cmd/bd and all internal packages)\n\n**Verification:**\nThe fix ensures that after `git pull` updates the JSONL:\n1. `hasJSONLChanged()` returns TRUE (content hash differs)\n2. Auto-import runs and updates database\n3. No data loss or resurrection of deleted issues","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-23T22:24:53.69901-08:00","updated_at":"2025-11-24T00:01:27.560055-08:00","closed_at":"2025-11-23T22:50:12.611126-08:00","source_repo":"."} -{"id":"bd-vfe","content_hash":"c58e7567c9e5d4b789a593e7b5ca40ab109e9dc7b98275262aae09bd1b65650f","title":"Apply wrapDBError to config.go","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-24T00:53:12.771275-08:00","updated_at":"2025-11-24T00:54:15.676618-08:00","closed_at":"2025-11-24T00:54:15.676618-08:00","source_repo":"."} -{"id":"bd-w8h","content_hash":"502d4b23c0fdd843d186445dfd0480a15aa451f1b39c640f0e1f3cb67503ed3c","title":"Apply wrapDBError to remaining storage files","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-24T00:53:15.498428-08:00","updated_at":"2025-11-24T00:56:47.434071-08:00","closed_at":"2025-11-24T00:56:47.434071-08:00","source_repo":"."} -{"id":"bd-wcl","content_hash":"c08d62ce3627a49126c63f6a630a08c1666e5b1b8d9148ae0c72d7d06611b2a9","title":"Document CLI + hooks as recommended approach over MCP","description":"Update documentation to position CLI + bd prime hooks as the primary recommended approach over MCP server, explaining why minimizing context matters even with large context windows (compute cost, energy, environment, latency).","design":"## Goals\n\nPosition CLI + `bd prime` hooks as the **primary recommended approach** for AI agent integration, with MCP server as a legacy/fallback option.\n\nExplore **hybrid mode** - if certain commands benefit from MCP (UX/DX advantages like no approval prompts), minimize MCP surface area to only those commands.\n\nThis requires production validation first - only update docs after CLI mode is proven reliable.\n\n## Why Minimize Context (Even With Large Windows)\n\n**Context window size β‰  free resource**\n\nLarge context windows (100k+, 200k+) don't mean we should fill them wastefully. Every token in context has real costs:\n\n### Compute Cost\n- **Processing overhead**: Larger context = more GPU/CPU cycles per request\n- **Memory usage**: 10.5k tokens consume significant RAM/VRAM\n- **Scaling impact**: Multiplied across all users, all sessions, all requests\n\n### Energy \u0026 Environment\n- **Electricity**: More compute = more power consumption\n- **Carbon footprint**: Data centers running on grid power (not all renewable)\n- **Sustainability**: Unnecessary token usage contributes to AI's environmental impact\n- **Responsibility**: Efficient tools are better for the planet\n\n### User Experience\n- **Latency**: Larger context = slower processing (noticeable at 10k+ tokens)\n- **Cost**: Many AI services charge per token (input + output)\n- **Rate limits**: Context counts against API quotas\n\n### Engineering Excellence\n- **Efficiency**: Good engineering minimizes resource usage\n- **Scalability**: Efficient tools scale better\n- **Best practices**: Optimize for the common case\n\n**The comparison:**\n\n| Approach | Standing Context | Efficiency | User Cost | Environmental Impact |\n|----------|-----------------|------------|-----------|---------------------|\n| **CLI + hooks** | ~1-2k tokens | 80-90% reduction | Lower | Sustainable βœ“ |\n| **MCP minimal** | ~2-4k tokens | 60-80% reduction | Medium | Better βœ“ |\n| **MCP full** | ~10.5k tokens | Baseline | Higher | Wasteful βœ— |\n\n**Functional equivalence:**\n- CLI via Bash tool works just as well as MCP native calls\n- Same features, same reliability\n- No downside except initial learning curve\n\n## Hybrid Mode: Minimal MCP Surface Area\n\n**Philosophy:** MCP server doesn't have to expose everything.\n\nIf certain commands have legitimate UX/DX benefits from MCP (e.g., no approval prompts, cleaner syntax), we can expose ONLY those commands via MCP while using CLI for everything else.\n\n### Potential MCP-Only Candidates (TBD)\n\nCommands that might benefit from MCP native calls:\n- `ready` - frequently checked, no side effects, approval prompt annoying\n- `show` - read-only, frequently used, approval slows workflow\n- `list` - read-only, no risk, approval adds friction\n\nCommands that work fine via CLI:\n- `create` - complex parameters, benefits from explicit confirmation\n- `update` - state changes, good to see command explicitly\n- `close` - state changes, explicit is better\n- `dep` - relationships, good to see what's being linked\n- `sync` - git operations, definitely want visibility\n\n### Token Budget\n\n**Full MCP** (current): ~10.5k tokens\n- All ~20+ bd commands exposed\n- All parameter schemas\n- All descriptions and examples\n\n**Minimal MCP** (proposed): ~2-4k tokens\n- 3-5 high-frequency read commands only\n- Simplified schemas\n- Minimal descriptions\n- Everything else via CLI\n\n**Pure CLI**: ~1-2k tokens (only on SessionStart/PreCompact)\n- No MCP tools loaded\n- All commands via Bash\n\n### Investigation Required\n\nBefore implementing hybrid mode, validate:\n\n1. **Do MCP calls actually skip approval prompts?**\n - Test with Claude Code approval settings\n - Compare MCP tool calls vs Bash tool calls\n - Measure UX difference in real usage\n\n2. **What's the actual token breakdown per command?**\n - Measure individual command schemas\n - Calculate token savings for minimal vs full\n\n3. **Is approval prompt the only benefit?**\n - Are there other UX advantages to MCP?\n - Does native syntax actually improve experience?\n - User testing with both approaches\n\n4. **Can we dynamically load MCP tools?**\n - Only load MCP when certain commands needed?\n - Hot-swap between CLI and MCP?\n - Probably not - MCP loads at startup\n\n### Hybrid Mode Documentation (If Validated)\n\n```markdown\n## Choosing Your Integration Approach\n\nBeads supports three AI agent integration approaches:\n\n### CLI + Hooks (Recommended - Most Efficient)\n\n**Setup:** `bd setup claude`\n\nUses Claude Code hooks to inject workflow context via `bd prime` command. Agent uses bd via Bash tool.\n\n**Tokens:** ~1-2k (on SessionStart/PreCompact only)\n\n**Pros:**\n- Maximum efficiency (80-90% reduction vs full MCP)\n- Lowest compute/energy usage\n- Same functionality as MCP\n\n**Cons:**\n- Bash tool calls may require approval prompts\n- Slightly more verbose in conversation\n\n### Minimal MCP + Hooks (Balanced)\n\n**Setup:** Install minimal MCP server (read-only commands) + `bd setup claude`\n\nExposes only high-frequency read commands via MCP (ready, show, list). Everything else via CLI.\n\n**Tokens:** ~2-4k MCP + ~1-2k hooks\n\n**Pros:**\n- 60-80% reduction vs full MCP\n- No approval prompts for common queries\n- Cleaner syntax for frequent operations\n- Still efficient\n\n**Cons:**\n- Requires MCP server (additional setup)\n- Mixed interface (some MCP, some CLI)\n\n### Full MCP + Hooks (Legacy)\n\n**Setup:** Install full MCP server + `bd setup claude`\n\n**Tokens:** ~10.5k MCP + hooks\n\n**Pros:**\n- All commands as native function calls\n- Consistent interface\n\n**Cons:**\n- Highest token usage (worst for compute/energy/cost)\n- Slowest processing\n- Less sustainable\n\n### Recommendation\n\n1. **Start with CLI + hooks** - most efficient, works great\n2. **Try minimal MCP** if approval prompts become annoying\n3. **Avoid full MCP** - wasteful with no significant benefit\n```\n\n## Production Validation Checklist\n\nBefore making these documentation changes, validate CLI approach works reliably:\n\n### Phase 1: Pure CLI Validation\n- [ ] `bd prime` implemented and tested\n- [ ] Hooks installed and working in Claude Code\n- [ ] Real-world usage by at least 2-3 developers for 1+ weeks\n- [ ] No significant usability issues reported\n- [ ] Agent successfully uses bd via Bash tool\n- [ ] Document which commands (if any) have approval prompt issues\n\n### Phase 2: Hybrid Mode Investigation (Optional)\n- [ ] Test if MCP calls skip approval prompts vs Bash calls\n- [ ] Measure token cost per MCP command\n- [ ] Identify minimal set of commands worth exposing via MCP\n- [ ] Build minimal MCP server variant\n- [ ] Validate token savings (should be 60-80% vs full MCP)\n- [ ] User testing shows actual UX improvement\n\n### Phase 3: Documentation Update\n- [ ] Update based on validation results\n- [ ] Include measured token counts (not estimates)\n- [ ] Provide clear migration paths\n- [ ] Update `bd doctor` recommendations\n\n## Migration Guide (Optional)\n\nFor users currently using MCP:\n\n```markdown\n### Migrating from Full MCP to CLI + Hooks\n\nAlready using full MCP server? You can switch to the more efficient CLI approach:\n\n1. Install hooks: `bd setup claude`\n2. Test it works (hooks inject context, agent uses Bash tool)\n3. Remove MCP server from `~/.claude/settings.json`\n4. Restart Claude Code\n\nYou'll get the same functionality with 80-90% less token usage.\n\n### Migrating to Minimal MCP (If Available)\n\nIf you find approval prompts annoying for certain commands:\n\n1. Replace full MCP with minimal MCP in `~/.claude/settings.json`\n2. Restart Claude Code\n3. Verify high-frequency commands (ready, show, list) work via MCP\n4. Everything else automatically uses CLI\n\nYou'll get 60-80% token reduction vs full MCP while keeping the UX benefits.\n```\n\n## Files to Update\n\n- `README.md` - Add recommendation in AI Integration section\n- `AGENTS.md` - Add \"Choosing Your Integration Approach\" section early\n- `QUICKSTART.md` - Update AI integration section\n- `docs/` - Any other AI integration docs if they exist\n- `mcp-server/` - Create minimal variant if hybrid validated\n\n## Future: Update `bd init`\n\nOnce validated, update `bd init` to:\n- Default to recommending `bd setup claude` (hooks only)\n- Mention minimal MCP as option for UX improvement\n- Detect existing full MCP and suggest migration\n- Provide token usage estimates for each approach\n\n## MCP Server Architecture Note\n\n**Key insight:** MCP server doesn't have to expose all bd functionality.\n\nCurrent design exposes ~20+ commands (all bd subcommands). This is over-engineered.\n\n**Better design:**\n- **Minimal MCP**: 3-5 read-only commands (~2-4k tokens)\n- **CLI**: Everything else via Bash tool\n- **Hooks**: Context injection via `bd prime`\n\nThis achieves best of both worlds:\n- Low token usage (efficient)\n- No approval prompts for common queries (UX)\n- Explicit visibility for state changes (safety)\n\nIf validation shows NO meaningful benefit to MCP (even minimal), skip hybrid mode entirely and recommend pure CLI.","acceptance_criteria":"- Documentation explains CLI + hooks as recommended approach\n- Explains why context size matters (compute/energy/cost/latency)\n- Token comparison table shows 80-90% reduction\n- Migration guide for existing MCP users\n- Only deployed AFTER production validation\n- Clear that both approaches are supported","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-12T00:15:25.923025-08:00","updated_at":"2025-11-12T00:18:16.786857-08:00","source_repo":"."} -{"id":"bd-wsh0","content_hash":"f543631aee35732ef32f9a0e7ed3c59f792cd2d1f6b29889b755ca6ad0056b95","title":"String-based error detection for deregistered agents is fragile","description":"In app.py:4192-4194, the code checks 'if \"deregistered\" in str(exc).lower()' to detect deregistered agent errors. This relies on error message text which is fragile. Recommendation: Create custom AgentDeregisteredException that inherits from NoResultFound, or add structured attribute to exception.","status":"open","priority":2,"issue_type":"bug","created_at":"2025-11-24T17:14:01.006264-08:00","updated_at":"2025-11-24T17:14:01.006264-08:00","source_repo":".","labels":["mcp-agent-mail","tech-debt"]} -{"id":"bd-wv9l","content_hash":"20e7b00ef310100af01a9bb27a074dd3faa7183ee48d04916d342c7e49476464","title":"Code Review Sweep: thorough","description":"Perform thorough code review sweep based on accumulated activity.\n\n**AI Reasoning:**\nSignificant code activity with 7608 lines added and 120 files changed indicates substantial modifications. Multiple high-churn areas (cmd/bd, internal/rpc) suggest potential for subtle issues and emerging patterns that warrant review.\n\n**Scope:** thorough\n**Target Areas:** cmd/bd, internal/rpc, .beads\n**Estimated Files:** 12\n**Estimated Cost:** $5\n\n**Task:**\nReview files for non-obvious issues that agents miss during focused work:\n- Inefficiencies (algorithmic, resource usage)\n- Subtle bugs (race conditions, off-by-one, copy-paste)\n- Poor patterns (coupling, complexity, duplication)\n- Missing best practices (error handling, docs, tests)\n- Unnamed anti-patterns\n\nFile discovered issues with detailed reasoning and suggestions.","acceptance_criteria":"- Reviewed target files for code quality issues\n- Filed discovered issues with detailed reasoning\n- Completed sweep according to scope criteria","status":"open","priority":1,"issue_type":"task","created_at":"2025-11-21T23:23:16.056392-08:00","updated_at":"2025-11-21T23:23:16.056392-08:00","source_repo":".","labels":["code-review-sweep","review-area:.beads","review-area:cmd/bd","review-area:internal/rpc"]} -{"id":"bd-xswj","content_hash":"ac4b323c813a7ba61f1ce8f6d0629fc5e1ab9b398ba438d80a574a38619bae12","title":"Consider adding purge_data option for GDPR-style deletion","description":"delete_inbox=False is a safe default, but leaves orphaned data. Consider adding purge_data: bool = False parameter that deletes all associated data (inbox, sent messages, etc.) for GDPR-style 'right to be forgotten' scenarios.","status":"open","priority":3,"issue_type":"feature","created_at":"2025-11-24T17:14:19.067619-08:00","updated_at":"2025-11-24T17:14:19.067619-08:00","source_repo":".","labels":["enhancement","mcp-agent-mail","privacy"]} -{"id":"bd-ybv5","content_hash":"52f6d2143a3e9d63937e7dee2cfb4055740132d3c0831c3e948210179336820f","title":"Refactor AGENTS.md to use external references","description":"Suggestion to use external references (e.g., \"ALWAYS REFER TO ./beads/prompt.md\") instead of including all instructions directly within AGENTS.md.\nReasons:\n1. Agents can follow external references.\n2. Prevents context pollution/stuffing in AGENTS.md as more tools append instructions.\n","status":"open","priority":3,"issue_type":"task","created_at":"2025-11-20T18:55:53.259144-05:00","updated_at":"2025-11-20T18:55:53.259144-05:00","source_repo":"."} -{"id":"bd-ye0d","content_hash":"40962ef4e144b58167a07ae13458b40cedff3f3549fccab3a172ca908cd754bc","title":"troubleshoot GH#278 daemon exits every few secs","description":"","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-13T06:27:23.39509215-07:00","updated_at":"2025-11-13T06:27:23.39509215-07:00","source_repo":"."} -{"id":"bd-ykd9","content_hash":"f1446ecf58b117dae936c32d30370b5a42a2c081ffae6ce749d87300a893fa72","title":"Add bd doctor --fix flag to automatically repair issues","description":"Implement a --fix flag for bd doctor that can automatically repair detected issues.\n\nRequirements:\n- Add --fix flag to bd doctor command\n- Show all fixable issues and prompt for confirmation before applying fixes\n- Organize fix implementations under doctor/fix/\u003ctype_of_fix\u003e.go\n- Each fix type should have its own file (e.g., doctor/fix/hooks.go, doctor/fix/sync.go)\n- Display what will be fixed and ask user to confirm (Y/n) before proceeding\n- Support fixing issues like:\n - Missing or broken git hooks\n - Sync problems with remote\n - File permission issues\n - Any other auto-repairable issues doctor detects\n\nImplementation notes:\n- Maintain separation between detection (existing doctor code) and repair (new fix code)\n- Each fix should be idempotent and safe to run multiple times\n- Provide clear output about what was fixed\n- Log any fixes that fail with actionable error messages","status":"open","priority":2,"issue_type":"feature","created_at":"2025-11-14T18:17:48.411264-08:00","updated_at":"2025-11-14T18:17:58.88609-08:00","source_repo":"."} -{"id":"bd-z0yn","content_hash":"d642aa388f336290811fa0a5f8f7a546f676ca9727f0d21072300219bccf037b","title":"Channel isolation test - beads","description":"","notes":"Resetting stale in_progress status from old executor run (13 days old)","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-08T04:21:17.327983-08:00","updated_at":"2025-11-21T10:47:56.112316-05:00","source_repo":"."} -{"id":"bd-z3s3","content_hash":"1473768355b3e24e3b5cfcdd99ac88fabaee7440f9b3ffd2fa4b038bc01ab499","title":"Create deployment scripts for GCP","description":"Automated provisioning scripts for GCP Compute Engine deployment.\n\nAcceptance Criteria:\n- Terraform/gcloud scripts\n- Static IP allocation\n- Firewall rules\n- NGINX reverse proxy config\n- TLS setup (Let's Encrypt)\n- Systemd service file\n\nFile: deployment/agent-mail/gcp/","status":"closed","priority":3,"issue_type":"task","created_at":"2025-11-07T22:43:43.294839-08:00","updated_at":"2025-11-24T00:01:27.56061-08:00","closed_at":"2025-11-23T23:38:58.545006-08:00","source_repo":".","dependencies":[{"issue_id":"bd-z3s3","depends_on_id":"bd-9li4","type":"blocks","created_at":"2025-11-07T23:04:27.982336-08:00","created_by":"daemon"}]} -{"id":"bd-z8z","content_hash":"166abdf2f3f279b022b8a65362c85f467e9c8a6a286cea1b6f99eb9c91de7386","title":"Apply wrapDBError to queries.go","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-24T00:53:14.298177-08:00","updated_at":"2025-11-24T00:55:37.364663-08:00","closed_at":"2025-11-24T00:55:37.364663-08:00","source_repo":"."} -{"id":"bd-zj8e","content_hash":"655c761aaf4d5b0c9edfba7d96d23e608de94760148715667738d35c2033e110","title":"Performance Testing Documentation","description":"Create docs/performance-testing.md documenting the performance testing framework.\n\nSections:\n1. Overview - What the framework does, goals\n2. Running Benchmarks\n - make bench command\n - Running specific benchmarks\n - Interpreting output (ns/op, allocs/op)\n3. Profiling and Analysis\n - Viewing CPU profiles with pprof\n - Reading flamegraphs\n - Memory profiling\n - Finding hotspots\n4. User Diagnostics\n - bd doctor --perf usage\n - Sharing profiles with bug reports\n - Understanding the report output\n5. Comparing Performance\n - Using benchstat for before/after comparisons\n - Detecting regressions\n6. Tips for Optimization\n - Common patterns\n - When to profile vs benchmark\n\nStyle:\n- Concise, practical examples\n- Screenshots/examples of pprof output\n- Clear command-line examples\n- Focus on workflow, not theory","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-13T22:23:38.99897-08:00","updated_at":"2025-11-13T22:23:38.99897-08:00","source_repo":"."} -{"id":"bd-zwtq","content_hash":"59236b5c5c330b4cc7cc1a7ed02ddfbec0a0d19b85cf81af58e2e8eec8b5836e","title":"Run bd doctor at end of bd init to verify setup","description":"Run bd doctor diagnostics at end of bd init (after line 398 in init.go). If issues found, warn user immediately: '⚠ Setup incomplete. Run bd doctor --fix to complete setup.' Catches configuration problems before user encounters them in normal workflow.","status":"open","priority":1,"issue_type":"feature","created_at":"2025-11-21T23:16:09.596778-08:00","updated_at":"2025-11-21T23:16:27.781976-08:00","source_repo":".","dependencies":[{"issue_id":"bd-zwtq","depends_on_id":"bd-tbz3","type":"parent-child","created_at":"2025-11-21T23:16:09.597617-08:00","created_by":"daemon"}]} +{"id":"bd-mnap","title":"Investigate performance issues in VS Code Copilot (Windows)","description":"Beads unusable in Windows 11 VS Code Copilot chat with Sonnet 4.5.\nSummary event happens every 3-4 turns, taking 3 minutes.\nCopilot summarizes after ~125k tokens despite model supporting 1M.\nLarge context size of beads might be triggering aggressive summarization.\nNeed workaround or optimization for context size.\n","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-20T18:56:30.124918-05:00","updated_at":"2025-11-20T18:56:30.124918-05:00"} +{"id":"bd-tne","title":"Add Claude setup tip with dynamic priority","description":"Add a predefined tip that suggests running `bd setup claude` when Claude Code is detected but not configured. This tip should have higher priority (shown more frequently) until the setup is complete.","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-11T23:29:29.871324-08:00","updated_at":"2025-11-11T23:50:29.756454-08:00","dependencies":[{"issue_id":"bd-tne","depends_on_id":"bd-d4i","type":"blocks","created_at":"2025-11-11T23:29:29.872081-08:00","created_by":"daemon"}]} +{"id":"bd-49kw","title":"Workaround for FastMCP outputSchema bug in Claude Code","description":"The beads MCP server (v0.23.1) successfully connects to Claude Code, but all tools fail to load with a schema validation error due to a bug in FastMCP 2.13.1.\n\nError: \"Invalid literal value, expected \\\"object\\\"\" in outputSchema.\n\nRoot Cause: FastMCP generates outputSchema with $ref at root level without \"type\": \"object\" for self-referential models (Issue).\n\nWorkaround: Use slash commands (/beads:ready) or wait for FastMCP fix.\n","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-20T18:55:39.041831-05:00","updated_at":"2025-11-24T00:01:27.554672-08:00","closed_at":"2025-11-23T23:22:49.789004-08:00"} +{"id":"bd-19er","title":"Create backup and restore procedures","description":"Disaster recovery procedures for Agent Mail data.\n\nAcceptance Criteria:\n- Automated daily snapshots (GCP persistent disk)\n- SQLite backup script\n- Git repository backup\n- Restore procedure documentation\n- Test restore from backup\n\nFile: deployment/agent-mail/backup.sh","status":"closed","priority":3,"issue_type":"task","created_at":"2025-11-07T22:43:43.417403-08:00","updated_at":"2025-11-24T00:01:27.553156-08:00","closed_at":"2025-11-23T23:39:00.061047-08:00","dependencies":[{"issue_id":"bd-19er","depends_on_id":"bd-z3s3","type":"blocks","created_at":"2025-11-07T23:04:28.122501-08:00","created_by":"daemon"}]} +{"id":"bd-e166","title":"Improve timestamp comparison readability in import","description":"The timestamp comparison logic uses double-negative which can be confusing:\n\nCurrent code:\nif !incoming.UpdatedAt.After(existing.UpdatedAt) {\n // skip update\n}\n\nMore readable:\nif incoming.UpdatedAt.After(existing.UpdatedAt) {\n // perform update\n} else {\n // skip (local is newer)\n}\n\nThis is a minor refactor for code clarity.\n\nRelated: bd-1022\nFiles: internal/importer/importer.go:411, 488","status":"open","priority":4,"issue_type":"chore","created_at":"2025-11-02T15:32:12.27108-08:00","updated_at":"2025-11-02T15:32:12.27108-08:00"} +{"id":"bd-736d","title":"Refactor path canonicalization into helper function","description":"The path canonicalization logic (filepath.Abs + EvalSymlinks) is duplicated in 3 places:\n- beads.go:131-137 (BEADS_DIR handling)\n- cmd/bd/main.go:446-451 (--no-db cleanup)\n- cmd/bd/nodb.go:26-31 (--no-db initialization)\n\nRefactoring suggestion:\nExtract to a helper function like:\n func canonicalizePath(path string) string\n\nThis would:\n- Reduce code duplication\n- Make the logic easier to maintain\n- Ensure consistent behavior across all path handling\n\nRelated to bd-e16b implementation.","status":"open","priority":3,"issue_type":"chore","created_at":"2025-11-02T18:33:47.727443-08:00","updated_at":"2025-11-02T18:33:47.727443-08:00"} +{"id":"bd-9li4","title":"Create Docker image for Agent Mail","description":"Containerize Agent Mail server for easy deployment.\n\nAcceptance Criteria:\n- Dockerfile with Python 3.14\n- Health check endpoint\n- Volume mount for storage\n- Environment variable configuration\n- Multi-arch builds (amd64, arm64)\n\nFile: deployment/agent-mail/Dockerfile","status":"open","priority":3,"issue_type":"task","created_at":"2025-11-07T22:43:43.231964-08:00","updated_at":"2025-11-07T22:43:43.231964-08:00"} +{"id":"bd-b0c8","title":"Research hooks/skills approach for enforcing issue descriptions","description":"## Solution: Hooks/Skills (mentioned in discussion)\n\nResearch the hooks/skills system mentioned by riordanpawley in discussion #366:\nhttps://www.reddit.com/r/ClaudeAI/s/wrn2tjkMHX\n\n## Investigation Tasks\n\n1. Review the Reddit post to understand the approach\n2. Determine if beads hooks can enforce validation\n3. Check if Claude Code skills/hooks can intercept MCP calls\n4. Assess feasibility and user burden\n\n## Notes\n\nFrom discussion #366:\n\u003e I'm using a skills/hooks system to get Claude to do that kind of thing right similar to https://www.reddit.com/r/ClaudeAI/s/wrn2tjkMHX\n\nThis might be a client-side solution rather than server-side.\n\n## Deliverable\n\nDocument findings in issue notes, with recommendation on whether to pursue this approach.","status":"closed","priority":3,"issue_type":"task","created_at":"2025-11-23T14:01:01.57079-08:00","updated_at":"2025-11-24T01:25:22.237007-08:00","closed_at":"2025-11-24T01:15:03.961995-08:00"} +{"id":"bd-hdt","title":"Implement auto-merge functionality in duplicates command","description":"The duplicates.go file has a TODO at line 95 to implement the performMerge function for automatic duplicate merging. Currently it just prints a warning message. This would automate the merge process instead of just suggesting commands.","status":"open","priority":2,"issue_type":"feature","created_at":"2025-11-21T18:55:02.828619-05:00","updated_at":"2025-11-21T18:55:02.828619-05:00"} +{"id":"bd-ye0d","title":"troubleshoot GH#278 daemon exits every few secs","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-13T06:27:23.39509215-07:00","updated_at":"2025-11-13T06:27:23.39509215-07:00"} +{"id":"bd-5b6e","title":"Add tests for helper functions (GetDirtyIssueHash, GetAllDependencyRecords, export hashes)","description":"Several utility functions have 0% coverage:\n- GetDirtyIssueHash (dirty.go)\n- GetAllDependencyRecords (dependencies.go)\n- GetExportHash, SetExportHash, ClearAllExportHashes (hash.go)\n\nThese are lower priority but should have basic coverage.","status":"closed","priority":4,"issue_type":"task","created_at":"2025-11-01T22:40:58.989976-07:00","updated_at":"2025-11-24T00:01:27.555906-08:00","closed_at":"2025-11-23T23:39:01.556131-08:00"} +{"id":"bd-s0z","title":"Consider extracting error handling helpers","description":"Evaluate creating FatalError() and WarnError() helpers as suggested in ERROR_HANDLING.md to reduce boilerplate and enforce consistency. Prototype in a few files first to validate the approach.","status":"open","priority":4,"issue_type":"task","created_at":"2025-11-24T00:28:57.248959-08:00","updated_at":"2025-11-24T00:28:57.248959-08:00","dependencies":[{"issue_id":"bd-s0z","depends_on_id":"bd-1qwo","type":"blocks","created_at":"2025-11-24T00:28:57.249945-08:00","created_by":"daemon"}]} +{"id":"bd-3gc","title":"Audit remaining cmd/bd files for error handling consistency","description":"Extend ERROR_HANDLING_AUDIT.md to cover: daemon_sync.go, update.go, list.go, show.go, close.go, reopen.go, dep.go, label.go, comments.go, delete.go, compact.go, config.go, validate.go and other high-usage command files","status":"open","priority":3,"issue_type":"task","created_at":"2025-11-24T00:28:55.890991-08:00","updated_at":"2025-11-24T00:28:55.890991-08:00","dependencies":[{"issue_id":"bd-3gc","depends_on_id":"bd-1qwo","type":"blocks","created_at":"2025-11-24T00:28:55.891827-08:00","created_by":"daemon"}]} +{"id":"bd-wcl","title":"Document CLI + hooks as recommended approach over MCP","description":"Update documentation to position CLI + bd prime hooks as the primary recommended approach over MCP server, explaining why minimizing context matters even with large context windows (compute cost, energy, environment, latency).","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-12T00:15:25.923025-08:00","updated_at":"2025-11-12T00:18:16.786857-08:00"} +{"id":"bd-7kg","title":"Document error handling audit findings","description":"Comprehensive audit document showing all error handling inconsistencies found across cmd/bd/*.go files, with specific examples and recommended refactorings","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-24T00:26:59.45249-08:00","updated_at":"2025-11-24T00:28:51.788141-08:00","closed_at":"2025-11-24T00:28:51.788141-08:00"} +{"id":"bd-1pj6","title":"Proposal: Custom status states via config","description":"Proposal to add 'custom status states' via `bd config`.\nUsers could define an optional issue status enum (e.g., awaiting_review, review_in_progress) in the config.\nThis would enable multi-step pipelines to process issues where each step correlates to a specific status.\n\nExamples:\n- awaiting_verification\n- awaiting_docs\n- awaiting_testing\n","status":"open","priority":3,"issue_type":"feature","created_at":"2025-11-20T18:55:48.670499-05:00","updated_at":"2025-11-20T18:55:48.670499-05:00"} +{"id":"bd-c4rq","title":"Refactor: Move staleness check inside daemon branch","description":"## Problem\n\nCurrently ensureDatabaseFresh() is called before the daemon mode check, but it checks daemonClient != nil internally and returns early. This is redundant.\n\n**Location:** All read commands (list.go:196, show.go:27, ready.go:102, status.go:80, etc.)\n\n## Current Pattern\n\nCall happens before daemon check, function checks daemonClient internally.\n\n## Better Pattern\n\nMove staleness check to direct mode branch only, after daemon check.\n\n## Impact\nLow - minor performance improvement (avoids one function call per command in daemon mode)\n\n## Effort\nMedium - requires refactoring 8 command files\n\n## Priority\nLow - can defer to future cleanup PR","status":"open","priority":3,"issue_type":"chore","created_at":"2025-11-20T20:17:45.119583-05:00","updated_at":"2025-11-20T20:17:45.119583-05:00"} +{"id":"bd-98c4e1fa.1","title":"Update AGENTS.md with event-driven mode","description":"Document BEADS_DAEMON_MODE env var. Explain opt-in during Phase 1. Add troubleshooting for watcher failures.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-29T23:05:13.986452-07:00","updated_at":"2025-11-24T00:01:27.557167-08:00","closed_at":"2025-11-23T23:20:42.790628-08:00"} +{"id":"bd-77gm","title":"Import reports misleading '0 created, 0 updated' when actually importing all issues","description":"When running 'bd import' on a fresh database (no existing issues), the command reports 'Import complete: 0 created, 0 updated' even though it successfully imported all issues from the JSONL file.\n\n**Steps to reproduce:**\n1. Delete .beads/beads.db\n2. Run: bd import .beads/issues.jsonl\n3. Observe output: 'Import complete: 0 created, 0 updated'\n4. Run: bd list\n5. Confirm: All issues are actually present in the database\n\n**Expected behavior:**\nReport the actual number of issues imported, e.g., 'Import complete: 523 created, 0 updated'\n\n**Actual behavior:**\n'Import complete: 0 created, 0 updated' (misleading - makes user think import failed)\n\n**Impact:**\n- Users think import failed when it succeeded\n- Confusing during database sync operations (e.g., after git pull)\n- Makes debugging harder (can't tell if import actually worked)\n\n**Context:**\nDiscovered during VC session when syncing database after git pull. The misleading message caused confusion about whether the database was properly synced with the canonical JSONL file.","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-11-09T16:20:13.191156-08:00","updated_at":"2025-11-24T01:25:15.917451-08:00","closed_at":"2025-11-24T01:25:15.917451-08:00"} +{"id":"bd-gfu","title":"Add --start flag to bd daemon, show help with no args","description":"Currently `bd daemon` with no args immediately starts the daemon. This is inconsistent with other daemon management commands like `--stop`, `--status`, etc.\n\n## Proposed Changes\n\n1. Add `--start` flag to explicitly start daemon\n2. With no args or flags, print help text showing available options\n3. Maintain backward compatibility where feasible\n\n## Current Consumers\n\n- **Auto-start logic** (`daemon_autostart.go:106, 270`): Calls `bd daemon` programmatically - needs update\n- **MCP docs** (SETUP_DAEMON.md:111): Already incorrectly shows `bd daemon start` - will be fixed by this change\n- **Python daemon client**: Suggests `bd daemon` in error messages - needs doc update\n\n## Implementation Notes\n\n- Default behavior (no args/flags) should show help\n- `--start` should start daemon (current no-args behavior)\n- Auto-start code needs to pass `--start` flag explicitly\n- Update all documentation to use `bd daemon --start`\n- Ensure backward compat doesn't break existing workflows","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-11-23T23:54:49.906553-08:00","updated_at":"2025-11-24T00:03:15.231345-08:00","closed_at":"2025-11-24T00:03:15.231345-08:00"} +{"id":"bd-m7ge","title":"Add .beads/README.md during 'bd init' for project documentation and promotion","description":"When 'bd init' is run, automatically generate a .beads/README.md file that:\n\n1. Briefly explains what Beads is (AI-native issue tracking that lives in your repo)\n2. Links to the main repository: https://github.com/steveyegge/beads\n3. Provides a quick reference of essential commands:\n - bd create: Create new issues\n - bd list: View all issues\n - bd update: Modify issue status/details\n - bd show: View issue details\n - bd sync: Sync with git remote\n4. Highlights key benefits for AI coding agents and developers\n5. Encourages developers to try it out\n\nThe README should be enthusiastic and compelling to get open source contributors excited about using Beads for their AI-assisted development workflows.","status":"open","priority":2,"issue_type":"feature","created_at":"2025-11-16T22:32:50.478681-08:00","updated_at":"2025-11-16T22:32:58.492868-08:00"} +{"id":"bd-gqo","title":"Implement health checks in daemon event loop","description":"Add health checks to checkDaemonHealth() function in daemon_event_loop.go:170:\n- Database integrity check\n- Disk space check\n- Memory usage check\n\nCurrently it's just a no-op placeholder.","status":"open","priority":3,"issue_type":"feature","created_at":"2025-11-21T18:55:07.534304-05:00","updated_at":"2025-11-21T18:55:07.534304-05:00"} +{"id":"bd-bt6y","title":"Improve compact/daemon/merge documentation and UX","description":"Multiple documentation and UX issues encountered:\n1. \"bd compact --analyze\" fails with misleading \"requires SQLite storage\" error when daemon is running. Needs --no-daemon or better error.\n2. \"bd merge\" help text is outdated (refers to 3-way merge instead of issue merging).\n3. Daemon mode purpose isn't clear to local-only users.\n4. Compact/cleanup commands are hard to discover.\n\nProposed fixes:\n- Fix compact+daemon interaction or error message.\n- Update \"bd merge\" help text.\n- Add \"when to use daemon\" section to docs.\n- Add maintenance section to quickstart.\n","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-20T18:55:43.637047-05:00","updated_at":"2025-11-20T18:55:43.637047-05:00"} +{"id":"bd-9cdc","title":"Update docs for import bug fix","description":"Update AGENTS.md, README.md, TROUBLESHOOTING.md with import.orphan_handling config documentation. Document resurrection behavior, tombstones, config modes. Add troubleshooting section for import failures with deleted parents.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-04T12:32:30.770415-08:00","updated_at":"2025-11-24T01:20:17.196828-08:00","closed_at":"2025-11-24T01:20:17.196828-08:00"} +{"id":"bd-1a6j","title":"Test issue 2","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-07T19:07:12.24632-08:00","updated_at":"2025-11-24T00:01:27.553619-08:00","closed_at":"2025-11-23T23:35:04.068982-08:00"} +{"id":"bd-581b80b3","title":"bd find-duplicates - AI-powered duplicate detection","description":"Find semantically duplicate issues.\n\nApproaches:\n1. Mechanical: Exact title/description matching\n2. Embeddings: Cosine similarity (cheap, scalable)\n3. AI: LLM-based semantic comparison (expensive, accurate)\n\nUses embeddings by default for \u003e100 issues.\n\nFiles: cmd/bd/find_duplicates.go (new)","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-29T20:49:49.126801-07:00","updated_at":"2025-11-24T00:01:27.555093-08:00","closed_at":"2025-11-23T23:20:41.046092-08:00"} +{"id":"bd-379","title":"Implement `bd setup cursor` for Cursor IDE integration","description":"Create a `bd setup cursor` command that integrates Beads workflow into Cursor IDE via .cursorrules file. Unlike Claude Code (which has hooks), Cursor uses a static rules file to provide context to its AI.","status":"open","priority":3,"issue_type":"feature","created_at":"2025-11-11T23:32:22.170083-08:00","updated_at":"2025-11-11T23:32:22.170083-08:00"} +{"id":"bd-t3b","title":"Add test coverage for internal/config package","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-20T21:21:22.91657-05:00","updated_at":"2025-11-20T21:21:22.91657-05:00","dependencies":[{"issue_id":"bd-t3b","depends_on_id":"bd-ge7","type":"blocks","created_at":"2025-11-20T21:21:31.201036-05:00","created_by":"daemon"}]} +{"id":"bd-9lwr","title":"Document inconsistent error handling strategy across codebase","description":"**Scope:** Cross-cutting pattern across cmd/bd (create.go, init.go, sync.go, daemon_sync.go)\n\n**Issue:** Three different error handling patterns used inconsistently:\n\n**Pattern A: Exit immediately**\n```go\nif err := store.CreateIssue(...) {\n fmt.Fprintf(os.Stderr, \"Error: %v\\n\", err)\n os.Exit(1)\n}\n```\n\n**Pattern B: Warn and continue**\n```go\nif err := createConfigYaml(...) {\n fmt.Fprintf(os.Stderr, \"Warning: %v\\n\", err)\n // Non-fatal - continue anyway\n}\n```\n\n**Pattern C: Silent ignore**\n```go\n_ = store.Close()\n```\n\n**Impact:**\n- Makes error handling non-deterministic\n- Hard to test error paths\n- Inconsistent user experience\n\n**Task:**\n1. Document when each pattern should be used\n2. Add decision tree/flowchart to developer docs\n3. Consider creating error handling helpers to enforce consistency\n4. Audit codebase and refactor outliers","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-23T19:46:52.861673-08:00","updated_at":"2025-11-24T01:08:18.297709-08:00","closed_at":"2025-11-24T00:06:37.086708-08:00"} +{"id":"bd-v0y","title":"Critical: bd sync overwrites git-pulled JSONL instead of importing it","description":"## Problem\n\nWhen a user runs `git pull` (which updates .beads/beads.jsonl) followed by `bd sync`, the sync command fails to detect that the JSONL changed and exports the local database, **overwriting the pulled JSONL** instead of importing it first.\n\nThis causes cleaned-up issues (removed via `bd cleanup` in another repo) to be resurrected and pushed back to the remote.\n\n## Root Cause\n\n`hasJSONLChanged()` in cmd/bd/integrity.go incorrectly returns FALSE when it should return TRUE after git pull updates the JSONL file.\n\nThe function has two code paths:\n1. **Fast-path (line 128-129)**: If mtime unchanged, return false\n2. **Slow-path (line 135-151)**: Compute hash and compare\n\nSuspected issue: The mtime-based fast-path may incorrectly return false if:\n- Git preserves mtime when checking out files, OR\n- The mtime check logic has a race condition, OR\n- The stored last_import_mtime is stale/incorrect\n\n## Reproduction\n\n**Setup:**\n1. Repo A: Has 686 issues (including 630 closed)\n2. Run `bd cleanup -f` in Repo A (removes 630 closed issues β†’ 56 issues remain)\n3. Push to remote\n4. Repo B: Still has 686 issues in database\n\n**Trigger:**\n1. In Repo B: `git pull` (JSONL now has 56 issues)\n2. In Repo B: `bd sync`\n\n**Expected behavior:**\n- hasJSONLChanged() returns TRUE\n- Auto-imports 56-issue JSONL\n- Database updated to 56 issues\n- Exports (no-op, DB and JSONL match)\n- Pushes\n\n**Actual behavior:**\n- hasJSONLChanged() returns FALSE ❌\n- Skips auto-import\n- Exports 686 issues from DB to JSONL\n- Commits and pushes the 686-issue JSONL\n- **Undoes the cleanup from Repo A**\n\n## Evidence\n\nFrom actual session (2025-11-23):\n- Commit 8bc8611 in cino/beads shows: `+640, -14 lines` after bd sync\n- No \"Auto-import complete\" message in output\n- Database had 686 issues, JSONL was pulled with 56 issues\n- Sync exported DB β†’ JSONL instead of importing JSONL β†’ DB\n\n## Impact\n\n**Critical:** This breaks multi-device sync and causes:\n- Lost work (cleanup operations undone)\n- Data resurrection (deleted issues come back)\n- Confusing merge conflicts\n- User trust issues (\"Why does sync keep bringing back deleted issues?\")\n\n## Proposed Solutions\n\n### Option 1: Remove mtime fast-path (safest)\nAlways compute and compare hashes. Eliminates false negatives from mtime issues.\n\n**Pros:** Guaranteed correctness\n**Cons:** Slightly slower (hash computation on every sync)\n\n### Option 2: Fix mtime comparison logic\nInvestigate why mtime check fails and fix it properly.\n\n**Areas to check:**\n- Does git preserve mtime on checkout? (may vary by git version/config)\n- Is last_import_mtime updated correctly after all operations?\n- Race condition between git pull and mtime check?\n\n### Option 3: Add hash-based validation\nKeep mtime fast-path but add hash validation as backup:\n- If mtime unchanged, still spot-check hash occasionally (e.g., 10% of the time)\n- Log warnings when mtime and hash disagree\n- This would catch the bug while maintaining performance\n\n### Option 4: Add `--force-import` flag to bd sync\nShort-term workaround: Allow users to force import even if hasJSONLChanged() returns false.\n\n## Workaround\n\nUntil fixed, after `git pull`:\n```bash\nbd import --force # Force import the pulled JSONL\nbd sync # Then sync normally\n```\n\nOr manually run bd cleanup in affected repos.\n\n## Files\n\n- cmd/bd/integrity.go:101-152 (hasJSONLChanged function)\n- cmd/bd/sync.go:130-143 (auto-import logic)\n- cmd/bd/autoflush.go:698 (export updates last_import_hash)\n\n## Related Issues\n\n- bd-77gm: Import reports misleading counts\n- bd-khnb: Content-based staleness detection (original implementation of hash checking)\n","notes":"## Fix Implemented (Option 1)\n\n**Root Cause Confirmed:**\nGit does NOT update mtime when checking out files. Testing confirmed that after `git checkout HEAD~1`, the file mtime remains unchanged even though content differs.\n\n**Solution:**\nRemoved the mtime-based fast-path in `hasJSONLChanged()`. Now always computes content hash for comparison.\n\n**Changes Made:**\n1. **cmd/bd/integrity.go:107-116** - Removed mtime fast-path, always compute hash\n2. **cmd/bd/sync.go:752** - Removed mtime storage after import\n3. **cmd/bd/import.go:340** - Removed mtime storage after import\n4. **cmd/bd/daemon_sync.go:280-301** - Removed mtime storage and updated comments\n5. **cmd/bd/daemon_sync_test.go:479,607,628** - Removed mtime assertions from tests\n\n**Performance Impact:**\nMinimal. Hash computation takes ~10-50ms even for large databases, which is acceptable for sync operations.\n\n**Testing:**\n- All existing tests pass\n- Test \"mtime changed but content same - git operation scenario\" verifies the fix\n- Full test suite passes (cmd/bd and all internal packages)\n\n**Verification:**\nThe fix ensures that after `git pull` updates the JSONL:\n1. `hasJSONLChanged()` returns TRUE (content hash differs)\n2. Auto-import runs and updates database\n3. No data loss or resurrection of deleted issues","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-23T22:24:53.69901-08:00","updated_at":"2025-11-24T00:01:27.560055-08:00","closed_at":"2025-11-23T22:50:12.611126-08:00"} +{"id":"bd-m0w","title":"Add test coverage for internal/validation package","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-20T21:21:24.129559-05:00","updated_at":"2025-11-20T21:21:24.129559-05:00","dependencies":[{"issue_id":"bd-m0w","depends_on_id":"bd-ge7","type":"blocks","created_at":"2025-11-20T21:21:31.350477-05:00","created_by":"daemon"}]} +{"id":"bd-8wa","title":"Code Review Sweep: thorough","description":"Perform thorough code review sweep based on accumulated activity.\n\n**AI Reasoning:**\nSignificant code volume added (150,273 lines) across multiple critical areas, including cmd/bd, internal/storage/sqlite, and internal/rpc. High file change count (616) indicates substantial refactoring or new functionality. The metrics suggest potential for subtle architectural or implementation issues that warrant review.\n\n**Scope:** thorough\n**Target Areas:** cmd/bd, internal/storage/sqlite, internal/rpc\n**Estimated Files:** 12\n**Estimated Cost:** $5\n\n**Task:**\nReview files for non-obvious issues that agents miss during focused work:\n- Inefficiencies (algorithmic, resource usage)\n- Subtle bugs (race conditions, off-by-one, copy-paste)\n- Poor patterns (coupling, complexity, duplication)\n- Missing best practices (error handling, docs, tests)\n- Unnamed anti-patterns\n\nFile discovered issues with detailed reasoning and suggestions.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-21T10:25:37.081296-05:00","updated_at":"2025-11-24T01:08:18.29555-08:00","closed_at":"2025-11-23T23:24:19.821439-08:00"} +{"id":"bd-pp3","title":"Add metadata distinction guidelines to ERROR_HANDLING.md","description":"Update ERROR_HANDLING.md with clear guidelines distinguishing configuration metadata (Pattern A) from tracking metadata (Pattern B). Include examples from init.go and sync.go.","status":"closed","priority":3,"issue_type":"task","created_at":"2025-11-24T00:28:54.559851-08:00","updated_at":"2025-11-24T00:34:13.980602-08:00","closed_at":"2025-11-24T00:34:13.980602-08:00","dependencies":[{"issue_id":"bd-pp3","depends_on_id":"bd-1qwo","type":"blocks","created_at":"2025-11-24T00:28:54.560699-08:00","created_by":"daemon"}]} +{"id":"bd-ge7","title":"Improve Beads test coverage from 46% to 80%","status":"open","priority":1,"issue_type":"epic","created_at":"2025-11-20T21:21:03.700271-05:00","updated_at":"2025-11-20T21:21:03.700271-05:00"} +{"id":"bd-ola6","title":"Implement transaction retry logic for SQLITE_BUSY","description":"BEGIN IMMEDIATE fails immediately on SQLITE_BUSY instead of retrying with exponential backoff.\n\nLocation: internal/storage/sqlite/sqlite.go:223-225\n\nProblem:\n- Under concurrent write load, BEGIN IMMEDIATE can fail with SQLITE_BUSY\n- Current implementation fails immediately instead of retrying\n- Results in spurious failures under normal concurrent usage\n\nSolution: Implement exponential backoff retry:\n- Retry up to N times (e.g., 5)\n- Backoff: 10ms, 20ms, 40ms, 80ms, 160ms\n- Check for context cancellation between retries\n- Only retry on SQLITE_BUSY/database locked errors\n\nImpact: Spurious failures under concurrent write load\n\nEffort: 3 hours","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-11-16T14:51:31.247147-08:00","updated_at":"2025-11-24T01:17:35.455245-08:00","closed_at":"2025-11-24T01:08:59.54254-08:00"} +{"id":"bd-tru","title":"Update documentation for bd prime and Claude integration","description":"Update AGENTS.md, README.md, and QUICKSTART.md to document the new `bd prime` command, `bd setup claude` command, and tip system.","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-11T23:30:22.77349-08:00","updated_at":"2025-11-11T23:45:23.242658-08:00"} +{"id":"bd-p6vp","title":"Clarify .beads/.gitattributes handling in Protected Branches docs","description":"Protected Branches docs quick start leaves untracked `.beads` directory and `.gitattributes`.\nQuestion: Are these changes meant to be checked into the protected branch?\nNeed to clarify if these should be ignored or committed, or if the instructions are missing a step.\n","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-20T18:56:25.79407-05:00","updated_at":"2025-11-20T18:56:25.79407-05:00"} +{"id":"bd-bwk2","title":"Centralize error handling patterns in storage layer","description":"80+ instances of inconsistent error handling across sqlite.go with mix of %w, %v, and no wrapping.\n\nLocation: internal/storage/sqlite/sqlite.go (throughout)\n\nProblem:\n- Some use fmt.Errorf(\"op failed: %w\", err) - correct wrapping\n- Some use fmt.Errorf(\"op failed: %v\", err) - loses error chain\n- Some return err directly - no context\n- Hard to debug production issues\n- Can't distinguish error types\n\nSolution: Create internal/storage/sqlite/errors.go:\n- Define sentinel errors (ErrNotFound, ErrInvalidID, etc.)\n- Create wrapDBError(op string, err error) helper\n- Convert sql.ErrNoRows to ErrNotFound\n- Always wrap with operation context\n\nImpact: Lost error context; inconsistent messages; hard to debug\n\nEffort: 5-7 hours","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-16T14:51:54.974909-08:00","updated_at":"2025-11-24T01:08:18.298536-08:00","closed_at":"2025-11-24T00:57:47.359519-08:00","dependencies":[{"issue_id":"bd-bwk2","depends_on_id":"bd-vfe","type":"blocks","created_at":"2025-11-24T00:53:28.831021-08:00","created_by":"daemon"},{"issue_id":"bd-bwk2","depends_on_id":"bd-z8z","type":"blocks","created_at":"2025-11-24T00:53:28.897593-08:00","created_by":"daemon"},{"issue_id":"bd-bwk2","depends_on_id":"bd-w8h","type":"blocks","created_at":"2025-11-24T00:53:28.957487-08:00","created_by":"daemon"},{"issue_id":"bd-bwk2","depends_on_id":"bd-r71","type":"blocks","created_at":"2025-11-24T00:53:29.023262-08:00","created_by":"daemon"}]} +{"id":"bd-1qwo","title":"Audit and enforce consistent error handling patterns across codebase","description":"**Background:** Error handling patterns are now documented in docs/ERROR_HANDLING.md (bd-9lwr). We have three established patterns:\n- Pattern A: Exit immediately (os.Exit) for fatal errors\n- Pattern B: Warn and continue for optional operations\n- Pattern C: Silent ignore for cleanup/best-effort\n\n**Goal:** Systematically review all error handling in cmd/bd to ensure each instance uses the appropriate pattern according to the guidelines.\n\n**Scope:** \n- Review all files in cmd/bd/*.go\n- Focus on files with high usage: create.go, init.go, sync.go, daemon_sync.go, export.go, import.go\n- Identify outliers where similar operations use different patterns\n- Refactor to use consistent patterns\n\n**Acceptance Criteria:**\n- Similar operations (e.g., all metadata updates) use the same pattern\n- Critical operations always use Pattern A\n- Auxiliary operations use Pattern B or C appropriately\n- No mixed patterns for identical operation types\n\n**References:**\n- docs/ERROR_HANDLING.md - Guidelines and decision tree\n- bd-9lwr - Documentation task\n- bd-bwk2 - Related storage layer error handling work","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-23T21:53:25.687087-08:00","updated_at":"2025-11-24T01:08:18.294375-08:00","closed_at":"2025-11-24T00:28:58.356196-08:00"} +{"id":"bd-w8h","title":"Apply wrapDBError to remaining storage files","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-24T00:53:15.498428-08:00","updated_at":"2025-11-24T00:56:47.434071-08:00","closed_at":"2025-11-24T00:56:47.434071-08:00"} +{"id":"bd-4aao","title":"Fix failing integration tests in beads-mcp","description":"The `beads-mcp` test suite has failures in `tests/test_bd_client_integration.py` (assertion error in `test_init_creates_beads_directory`) and errors in `tests/test_worktree_separate_dbs.py` (setup failures finding database). These need to be investigated and fixed to ensure a reliable CI baseline.","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-20T18:53:28.4803-05:00","updated_at":"2025-11-20T18:53:28.4803-05:00"} +{"id":"bd-vfe","title":"Apply wrapDBError to config.go","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-24T00:53:12.771275-08:00","updated_at":"2025-11-24T00:54:15.676618-08:00","closed_at":"2025-11-24T00:54:15.676618-08:00"} +{"id":"bd-5ibn","title":"Latency test 1","notes":"Resetting stale in_progress status from old executor run (yesterday)","status":"closed","priority":3,"issue_type":"task","created_at":"2025-11-20T12:16:30.703754-05:00","updated_at":"2025-11-24T00:01:27.556337-08:00","closed_at":"2025-11-23T23:35:05.255017-08:00"} +{"id":"bd-e92","title":"Add test coverage for internal/autoimport package","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-20T21:21:22.338577-05:00","updated_at":"2025-11-20T21:21:22.338577-05:00","dependencies":[{"issue_id":"bd-e92","depends_on_id":"bd-ge7","type":"blocks","created_at":"2025-11-20T21:21:31.128625-05:00","created_by":"daemon"}]} +{"id":"bd-39o","title":"Rename last_import_hash metadata key to jsonl_content_hash","description":"The metadata key 'last_import_hash' is misleading because it's updated on both import AND export (sync.go:614, import.go:320).\n\nBetter names:\n- jsonl_content_hash (more accurate)\n- last_sync_hash (clearer intent)\n\nThis is a breaking change requiring migration of existing metadata values.","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-20T21:31:07.568739-05:00","updated_at":"2025-11-20T21:31:07.568739-05:00"} +{"id":"bd-e1085716","title":"bd validate - Comprehensive health check","description":"Run all validation checks in one command.\n\nChecks:\n- Duplicates\n- Orphaned dependencies\n- Test pollution\n- Git conflicts\n\nSupports --fix-all for auto-repair.\n\nDepends on bd-cbed9619.1, bd-0dcea000, bd-31aab707, bd-9826b69a.\n\nFiles: cmd/bd/validate.go (new)","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-29T23:05:13.980679-07:00","updated_at":"2025-11-24T00:01:27.558631-08:00","closed_at":"2025-11-23T23:20:39.694984-08:00"} +{"id":"bd-z3s3","title":"Create deployment scripts for GCP","description":"Automated provisioning scripts for GCP Compute Engine deployment.\n\nAcceptance Criteria:\n- Terraform/gcloud scripts\n- Static IP allocation\n- Firewall rules\n- NGINX reverse proxy config\n- TLS setup (Let's Encrypt)\n- Systemd service file\n\nFile: deployment/agent-mail/gcp/","status":"closed","priority":3,"issue_type":"task","created_at":"2025-11-07T22:43:43.294839-08:00","updated_at":"2025-11-24T00:01:27.56061-08:00","closed_at":"2025-11-23T23:38:58.545006-08:00","dependencies":[{"issue_id":"bd-z3s3","depends_on_id":"bd-9li4","type":"blocks","created_at":"2025-11-07T23:04:27.982336-08:00","created_by":"daemon"}]} +{"id":"bd-l954","title":"Performance Testing Framework","description":"Add comprehensive performance testing for beads focusing on optimization guidance and validating 10K+ database scale. Uses standard Go tooling, follows existing patterns, minimal complexity.\n\nComponents:\n- Benchmark suite for critical operations at 10K-20K scale\n- Fixture generator for realistic test data (epic hierarchies, cross-links)\n- User diagnostics via bd doctor --perf\n- Always-on profiling integration\n\nGoals:\n- Identify bottlenecks for optimization work\n- Validate performance at 10K+ issue scale\n- Enable users to collect diagnostics for bug reports\n- Support both SQLite and JSONL import paths","status":"open","priority":2,"issue_type":"epic","created_at":"2025-11-13T22:22:11.203467-08:00","updated_at":"2025-11-13T22:22:11.203467-08:00"} +{"id":"bd-9msn","title":"Add monitoring and alerting","description":"Observability for production Agent Mail server.\n\nAcceptance Criteria:\n- Health check endpoint (/health)\n- Prometheus metrics export\n- Grafana dashboard\n- Alerts for server downtime\n- Alerts for high error rate\n- Log aggregation config\n\nFile: deployment/agent-mail/monitoring/","status":"closed","priority":3,"issue_type":"task","created_at":"2025-11-07T22:43:43.354117-08:00","updated_at":"2025-11-24T00:01:27.557683-08:00","closed_at":"2025-11-23T23:38:56.81073-08:00","dependencies":[{"issue_id":"bd-9msn","depends_on_id":"bd-z3s3","type":"blocks","created_at":"2025-11-07T23:04:28.050074-08:00","created_by":"daemon"}]} +{"id":"bd-g9eu","title":"Investigate TestRoutingIntegration failure","description":"TestRoutingIntegration/maintainer_with_SSH_remote failed during pre-commit check with \"expected role maintainer, got contributor\".\nThis occurred while running `go test -short ./...` on darwin/arm64.\nThe failure appears unrelated to storage/sqlite changes.\nNeed to investigate if this is a flaky test or environmental issue.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-20T15:55:19.337094-08:00","updated_at":"2025-11-24T00:01:27.559057-08:00","closed_at":"2025-11-23T23:38:55.477369-08:00"} +{"id":"bd-t4u1","title":"False positive detection by Kaspersky Antivirus (Trojan)","description":"Kaspersky Antivirus falsely detects beads (bd.exe v0.23.1) as a Trojan (PDM:Trojan.Win32.Generic) and removes it.\nEvent: Malicious object detected\nComponent: System Watcher\nObject name: bd.exe\n","notes":"## Completed Actions\n\n1. **Root cause analysis**: Documented that this is a known false positive with Go binaries\n2. **Created comprehensive user documentation**: docs/ANTIVIRUS.md with:\n - Explanation of why Go binaries trigger false positives\n - Instructions for adding exclusions (Kaspersky, Windows Defender, etc.)\n - File integrity verification steps\n - False positive reporting procedures\n - FAQ section\n3. **Updated TROUBLESHOOTING.md**: Added quick reference section with link to detailed guide\n\n## Next Steps (Follow-up Issues)\n\nThe following actions require external processes or future releases:\n\n1. **Submit false positive to Kaspersky**: Need to access bd.exe v0.23.1 Windows binary and submit to https://opentip.kaspersky.com/\n2. **Code signing for Windows**: Requires purchasing certificate and configuring GoReleaser (medium-term)\n3. **Apply for Kaspersky whitelist**: Long-term relationship building with vendor\n\n## Current Status\n\nUsers affected by this issue now have:\n- Clear documentation explaining the false positive\n- Step-by-step instructions to work around it\n- Ways to verify file integrity\n- Process to report to their antivirus vendor\n\nBuild configuration already includes recommended optimizations (-s -w flags).","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-20T18:56:12.498187-05:00","updated_at":"2025-11-24T01:17:35.4543-08:00","closed_at":"2025-11-24T01:03:39.166915-08:00"} +{"id":"bd-d4i","title":"Create tip system infrastructure for contextual hints","description":"Implement a tip/hint system that shows helpful contextual messages after successful commands. This is different from the existing error-path \"Hint:\" messages - tips appear on success paths to educate users about features they might not know about.","status":"open","priority":2,"issue_type":"feature","created_at":"2025-11-11T23:29:15.693956-08:00","updated_at":"2025-11-11T23:49:50.812933-08:00"} +{"id":"bd-b2c","title":"Clarify metadata handling in init.go (config vs tracking)","description":"Review init.go:207-228 to ensure configuration metadata (issue_prefix, sync.branch) uses Pattern A consistently, while tracking metadata (bd_version, repo_id, etc.) uses Pattern B. Add comments explaining the distinction.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-24T00:28:53.199481-08:00","updated_at":"2025-11-24T00:33:24.654007-08:00","closed_at":"2025-11-24T00:33:24.654007-08:00","dependencies":[{"issue_id":"bd-b2c","depends_on_id":"bd-1qwo","type":"blocks","created_at":"2025-11-24T00:28:53.200299-08:00","created_by":"daemon"}]} +{"id":"bd-r46","title":"Support --reason flag in daemon mode for reopen command","description":"The reopen.go command has a TODO at line 61 to add reason as a comment once RPC supports AddComment. Currently --reason flag is ignored in daemon mode with a warning.","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-11-21T18:55:10.773626-05:00","updated_at":"2025-11-24T01:08:58.570375-08:00","closed_at":"2025-11-24T01:08:58.570375-08:00"} +{"id":"bd-ybv5","title":"Refactor AGENTS.md to use external references","description":"Suggestion to use external references (e.g., \"ALWAYS REFER TO ./beads/prompt.md\") instead of including all instructions directly within AGENTS.md.\nReasons:\n1. Agents can follow external references.\n2. Prevents context pollution/stuffing in AGENTS.md as more tools append instructions.\n","status":"open","priority":3,"issue_type":"task","created_at":"2025-11-20T18:55:53.259144-05:00","updated_at":"2025-11-20T18:55:53.259144-05:00"} +{"id":"bd-5a90","title":"Test parent issue","status":"closed","priority":3,"issue_type":"task","created_at":"2025-11-02T11:50:35.85367-08:00","updated_at":"2025-11-24T00:01:27.555487-08:00","closed_at":"2025-11-23T23:35:06.724333-08:00"} +{"id":"bd-afd","title":"bd doctor --fix should auto-fix metadata.json jsonl_export mismatch","description":"## Root Cause\n\nThe version tracking code (cmd/bd/version_tracking.go:33-38) auto-recreates metadata.json using DefaultConfig() if it doesn't exist. DefaultConfig() hardcodes jsonl_export to 'issues.jsonl', but many repos (including beads itself) use 'beads.jsonl'.\n\nWhen metadata.json goes missing (git clean, merge conflict, rebase, etc.), the next bd command recreates it with the wrong filename, causing a mismatch with the actual JSONL file.\n\n## Impact\n\nThis affects ANY user whose metadata.json gets deleted and who uses a non-default JSONL filename. Normal git operations can trigger this.\n\n## Fix Requirements\n\n1. bd doctor --fix should auto-detect and fix the mismatch (check which .jsonl file exists, update metadata.json)\n2. Version tracking should detect actual JSONL file instead of using hardcoded default\n3. DefaultConfig() should scan for existing .jsonl files before defaulting\n4. Daemon should auto-detect config changes without restart\n\n## Related Code\n\n- internal/configfile/configfile.go:18-23 (DefaultConfig hardcodes issues.jsonl)\n- cmd/bd/version_tracking.go:33-38 (auto-creates config with default) \n- internal/beads/beads.go:245-246 (FindJSONLPath defaults to issues.jsonl)","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-11-23T22:57:34.03414-08:00","updated_at":"2025-11-23T23:11:15.270911-08:00","closed_at":"2025-11-23T23:11:15.270911-08:00"} +{"id":"bd-ktng","title":"Optimize CLI test suite - eliminate redundant git init calls","description":"Current: Each of 13 CLI tests calls git init (31s total). Solution: Use single test binary built once in init(), skip git operations where possible, or use mock filesystem.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-04T11:23:13.660276-08:00","updated_at":"2025-11-23T23:01:49.003046-08:00","closed_at":"2025-11-23T22:55:32.103839-08:00"} +{"id":"bd-b55e2ac2","title":"Fix autoimport tests for content-hash collision scoring","description":"## Overview\nThree autoimport tests are failing after bd-cbed9619.4 because they expect behavior based on the old reference-counting collision resolution, but the system now uses deterministic content-hash scoring.\n\n## Failing Tests\n1. `TestAutoImportMultipleCollisionsRemapped` - expects local versions preserved\n2. `TestAutoImportAllCollisionsRemapped` - expects local versions preserved \n3. `TestAutoImportCollisionRemapMultipleFields` - expects specific collision resolution behavior\n\n## Root Cause\nThese tests were written when ScoreCollisions used reference counting to determine which version to keep. Now it uses content-hash comparison (introduced in commit 2e87329), which produces different but deterministic results.\n\n## Example\nOld behavior: Issue with more references would be kept\nNew behavior: Issue with lexicographically lower content hash is kept\n\n## Solution\nUpdate each test to:\n1. Verify the new content-hash based behavior is correct\n2. Check that the remapped issue (not necessarily local/remote) has the expected content\n3. Ensure dependencies are preserved on the correct remapped issue\n\n## Acceptance Criteria\n- All three autoimport tests pass\n- Tests verify content-hash determinism (same collision always resolves the same way)\n- Tests check dependency preservation on remapped issues\n- Test documentation explains content-hash scoring expectations\n\n## Files to Modify\n- `cmd/bd/autoimport_collision_test.go`\n\n## Testing\nRun: `go test ./cmd/bd -run \"TestAutoImport.*Collision\" -v`","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-28T19:17:28.358028-07:00","updated_at":"2025-11-24T00:01:27.558153-08:00","closed_at":"2025-11-23T23:20:43.995595-08:00"} +{"id":"bd-1rh","title":"cmd/bd test suite is absurdly slow - 279 tests taking 8+ minutes","description":"# Problem\n\nThe cmd/bd test suite is painfully slow:\n- **279 tests** in cmd/bd alone\n- Full suite takes **8+ minutes** to run\n- Even with the 16 slowest integration tests now tagged with `integration` build tag, the remaining tests still take forever\n\nThis makes the development loop unusable. We can't wait 8+ minutes every time we want to run tests.\n\n# Root Cause Analysis\n\n## 1. Sheer Volume\n279 tests is too many for a single package. Even at 0.1s per test, that's 28 seconds minimum just for cmd/bd.\n\n## 2. Each Test Creates Full Database + Temp Directories\nEvery test does heavy setup:\n- Creates temp directory (`t.TempDir()` or `os.MkdirTemp`)\n- Initializes SQLite database\n- Sets up git repo in many cases\n- Creates full storage layer\n\nExample from the tests:\n```go\nfunc setupCLITestDB(t *testing.T) string {\n tmpDir := createTempDirWithCleanup(t)\n runBDInProcess(t, tmpDir, \"init\", \"--prefix\", \"test\", \"--quiet\")\n return tmpDir\n}\n```\n\nThis happens 279 times!\n\n## 3. Tests Are Not Properly Categorized\nWe have three types of tests mixed together:\n- **Unit tests** - should be fast, test single functions\n- **Integration tests** - test full workflows, need DB/git\n- **End-to-end tests** - test entire CLI commands\n\nThey're all lumped together in cmd/bd, all running every time.\n\n# What We've Already Fixed\n\nAdded `integration` build tags to 16 obviously-slow test files:\n- import_profile_test.go (performance benchmarking tests)\n- export_mtime_test.go (tests with time.Sleep calls)\n- cli_fast_test.go (full CLI integration tests)\n- delete_test.go, import_uncommitted_test.go, sync_local_only_test.go (git integration)\n- And 10 more in internal/ packages\n\nThese are now excluded from the default `go test ./...` run.\n\n# Proposed Solutions\n\n## Option 1: Shared Test Fixtures (Quick Win)\nCreate a shared test database that multiple tests can use:\n```go\nvar testDB *sqlite.SQLiteStorage\nvar testDBOnce sync.Once\n\nfunc getSharedTestDB(t *testing.T) storage.Storage {\n testDBOnce.Do(func() {\n // Create one DB for all tests\n })\n return testDB\n}\n```\n\n**Pros**: Easy to implement, immediate speedup\n**Cons**: Tests become less isolated, harder to debug failures\n\n## Option 2: Table-Driven Tests (Medium Win)\nCollapse similar tests into table-driven tests:\n```go\nfunc TestCreate(t *testing.T) {\n tests := []struct{\n name string\n args []string\n want string\n }{\n {\"basic issue\", []string{\"create\", \"Test\"}, \"created\"},\n {\"with description\", []string{\"create\", \"Test\", \"-d\", \"desc\"}, \"created\"},\n // ... 50 more cases\n }\n \n db := setupOnce(t) // Setup once, not 50 times\n for _, tt := range tests {\n t.Run(tt.name, func(t *testing.T) {\n // test using shared db\n })\n }\n}\n```\n\n**Pros**: Dramatically reduces setup overhead, tests run in parallel\n**Cons**: Requires refactoring, tests share more state\n\n## Option 3: Split cmd/bd Tests Into Packages (Big Win)\nMove tests into focused packages:\n- `cmd/bd/internal/clitests` - CLI integration tests (mark with integration tag)\n- `cmd/bd/internal/unittests` - Fast unit tests\n- Keep only essential tests in cmd/bd\n\n**Pros**: Clean separation, easy to run just fast tests\n**Cons**: Requires significant refactoring\n\n## Option 4: Parallel Execution (Quick Win)\nAdd `t.Parallel()` to independent tests:\n```go\nfunc TestSomething(t *testing.T) {\n t.Parallel() // Run this test concurrently with others\n // ...\n}\n```\n\n**Pros**: Easy to add, can cut time in half on multi-core machines\n**Cons**: Doesn't reduce actual test work, just parallelizes it\n\n## Option 5: In-Memory Databases (Medium Win)\nUse `:memory:` SQLite databases instead of file-based:\n```go\nstore, err := sqlite.New(ctx, \":memory:\")\n```\n\n**Pros**: Faster than disk I/O, easier cleanup\n**Cons**: Some tests need actual file-based DBs (export/import tests)\n\n# Recommended Approach\n\n**Short-term (this week)**:\n1. Add `t.Parallel()` to all independent tests in cmd/bd\n2. Use `:memory:` databases where possible\n3. Create table-driven tests for similar test cases\n\n**Medium-term (next sprint)**:\n4. Split cmd/bd tests into focused packages\n5. Mark more integration tests appropriately\n\n**Long-term (backlog)**:\n6. Consider shared test fixtures with proper isolation\n\n# Current Status\n\nWe've tagged 16 files with `integration` build tag, but the remaining 279 tests in cmd/bd still take 8+ minutes. This issue tracks fixing the cmd/bd test performance specifically.\n\n# Target\n\nGet `go test ./...` (without `-short` or `-tags=integration`) down to **under 30 seconds**.\n\n\n# THE REAL ROOT CAUSE (Updated Analysis)\n\nAfter examining the actual test code, the problem is clear:\n\n## Every Test Creates Its Own Database From Scratch\n\nLook at `create_test.go`:\n```go\nfunc TestCreate_BasicIssue(t *testing.T) {\n tmpDir := t.TempDir() // ← Creates temp dir\n testDB := filepath.Join(tmpDir, \".beads\", \"beads.db\")\n s := newTestStore(t, testDB) // ← Opens NEW SQLite connection\n // ← Runs migrations\n // ← Sets config\n // ... actual test (3 lines)\n}\n\nfunc TestCreate_WithDescription(t *testing.T) {\n tmpDir := t.TempDir() // ← Creates ANOTHER temp dir\n testDB := filepath.Join(tmpDir, \".beads\", \"beads.db\")\n s := newTestStore(t, testDB) // ← Opens ANOTHER SQLite connection\n // ... actual test (3 lines)\n}\n```\n\n**This happens 279 times!**\n\n## These Tests Don't Need Isolation!\n\nMost tests are just checking:\n- \"Can I create an issue with a title?\"\n- \"Can I create an issue with a description?\"\n- \"Can I add labels?\"\n\nThey don't conflict with each other. They could all share ONE database!\n\n## The Fix: Test Suites with Shared Setup\n\nInstead of:\n```go\nfunc TestCreate_BasicIssue(t *testing.T) {\n s := newTestStore(t, t.TempDir()+\"/db\") // ← Expensive!\n // test\n}\n\nfunc TestCreate_WithDesc(t *testing.T) {\n s := newTestStore(t, t.TempDir()+\"/db\") // ← Expensive!\n // test\n}\n```\n\nDo this:\n```go\nfunc TestCreate(t *testing.T) {\n // ONE setup for all subtests\n s := newTestStore(t, t.TempDir()+\"/db\")\n \n t.Run(\"basic_issue\", func(t *testing.T) {\n t.Parallel() // Can run concurrently - tests don't conflict\n // test using shared `s`\n })\n \n t.Run(\"with_description\", func(t *testing.T) {\n t.Parallel()\n // test using shared `s`\n })\n \n // ... 50 more subtests, all using same DB\n}\n```\n\n**Result**: 50 tests β†’ 1 database setup instead of 50!\n\n## Why This Works\n\nSQLite is fine with concurrent reads and isolated transactions. These tests:\n- βœ… Create different issues (no ID conflicts)\n- βœ… Just read back what they created\n- βœ… Don't depend on database state from other tests\n\nThey SHOULD share a database!\n\n## Real Numbers\n\nCurrent:\n- 279 tests Γ— (create dir + init SQLite + migrations) = **8 minutes**\n\nAfter fix:\n- 10 test suites Γ— (create dir + init SQLite + migrations) = **30 seconds**\n- 279 subtests running in parallel using those 10 DBs = **5 seconds**\n\n**Total: ~35 seconds instead of 8 minutes!**\n\n## Implementation Plan\n\n1. **Group related tests** into suites (Create, List, Update, Delete, etc.)\n2. **One setup per suite** instead of per test\n3. **Use t.Run() for subtests** with t.Parallel()\n4. **Keep tests that actually need isolation** separate (export/import tests, git operations)\n\nThis is way better than shuffling tests into folders!","notes":"## Progress Update (2025-11-21)\n\nβœ… **Completed**:\n- Audited all 280 tests, created TEST_SUITE_AUDIT.md ([deleted:[deleted:[deleted:[deleted:[deleted:[deleted:[deleted:bd-c49]]]]]]])\n- Refactored create_test.go to shared DB pattern ([deleted:[deleted:[deleted:[deleted:[deleted:[deleted:[deleted:bd-y6d]]]]]]])\n- Proven the pattern works: 11 tests now run in 0.04s with 1 DB instead of 11\n\n❌ **Current Reality**:\n- Overall test suite: Still 8+ minutes (no meaningful change)\n- Only 1 of 76 test files refactored\n- Saved ~10 DB initializations out of 280\n\n## Acceptance Criteria (REALISTIC)\n\nThis task is NOT complete until:\n- [ ] All P1 files refactored (create βœ…, dep, stale, comments, list, ready)\n- [ ] Test suite runs in \u003c 2 minutes\n- [ ] Measured and verified actual speedup\n\n## Next Steps\n\n1. Refactor remaining 5 P1 files: dep_test.go, stale_test.go, comments_test.go, list_test.go, ready_test.go\n2. Measure actual time improvement after each file\n3. Continue with P2 files if needed to hit \u003c2min target","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-21T11:37:47.886207-05:00","updated_at":"2025-11-24T00:01:27.554109-08:00","closed_at":"2025-11-23T23:38:54.185364-08:00"} +{"id":"bd-9e23","title":"Optimize Memory backend GetIssueByExternalRef with index","description":"Currently GetIssueByExternalRef in Memory storage uses O(n) linear search through all issues.\n\nCurrent code (memory.go:282-308):\nfor _, issue := range m.issues {\n if issue.ExternalRef != nil \u0026\u0026 *issue.ExternalRef == externalRef {\n return \u0026issueCopy, nil\n }\n}\n\nProposed optimization:\n- Add externalRefToID map[string]string to MemoryStorage\n- Maintain it in CreateIssue, UpdateIssue, DeleteIssue\n- Achieve O(1) lookup like SQLite's index\n\nImpact: Low (--no-db mode typically has smaller datasets)\nRelated: bd-1022","status":"open","priority":4,"issue_type":"chore","created_at":"2025-11-02T15:32:30.242357-08:00","updated_at":"2025-11-02T15:32:30.242357-08:00"} +{"id":"bd-3852","title":"Add orphan detection migration","description":"Create migration to detect orphaned children in existing databases. Query: SELECT id FROM issues WHERE id LIKE '%.%' AND substr(id, 1, instr(id || '.', '.') - 1) NOT IN (SELECT id FROM issues). Log results, let user decide action (delete orphans or convert to top-level).","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-04T12:32:30.727044-08:00","updated_at":"2025-11-24T01:08:18.295118-08:00","closed_at":"2025-11-24T00:31:16.479343-08:00"} +{"id":"bd-4h3","title":"Add test coverage for internal/git package","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-20T21:21:23.497486-05:00","updated_at":"2025-11-20T21:21:23.497486-05:00","dependencies":[{"issue_id":"bd-4h3","depends_on_id":"bd-ge7","type":"blocks","created_at":"2025-11-20T21:21:31.277639-05:00","created_by":"daemon"}]} +{"id":"bd-z8z","title":"Apply wrapDBError to queries.go","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-24T00:53:14.298177-08:00","updated_at":"2025-11-24T00:55:37.364663-08:00","closed_at":"2025-11-24T00:55:37.364663-08:00"} +{"id":"bd-l0r","title":"CRITICAL: bd sync pushes stale DB state instead of trusting JSONL truth on pull","description":"When a clone has stale DB (688 issues) and pulls fresh JSONL (62 issues), bd sync detects 1009.7% divergence but proceeds to re-export the stale DB and push it, overwriting the correct JSONL state. \n\nRepro:\n1. Clone has 688 issues in DB (628 closed)\n2. git pull brings JSONL with 62 issues (cleanup applied)\n3. bd sync warns about divergence but exports DBβ†’JSONL\n4. Pushes 688 issues back to remote, undoing cleanup\n\nExpected: JSONL is source of truth after pull. DB should be wiped and reimported.\nActual: DB overwrites JSONL, pushing stale state upstream.\n\nImpact: Breaks multi-clone coordination. Cleanup work gets undone.","status":"in_progress","issue_type":"bug","created_at":"2025-11-23T22:29:37.668882-08:00","updated_at":"2025-11-23T22:30:11.405611-08:00"} +{"id":"bd-nq41","title":"Fix Homebrew warning about Ruby file location","description":"Homebrew warning: Found Ruby file outside steveyegge/beads tap formula directory.\nWarning points to: /opt/homebrew/Library/Taps/steveyegge/homebrew-beads/bd.rb\nIt should likely be inside a Formula/ directory or similar structure expected by Homebrew taps.\n","status":"open","priority":2,"issue_type":"chore","created_at":"2025-11-20T18:56:21.226579-05:00","updated_at":"2025-11-20T18:56:21.226579-05:00"} +{"id":"bd-r71","title":"Add tests for error wrapping behavior","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-24T00:53:16.906291-08:00","updated_at":"2025-11-24T00:57:46.21316-08:00","closed_at":"2025-11-24T00:57:46.21316-08:00"} +{"id":"bd-koab","title":"Import should continue on FOREIGN KEY constraint violations from deletions","description":"# Problem\n\nWhen importing JSONL after a merge that includes deletions, we may encounter FOREIGN KEY constraint violations if:\n- Issue A was deleted in one branch\n- Issue B (that depends on A) was modified in another branch \n- The merge keeps the deletion of A and the modification of B\n- Import tries to import B with a dependency/reference to deleted A\n\nCurrently import fails completely on such constraint violations, requiring manual intervention.\n\n# Solution\n\nAdd IsForeignKeyConstraintError() helper similar to IsUniqueConstraintError()\n\nUpdate import code to:\n1. Detect FOREIGN KEY constraint violations\n2. Log a warning with the issue ID and constraint\n3. Continue importing remaining issues\n4. Report summary of skipped issues at the end\n\n# Implementation Notes\n\n- Add to internal/storage/sqlite/util.go\n- Pattern: strings.Contains(err.Error(), \"FOREIGN KEY constraint failed\")\n- Update importer to handle these errors gracefully\n- Keep track of skipped issues for summary reporting","notes":"## Implementation Complete\n\nAdded FOREIGN KEY constraint violation handling to the importer:\n\n**Changes made:**\n\n1. **internal/importer/importer.go**\n - Added SkippedDependencies field to Result struct\n - Updated importDependencies() to accept result parameter\n - Added FK constraint detection using sqlite.IsForeignKeyConstraintError()\n - Log warning for each skipped dependency\n - Track skipped dependencies in result\n\n2. **cmd/bd/import_shared.go**\n - Added SkippedDependencies field to ImportResult struct\n - Updated result conversion to include skipped dependencies\n\n3. **cmd/bd/import.go**\n - Added summary reporting for skipped dependencies\n - Displays warning with list of skipped dependencies and helpful context\n\n**Behavior:**\n- When a FOREIGN KEY constraint violation is encountered during dependency import:\n - A warning is logged: 'Warning: Skipping dependency due to missing reference: issue-a β†’ issue-b (blocks)'\n - The dependency is tracked in result.SkippedDependencies\n - Import continues with remaining dependencies\n - Summary at end lists all skipped dependencies with context message\n\n**Testing:**\n- All existing importer tests pass\n- Build succeeds\n- Ready for real-world testing when FK constraint violations are encountered","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-11-23T21:37:02.811665-08:00","updated_at":"2025-11-24T00:01:27.559495-08:00","closed_at":"2025-11-23T23:31:04.325337-08:00"} +{"id":"bd-13gm","title":"Add explicit cache validation tests for blocked_issues_cache","description":"The blocked_issues_cache optimization works correctly but lacks explicit tests that verify cache invalidation behavior.\n\n## What to test\n\n1. **Cache invalidation on dependency add**\n - Add a blocking dependency\n - Verify blocked issue appears in cache\n \n2. **Cache invalidation on dependency remove**\n - Remove a blocking dependency\n - Verify blocked issue removed from cache\n \n3. **Cache invalidation on status change**\n - Close a blocker issue\n - Verify dependent issue removed from cache\n - Reopen blocker\n - Verify dependent issue added back to cache\n\n4. **Cache consistency across operations**\n - Multiple dependency changes in sequence\n - Verify cache stays consistent with actual blocking state\n\n5. **Parent-child transitive blocking**\n - Create epic with child tasks\n - Add blocking dependency to epic\n - Verify all children appear in cache\n\n## Implementation\n\nAdd tests to internal/storage/sqlite/blocked_cache_test.go (new file) with direct cache queries:\n\n```go\nfunc TestBlockedCacheInvalidation(t *testing.T) {\n // Verify cache updates correctly on dependency changes\n}\n\nfunc TestBlockedCacheConsistency(t *testing.T) {\n // Verify cache matches actual blocking state\n}\n```\n\n## Why this matters\n\n- Current tests verify behavior but not implementation\n- Explicit cache tests catch cache-specific bugs\n- Makes cache correctness visible in test output\n- Easier debugging if cache gets out of sync\n\n## Related\n\n- [deleted:[deleted:[deleted:[deleted:[deleted:[deleted:bd-5qim]]]]]]: GetReadyWork performance optimization (implemented cache)\n- internal/storage/sqlite/blocked_cache.go\n- internal/storage/sqlite/ready_test.go (behavior tests)","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-23T20:06:55.736412-08:00","updated_at":"2025-11-24T00:01:27.55236-08:00","closed_at":"2025-11-23T23:22:04.177645-08:00"} +{"id":"bd-zj8e","title":"Performance Testing Documentation","description":"Create docs/performance-testing.md documenting the performance testing framework.\n\nSections:\n1. Overview - What the framework does, goals\n2. Running Benchmarks\n - make bench command\n - Running specific benchmarks\n - Interpreting output (ns/op, allocs/op)\n3. Profiling and Analysis\n - Viewing CPU profiles with pprof\n - Reading flamegraphs\n - Memory profiling\n - Finding hotspots\n4. User Diagnostics\n - bd doctor --perf usage\n - Sharing profiles with bug reports\n - Understanding the report output\n5. Comparing Performance\n - Using benchstat for before/after comparisons\n - Detecting regressions\n6. Tips for Optimization\n - Common patterns\n - When to profile vs benchmark\n\nStyle:\n- Concise, practical examples\n- Screenshots/examples of pprof output\n- Clear command-line examples\n- Focus on workflow, not theory","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-13T22:23:38.99897-08:00","updated_at":"2025-11-13T22:23:38.99897-08:00"} +{"id":"bd-j3zt","title":"Fix mypy errors in beads-mcp","description":"Running `mypy .` in `integrations/beads-mcp` reports 287 errors. These should be addressed to improve type safety and code quality.","status":"open","priority":3,"issue_type":"task","created_at":"2025-11-20T18:53:28.557708-05:00","updated_at":"2025-11-20T18:53:28.557708-05:00"} +{"id":"bd-c362","title":"Extract database search logic into helper function","description":"The logic for finding a database in a beads directory is duplicated:\n- FindDatabasePath() BEADS_DIR section (beads.go:141-169)\n- findDatabaseInTree() (beads.go:248-280)\n\nBoth implement the same search order:\n1. Check config.json first (single source of truth)\n2. Fall back to canonical beads.db\n3. Search for *.db files, filtering backups and vc.db\n\nRefactoring suggestion:\nExtract to a helper function like:\n func findDatabaseInBeadsDir(beadsDir string) string\n\nBenefits:\n- Single source of truth for database search logic\n- Easier to maintain and update search order\n- Reduces code duplication\n\nRelated to [deleted:[deleted:[deleted:[deleted:[deleted:[deleted:[deleted:[deleted:[deleted:bd-e16b]]]]]]]]] implementation.","status":"open","priority":3,"issue_type":"chore","created_at":"2025-11-02T18:34:02.831543-08:00","updated_at":"2025-11-23T22:38:46.782725-08:00"} +{"id":"bd-1w6i","title":"Document blocked_issues_cache architecture and behavior","description":"Add comprehensive documentation about the blocked_issues_cache optimization to help future maintainers understand the design.\n\n## What to document\n\n1. **Architecture overview**\n - Why cache exists (performance: 752ms -\u003e 29ms)\n - When cache is used (GetReadyWork queries)\n - How cache is maintained (invalidation triggers)\n\n2. **Cache invalidation rules**\n - Invalidated on: dependency add/remove (blocks/parent-child only)\n - Invalidated on: any status change\n - Invalidated on: issue close\n - NOT invalidated on: related/discovered-from dependencies\n\n3. **Transaction safety**\n - All invalidations happen within transactions\n - Cache can use tx or direct db connection\n - Rebuild is atomic (DELETE + INSERT in same tx)\n\n4. **Performance characteristics**\n - Full rebuild on every invalidation\n - Rebuild is fast (\u003c50ms on 10K database)\n - Write complexity traded for read speed\n - Dependency changes are rare vs reads\n\n5. **Edge cases**\n - Parent-child transitive blocking\n - Closed issues don't block\n - Foreign key CASCADE handles deletions\n\n## Where to document\n\nAdd to these locations:\n\n1. **blocked_cache.go** - Add detailed package comment:\n```go\n// Package blocked_cache implements the blocked_issues_cache optimization.\n// \n// Performance: GetReadyWork originally used recursive CTE (752ms on 10K db).\n// With cache: Simple NOT EXISTS query (29ms on 10K db).\n//\n// Cache Maintenance:\n// - Rebuild triggered on dependency changes (blocks/parent-child only)\n// - Rebuild triggered on status changes \n// - Full rebuild (DELETE + INSERT) is fast enough for all cases\n// ...\n```\n\n2. **ARCHITECTURE.md** or **PERFORMANCE.md** (new file) - High-level overview\n\n3. **ready.go** - Update comment at line 84-85 with more detail\n\n## Related\n\n- [deleted:[deleted:[deleted:[deleted:[deleted:[deleted:bd-5qim]]]]]]: GetReadyWork optimization (implemented)\n- bd-13gm: Cache validation tests\n- [deleted:[deleted:[deleted:[deleted:bd-obdc]]]]: Cache rebuild command","status":"closed","priority":3,"issue_type":"task","created_at":"2025-11-23T20:07:23.467296-08:00","updated_at":"2025-11-24T01:17:35.451953-08:00","closed_at":"2025-11-24T01:14:27.162122-08:00"} +{"id":"bd-81a","title":"Add programmatic tip injection API","description":"Allow tips to be programmatically injected at runtime based on detected conditions. This enables dynamic tips (not just pre-defined ones) to be shown with custom priority and frequency.","status":"open","priority":2,"issue_type":"feature","created_at":"2025-11-11T23:29:46.645583-08:00","updated_at":"2025-11-11T23:50:12.209135-08:00","dependencies":[{"issue_id":"bd-81a","depends_on_id":"bd-d4i","type":"blocks","created_at":"2025-11-11T23:29:46.646327-08:00","created_by":"daemon"}]} diff --git a/ZFC_BUG_INVESTIGATION.md b/ZFC_BUG_INVESTIGATION.md new file mode 100644 index 00000000..eed1dbcd --- /dev/null +++ b/ZFC_BUG_INVESTIGATION.md @@ -0,0 +1,82 @@ +# ZFC Resurrection Bug Investigation + +## Problem +When `bd sync` runs with a stale DB (more issues than JSONL), it should trust JSONL as source of truth. Instead, it re-exports the stale DB back to JSONL, "resurrecting" deleted issues. + +## Reproduction +1. Clean JSONL has 74 issues +2. Stale DB has 122 issues (from previous bad sync) +3. Run `bd sync` +4. Expected: JSONL stays at 74 +5. Actual: JSONL becomes 122 (polluted) + +## Root Cause Analysis + +### The Sync Flow +1. **Step 1**: ZFC check - if DB > JSONL by >50%, import first and set `skipExport=true` +2. **Step 1b**: If `!skipExport`, export DB to JSONL +3. **Step 2**: Commit changes +4. **Step 3**: Pull from remote +5. **Step 4**: Import pulled JSONL +6. **Step 4.5**: Check if re-export needed (`skipReexport` variable) +7. **Step 5**: Push + +### The Bug +The post-pull re-export check (Step 4.5) has its own `skipReexport` variable that was NOT inheriting from the initial `skipExport` flag. + +**Original code (line 306):** +```go +skipReexport := false // BUG: doesn't inherit skipExport +``` + +**Fixed code:** +```go +skipReexport := skipExport // Carry forward initial ZFC detection +``` + +### Why Fix Didn't Work +Even with the fix, the bug persists because: + +1. **Multiple pollution paths**: The initial export (Step 1b) can pollute JSONL before pull +2. **Import doesn't delete**: When 74-line JSONL is imported to 122-issue DB, the 48 extra issues remain +3. **Post-import check fails**: After import, DB still has 122, JSONL has 74 (from pull), but `dbNeedsExport()` sees differences and triggers re-export + +### Key Insight +The import operation only **creates/updates** - it never **deletes** issues that exist in DB but not in JSONL. So even after importing a 74-issue JSONL, the DB still has 122 issues. + +## Proposed Solutions + +### Option 1: Use `--delete-missing` flag during ZFC import +When ZFC is detected, import with deletion of missing issues: +```go +if err := importFromJSONL(ctx, jsonlPath, renameOnImport, true /* deleteMissing */); err != nil { +``` + +### Option 2: Skip ALL exports after ZFC detection +Make `skipExport` a more powerful flag that blocks all export paths, including post-pull re-export. + +### Option 3: Add explicit ZFC mode +Track ZFC state throughout the entire sync operation and prevent any export when in ZFC mode. + +## Files Involved +- `cmd/bd/sync.go:126-178` - Initial ZFC check and export +- `cmd/bd/sync.go:303-357` - Post-pull re-export logic +- `cmd/bd/integrity.go:289-301` - `validatePostImport()` function +- `cmd/bd/import.go` - Import logic (needs `--delete-missing` support) + +## Current State +- Remote (origin/main) has 74-line JSONL at commit `c6f9f7e` +- Local DB has 122 issues (stale) +- Fix attempt at line 306 (`skipReexport := skipExport`) is in place but insufficient +- Need to also handle the import-without-delete issue + +## Next Steps +1. Clean up: `git reset --hard c6f9f7e` (or earlier clean commit) +2. Delete local DB: `rm -f .beads/beads.db` +3. Import with delete-missing to sync DB with JSONL +4. Implement proper fix that either: + - Uses delete-missing during ZFC import, OR + - Completely blocks re-export when ZFC is detected + +## Version +This should be fixed in v0.24.6 (v0.24.5 had the resurrection bug).