bd sync: 2025-10-28 12:03:57

This commit is contained in:
Steve Yegge
2025-10-28 12:03:57 -07:00
parent 79b952fccf
commit 96fb7ed29c

View File

@@ -5,7 +5,7 @@
{"id":"bd-13","title":"Test database naming","description":"","status":"open","priority":2,"issue_type":"task","created_at":"2025-10-27T18:27:28.309676-07:00","updated_at":"2025-10-27T22:22:23.816439-07:00"}
{"id":"bd-14","title":"Final validation test","description":"","status":"open","priority":2,"issue_type":"task","created_at":"2025-10-27T18:27:28.310533-07:00","updated_at":"2025-10-27T22:22:23.816672-07:00"}
{"id":"bd-15","title":"Update LINTING.md with current baseline","description":"After cleanup, document the remaining acceptable baseline in LINTING.md so we can track regression.","status":"open","priority":2,"issue_type":"task","created_at":"2025-10-27T18:53:10.38679-07:00","updated_at":"2025-10-27T22:22:23.816904-07:00"}
{"id":"bd-16","title":"Delete skipped tests for \"old buggy behavior\"","description":"Three test functions are permanently skipped with comments indicating they test behavior that was fixed in GH#120. These tests will never run again and should be deleted.\n\nTest functions to remove:\n\n1. `cmd/bd/import_collision_test.go:228`\n ```go\n t.Skip(\"Test expects old buggy behavior - needs rewrite for GH#120 fix\")\n ```\n\n2. `cmd/bd/import_collision_test.go:505`\n ```go\n t.Skip(\"Test expects old buggy behavior - needs rewrite for GH#120 fix\")\n ```\n\n3. `internal/storage/sqlite/collision_test.go:919`\n ```go\n t.Skip(\"Test expects old buggy behavior - needs rewrite for GH#120 fix\")\n ```\n\nImpact: Removes ~150 LOC of permanently skipped tests","acceptance_criteria":"- Delete the 3 test functions entirely (~150 LOC total)\n- Update test file comments to reference GH#120 fix if needed\n- All remaining tests pass: `go test ./...`\n- No reduction in meaningful test coverage (these test fixed bugs)","status":"open","priority":1,"issue_type":"task","created_at":"2025-10-27T20:30:19.961185-07:00","updated_at":"2025-10-27T22:22:23.817121-07:00","labels":["cleanup","dead-code","phase-1","test-cleanup"],"dependencies":[{"issue_id":"bd-16","depends_on_id":"bd-26","type":"parent-child","created_at":"2025-10-27T20:30:19.962815-07:00","created_by":"daemon"}]}
{"id":"bd-16","title":"Delete skipped tests for \"old buggy behavior\"","description":"Three test functions are permanently skipped with comments indicating they test behavior that was fixed in GH#120. These tests will never run again and should be deleted.\n\nTest functions to remove:\n\n1. `cmd/bd/import_collision_test.go:228`\n ```go\n t.Skip(\"Test expects old buggy behavior - needs rewrite for GH#120 fix\")\n ```\n\n2. `cmd/bd/import_collision_test.go:505`\n ```go\n t.Skip(\"Test expects old buggy behavior - needs rewrite for GH#120 fix\")\n ```\n\n3. `internal/storage/sqlite/collision_test.go:919`\n ```go\n t.Skip(\"Test expects old buggy behavior - needs rewrite for GH#120 fix\")\n ```\n\nImpact: Removes ~150 LOC of permanently skipped tests","acceptance_criteria":"- Delete the 3 test functions entirely (~150 LOC total)\n- Update test file comments to reference GH#120 fix if needed\n- All remaining tests pass: `go test ./...`\n- No reduction in meaningful test coverage (these test fixed bugs)","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-27T20:30:19.961185-07:00","updated_at":"2025-10-28T12:03:12.625287-07:00","closed_at":"2025-10-28T12:03:12.625287-07:00","labels":["cleanup","dead-code","phase-1","test-cleanup"],"dependencies":[{"issue_id":"bd-16","depends_on_id":"bd-26","type":"parent-child","created_at":"2025-10-27T20:30:19.962815-07:00","created_by":"daemon"}]}
{"id":"bd-17","title":"Remove unreachable RPC methods","description":"Several RPC server and client methods are unreachable and should be removed:\n\nServer methods (internal/rpc/server.go):\n- `Server.GetLastImportTime` (line 2116)\n- `Server.SetLastImportTime` (line 2123)\n- `Server.findJSONLPath` (line 2255)\n\nClient methods (internal/rpc/client.go):\n- `Client.Import` (line 311) - RPC import not used (daemon uses autoimport)\n\nEvidence:\n```bash\ngo run golang.org/x/tools/cmd/deadcode@latest -test ./...\n```\n\nImpact: Removes ~80 LOC of unused RPC code","acceptance_criteria":"- Remove the 4 unreachable methods (~80 LOC total)\n- Verify no callers: `grep -r \"GetLastImportTime\\|SetLastImportTime\\|findJSONLPath\" .`\n- All tests pass: `go test ./internal/rpc/...`\n- Daemon functionality works: test daemon start/stop/operations","status":"open","priority":2,"issue_type":"task","created_at":"2025-10-27T20:30:19.962209-07:00","updated_at":"2025-10-27T22:22:23.81754-07:00","labels":["cleanup","dead-code","phase-1","rpc"],"dependencies":[{"issue_id":"bd-17","depends_on_id":"bd-26","type":"parent-child","created_at":"2025-10-27T20:30:19.965239-07:00","created_by":"daemon"}]}
{"id":"bd-18","title":"Remove unreachable utility functions","description":"Several small utility functions are unreachable:\n\nFiles to clean:\n1. `internal/storage/sqlite/hash.go` - `computeIssueContentHash` (line 17)\n - Check if entire file can be deleted if only contains this function\n\n2. `internal/config/config.go` - `FileUsed` (line 151)\n - Delete unused config helper\n\n3. `cmd/bd/git_sync_test.go` - `verifyIssueOpen` (line 300)\n - Delete dead test helper\n\n4. `internal/compact/haiku.go` - `HaikuClient.SummarizeTier2` (line 81)\n - Tier 2 summarization not implemented\n - Options: implement feature OR delete method\n\nImpact: Removes 50-100 LOC depending on decisions","acceptance_criteria":"- Remove unreachable functions\n- If entire files can be deleted (like hash.go), delete them\n- For SummarizeTier2: decide to implement or delete, document decision\n- All tests pass: `go test ./...`\n- Verify no callers exist for each function","status":"open","priority":2,"issue_type":"task","created_at":"2025-10-27T20:30:19.963392-07:00","updated_at":"2025-10-27T22:22:23.81795-07:00","labels":["cleanup","dead-code","phase-1"],"dependencies":[{"issue_id":"bd-18","depends_on_id":"bd-26","type":"parent-child","created_at":"2025-10-27T20:30:19.968126-07:00","created_by":"daemon"}]}
{"id":"bd-19","title":"Extract SQLite migrations into separate files","description":"The file `internal/storage/sqlite/sqlite.go` is 2,136 lines and contains 11 sequential migrations alongside core storage logic. Extract migrations into a versioned system.\n\nCurrent issues:\n- 11 migration functions mixed with core logic\n- Hard to see migration history\n- Sequential migrations slow database open\n- No clear migration versioning\n\nMigration functions to extract:\n- `migrateDirtyIssuesTable()`\n- `migrateIssueCountersTable()`\n- `migrateExternalRefColumn()`\n- `migrateCompositeIndexes()`\n- `migrateClosedAtConstraint()`\n- `migrateCompactionColumns()`\n- `migrateSnapshotsTable()`\n- `migrateCompactionConfig()`\n- `migrateCompactedAtCommitColumn()`\n- `migrateExportHashesTable()`\n- Plus 1 more (11 total)\n\nTarget structure:\n```\ninternal/storage/sqlite/\n├── sqlite.go # Core storage (~800 lines)\n├── schema.go # Table definitions (~200 lines)\n├── migrations.go # Migration orchestration (~200 lines)\n└── migrations/ # Individual migrations\n ├── 001_initial_schema.go\n ├── 002_dirty_issues.go\n ├── 003_issue_counters.go\n [... through 011_export_hashes.go]\n```\n\nBenefits:\n- Clear migration history\n- Each migration self-contained\n- Easier to review migration changes in PRs\n- Future migrations easier to add","acceptance_criteria":"- All 11 migrations extracted to separate files\n- Migration version tracking in database\n- Migrations run in order on fresh database\n- Existing databases upgrade correctly\n- All tests pass: `go test ./internal/storage/sqlite/...`\n- Database initialization time unchanged or improved\n- Add migration rollback capability (optional, nice-to-have)","status":"open","priority":2,"issue_type":"task","created_at":"2025-10-27T20:30:47.870671-07:00","updated_at":"2025-10-27T22:22:23.81842-07:00","labels":["database","phase-2","refactor"],"dependencies":[{"issue_id":"bd-19","depends_on_id":"bd-26","type":"parent-child","created_at":"2025-10-27T20:30:47.875564-07:00","created_by":"daemon"}]}
@@ -41,8 +41,24 @@
{"id":"bd-46","title":"Audit Current Cache Usage","description":"Understand exactly what code depends on the storage cache","acceptance_criteria":"- Document showing all cache dependencies\n- Confirmation that removing cache won't break MCP\n- List of tests that need updating\n\nFiles to examine:\n- internal/rpc/server_cache_storage.go (cache implementation)\n- internal/rpc/client.go (how req.Cwd is set)\n- internal/rpc/server_*.go (all getStorageForRequest calls)\n- integrations/beads-mcp/ (MCP multi-repo logic)\n\nTasks:\n- Document all callers of getStorageForRequest()\n- Verify req.Cwd is only set by RPC client for database discovery\n- Confirm MCP server doesn't rely on multi-repo cache behavior\n- Check if any tests assume multi-repo routing\n- Review environment variables: BEADS_DAEMON_MAX_CACHE_SIZE, BEADS_DAEMON_CACHE_TTL, BEADS_DAEMON_MEMORY_THRESHOLD_MB","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-27T23:20:10.393143-07:00","updated_at":"2025-10-28T10:47:47.064858-07:00","closed_at":"2025-10-28T10:47:47.064858-07:00"}
{"id":"bd-47","title":"Remove Storage Cache from Server Struct","description":"Eliminate cache fields and use s.storage directly","acceptance_criteria":"- Server struct has no cache fields\n- NewServer() doesn't initialize cache\n- Start() doesn't run cache cleanup goroutines\n- Stop() only closes single s.storage\n\nChanges needed:\n- Remove cache-related fields from Server struct in server_core.go\n- Remove cache size/TTL parsing from env vars in NewServer()\n- Remove cleanup ticker goroutine from Start()\n- Remove cache cleanup logic from Stop()","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-27T23:20:10.393456-07:00","updated_at":"2025-10-28T10:47:47.065098-07:00","closed_at":"2025-10-28T10:47:47.065098-07:00"}
{"id":"bd-48","title":"Replace getStorageForRequest with Direct Access","description":"Replace all getStorageForRequest(req) calls with s.storage","acceptance_criteria":"- No references to getStorageForRequest() in codebase (except in deleted file)\n- All handlers use s.storage directly\n- Code compiles without errors\n\nFiles to update:\n- internal/rpc/server_issues_epics.go (~8 calls)\n- internal/rpc/server_labels_deps_comments.go (~4 calls)\n- internal/rpc/server_compact.go (~2 calls)\n- internal/rpc/server_export_import_auto.go (~2 calls)\n- internal/rpc/server_routing_validation_diagnostics.go (~1 call)\n\nPattern: store, err := s.getStorageForRequest(req) → store := s.storage","status":"open","priority":1,"issue_type":"task","created_at":"2025-10-27T23:20:10.393759-07:00","updated_at":"2025-10-27T23:20:10.393759-07:00"}
{"id":"bd-49","title":"Event-driven daemon architecture","description":"Replace 5-second polling sync loop with event-driven architecture that reacts instantly to changes. Eliminates stale data issues while reducing CPU ~60%. Key components: FileWatcher (fsnotify), Debouncer (500ms), RPC mutation events, optional git hooks. Target latency: \u003c500ms (vs 5000ms). See event_driven_daemon.md for full design.","status":"open","priority":1,"issue_type":"epic","created_at":"2025-10-28T12:01:46.480062-07:00","updated_at":"2025-10-28T12:01:46.480062-07:00"}
{"id":"bd-5","title":"Address gosec security warnings (102 issues)","description":"Security linter warnings: file permissions (0755 should be 0750), G304 file inclusion via variable, G204 subprocess launches. Many are false positives but should be reviewed.","design":"Review each gosec warning. Add exclusions for legitimate cases to .golangci.yml. Fix real security issues (overly permissive file modes).","status":"open","priority":2,"issue_type":"task","created_at":"2025-10-25T13:47:10.719134-07:00","updated_at":"2025-10-27T22:22:23.814301-07:00"}
{"id":"bd-50","title":"Add BEADS_DAEMON_MODE flag handling","description":"Add environment variable BEADS_DAEMON_MODE (values: poll, events). Default to 'poll' for Phase 1. Wire into daemon startup to select runEventLoop vs runEventDrivenLoop.","status":"open","priority":1,"issue_type":"task","created_at":"2025-10-28T12:02:03.230043-07:00","updated_at":"2025-10-28T12:02:03.230043-07:00","dependencies":[{"issue_id":"bd-50","depends_on_id":"bd-49","type":"parent-child","created_at":"2025-10-28T12:02:03.230666-07:00","created_by":"daemon"}]}
{"id":"bd-51","title":"Create cmd/bd/daemon_debouncer.go (~60 LOC)","description":"Implement Debouncer to batch rapid events into single action. Default 500ms, configurable via BEADS_DEBOUNCE_MS. Thread-safe with mutex.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-28T12:02:03.234539-07:00","updated_at":"2025-10-28T12:03:35.614191-07:00","closed_at":"2025-10-28T12:03:35.614191-07:00","dependencies":[{"issue_id":"bd-51","depends_on_id":"bd-49","type":"parent-child","created_at":"2025-10-28T12:02:03.235218-07:00","created_by":"daemon"}]}
{"id":"bd-52","title":"Add fallback to polling on watcher failure","description":"Detect fsnotify.NewWatcher() errors and log warning. Auto-switch to polling mode with 5s ticker. Add BEADS_WATCHER_FALLBACK env var to control behavior.","status":"open","priority":1,"issue_type":"task","created_at":"2025-10-28T12:02:03.235717-07:00","updated_at":"2025-10-28T12:02:03.235717-07:00"}
{"id":"bd-53","title":"Create cmd/bd/daemon_watcher.go (~150 LOC)","description":"Implement FileWatcher using fsnotify to watch JSONL file and git refs. Handle platform differences (inotify/FSEvents/ReadDirectoryChangesW). Include edge case handling for file rename, event storm, watcher failure.","status":"in_progress","priority":1,"issue_type":"task","created_at":"2025-10-28T12:02:03.236475-07:00","updated_at":"2025-10-28T12:03:52.950843-07:00","dependencies":[{"issue_id":"bd-53","depends_on_id":"bd-49","type":"parent-child","created_at":"2025-10-28T12:02:03.238539-07:00","created_by":"daemon"}]}
{"id":"bd-54","title":"Add fsnotify dependency to go.mod","description":"","status":"in_progress","priority":1,"issue_type":"task","created_at":"2025-10-28T12:02:03.239116-07:00","updated_at":"2025-10-28T12:03:26.102869-07:00","dependencies":[{"issue_id":"bd-54","depends_on_id":"bd-49","type":"parent-child","created_at":"2025-10-28T12:02:03.239656-07:00","created_by":"daemon"}]}
{"id":"bd-55","title":"Create cmd/bd/daemon_event_loop.go (~200 LOC)","description":"Implement runEventDrivenLoop to replace polling ticker. Coordinate FileWatcher, mutation events, debouncer. Include health check ticker (60s) for daemon validation.","status":"open","priority":1,"issue_type":"task","created_at":"2025-10-28T12:02:03.23654-07:00","updated_at":"2025-10-28T12:02:03.23654-07:00","dependencies":[{"issue_id":"bd-55","depends_on_id":"bd-49","type":"parent-child","created_at":"2025-10-28T12:02:03.242148-07:00","created_by":"daemon"}]}
{"id":"bd-56","title":"Add mutation channel to internal/rpc/server.go","description":"Add mutationChan chan MutationEvent to Server struct. Emit events on CreateIssue, UpdateIssue, DeleteIssue, AddComment. Non-blocking send with default case for full channel.","status":"open","priority":1,"issue_type":"task","created_at":"2025-10-28T12:02:03.23581-07:00","updated_at":"2025-10-28T12:02:03.23581-07:00","dependencies":[{"issue_id":"bd-56","depends_on_id":"bd-49","type":"parent-child","created_at":"2025-10-28T12:02:03.246888-07:00","created_by":"daemon"}]}
{"id":"bd-57","title":"Platform tests: Linux, macOS, Windows","description":"Test event-driven mode on all platforms. Verify inotify (Linux), FSEvents (macOS), ReadDirectoryChangesW (Windows). Test fallback behavior on each.","status":"open","priority":1,"issue_type":"task","created_at":"2025-10-28T12:02:21.606053-07:00","updated_at":"2025-10-28T12:02:21.606053-07:00","dependencies":[{"issue_id":"bd-57","depends_on_id":"bd-49","type":"parent-child","created_at":"2025-10-28T12:02:21.607758-07:00","created_by":"daemon"}]}
{"id":"bd-58","title":"Unit tests for Debouncer","description":"Test debouncer batches multiple triggers into single action. Test timer reset on subsequent triggers. Test cancel during wait. Test thread safety.","status":"open","priority":1,"issue_type":"task","created_at":"2025-10-28T12:02:21.6068-07:00","updated_at":"2025-10-28T12:02:21.6068-07:00","dependencies":[{"issue_id":"bd-58","depends_on_id":"bd-49","type":"parent-child","created_at":"2025-10-28T12:02:21.60732-07:00","created_by":"daemon"}]}
{"id":"bd-59","title":"Stress test: event storm handling","description":"Simulate 100+ rapid JSONL writes. Verify debouncer batches to single import. Verify no data loss. Test daemon stability.","status":"open","priority":1,"issue_type":"task","created_at":"2025-10-28T12:02:21.616212-07:00","updated_at":"2025-10-28T12:02:21.616212-07:00","dependencies":[{"issue_id":"bd-59","depends_on_id":"bd-49","type":"parent-child","created_at":"2025-10-28T12:02:21.616846-07:00","created_by":"daemon"}]}
{"id":"bd-6","title":"Add optional post-merge git hook example for bd sync","description":"Create example git hook that auto-runs bd sync after git pull/merge.\n\nAdd to examples/git-hooks/:\n- post-merge hook that checks if .beads/issues.jsonl changed\n- If changed: run `bd sync` automatically\n- Make it optional/documented (not auto-installed)\n\nBenefits:\n- Zero-friction sync after git pull\n- Complements auto-detection as belt-and-suspenders\n\nNote: post-merge hook already exists for pre-commit/post-merge. Extend it to support sync.","status":"open","priority":2,"issue_type":"task","created_at":"2025-10-25T22:47:14.668842-07:00","updated_at":"2025-10-27T22:22:23.814647-07:00"}
{"id":"bd-60","title":"Add fallback to polling on watcher failure","description":"Detect fsnotify.NewWatcher() errors and log warning. Auto-switch to polling mode with 5s ticker. Add BEADS_WATCHER_FALLBACK env var to control behavior.","status":"open","priority":1,"issue_type":"task","created_at":"2025-10-28T12:02:21.618295-07:00","updated_at":"2025-10-28T12:02:21.618295-07:00"}
{"id":"bd-61","title":"Add docs/architecture/event_driven.md","description":"Copy event_driven_daemon.md into docs/ folder. Add to documentation index.","status":"open","priority":2,"issue_type":"task","created_at":"2025-10-28T12:02:21.618304-07:00","updated_at":"2025-10-28T12:02:21.618304-07:00"}
{"id":"bd-62","title":"Integration test: mutation to export latency","description":"Measure time from bd create to JSONL update. Verify \u003c500ms latency. Test with multiple rapid mutations to verify batching.","status":"open","priority":1,"issue_type":"task","created_at":"2025-10-28T12:02:21.620034-07:00","updated_at":"2025-10-28T12:02:21.620034-07:00"}
{"id":"bd-63","title":"Unit tests for FileWatcher","description":"Test watcher detects JSONL changes. Test git ref changes trigger import. Test debounce integration. Test watcher recovery from file removal/rename.","status":"open","priority":1,"issue_type":"task","created_at":"2025-10-28T12:02:21.621407-07:00","updated_at":"2025-10-28T12:02:21.621407-07:00","dependencies":[{"issue_id":"bd-63","depends_on_id":"bd-49","type":"parent-child","created_at":"2025-10-28T12:02:21.622215-07:00","created_by":"daemon"}]}
{"id":"bd-64","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":"open","priority":2,"issue_type":"task","created_at":"2025-10-28T12:02:21.621626-07:00","updated_at":"2025-10-28T12:02:21.621626-07:00","dependencies":[{"issue_id":"bd-64","depends_on_id":"bd-49","type":"parent-child","created_at":"2025-10-28T12:02:21.623222-07:00","created_by":"daemon"}]}
{"id":"bd-7","title":"Enforce daemon singleton per workspace with file locking","description":"Agent in ~/src/wyvern discovered 4 simultaneous daemon processes running, causing infinite directory recursion (.beads/.beads/.beads/...). Each daemon used relative paths and created nested .beads/ directories.\n\nRoot cause: No singleton enforcement. Multiple `bd daemon` processes can start in same workspace.\n\nExpected: One daemon per workspace (each workspace = separate .beads/ dir with bd.sock)\nActual: Multiple daemons can run simultaneously in same workspace\n\nNote: Separate git clones = separate workspaces = separate daemons (correct). Git worktrees share .beads/ and have known limitations (documented, use --no-daemon).","design":"Use flock (file locking) on daemon socket or database file to enforce singleton:\n\n1. On daemon start, attempt exclusive lock on .beads/bd.sock or .beads/daemon.lock\n2. If lock held by another process, refuse to start (exit with clear error)\n3. Hold lock for lifetime of daemon process\n4. Release lock on daemon shutdown\n\nAlternative: Use PID file with stale detection (check if PID is still running)\n\nImplementation location: Daemon startup code in cmd/bd/ or internal/daemon/","acceptance_criteria":"1. Starting second daemon process in same workspace fails with clear error\n2. Test: Start daemon, attempt second start, verify failure\n3. Killing daemon releases lock, allowing new daemon to start\n4. No infinite .beads/ directory recursion possible\n5. Works correctly with auto-start mechanism","status":"in_progress","priority":0,"issue_type":"bug","created_at":"2025-10-25T23:13:12.269549-07:00","updated_at":"2025-10-27T22:22:23.814937-07:00"}
{"id":"bd-8","title":"Daemon fails to auto-import after git pull updates JSONL","description":"After git pull updates .beads/issues.jsonl, daemon doesn't automatically re-import changes, causing stale data to be shown until next sync cycle (up to 5 minutes).\n\nReproduction:\n1. Repo A: Close issues, export, commit, push\n2. Repo B: git pull (successfully updates .beads/issues.jsonl)\n3. bd show \u003cissue\u003e shows OLD status from daemon's SQLite db\n4. JSONL on disk has correct new status\n\nRoot cause: Daemon sync cycle runs on timer (5min). When user manually runs git pull, daemon doesn't detect JSONL was updated externally and continues serving stale data from SQLite.\n\nImpact:\n- High for AI agents using beads in git workflows\n- Breaks fundamental git-as-source-of-truth model\n- Confusing UX: git log shows commit, bd shows old state\n- Data consistency issues between JSONL and daemon\n\nSee WYVERN_SYNC_ISSUE.md for full analysis.","design":"Three possible solutions:\n\nOption 1: Auto-detect and re-import (recommended)\n- Before serving any bd command, check if .beads/issues.jsonl mtime \u003e last import time\n- If newer, auto-import before processing request\n- Fast check, minimal overhead\n\nOption 2: File watcher in daemon\n- Daemon watches .beads/issues.jsonl for mtime changes\n- Auto-imports when file changes\n- More complex, requires file watching infrastructure\n\nOption 3: Explicit sync command\n- User runs `bd sync` after git pull\n- Manual, error-prone, defeats automation\n\nRecommended: Option 1 (auto-detect) + Option 3 (explicit sync) as fallback.","acceptance_criteria":"1. After git pull updates .beads/issues.jsonl, next bd command sees fresh data\n2. No manual import or daemon restart required\n3. Performance impact \u003c 10ms per command (mtime check is fast)\n4. Works in both daemon and non-daemon modes\n5. Test: Two repo clones, update in one, pull in other, verify immediate sync","notes":"**Current Status (2025-10-26):**\n\n✅ **Completed (bd-128):**\n- Created internal/autoimport package with staleness detection\n- Daemon can detect when JSONL is newer than last import\n- Infrastructure exists to call import logic\n\n❌ **Remaining Work:**\nThe daemon's importFunc in server.go (line 2096-2102) is a stub that just logs a notice. It needs to actually import the issues.\n\n**Problem:** \n- importIssuesCore is in cmd/bd package, not accessible from internal/rpc\n- daemon's handleImport() returns 'not yet implemented' error\n\n**Two approaches:**\n1. Move importIssuesCore to internal/import package (shares with daemon)\n2. Use storage layer directly in daemon (create/update issues via Storage interface)\n\n**Blocker:** \nThis is the critical bug causing data corruption:\n- Agent A pushes changes\n- Agent B does git pull\n- Agent B's daemon serves stale SQLite data\n- Agent B exports stale data back to JSONL, overwriting Agent A's changes\n- Agent B pushes, losing Agent A's work\n\n**Next Steps:**\n1. Choose approach (probably #1 - move importIssuesCore to internal/import)\n2. Implement real importFunc in daemon's checkAndAutoImportIfStale()\n3. Test with two-repo scenario (push from A, pull in B, verify B sees changes)\n4. Ensure no data corruption in multi-agent workflows","status":"in_progress","priority":0,"issue_type":"epic","created_at":"2025-10-25T23:13:12.270766-07:00","updated_at":"2025-10-27T22:22:23.815209-07:00"}
{"id":"bd-9","title":"Document bd edit command and verify MCP exclusion","description":"Follow-up from PR #152:\n1. Add \"bd edit\" to AGENTS.md with \"Humans only\" note\n2. Verify MCP server doesn't expose bd edit command\n3. Consider adding test for command registration","status":"open","priority":2,"issue_type":"task","created_at":"2025-10-26T13:23:47.982295-07:00","updated_at":"2025-10-27T22:22:23.815469-07:00"}