Implement auto-import to complete automatic git sync workflow
Adds auto-import feature to complement bd-35's auto-export, completing the automatic sync workflow for git collaboration. **Implementation:** - Auto-import checks if JSONL is newer than DB on command startup - Silently imports JSONL when modification time is newer - Skips import command itself to avoid recursion - Can be disabled with --no-auto-import flag **Documentation updates:** - Updated README.md git workflow section - Updated CLAUDE.md workflow and pro tips - Updated bd quickstart with auto-sync section - Updated git hooks README to clarify they're now optional **Testing:** - Tested auto-import by touching JSONL and running commands - Tested auto-export with create/close operations - Complete workflow verified working Closes bd-33 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,42 +1,43 @@
|
||||
{"id":"bd-1","title":"Add export/import commands","description":"Support bd export --format=jsonl and bd import for text-based git workflow","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-10-12T00:43:03.453438-07:00","updated_at":"2025-10-12T20:20:06.977679-07:00","closed_at":"2025-10-12T20:20:06.977679-07:00"}
|
||||
{"id":"bd-10","title":"Extend export to include dependencies in JSONL","description":"Modify export.go to include dependencies array in each issue's JSONL output. This makes JSONL self-contained and enables proper collision resolution. Format: {\"id\":\"bd-10\",\"dependencies\":[{\"depends_on_id\":\"bd-5\",\"type\":\"blocks\"}]}","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-12T14:32:19.163526-07:00","updated_at":"2025-10-12T16:19:11.969345-07:00","closed_at":"2025-10-12T15:07:47.937992-07:00","dependencies":[{"issue_id":"bd-10","depends_on_id":"bd-9","type":"parent-child","created_at":"2025-10-12T14:35:59.213222-07:00","created_by":"stevey"}]}
|
||||
{"id":"bd-11","title":"Test issue to verify fix","description":"This should be bd-11 if the fix works","status":"closed","priority":3,"issue_type":"task","created_at":"2025-10-12T14:40:21.419082-07:00","updated_at":"2025-10-12T16:19:11.96945-07:00","closed_at":"2025-10-12T14:40:32.963312-07:00"}
|
||||
{"id":"bd-12","title":"Implement collision detection in import","description":"Create collision.go with detectCollisions() function. Compare incoming JSONL issues against DB state. Distinguish between: (1) exact match (idempotent), (2) ID match but different content (collision), (3) new issue. Return list of colliding issues.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-12T14:40:56.056588-07:00","updated_at":"2025-10-12T16:19:11.96955-07:00","closed_at":"2025-10-12T16:06:25.575038-07:00","dependencies":[{"issue_id":"bd-12","depends_on_id":"bd-9","type":"parent-child","created_at":"2025-10-12T14:41:07.947358-07:00","created_by":"stevey"}]}
|
||||
{"id":"bd-13","title":"Implement reference scoring algorithm","description":"Count references for each colliding issue: text mentions in descriptions/notes/design fields + dependency references. Sort collisions by score ascending (fewest refs first). This minimizes total updates during renumbering.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-12T14:40:56.204518-07:00","updated_at":"2025-10-12T16:26:46.572201-07:00","closed_at":"2025-10-12T16:26:46.572201-07:00","dependencies":[{"issue_id":"bd-13","depends_on_id":"bd-9","type":"parent-child","created_at":"2025-10-12T14:41:07.951605-07:00","created_by":"stevey"}]}
|
||||
{"id":"bd-14","title":"Implement ID remapping with reference updates","description":"Allocate new IDs for colliding issues. Update all text field references using word-boundary regex (\\bbd-10\\b). Update dependency records. Build id_mapping for reporting. Handle chain dependencies properly.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-12T14:40:56.367596-07:00","updated_at":"2025-10-12T16:35:13.159992-07:00","closed_at":"2025-10-12T16:35:13.159992-07:00","dependencies":[{"issue_id":"bd-14","depends_on_id":"bd-9","type":"parent-child","created_at":"2025-10-12T14:41:07.956041-07:00","created_by":"stevey"}]}
|
||||
{"id":"bd-15","title":"Add --resolve-collisions flag and user reporting","description":"Add import flags: --resolve-collisions (auto-fix) and --dry-run (preview). Display clear report: collisions detected, remappings applied (old→new with scores), reference counts updated. Default behavior: fail on collision (safe).","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-12T14:40:56.534721-07:00","updated_at":"2025-10-12T16:47:11.491645-07:00","closed_at":"2025-10-12T16:47:11.491645-07:00","dependencies":[{"issue_id":"bd-15","depends_on_id":"bd-9","type":"parent-child","created_at":"2025-10-12T14:41:07.961157-07:00","created_by":"stevey"}]}
|
||||
{"id":"bd-16","title":"Write comprehensive collision resolution tests","description":"Test cases: simple collision, multiple collisions, dependency updates, text reference updates, chain dependencies, edge cases (partial ID matches, case sensitivity, triple merges). Add to import_test.go and collision_test.go.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-12T14:40:56.702127-07:00","updated_at":"2025-10-12T16:54:25.273886-07:00","closed_at":"2025-10-12T16:54:25.273886-07:00","dependencies":[{"issue_id":"bd-16","depends_on_id":"bd-9","type":"parent-child","created_at":"2025-10-12T14:41:07.965816-07:00","created_by":"stevey"}]}
|
||||
{"id":"bd-17","title":"Update documentation for collision resolution","description":"Update README.md with collision resolution section. Update CLAUDE.md with new workflow. Document --resolve-collisions and --dry-run flags. Add example scenarios showing branch merge workflows.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-12T14:40:56.866649-07:00","updated_at":"2025-10-12T17:06:14.930928-07:00","closed_at":"2025-10-12T17:06:14.930928-07:00","dependencies":[{"issue_id":"bd-17","depends_on_id":"bd-9","type":"parent-child","created_at":"2025-10-12T14:41:07.970302-07:00","created_by":"stevey"}]}
|
||||
{"id":"bd-18","title":"Add design/notes/acceptance_criteria fields to update command","description":"Currently bd update only supports status, priority, title, assignee. Add support for --design, --notes, --acceptance-criteria flags. This makes it easier to add detailed designs to issues after creation.","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-10-12T14:40:57.032395-07:00","updated_at":"2025-10-12T17:10:53.958318-07:00","closed_at":"2025-10-12T17:10:53.958318-07:00"}
|
||||
{"id":"bd-19","title":"Fix import zero-value field handling","description":"Import uses zero-value checks (Priority != 0) to determine field updates. This prevents setting priority to 0 or clearing string fields. Export/import round-trip not fully idempotent for zero values. Consider JSON presence detection or explicit preserve-existing semantics. Location: cmd/bd/import.go:95-106","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-10-12T15:13:17.895083-07:00","updated_at":"2025-10-12T16:19:11.970157-07:00"}
|
||||
{"id":"bd-2","title":"Add PostgreSQL backend","description":"Implement PostgreSQL storage backend as alternative to SQLite for larger teams","status":"closed","priority":3,"issue_type":"feature","created_at":"2025-10-12T00:43:03.457453-07:00","updated_at":"2025-10-12T16:19:11.97024-07:00","closed_at":"2025-10-12T14:15:04.00695-07:00"}
|
||||
{"id":"bd-20","title":"Add --strict flag for dependency import failures","description":"Currently dependency import errors are warnings (logged to stderr, execution continues). Missing targets or cycles may indicate JSONL corruption. Add --strict flag to fail on any dependency errors for data integrity validation. Location: cmd/bd/import.go:159-164","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-10-12T15:13:18.954834-07:00","updated_at":"2025-10-12T16:19:11.970327-07:00"}
|
||||
{"id":"bd-21","title":"Simplify getNextID SQL query parameters","description":"Query passes prefix four times to same SQL query. Works but fragile if query changes. Consider simplifying SQL to require fewer parameters. Location: internal/storage/sqlite/sqlite.go:73-78","status":"closed","priority":3,"issue_type":"task","created_at":"2025-10-12T15:13:20.114733-07:00","updated_at":"2025-10-12T16:19:11.970421-07:00"}
|
||||
{"id":"bd-22","title":"Add validation/warning for malformed issue IDs","description":"getNextID silently ignores non-numeric ID suffixes (e.g., bd-foo). CAST returns NULL for invalid strings. Consider detecting and warning about malformed IDs in database. Location: internal/storage/sqlite/sqlite.go:79-82","status":"closed","priority":3,"issue_type":"task","created_at":"2025-10-12T15:13:21.195975-07:00","updated_at":"2025-10-12T16:19:11.970492-07:00"}
|
||||
{"id":"bd-23","title":"Optimize export dependency queries (N+1 problem)","description":"Export triggers separate GetDependencyRecords() per issue. For large DBs (1000+ issues), this is N+1 queries. Add GetAllDependencyRecords() to fetch all dependencies in one query. Location: cmd/bd/export.go:52-59, import.go:138-142","status":"closed","priority":3,"issue_type":"task","created_at":"2025-10-12T15:13:22.325113-07:00","updated_at":"2025-10-12T16:19:11.97058-07:00"}
|
||||
{"id":"bd-24","title":"Support ID space partitioning for parallel worker agents","description":"Enable external orchestrators (like AI worker swarms) to control issue ID assignment. Add --id flag to 'bd create' for explicit ID specification. Optionally support 'bd config set next_id N' to set the starting point for auto-increment. Storage layer already supports pre-assigned IDs (sqlite.go:52-71), just need CLI wiring. This keeps beads simple while letting orchestrators implement their own ID partitioning strategies to minimize merge conflicts. Complementary to bd-9's collision resolution.","status":"open","priority":1,"issue_type":"feature","created_at":"2025-10-12T16:10:37.808226-07:00","updated_at":"2025-10-12T16:19:11.970666-07:00"}
|
||||
{"id":"bd-25","title":"Add transaction support to storage layer for atomic multi-operation workflows","description":"Currently each storage method (CreateIssue, UpdateIssue, etc.) starts its own transaction. This makes it impossible to perform atomic multi-step operations like collision resolution. Add support for passing *sql.Tx through the storage interface, or create transaction-aware versions of methods. This would make remapCollisions and other batch operations truly atomic.","status":"open","priority":1,"issue_type":"feature","created_at":"2025-10-12T16:39:00.66572-07:00","updated_at":"2025-10-12T16:39:00.66572-07:00"}
|
||||
{"id":"bd-26","title":"Optimize reference updates to avoid loading all issues into memory","description":"In updateReferences(), we call SearchIssues with no filter to get ALL issues for updating references. For large databases (10k+ issues), this loads everything into memory. Options: 1) Use batched processing with LIMIT/OFFSET, 2) Use SQL UPDATE with REPLACE() directly, 3) Stream results instead of loading all at once. Located in collision.go:266","status":"open","priority":2,"issue_type":"task","created_at":"2025-10-12T16:39:10.327861-07:00","updated_at":"2025-10-12T16:39:10.327861-07:00"}
|
||||
{"id":"bd-27","title":"Cache compiled regexes in replaceIDReferences for performance","description":"replaceIDReferences() compiles the same regex patterns on every call. With 100 issues and 10 ID mappings, that's 1000 regex compilations. Pre-compile regexes once and reuse. Can use a struct with compiled regex, placeholder, and newID. Located in collision.go:329. Estimated performance improvement: 10-100x for large batches.","status":"open","priority":2,"issue_type":"task","created_at":"2025-10-12T16:39:18.305517-07:00","updated_at":"2025-10-12T16:39:18.305517-07:00"}
|
||||
{"id":"bd-28","title":"Improve error handling in dependency removal during remapping","description":"In updateDependencyReferences(), RemoveDependency errors are caught and ignored with continue (line 392). Comment says 'if dependency doesn't exist' but this catches ALL errors including real failures. Should check error type with errors.Is(err, ErrDependencyNotFound) and only ignore not-found errors, returning other errors properly.","status":"open","priority":3,"issue_type":"bug","created_at":"2025-10-12T16:39:26.78219-07:00","updated_at":"2025-10-12T16:39:26.78219-07:00"}
|
||||
{"id":"bd-29","title":"Use safer placeholder pattern in replaceIDReferences","description":"Currently uses __PLACEHOLDER_0__ which could theoretically collide with user text. Use a truly unique placeholder like null bytes: \\x00REMAP\\x00_0_\\x00 which are unlikely to appear in normal text. Located in collision.go:324. Very low probability issue but worth fixing for completeness.","status":"open","priority":3,"issue_type":"task","created_at":"2025-10-12T16:39:33.665449-07:00","updated_at":"2025-10-12T16:39:33.665449-07:00"}
|
||||
{"id":"bd-3","title":"Document git workflow in README","description":"Add Git Workflow section to README explaining binary vs text approaches","status":"closed","priority":1,"issue_type":"chore","created_at":"2025-10-12T00:43:03.461615-07:00","updated_at":"2025-10-12T16:19:11.970753-07:00","closed_at":"2025-10-12T00:43:30.283178-07:00"}
|
||||
{"id":"bd-30","title":"Remove unused issueMap in scoreCollisions","description":"scoreCollisions() creates issueMap and populates it (lines 135-138) but never uses it. Either remove it or add a TODO comment explaining future use. Located in collision.go:135-138. Cosmetic cleanup.","status":"open","priority":4,"issue_type":"chore","created_at":"2025-10-12T16:39:40.101611-07:00","updated_at":"2025-10-12T16:39:40.101611-07:00"}
|
||||
{"id":"bd-31","title":"Test issue for design field","description":"Testing the new update flags","design":"## Design Plan\\n- Add flags to update command\\n- Test thoroughly\\n- Document changes","acceptance_criteria":"- All three fields (design, notes, acceptance-criteria) can be updated\\n- Changes persist in database\\n- bd show displays the fields correctly","notes":"Implementation complete. All tests passing.","status":"closed","priority":3,"issue_type":"task","created_at":"2025-10-12T17:09:22.147446-07:00","updated_at":"2025-10-12T17:10:32.828906-07:00","closed_at":"2025-10-12T17:10:32.828906-07:00"}
|
||||
{"id":"bd-32","title":"bd should auto-detect .beads/*.db in current directory","description":"When bd is run without --db flag, it defaults to beads' own database instead of looking for a .beads/*.db file in the current working directory. This causes confusion when working on other projects that use beads for issue tracking (like vc).\n\nExpected behavior: bd should search for .beads/*.db in cwd and use that if found, before falling back to default beads database.\n\nExample: Running 'bd ready' in /Users/stevey/src/vc/vc/ should automatically find and use .beads/vc.db without requiring --db flag every time.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-10-13T21:15:16.866255-07:00","updated_at":"2025-10-13T21:30:47.456341-07:00","closed_at":"2025-10-13T21:30:47.456341-07:00"}
|
||||
{"id":"bd-33","title":"Document or automate JSONL sync workflow for git collaboration","description":"When using beads across multiple machines/environments via git, there's a workflow gap:\n\n1. Machine A: Create issues → stored in .beads/project.db\n2. Machine A: bd export -o .beads/issues.jsonl\n3. Machine A: git add .beads/issues.jsonl \u0026\u0026 git commit \u0026\u0026 git push\n4. Machine B: git pull\n5. Machine B: ??? issues.jsonl exists but project.db is empty/stale\n\nThe missing step is: bd import --db .beads/project.db -i .beads/issues.jsonl\n\nThis needs to be either:\na) Documented clearly in workflow docs\nb) Automated (e.g., git hook, or bd auto-imports if jsonl is newer than db)\nc) Both\n\nReal-world impact: User had Claude Code on GCP VM create vc issues from BOOTSTRAP.md. They were exported to issues.jsonl and committed. But on local machine, vc.db was empty until manual import was run.","status":"open","priority":1,"issue_type":"task","created_at":"2025-10-13T21:15:30.271236-07:00","updated_at":"2025-10-13T21:15:30.271236-07:00"}
|
||||
{"id":"bd-34","title":"Implement reserved database name _.db","description":"Auto-detection now skips .beads/_.db to prevent pollution when beads dogfoods itself. This allows beads to use its own issue tracker without interfering with other projects using beads in the same directory tree. Implementation includes filtering in findDatabase(), stopping directory walk when .beads/ is found, and documentation in README.md and CLAUDE.md.","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-10-13T21:46:15.189582-07:00","updated_at":"2025-10-13T21:54:26.388271-07:00","closed_at":"2025-10-13T21:54:26.388271-07:00"}
|
||||
{"id":"bd-35","title":"Auto-flush JSONL on CRUD operations with 5-second debounce","description":"Implemented automatic write-through from SQLite to JSONL with 5-second debouncing. After any CRUD operation (create, update, close, dep add/remove), changes are scheduled to flush to JSONL after 5 seconds of inactivity. On process exit, any pending changes are flushed immediately. This prevents .db and .jsonl from getting out of sync, solving the workflow gap where agents forget to run 'bd export'. Can be disabled with --no-auto-flush flag. Addresses bd-33.","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-10-13T22:21:13.94705-07:00","updated_at":"2025-10-13T22:22:38.359968-07:00","closed_at":"2025-10-13T22:22:38.359968-07:00"}
|
||||
{"id":"bd-36","title":"Handle missing JSONL directory in findJSONLPath","description":"findJSONLPath() assumes the database directory exists. If someone runs bd init to create a new database but the .beads directory doesn't exist yet, the glob operations might fail silently. Add os.MkdirAll(dbDir, 0755) to ensure directory exists before globbing. Located in cmd/bd/main.go:188-201.","status":"open","priority":2,"issue_type":"bug","created_at":"2025-10-13T22:34:35.944346-07:00","updated_at":"2025-10-13T22:34:35.944346-07:00"}
|
||||
{"id":"bd-37","title":"Refactor duplicate flush logic in PersistentPostRun","description":"PersistentPostRun contains a complete copy of the flush logic instead of calling flushToJSONL(). This violates DRY principle and makes maintenance harder. Refactor to use flushToJSONL() with a force parameter to bypass isDirty check, or extract shared logic into a helper function. Located in cmd/bd/main.go:104-138.","status":"open","priority":3,"issue_type":"task","created_at":"2025-10-13T22:34:43.429201-07:00","updated_at":"2025-10-13T22:34:43.429201-07:00"}
|
||||
{"id":"bd-38","title":"Add visibility for auto-flush failures","description":"flushToJSONL() writes warnings to stderr when flush fails, but calling code has no way to know if flush succeeded or failed. This means a command could return success even though JSONL is now out of sync. Consider maintaining a 'last flush status' variable or counter for failed flushes, and warn user after multiple consecutive failures (e.g., 3+). Located in cmd/bd/main.go:227-307.","status":"open","priority":2,"issue_type":"feature","created_at":"2025-10-13T22:34:52.440117-07:00","updated_at":"2025-10-13T22:34:52.440117-07:00"}
|
||||
{"id":"bd-39","title":"Optimize auto-flush to use incremental updates","description":"Every flush exports ALL issues and ALL dependencies, even if only one issue changed. For large projects (1000+ issues), this could be expensive. Current approach guarantees consistency, which is fine for MVP, but future optimization could track which issues changed and use incremental updates. Located in cmd/bd/main.go:255-276.","status":"open","priority":3,"issue_type":"feature","created_at":"2025-10-13T22:34:59.26425-07:00","updated_at":"2025-10-13T22:34:59.26425-07:00"}
|
||||
{"id":"bd-4","title":"Add demo GIF/video showing bd quickstart in action","description":"Record asciinema or create animated GIF showing the full workflow","status":"open","priority":2,"issue_type":"feature","created_at":"2025-10-12T10:50:49.500051-07:00","updated_at":"2025-10-12T16:19:11.97083-07:00","dependencies":[{"issue_id":"bd-4","depends_on_id":"bd-8","type":"parent-child","created_at":"2025-10-12T10:51:08.399915-07:00","created_by":"stevey"}]}
|
||||
{"id":"bd-40","title":"Make auto-flush debounce duration configurable","description":"flushDebounce is hardcoded to 5 seconds. Make it configurable via environment variable BEADS_FLUSH_DEBOUNCE (e.g., '500ms', '10s'). Current 5-second value is reasonable for interactive use, but CI/automated scenarios might want faster flush. Add getDebounceDuration() helper function. Located in cmd/bd/main.go:31.","status":"open","priority":3,"issue_type":"feature","created_at":"2025-10-13T22:35:06.126282-07:00","updated_at":"2025-10-13T22:35:06.126282-07:00"}
|
||||
{"id":"bd-41","title":"Add godoc comments for auto-flush functions","description":"Add comprehensive godoc comments for findJSONLPath(), markDirtyAndScheduleFlush(), and flushToJSONL() explaining behavior, concurrency considerations, and error handling. Include notes about debouncing behavior (timer resets on each write, flush occurs 5s after LAST operation) and flush-on-exit guarantees. Located in cmd/bd/main.go:188-307.","status":"open","priority":4,"issue_type":"chore","created_at":"2025-10-13T22:35:13.518442-07:00","updated_at":"2025-10-13T22:35:13.518442-07:00"}
|
||||
{"id":"bd-42","title":"Add test coverage for auto-flush feature","description":"Add comprehensive tests for auto-flush functionality:\\n- Test that markDirtyAndScheduleFlush() is called after CRUD operations\\n- Test debounce timing (rapid operations result in single flush)\\n- Test --no-auto-flush flag disables feature\\n- Test flush on program exit\\n- Test concurrent operations don't cause races\\n- Test error scenarios (disk full, permission denied, etc.)\\n- Test import command triggers auto-flush\\n\\nCurrent implementation has no test coverage for the auto-flush feature. Located in cmd/bd/main_test.go (to be created).","status":"open","priority":2,"issue_type":"task","created_at":"2025-10-13T22:35:22.079794-07:00","updated_at":"2025-10-13T22:35:22.079794-07:00"}
|
||||
{"id":"bd-5","title":"Implement MCP server for Claude Desktop","description":"Complete the claude-desktop-mcp example with working TypeScript implementation","status":"open","priority":1,"issue_type":"feature","created_at":"2025-10-12T10:50:50.942964-07:00","updated_at":"2025-10-12T16:19:11.970913-07:00","dependencies":[{"issue_id":"bd-5","depends_on_id":"bd-8","type":"parent-child","created_at":"2025-10-12T10:51:08.404381-07:00","created_by":"stevey"}]}
|
||||
{"id":"bd-6","title":"Add migration scripts for GitHub Issues","description":"Create scripts to import from GitHub Issues API or exported JSON","status":"open","priority":2,"issue_type":"feature","created_at":"2025-10-12T10:50:52.140018-07:00","updated_at":"2025-10-12T16:19:11.97099-07:00","dependencies":[{"issue_id":"bd-6","depends_on_id":"bd-8","type":"parent-child","created_at":"2025-10-12T10:51:08.40857-07:00","created_by":"stevey"}]}
|
||||
{"id":"bd-7","title":"Add performance benchmarks document","description":"Document actual performance metrics with hyperfine tests","status":"open","priority":3,"issue_type":"task","created_at":"2025-10-12T10:50:53.294516-07:00","updated_at":"2025-10-12T16:19:11.971065-07:00","dependencies":[{"issue_id":"bd-7","depends_on_id":"bd-8","type":"parent-child","created_at":"2025-10-12T10:51:08.412835-07:00","created_by":"stevey"}]}
|
||||
{"id":"bd-8","title":"Reach 1.0 release milestone","description":"Stabilize API, finalize documentation, comprehensive testing","status":"open","priority":1,"issue_type":"epic","created_at":"2025-10-12T10:50:54.457348-07:00","updated_at":"2025-10-12T16:19:11.971154-07:00"}
|
||||
{"id":"bd-9","title":"Build collision resolution tooling for distributed branch workflows","description":"When branches diverge and both create issues, auto-incrementing IDs collide on merge. Build excellent tooling to detect collisions during import, auto-renumber issues with fewer dependencies, update all references in descriptions and dependency links, and provide clear user feedback. Goal: keep beautiful brevity of numeric IDs (bd-302) while handling distributed creation gracefully.","status":"in_progress","priority":1,"issue_type":"feature","created_at":"2025-10-12T13:39:34.608218-07:00","updated_at":"2025-10-12T16:19:11.971233-07:00"}
|
||||
{"id":"bd-1","title":"Add export/import commands","description":"Support bd export --format=jsonl and bd import for text-based git workflow","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-10-12T00:43:03.453438-07:00","updated_at":"2025-10-13T22:47:34.424793-07:00","closed_at":"2025-10-12T20:20:06.977679-07:00"}
|
||||
{"id":"bd-10","title":"Extend export to include dependencies in JSONL","description":"Modify export.go to include dependencies array in each issue's JSONL output. This makes JSONL self-contained and enables proper collision resolution. Format: {\"id\":\"bd-10\",\"dependencies\":[{\"depends_on_id\":\"bd-5\",\"type\":\"blocks\"}]}","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-12T14:32:19.163526-07:00","updated_at":"2025-10-13T22:47:34.425938-07:00","closed_at":"2025-10-12T15:07:47.937992-07:00","dependencies":[{"issue_id":"bd-10","depends_on_id":"bd-9","type":"parent-child","created_at":"2025-10-12T14:35:59.213222-07:00","created_by":"stevey"}]}
|
||||
{"id":"bd-11","title":"Test issue to verify fix","description":"This should be bd-11 if the fix works","status":"closed","priority":3,"issue_type":"task","created_at":"2025-10-12T14:40:21.419082-07:00","updated_at":"2025-10-13T22:47:34.426147-07:00","closed_at":"2025-10-12T14:40:32.963312-07:00"}
|
||||
{"id":"bd-12","title":"Implement collision detection in import","description":"Create collision.go with detectCollisions() function. Compare incoming JSONL issues against DB state. Distinguish between: (1) exact match (idempotent), (2) ID match but different content (collision), (3) new issue. Return list of colliding issues.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-12T14:40:56.056588-07:00","updated_at":"2025-10-13T22:47:34.426356-07:00","closed_at":"2025-10-12T16:06:25.575038-07:00","dependencies":[{"issue_id":"bd-12","depends_on_id":"bd-9","type":"parent-child","created_at":"2025-10-12T14:41:07.947358-07:00","created_by":"stevey"}]}
|
||||
{"id":"bd-13","title":"Implement reference scoring algorithm","description":"Count references for each colliding issue: text mentions in descriptions/notes/design fields + dependency references. Sort collisions by score ascending (fewest refs first). This minimizes total updates during renumbering.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-12T14:40:56.204518-07:00","updated_at":"2025-10-13T22:47:34.426545-07:00","closed_at":"2025-10-12T16:26:46.572201-07:00","dependencies":[{"issue_id":"bd-13","depends_on_id":"bd-9","type":"parent-child","created_at":"2025-10-12T14:41:07.951605-07:00","created_by":"stevey"}]}
|
||||
{"id":"bd-14","title":"Implement ID remapping with reference updates","description":"Allocate new IDs for colliding issues. Update all text field references using word-boundary regex (\\bbd-10\\b). Update dependency records. Build id_mapping for reporting. Handle chain dependencies properly.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-12T14:40:56.367596-07:00","updated_at":"2025-10-13T22:47:34.42673-07:00","closed_at":"2025-10-12T16:35:13.159992-07:00","dependencies":[{"issue_id":"bd-14","depends_on_id":"bd-9","type":"parent-child","created_at":"2025-10-12T14:41:07.956041-07:00","created_by":"stevey"}]}
|
||||
{"id":"bd-15","title":"Add --resolve-collisions flag and user reporting","description":"Add import flags: --resolve-collisions (auto-fix) and --dry-run (preview). Display clear report: collisions detected, remappings applied (old→new with scores), reference counts updated. Default behavior: fail on collision (safe).","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-12T14:40:56.534721-07:00","updated_at":"2025-10-13T22:47:34.426927-07:00","closed_at":"2025-10-12T16:47:11.491645-07:00","dependencies":[{"issue_id":"bd-15","depends_on_id":"bd-9","type":"parent-child","created_at":"2025-10-12T14:41:07.961157-07:00","created_by":"stevey"}]}
|
||||
{"id":"bd-16","title":"Write comprehensive collision resolution tests","description":"Test cases: simple collision, multiple collisions, dependency updates, text reference updates, chain dependencies, edge cases (partial ID matches, case sensitivity, triple merges). Add to import_test.go and collision_test.go.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-12T14:40:56.702127-07:00","updated_at":"2025-10-13T22:47:34.427136-07:00","closed_at":"2025-10-12T16:54:25.273886-07:00","dependencies":[{"issue_id":"bd-16","depends_on_id":"bd-9","type":"parent-child","created_at":"2025-10-12T14:41:07.965816-07:00","created_by":"stevey"}]}
|
||||
{"id":"bd-17","title":"Update documentation for collision resolution","description":"Update README.md with collision resolution section. Update CLAUDE.md with new workflow. Document --resolve-collisions and --dry-run flags. Add example scenarios showing branch merge workflows.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-12T14:40:56.866649-07:00","updated_at":"2025-10-13T22:47:34.42731-07:00","closed_at":"2025-10-12T17:06:14.930928-07:00","dependencies":[{"issue_id":"bd-17","depends_on_id":"bd-9","type":"parent-child","created_at":"2025-10-12T14:41:07.970302-07:00","created_by":"stevey"}]}
|
||||
{"id":"bd-18","title":"Add design/notes/acceptance_criteria fields to update command","description":"Currently bd update only supports status, priority, title, assignee. Add support for --design, --notes, --acceptance-criteria flags. This makes it easier to add detailed designs to issues after creation.","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-10-12T14:40:57.032395-07:00","updated_at":"2025-10-13T22:47:34.427486-07:00","closed_at":"2025-10-12T17:10:53.958318-07:00"}
|
||||
{"id":"bd-19","title":"Fix import zero-value field handling","description":"Import uses zero-value checks (Priority != 0) to determine field updates. This prevents setting priority to 0 or clearing string fields. Export/import round-trip not fully idempotent for zero values. Consider JSON presence detection or explicit preserve-existing semantics. Location: cmd/bd/import.go:95-106","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-10-12T15:13:17.895083-07:00","updated_at":"2025-10-13T22:47:34.427656-07:00"}
|
||||
{"id":"bd-2","title":"Add PostgreSQL backend","description":"Implement PostgreSQL storage backend as alternative to SQLite for larger teams","status":"closed","priority":3,"issue_type":"feature","created_at":"2025-10-12T00:43:03.457453-07:00","updated_at":"2025-10-13T22:47:34.427865-07:00","closed_at":"2025-10-12T14:15:04.00695-07:00"}
|
||||
{"id":"bd-20","title":"Add --strict flag for dependency import failures","description":"Currently dependency import errors are warnings (logged to stderr, execution continues). Missing targets or cycles may indicate JSONL corruption. Add --strict flag to fail on any dependency errors for data integrity validation. Location: cmd/bd/import.go:159-164","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-10-12T15:13:18.954834-07:00","updated_at":"2025-10-13T22:47:34.428048-07:00"}
|
||||
{"id":"bd-21","title":"Simplify getNextID SQL query parameters","description":"Query passes prefix four times to same SQL query. Works but fragile if query changes. Consider simplifying SQL to require fewer parameters. Location: internal/storage/sqlite/sqlite.go:73-78","status":"closed","priority":3,"issue_type":"task","created_at":"2025-10-12T15:13:20.114733-07:00","updated_at":"2025-10-13T22:47:34.428218-07:00"}
|
||||
{"id":"bd-22","title":"Add validation/warning for malformed issue IDs","description":"getNextID silently ignores non-numeric ID suffixes (e.g., bd-foo). CAST returns NULL for invalid strings. Consider detecting and warning about malformed IDs in database. Location: internal/storage/sqlite/sqlite.go:79-82","status":"closed","priority":3,"issue_type":"task","created_at":"2025-10-12T15:13:21.195975-07:00","updated_at":"2025-10-13T22:47:34.428388-07:00"}
|
||||
{"id":"bd-23","title":"Optimize export dependency queries (N+1 problem)","description":"Export triggers separate GetDependencyRecords() per issue. For large DBs (1000+ issues), this is N+1 queries. Add GetAllDependencyRecords() to fetch all dependencies in one query. Location: cmd/bd/export.go:52-59, import.go:138-142","status":"closed","priority":3,"issue_type":"task","created_at":"2025-10-12T15:13:22.325113-07:00","updated_at":"2025-10-13T22:47:34.42855-07:00"}
|
||||
{"id":"bd-24","title":"Support ID space partitioning for parallel worker agents","description":"Enable external orchestrators (like AI worker swarms) to control issue ID assignment. Add --id flag to 'bd create' for explicit ID specification. Optionally support 'bd config set next_id N' to set the starting point for auto-increment. Storage layer already supports pre-assigned IDs (sqlite.go:52-71), just need CLI wiring. This keeps beads simple while letting orchestrators implement their own ID partitioning strategies to minimize merge conflicts. Complementary to bd-9's collision resolution.","status":"open","priority":1,"issue_type":"feature","created_at":"2025-10-12T16:10:37.808226-07:00","updated_at":"2025-10-13T22:47:34.428701-07:00"}
|
||||
{"id":"bd-25","title":"Add transaction support to storage layer for atomic multi-operation workflows","description":"Currently each storage method (CreateIssue, UpdateIssue, etc.) starts its own transaction. This makes it impossible to perform atomic multi-step operations like collision resolution. Add support for passing *sql.Tx through the storage interface, or create transaction-aware versions of methods. This would make remapCollisions and other batch operations truly atomic.","status":"open","priority":1,"issue_type":"feature","created_at":"2025-10-12T16:39:00.66572-07:00","updated_at":"2025-10-13T22:47:34.428848-07:00"}
|
||||
{"id":"bd-26","title":"Optimize reference updates to avoid loading all issues into memory","description":"In updateReferences(), we call SearchIssues with no filter to get ALL issues for updating references. For large databases (10k+ issues), this loads everything into memory. Options: 1) Use batched processing with LIMIT/OFFSET, 2) Use SQL UPDATE with REPLACE() directly, 3) Stream results instead of loading all at once. Located in collision.go:266","status":"open","priority":2,"issue_type":"task","created_at":"2025-10-12T16:39:10.327861-07:00","updated_at":"2025-10-13T22:47:34.429014-07:00"}
|
||||
{"id":"bd-27","title":"Cache compiled regexes in replaceIDReferences for performance","description":"replaceIDReferences() compiles the same regex patterns on every call. With 100 issues and 10 ID mappings, that's 1000 regex compilations. Pre-compile regexes once and reuse. Can use a struct with compiled regex, placeholder, and newID. Located in collision.go:329. Estimated performance improvement: 10-100x for large batches.","status":"open","priority":2,"issue_type":"task","created_at":"2025-10-12T16:39:18.305517-07:00","updated_at":"2025-10-13T22:47:34.429166-07:00"}
|
||||
{"id":"bd-28","title":"Improve error handling in dependency removal during remapping","description":"In updateDependencyReferences(), RemoveDependency errors are caught and ignored with continue (line 392). Comment says 'if dependency doesn't exist' but this catches ALL errors including real failures. Should check error type with errors.Is(err, ErrDependencyNotFound) and only ignore not-found errors, returning other errors properly.","status":"open","priority":3,"issue_type":"bug","created_at":"2025-10-12T16:39:26.78219-07:00","updated_at":"2025-10-13T22:47:34.429314-07:00"}
|
||||
{"id":"bd-29","title":"Use safer placeholder pattern in replaceIDReferences","description":"Currently uses __PLACEHOLDER_0__ which could theoretically collide with user text. Use a truly unique placeholder like null bytes: \\x00REMAP\\x00_0_\\x00 which are unlikely to appear in normal text. Located in collision.go:324. Very low probability issue but worth fixing for completeness.","status":"open","priority":3,"issue_type":"task","created_at":"2025-10-12T16:39:33.665449-07:00","updated_at":"2025-10-13T22:47:34.429483-07:00"}
|
||||
{"id":"bd-3","title":"Document git workflow in README","description":"Add Git Workflow section to README explaining binary vs text approaches","status":"closed","priority":1,"issue_type":"chore","created_at":"2025-10-12T00:43:03.461615-07:00","updated_at":"2025-10-13T22:47:34.429637-07:00","closed_at":"2025-10-12T00:43:30.283178-07:00"}
|
||||
{"id":"bd-30","title":"Remove unused issueMap in scoreCollisions","description":"scoreCollisions() creates issueMap and populates it (lines 135-138) but never uses it. Either remove it or add a TODO comment explaining future use. Located in collision.go:135-138. Cosmetic cleanup.","status":"open","priority":4,"issue_type":"chore","created_at":"2025-10-12T16:39:40.101611-07:00","updated_at":"2025-10-13T22:47:34.429789-07:00"}
|
||||
{"id":"bd-31","title":"Test issue for design field","description":"Testing the new update flags","design":"## Design Plan\\n- Add flags to update command\\n- Test thoroughly\\n- Document changes","acceptance_criteria":"- All three fields (design, notes, acceptance-criteria) can be updated\\n- Changes persist in database\\n- bd show displays the fields correctly","notes":"Implementation complete. All tests passing.","status":"closed","priority":3,"issue_type":"task","created_at":"2025-10-12T17:09:22.147446-07:00","updated_at":"2025-10-13T22:47:34.429937-07:00","closed_at":"2025-10-12T17:10:32.828906-07:00"}
|
||||
{"id":"bd-32","title":"bd should auto-detect .beads/*.db in current directory","description":"When bd is run without --db flag, it defaults to beads' own database instead of looking for a .beads/*.db file in the current working directory. This causes confusion when working on other projects that use beads for issue tracking (like vc).\n\nExpected behavior: bd should search for .beads/*.db in cwd and use that if found, before falling back to default beads database.\n\nExample: Running 'bd ready' in /Users/stevey/src/vc/vc/ should automatically find and use .beads/vc.db without requiring --db flag every time.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-10-13T21:15:16.866255-07:00","updated_at":"2025-10-13T22:47:34.430105-07:00","closed_at":"2025-10-13T21:30:47.456341-07:00"}
|
||||
{"id":"bd-33","title":"Document or automate JSONL sync workflow for git collaboration","description":"When using beads across multiple machines/environments via git, there's a workflow gap:\n\n1. Machine A: Create issues → stored in .beads/project.db\n2. Machine A: bd export -o .beads/issues.jsonl\n3. Machine A: git add .beads/issues.jsonl \u0026\u0026 git commit \u0026\u0026 git push\n4. Machine B: git pull\n5. Machine B: ??? issues.jsonl exists but project.db is empty/stale\n\nThe missing step is: bd import --db .beads/project.db -i .beads/issues.jsonl\n\nThis needs to be either:\na) Documented clearly in workflow docs\nb) Automated (e.g., git hook, or bd auto-imports if jsonl is newer than db)\nc) Both\n\nReal-world impact: User had Claude Code on GCP VM create vc issues from BOOTSTRAP.md. They were exported to issues.jsonl and committed. But on local machine, vc.db was empty until manual import was run.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-13T21:15:30.271236-07:00","updated_at":"2025-10-13T22:47:51.587822-07:00","closed_at":"2025-10-13T22:47:51.587822-07:00"}
|
||||
{"id":"bd-34","title":"Implement reserved database name _.db","description":"Auto-detection now skips .beads/_.db to prevent pollution when beads dogfoods itself. This allows beads to use its own issue tracker without interfering with other projects using beads in the same directory tree. Implementation includes filtering in findDatabase(), stopping directory walk when .beads/ is found, and documentation in README.md and CLAUDE.md.","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-10-13T21:46:15.189582-07:00","updated_at":"2025-10-13T22:47:34.430435-07:00","closed_at":"2025-10-13T21:54:26.388271-07:00"}
|
||||
{"id":"bd-35","title":"Auto-flush JSONL on CRUD operations with 5-second debounce","description":"Implemented automatic write-through from SQLite to JSONL with 5-second debouncing. After any CRUD operation (create, update, close, dep add/remove), changes are scheduled to flush to JSONL after 5 seconds of inactivity. On process exit, any pending changes are flushed immediately. This prevents .db and .jsonl from getting out of sync, solving the workflow gap where agents forget to run 'bd export'. Can be disabled with --no-auto-flush flag. Addresses bd-33.","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-10-13T22:21:13.94705-07:00","updated_at":"2025-10-13T22:47:34.430593-07:00","closed_at":"2025-10-13T22:22:38.359968-07:00"}
|
||||
{"id":"bd-36","title":"Handle missing JSONL directory in findJSONLPath","description":"findJSONLPath() assumes the database directory exists. If someone runs bd init to create a new database but the .beads directory doesn't exist yet, the glob operations might fail silently. Add os.MkdirAll(dbDir, 0755) to ensure directory exists before globbing. Located in cmd/bd/main.go:188-201.","status":"open","priority":2,"issue_type":"bug","created_at":"2025-10-13T22:34:35.944346-07:00","updated_at":"2025-10-13T22:47:34.43076-07:00"}
|
||||
{"id":"bd-37","title":"Refactor duplicate flush logic in PersistentPostRun","description":"PersistentPostRun contains a complete copy of the flush logic instead of calling flushToJSONL(). This violates DRY principle and makes maintenance harder. Refactor to use flushToJSONL() with a force parameter to bypass isDirty check, or extract shared logic into a helper function. Located in cmd/bd/main.go:104-138.","status":"open","priority":3,"issue_type":"task","created_at":"2025-10-13T22:34:43.429201-07:00","updated_at":"2025-10-13T22:47:34.430914-07:00"}
|
||||
{"id":"bd-38","title":"Add visibility for auto-flush failures","description":"flushToJSONL() writes warnings to stderr when flush fails, but calling code has no way to know if flush succeeded or failed. This means a command could return success even though JSONL is now out of sync. Consider maintaining a 'last flush status' variable or counter for failed flushes, and warn user after multiple consecutive failures (e.g., 3+). Located in cmd/bd/main.go:227-307.","status":"open","priority":2,"issue_type":"feature","created_at":"2025-10-13T22:34:52.440117-07:00","updated_at":"2025-10-13T22:47:34.4311-07:00"}
|
||||
{"id":"bd-39","title":"Optimize auto-flush to use incremental updates","description":"Every flush exports ALL issues and ALL dependencies, even if only one issue changed. For large projects (1000+ issues), this could be expensive. Current approach guarantees consistency, which is fine for MVP, but future optimization could track which issues changed and use incremental updates. Located in cmd/bd/main.go:255-276.","status":"open","priority":3,"issue_type":"feature","created_at":"2025-10-13T22:34:59.26425-07:00","updated_at":"2025-10-13T22:47:34.431263-07:00"}
|
||||
{"id":"bd-4","title":"Add demo GIF/video showing bd quickstart in action","description":"Record asciinema or create animated GIF showing the full workflow","status":"open","priority":2,"issue_type":"feature","created_at":"2025-10-12T10:50:49.500051-07:00","updated_at":"2025-10-13T22:47:34.431416-07:00","dependencies":[{"issue_id":"bd-4","depends_on_id":"bd-8","type":"parent-child","created_at":"2025-10-12T10:51:08.399915-07:00","created_by":"stevey"}]}
|
||||
{"id":"bd-40","title":"Make auto-flush debounce duration configurable","description":"flushDebounce is hardcoded to 5 seconds. Make it configurable via environment variable BEADS_FLUSH_DEBOUNCE (e.g., '500ms', '10s'). Current 5-second value is reasonable for interactive use, but CI/automated scenarios might want faster flush. Add getDebounceDuration() helper function. Located in cmd/bd/main.go:31.","status":"open","priority":3,"issue_type":"feature","created_at":"2025-10-13T22:35:06.126282-07:00","updated_at":"2025-10-13T22:47:34.431565-07:00"}
|
||||
{"id":"bd-41","title":"Add godoc comments for auto-flush functions","description":"Add comprehensive godoc comments for findJSONLPath(), markDirtyAndScheduleFlush(), and flushToJSONL() explaining behavior, concurrency considerations, and error handling. Include notes about debouncing behavior (timer resets on each write, flush occurs 5s after LAST operation) and flush-on-exit guarantees. Located in cmd/bd/main.go:188-307.","status":"open","priority":4,"issue_type":"chore","created_at":"2025-10-13T22:35:13.518442-07:00","updated_at":"2025-10-13T22:47:34.431729-07:00"}
|
||||
{"id":"bd-42","title":"Add test coverage for auto-flush feature","description":"Add comprehensive tests for auto-flush functionality:\\n- Test that markDirtyAndScheduleFlush() is called after CRUD operations\\n- Test debounce timing (rapid operations result in single flush)\\n- Test --no-auto-flush flag disables feature\\n- Test flush on program exit\\n- Test concurrent operations don't cause races\\n- Test error scenarios (disk full, permission denied, etc.)\\n- Test import command triggers auto-flush\\n\\nCurrent implementation has no test coverage for the auto-flush feature. Located in cmd/bd/main_test.go (to be created).","status":"open","priority":2,"issue_type":"task","created_at":"2025-10-13T22:35:22.079794-07:00","updated_at":"2025-10-13T22:47:34.431878-07:00"}
|
||||
{"id":"bd-43","title":"Test auto-sync feature","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-13T22:47:41.738165-07:00","updated_at":"2025-10-13T22:48:02.844213-07:00","closed_at":"2025-10-13T22:48:02.844213-07:00"}
|
||||
{"id":"bd-5","title":"Implement MCP server for Claude Desktop","description":"Complete the claude-desktop-mcp example with working TypeScript implementation","status":"open","priority":1,"issue_type":"feature","created_at":"2025-10-12T10:50:50.942964-07:00","updated_at":"2025-10-13T22:47:34.432027-07:00","dependencies":[{"issue_id":"bd-5","depends_on_id":"bd-8","type":"parent-child","created_at":"2025-10-12T10:51:08.404381-07:00","created_by":"stevey"}]}
|
||||
{"id":"bd-6","title":"Add migration scripts for GitHub Issues","description":"Create scripts to import from GitHub Issues API or exported JSON","status":"open","priority":2,"issue_type":"feature","created_at":"2025-10-12T10:50:52.140018-07:00","updated_at":"2025-10-13T22:47:34.432197-07:00","dependencies":[{"issue_id":"bd-6","depends_on_id":"bd-8","type":"parent-child","created_at":"2025-10-12T10:51:08.40857-07:00","created_by":"stevey"}]}
|
||||
{"id":"bd-7","title":"Add performance benchmarks document","description":"Document actual performance metrics with hyperfine tests","status":"open","priority":3,"issue_type":"task","created_at":"2025-10-12T10:50:53.294516-07:00","updated_at":"2025-10-13T22:47:34.432345-07:00","dependencies":[{"issue_id":"bd-7","depends_on_id":"bd-8","type":"parent-child","created_at":"2025-10-12T10:51:08.412835-07:00","created_by":"stevey"}]}
|
||||
{"id":"bd-8","title":"Reach 1.0 release milestone","description":"Stabilize API, finalize documentation, comprehensive testing","status":"open","priority":1,"issue_type":"epic","created_at":"2025-10-12T10:50:54.457348-07:00","updated_at":"2025-10-13T22:47:34.432488-07:00"}
|
||||
{"id":"bd-9","title":"Build collision resolution tooling for distributed branch workflows","description":"When branches diverge and both create issues, auto-incrementing IDs collide on merge. Build excellent tooling to detect collisions during import, auto-renumber issues with fewer dependencies, update all references in descriptions and dependency links, and provide clear user feedback. Goal: keep beautiful brevity of numeric IDs (bd-302) while handling distributed creation gracefully.","status":"in_progress","priority":1,"issue_type":"feature","created_at":"2025-10-12T13:39:34.608218-07:00","updated_at":"2025-10-13T22:47:34.432631-07:00"}
|
||||
|
||||
35
CLAUDE.md
35
CLAUDE.md
@@ -46,7 +46,7 @@ bd import -i .beads/issues.jsonl --resolve-collisions # Auto-resolve
|
||||
- `bd create "Found bug in auth" -t bug -p 1 --json`
|
||||
- Link it: `bd dep add <new-id> <current-id> --type discovered-from`
|
||||
5. **Complete**: `bd close <id> --reason "Implemented"`
|
||||
6. **Export**: Run `bd export -o .beads/issues.jsonl` before committing
|
||||
6. **Export**: Changes auto-sync to `.beads/issues.jsonl` (5-second debounce)
|
||||
|
||||
### Issue Types
|
||||
|
||||
@@ -99,29 +99,32 @@ beads/
|
||||
|
||||
1. **Run tests**: `go test ./...`
|
||||
2. **Run linter**: `golangci-lint run ./...` (ignore baseline warnings)
|
||||
3. **Export issues**: `bd export -o .beads/issues.jsonl`
|
||||
4. **Update docs**: If you changed behavior, update README.md or other docs
|
||||
5. **Git add both**: `git add .beads/issues.jsonl <your-changes>`
|
||||
3. **Update docs**: If you changed behavior, update README.md or other docs
|
||||
4. **Commit**: Issues auto-sync to `.beads/issues.jsonl` and import after pull
|
||||
|
||||
### Git Workflow
|
||||
|
||||
**Auto-sync is now automatic!** bd automatically:
|
||||
- **Exports** to JSONL after any CRUD operation (5-second debounce)
|
||||
- **Imports** from JSONL when it's newer than DB (e.g., after `git pull`)
|
||||
|
||||
```bash
|
||||
# Make changes
|
||||
git add <files>
|
||||
# Make changes and create/update issues
|
||||
bd create "Fix bug" -p 1
|
||||
bd update bd-42 --status in_progress
|
||||
|
||||
# Export beads issues
|
||||
bd export -o .beads/issues.jsonl
|
||||
git add .beads/issues.jsonl
|
||||
# JSONL is automatically updated after 5 seconds
|
||||
|
||||
# Commit
|
||||
# Commit (JSONL is already up-to-date)
|
||||
git add .
|
||||
git commit -m "Your message"
|
||||
|
||||
# After pull
|
||||
git pull
|
||||
bd import -i .beads/issues.jsonl # Sync SQLite cache
|
||||
# After pull - JSONL is automatically imported
|
||||
git pull # bd commands will auto-import the updated JSONL
|
||||
bd ready # Fresh data from git!
|
||||
```
|
||||
|
||||
Or use the git hooks in `examples/git-hooks/` for automation.
|
||||
**Optional**: Use the git hooks in `examples/git-hooks/` for immediate export (no 5-second wait) and guaranteed import after git operations. Not required with auto-sync enabled.
|
||||
|
||||
### Handling Import Collisions
|
||||
|
||||
@@ -227,12 +230,12 @@ bd dep tree bd-8 # Show 1.0 epic dependencies
|
||||
- Always use `--json` flags for programmatic use
|
||||
- Link discoveries with `discovered-from` to maintain context
|
||||
- Check `bd ready` before asking "what next?"
|
||||
- Export to JSONL before committing (or use git hooks)
|
||||
- Auto-sync is automatic! JSONL updates after CRUD ops, imports after git pull
|
||||
- Use `--no-auto-flush` or `--no-auto-import` to disable automatic sync if needed
|
||||
- Use `bd dep tree` to understand complex dependencies
|
||||
- Priority 0-1 issues are usually more important than 2-4
|
||||
- Use `--dry-run` to preview import collisions before resolving
|
||||
- Use `--resolve-collisions` for safe automatic branch merges
|
||||
- After resolving collisions, run `bd export` to save the updated state
|
||||
|
||||
## Building and Testing
|
||||
|
||||
|
||||
43
README.md
43
README.md
@@ -137,11 +137,11 @@ When you install bd on any machine with your project repo, you get:
|
||||
**How it works:**
|
||||
1. Each machine has a local SQLite cache (`.beads/*.db`) - gitignored
|
||||
2. Source of truth is JSONL (`.beads/issues.jsonl`) - committed to git
|
||||
3. `bd export` syncs SQLite → JSONL before commits
|
||||
4. `bd import` syncs JSONL → SQLite after pulls
|
||||
3. Auto-export syncs SQLite → JSONL after CRUD operations (5-second debounce)
|
||||
4. Auto-import syncs JSONL → SQLite when JSONL is newer (e.g., after `git pull`)
|
||||
5. Git handles distribution; AI handles merge conflicts
|
||||
|
||||
**The result:** Agents on your laptop, your desktop, and your coworker's machine all query and update what *feels* like a single shared database, but it's really just git doing what git does best - syncing text files across machines.
|
||||
**The result:** Agents on your laptop, your desktop, and your coworker's machine all query and update what *feels* like a single shared database, but it's really just git doing what git does best - syncing text files across machines. No manual export/import needed!
|
||||
|
||||
No PostgreSQL instance. No MySQL server. No hosted service. Just install bd, clone the repo, and you're connected to the "database."
|
||||
|
||||
@@ -428,10 +428,10 @@ bd uses a dual-storage approach:
|
||||
This gives you:
|
||||
- ✅ **Git-friendly storage** - Text diffs, AI-resolvable conflicts
|
||||
- ✅ **Fast queries** - SQLite indexes for dependency graphs
|
||||
- ✅ **Simple workflow** - Export before commit, import after pull
|
||||
- ✅ **Automatic sync** - Auto-export after CRUD ops, auto-import after pulls
|
||||
- ✅ **No daemon required** - In-process SQLite, ~10-100ms per command
|
||||
|
||||
When you run `bd create`, it writes to SQLite. Before committing to git, run `bd export` to sync to JSONL. After pulling, run `bd import` to sync back to SQLite. Git hooks can automate this.
|
||||
When you run `bd create`, it writes to SQLite. After 5 seconds of inactivity, changes automatically export to JSONL. After `git pull`, the next bd command automatically imports if JSONL is newer. No manual steps needed!
|
||||
|
||||
## Export/Import (JSONL Format)
|
||||
|
||||
@@ -590,7 +590,9 @@ Each line is a complete JSON issue object:
|
||||
|
||||
## Git Workflow
|
||||
|
||||
**Recommended approach**: Use JSONL export as source of truth, SQLite database as ephemeral cache (not committed to git).
|
||||
**Automatic sync by default!** bd now automatically syncs between SQLite and JSONL:
|
||||
- **Auto-export**: After CRUD operations, changes flush to JSONL after 5 seconds of inactivity
|
||||
- **Auto-import**: When JSONL is newer than DB (e.g., after `git pull`), next bd command imports automatically
|
||||
|
||||
### Setup
|
||||
|
||||
@@ -608,18 +610,21 @@ Add to git:
|
||||
### Workflow
|
||||
|
||||
```bash
|
||||
# Export before committing
|
||||
bd export -o .beads/issues.jsonl
|
||||
git add .beads/issues.jsonl
|
||||
# Create/update issues - they auto-export after 5 seconds
|
||||
bd create "Fix bug" -p 1
|
||||
bd update bd-42 --status in_progress
|
||||
|
||||
# Commit (JSONL is already up-to-date)
|
||||
git add .
|
||||
git commit -m "Update issues"
|
||||
git push
|
||||
|
||||
# Import after pulling
|
||||
# Pull and use - auto-imports if JSONL is newer
|
||||
git pull
|
||||
bd import -i .beads/issues.jsonl
|
||||
bd ready # Automatically imports first, then shows ready work
|
||||
```
|
||||
|
||||
### Automated with Git Hooks
|
||||
### Optional: Git Hooks for Immediate Sync
|
||||
|
||||
Create `.git/hooks/pre-commit`:
|
||||
```bash
|
||||
@@ -700,12 +705,22 @@ For true multi-agent coordination, you'd need additional tooling (like locks or
|
||||
|
||||
### Do I need to run export/import manually?
|
||||
|
||||
No! Install the git hooks from [examples/git-hooks/](examples/git-hooks/):
|
||||
**No! Sync is automatic by default.**
|
||||
|
||||
bd automatically:
|
||||
- **Exports** to JSONL after CRUD operations (5-second debounce)
|
||||
- **Imports** from JSONL when it's newer than DB (after `git pull`)
|
||||
|
||||
**Optional**: For immediate export (no 5-second wait) and guaranteed import after git operations, install the git hooks:
|
||||
```bash
|
||||
cd examples/git-hooks && ./install.sh
|
||||
```
|
||||
|
||||
The hooks automatically export before commits and import after pulls/merges/checkouts. Set it up once, forget about it.
|
||||
**Disable auto-sync** if needed:
|
||||
```bash
|
||||
bd --no-auto-flush create "Issue" # Disable auto-export
|
||||
bd --no-auto-import list # Disable auto-import
|
||||
```
|
||||
|
||||
### Can I track issues for multiple projects?
|
||||
|
||||
|
||||
136
cmd/bd/main.go
136
cmd/bd/main.go
@@ -1,6 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
@@ -31,6 +32,9 @@ var (
|
||||
flushDebounce = 5 * time.Second
|
||||
storeMutex sync.Mutex // Protects store access from background goroutine
|
||||
storeActive = false // Tracks if store is available
|
||||
|
||||
// Auto-import state
|
||||
autoImportEnabled = true // Can be disabled with --no-auto-import
|
||||
)
|
||||
|
||||
var rootCmd = &cobra.Command{
|
||||
@@ -46,6 +50,9 @@ var rootCmd = &cobra.Command{
|
||||
// Set auto-flush based on flag (invert no-auto-flush)
|
||||
autoFlushEnabled = !noAutoFlush
|
||||
|
||||
// Set auto-import based on flag (invert no-auto-import)
|
||||
autoImportEnabled = !noAutoImport
|
||||
|
||||
// Initialize storage
|
||||
if dbPath == "" {
|
||||
// Try to find database in order:
|
||||
@@ -81,6 +88,12 @@ var rootCmd = &cobra.Command{
|
||||
actor = "unknown"
|
||||
}
|
||||
}
|
||||
|
||||
// Auto-import if JSONL is newer than DB (e.g., after git pull)
|
||||
// Skip for import command itself to avoid recursion
|
||||
if cmd.Name() != "import" && autoImportEnabled {
|
||||
autoImportIfNewer()
|
||||
}
|
||||
},
|
||||
PersistentPostRun: func(cmd *cobra.Command, args []string) {
|
||||
// Signal that store is closing (prevents background flush from accessing closed store)
|
||||
@@ -201,6 +214,123 @@ func findJSONLPath() string {
|
||||
return filepath.Join(dbDir, "issues.jsonl")
|
||||
}
|
||||
|
||||
// autoImportIfNewer checks if JSONL is newer than DB and imports if so
|
||||
func autoImportIfNewer() {
|
||||
// Find JSONL path
|
||||
jsonlPath := findJSONLPath()
|
||||
|
||||
// Check if JSONL exists
|
||||
jsonlInfo, err := os.Stat(jsonlPath)
|
||||
if err != nil {
|
||||
// JSONL doesn't exist or can't be accessed, skip import
|
||||
return
|
||||
}
|
||||
|
||||
// Check if DB exists
|
||||
dbInfo, err := os.Stat(dbPath)
|
||||
if err != nil {
|
||||
// DB doesn't exist (new init?), skip import
|
||||
return
|
||||
}
|
||||
|
||||
// Compare modification times
|
||||
if !jsonlInfo.ModTime().After(dbInfo.ModTime()) {
|
||||
// JSONL is not newer than DB, skip import
|
||||
return
|
||||
}
|
||||
|
||||
// JSONL is newer, perform silent import
|
||||
ctx := context.Background()
|
||||
|
||||
// Read and parse JSONL
|
||||
f, err := os.Open(jsonlPath)
|
||||
if err != nil {
|
||||
// Can't open JSONL, skip import
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
scanner := bufio.NewScanner(f)
|
||||
var allIssues []*types.Issue
|
||||
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
if line == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
var issue types.Issue
|
||||
if err := json.Unmarshal([]byte(line), &issue); err != nil {
|
||||
// Parse error, skip this import
|
||||
return
|
||||
}
|
||||
|
||||
allIssues = append(allIssues, &issue)
|
||||
}
|
||||
|
||||
if err := scanner.Err(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Import issues (create new, update existing)
|
||||
for _, issue := range allIssues {
|
||||
existing, err := store.GetIssue(ctx, issue.ID)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if existing != nil {
|
||||
// Update existing issue
|
||||
updates := make(map[string]interface{})
|
||||
updates["title"] = issue.Title
|
||||
updates["description"] = issue.Description
|
||||
updates["design"] = issue.Design
|
||||
updates["acceptance_criteria"] = issue.AcceptanceCriteria
|
||||
updates["notes"] = issue.Notes
|
||||
updates["status"] = issue.Status
|
||||
updates["priority"] = issue.Priority
|
||||
updates["issue_type"] = issue.IssueType
|
||||
updates["assignee"] = issue.Assignee
|
||||
if issue.EstimatedMinutes != nil {
|
||||
updates["estimated_minutes"] = *issue.EstimatedMinutes
|
||||
}
|
||||
|
||||
_ = store.UpdateIssue(ctx, issue.ID, updates, "auto-import")
|
||||
} else {
|
||||
// Create new issue
|
||||
_ = store.CreateIssue(ctx, issue, "auto-import")
|
||||
}
|
||||
}
|
||||
|
||||
// Import dependencies
|
||||
for _, issue := range allIssues {
|
||||
if len(issue.Dependencies) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
// Get existing dependencies
|
||||
existingDeps, err := store.GetDependencyRecords(ctx, issue.ID)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// Add missing dependencies
|
||||
for _, dep := range issue.Dependencies {
|
||||
exists := false
|
||||
for _, existing := range existingDeps {
|
||||
if existing.DependsOnID == dep.DependsOnID && existing.Type == dep.Type {
|
||||
exists = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !exists {
|
||||
_ = store.AddDependency(ctx, dep, "auto-import")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// markDirtyAndScheduleFlush marks the database as dirty and schedules a flush
|
||||
func markDirtyAndScheduleFlush() {
|
||||
if !autoFlushEnabled {
|
||||
@@ -307,13 +437,17 @@ func flushToJSONL() {
|
||||
}
|
||||
}
|
||||
|
||||
var noAutoFlush bool
|
||||
var (
|
||||
noAutoFlush bool
|
||||
noAutoImport bool
|
||||
)
|
||||
|
||||
func init() {
|
||||
rootCmd.PersistentFlags().StringVar(&dbPath, "db", "", "Database path (default: auto-discover .beads/*.db or ~/.beads/default.db)")
|
||||
rootCmd.PersistentFlags().StringVar(&actor, "actor", "", "Actor name for audit trail (default: $USER)")
|
||||
rootCmd.PersistentFlags().BoolVar(&jsonOutput, "json", false, "Output in JSON format")
|
||||
rootCmd.PersistentFlags().BoolVar(&noAutoFlush, "no-auto-flush", false, "Disable automatic JSONL sync after CRUD operations")
|
||||
rootCmd.PersistentFlags().BoolVar(&noAutoImport, "no-auto-import", false, "Disable automatic JSONL import when newer than DB")
|
||||
}
|
||||
|
||||
var createCmd = &cobra.Command{
|
||||
|
||||
@@ -84,6 +84,14 @@ var quickstartCmd = &cobra.Command{
|
||||
fmt.Printf(" • Join with %s table for powerful queries\n", cyan("issues"))
|
||||
fmt.Printf(" • See %s for integration patterns\n\n", cyan("EXTENDING.md"))
|
||||
|
||||
fmt.Printf("%s\n", bold("GIT WORKFLOW (AUTO-SYNC)"))
|
||||
fmt.Printf(" bd automatically keeps git in sync:\n")
|
||||
fmt.Printf(" • %s Export to JSONL after CRUD operations (5s debounce)\n", green("✓"))
|
||||
fmt.Printf(" • %s Import from JSONL when newer than DB (after %s)\n", green("✓"), cyan("git pull"))
|
||||
fmt.Printf(" • %s Works seamlessly across machines and team members\n", green("✓"))
|
||||
fmt.Printf(" • No manual export/import needed!\n")
|
||||
fmt.Printf(" Disable with: %s or %s\n\n", cyan("--no-auto-flush"), cyan("--no-auto-import"))
|
||||
|
||||
fmt.Printf("%s\n", green("Ready to start!"))
|
||||
fmt.Printf("Run %s to create your first issue.\n\n", cyan("bd create \"My first issue\""))
|
||||
},
|
||||
|
||||
@@ -1,15 +1,32 @@
|
||||
# Git Hooks for Beads
|
||||
|
||||
Automatic export/import of beads issues during git operations.
|
||||
Optional git hooks for immediate export/import of beads issues.
|
||||
|
||||
**NOTE**: As of bd v0.9+, **auto-sync is enabled by default!** These hooks are optional and provide:
|
||||
- **Immediate export** (no 5-second debounce wait)
|
||||
- **Guaranteed import** after every git operation
|
||||
- **Extra safety** for critical workflows
|
||||
|
||||
## What These Hooks Do
|
||||
|
||||
- **pre-commit**: Exports SQLite → JSONL before every commit
|
||||
- **post-merge**: Imports JSONL → SQLite after git pull/merge
|
||||
- **post-checkout**: Imports JSONL → SQLite after branch switching
|
||||
- **pre-commit**: Exports SQLite → JSONL before every commit (immediate, no debounce)
|
||||
- **post-merge**: Imports JSONL → SQLite after git pull/merge (guaranteed)
|
||||
- **post-checkout**: Imports JSONL → SQLite after branch switching (guaranteed)
|
||||
|
||||
This keeps your `.beads/issues.jsonl` (committed to git) in sync with your local SQLite database (gitignored).
|
||||
|
||||
## Do You Need These Hooks?
|
||||
|
||||
**Most users don't need hooks anymore!** bd automatically:
|
||||
- Exports after CRUD operations (5-second debounce)
|
||||
- Imports when JSONL is newer than DB
|
||||
|
||||
**Install hooks if you:**
|
||||
- Want immediate export (no waiting 5 seconds)
|
||||
- Want guaranteed import after every git operation
|
||||
- Need extra certainty for team workflows
|
||||
- Prefer explicit automation over automatic behavior
|
||||
|
||||
## Installation
|
||||
|
||||
### Quick Install
|
||||
|
||||
Reference in New Issue
Block a user