diff --git a/.beads/beads.jsonl b/.beads/beads.jsonl index c59e520d..dbb4a676 100644 --- a/.beads/beads.jsonl +++ b/.beads/beads.jsonl @@ -29,7 +29,7 @@ {"id":"bd-124","title":"Add 'bd sync' command for explicit synchronization","description":"Add explicit `bd sync` command as fallback for manual synchronization after git pull.\n\nBehavior:\n- Import from .beads/issues.jsonl\n- If daemon mode: send RPC command to daemon to re-import\n- If non-daemon: directly import to local db\n- Show summary: \"Imported N issues, updated M issues\"\n\nUsage:\n```bash\ngit pull\nbd sync # Force immediate sync\n```\n\nThis complements auto-detection but gives users manual control.","notes":"IMPLEMENTED:\n\nAdded `bd sync --import-only` flag that:\n- Imports from .beads/issues.jsonl automatically (no need to specify path)\n- Works in both daemon and non-daemon modes\n- Shows summary: \"Import complete: X created, Y updated, Z unchanged, N remapped\"\n- Handles collisions automatically with --resolve-collisions\n\nUsage:\n```bash\ngit pull\nbd sync --import-only # Force immediate sync\n```\n\nThe existing `bd sync` command does full git workflow (export, commit, pull, import, push). The new --import-only flag complements --flush-only for granular control.\n\nImplementation in cmd/bd/sync.go","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-25T22:46:52.139434-07:00","updated_at":"2025-10-26T12:27:40.539108-07:00","closed_at":"2025-10-26T12:27:40.539108-07:00"} {"id":"bd-125","title":"Add integration test for git pull sync scenario","description":"Add integration test simulating the git pull sync issue.\n\nTest scenario:\n1. Create temp git repo with beads initialized\n2. Clone 1: Create and close issue, export, commit, push\n3. Clone 2: Start daemon, git pull\n4. Clone 2: Verify bd show \u003cissue\u003e reflects closed status immediately\n5. Verify no manual import or daemon restart needed\n\nAlso test:\n- Non-daemon mode (--no-daemon) handles git pull correctly\n- bd sync command works in both modes\n- Performance: staleness check adds \u003c10ms overhead\n\nDepends on staleness detection implementation.","status":"closed","priority":0,"issue_type":"task","created_at":"2025-10-25T22:47:01.101808-07:00","updated_at":"2025-10-26T12:32:34.054034-07:00","closed_at":"2025-10-26T12:32:34.054034-07:00","dependencies":[{"issue_id":"bd-125","depends_on_id":"bd-123","type":"blocks","created_at":"2025-10-25T22:47:05.615638-07:00","created_by":"daemon"}]} {"id":"bd-126","title":"Add optional post-merge git hook example for bd sync","description":"Create example git hook that auto-runs bd sync after git pull/merge.\n\nAdd to examples/git-hooks/:\n- post-merge hook that checks if .beads/issues.jsonl changed\n- If changed: run `bd sync` automatically\n- Make it optional/documented (not auto-installed)\n\nBenefits:\n- Zero-friction sync after git pull\n- Complements auto-detection as belt-and-suspenders\n\nNote: post-merge hook already exists for pre-commit/post-merge. Extend it to support sync.","status":"open","priority":2,"issue_type":"task","created_at":"2025-10-25T22:47:14.668842-07:00","updated_at":"2025-10-25T23:15:33.515404-07:00","dependencies":[{"issue_id":"bd-126","depends_on_id":"bd-124","type":"blocks","created_at":"2025-10-25T22:47:16.949519-07:00","created_by":"daemon"}]} -{"id":"bd-127","title":"Update documentation for auto-sync behavior","description":"Update documentation to explain auto-sync after git pull.\n\nFiles to update:\n1. README.md - Add section on git workflow and auto-sync\n2. AGENTS.md - Note that bd auto-detects JSONL changes after git pull\n3. WORKFLOW.md - Update git pull workflow to remove manual import step\n4. FAQ.md - Add Q\u0026A about sync behavior and staleness\n\nKey points:\n- bd automatically detects when JSONL is newer than database\n- No manual import needed after git pull\n- bd sync command available for manual control\n- Optional git hook for guaranteed sync","status":"open","priority":2,"issue_type":"task","created_at":"2025-10-25T22:47:24.618649-07:00","updated_at":"2025-10-25T23:15:33.515627-07:00"} +{"id":"bd-127","title":"Update documentation for auto-sync behavior","description":"Update documentation to explain auto-sync after git pull.\n\nFiles to update:\n1. README.md - Add section on git workflow and auto-sync\n2. AGENTS.md - Note that bd auto-detects JSONL changes after git pull\n3. WORKFLOW.md - Update git pull workflow to remove manual import step\n4. FAQ.md - Add Q\u0026A about sync behavior and staleness\n\nKey points:\n- bd automatically detects when JSONL is newer than database\n- No manual import needed after git pull\n- bd sync command available for manual control\n- Optional git hook for guaranteed sync","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-25T22:47:24.618649-07:00","updated_at":"2025-10-26T12:44:33.996187-07:00","closed_at":"2025-10-26T12:44:33.996187-07:00"} {"id":"bd-128","title":"Refactor autoImportIfNewer to be callable from daemon","description":"The staleness check in [deleted:bd-160] detects when JSONL is newer than last import, but can't trigger the actual import because autoImportIfNewer() is in cmd/bd and uses global variables.\n\nNeed to:\n1. Extract core import logic from autoImportIfNewer() into importable function\n2. Move to internal/autoimport or similar package\n3. Make it callable from daemon (no global state dependency)\n4. Update staleness check in server.go to call actual import instead of just logging\n\nThis completes the auto-sync feature - daemon will truly auto-import after git pull.","status":"closed","priority":0,"issue_type":"task","created_at":"2025-10-25T23:10:41.392416-07:00","updated_at":"2025-10-25T23:51:09.811006-07:00","closed_at":"2025-10-25T23:51:09.811006-07:00"} {"id":"bd-129","title":"Enforce daemon singleton per workspace with file locking","description":"Agent in ~/src/wyvern discovered 4 simultaneous daemon processes running, causing infinite directory recursion (.beads/.beads/.beads/...). Each daemon used relative paths and created nested .beads/ directories.\n\nRoot cause: No singleton enforcement. Multiple `bd daemon` processes can start in same workspace.\n\nExpected: One daemon per workspace (each workspace = separate .beads/ dir with bd.sock)\nActual: Multiple daemons can run simultaneously in same workspace\n\nNote: Separate git clones = separate workspaces = separate daemons (correct). Git worktrees share .beads/ and have known limitations (documented, use --no-daemon).","design":"Use flock (file locking) on daemon socket or database file to enforce singleton:\n\n1. On daemon start, attempt exclusive lock on .beads/bd.sock or .beads/daemon.lock\n2. If lock held by another process, refuse to start (exit with clear error)\n3. Hold lock for lifetime of daemon process\n4. Release lock on daemon shutdown\n\nAlternative: Use PID file with stale detection (check if PID is still running)\n\nImplementation location: Daemon startup code in cmd/bd/ or internal/daemon/","acceptance_criteria":"1. Starting second daemon process in same workspace fails with clear error\n2. Test: Start daemon, attempt second start, verify failure\n3. Killing daemon releases lock, allowing new daemon to start\n4. No infinite .beads/ directory recursion possible\n5. Works correctly with auto-start mechanism","status":"in_progress","priority":0,"issue_type":"bug","created_at":"2025-10-25T23:13:12.269549-07:00","updated_at":"2025-10-25T23:15:33.516072-07:00"} {"id":"bd-13","title":"Phase 2: Implement VCStorage Wrapper","description":"Create VCStorage wrapper that embeds beads.Storage and adds VC-specific operations.\n\n**Goal:** Build clean abstraction layer where VC extends Beads without modifying Beads library.\n\n**Architecture:**\n- VCStorage embeds beads.Storage (delegates core operations)\n- VCStorage adds VC-specific methods (executor instances, events)\n- Same database, separate table namespaces (Beads tables + VC tables)\n- Zero changes to Beads library code\n\n**Key Tasks:**\n1. Create VCStorage struct that embeds beads.Storage\n2. Implement VC-specific methods: CreateExecutorInstance(), GetStaleExecutors(), LogEvent(), UpdateExecutionState()\n3. Create VC table schemas (executor_instances, issue_execution_state, agent_events)\n4. Verify type compatibility between VC types.Issue and Beads Issue\n5. Create MockVCStorage for testing\n6. Write unit tests for VC-specific methods\n7. Write integration tests (end-to-end with Beads)\n8. Benchmark performance vs current SQLite\n9. Verify NO changes needed to Beads library\n\n**Acceptance Criteria:**\n- VCStorage successfully wraps Beads storage (embedding works)\n- VC-specific tables created and accessible via foreign keys to Beads tables\n- VC-specific methods work (executor instances, events)\n- Core operations delegate to Beads correctly\n- Tests pass with \u003e90% coverage\n- Performance benchmark shows no regression\n- Beads library remains unmodified and standalone\n\n**Technical Details:**\n- Use beadsStore.DB() to get underlying database connection\n- Create VC tables with FOREIGN KEY references to Beads issues table\n- Schema separation: Beads owns (issues, dependencies, labels), VC owns (executor_instances, agent_events)\n- Testing: Embed MockBeadsStorage in MockVCStorage\n\n**Dependencies:**\n- Blocked by Phase 1 (need Beads library imported)\n\n**Estimated Effort:** 1.5 sprints","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-22T14:04:36.674165-07:00","updated_at":"2025-10-25T23:15:33.472658-07:00","closed_at":"2025-10-22T21:37:48.747033-07:00","dependencies":[{"issue_id":"bd-13","depends_on_id":"bd-11","type":"parent-child","created_at":"2025-10-24T13:17:40.321936-07:00","created_by":"renumber"},{"issue_id":"bd-13","depends_on_id":"bd-12","type":"blocks","created_at":"2025-10-24T13:17:40.322171-07:00","created_by":"renumber"}]} @@ -44,6 +44,8 @@ {"id":"bd-138","title":"Add configurable SortPolicy to GetReadyWork","description":"Add SortPolicy field to WorkFilter to support different ordering strategies: hybrid (default), priority-first, oldest-first. See SORT_POLICY_DESIGN.md for full specification.","design":"See SORT_POLICY_DESIGN.md for complete design.\n\nImplementation summary:\n1. Add SortPolicy type and constants (hybrid, priority, oldest)\n2. Add SortPolicy field to WorkFilter \n3. Implement buildOrderByClause() to generate SQL based on policy\n4. Default to hybrid for backwards compatibility\n5. Add --sort flag to bd ready command\n\nThis enables autonomous execution systems (like VC) to use strict priority ordering while preserving the current hybrid behavior for interactive use.","acceptance_criteria":"Unit tests verify each policy generates correct ORDER BY. Integration tests verify priority, hybrid, and oldest policies select issues in expected order. CLI bd ready --sort priority works. Empty SortPolicy defaults to hybrid (backwards compatible).","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-10-26T12:27:22.889669-07:00","updated_at":"2025-10-26T12:28:21.152107-07:00","closed_at":"2025-10-26T12:28:21.152107-07:00"} {"id":"bd-139","title":"Add 'bd sync' command for explicit synchronization","description":"Add explicit `bd sync` command as fallback for manual synchronization after git pull.\n\nBehavior:\n- Import from .beads/issues.jsonl\n- If daemon mode: send RPC command to daemon to re-import\n- If non-daemon: directly import to local db\n- Show summary: \"Imported N issues, updated M issues\"\n\nUsage:\n```bash\ngit pull\nbd sync # Force immediate sync\n```\n\nThis complements auto-detection but gives users manual control.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-26T12:27:22.890111-07:00","updated_at":"2025-10-26T12:28:21.133303-07:00","closed_at":"2025-10-26T12:28:21.133303-07:00"} {"id":"bd-14","title":"Phase 3: Migration Path \u0026 Database Schema Alignment","description":"Enable existing .beads/vc.db files to work with Beads library through automated migration.\n\n**Goal:** Provide safe, tested migration path from SQLite implementation to Beads library.\n\n**Key Tasks:**\n1. Run compatibility tests against production databases\n2. Identify schema differences (columns, indexes, constraints)\n3. Document required migrations\n4. Create migration CLI command: 'vc migrate --from sqlite --to beads'\n5. Add dry-run mode for preview\n6. Add backup/restore capability\n7. Implement rollback mechanism\n8. Add auto-detection of schema version on startup\n9. Add auto-migrate with user prompt\n\n**Acceptance Criteria:**\n- Existing databases migrate successfully\n- Data integrity preserved (zero data loss verified via checksums)\n- Rollback works if migration fails\n- Migration tested on real production VC databases\n- Dry-run mode shows exactly what will change\n- Backup created before migration\n- Feature flag: VC_FORCE_SQLITE=true provides escape hatch\n\n**Technical Details:**\n- Compare current SQLite schema with Beads schema\n- Handle version detection (read schema_version or detect from structure)\n- Migration should be idempotent (safe to run multiple times)\n- Backup strategy: Copy .beads/vc.db to .beads/vc.db.backup-\u003ctimestamp\u003e\n- Verify foreign key integrity after migration\n\n**Safety Measures:**\n- Require executor shutdown before migration (check for running executors)\n- Atomic migration (BEGIN IMMEDIATE transaction)\n- Comprehensive pre/post migration validation\n- Clear error messages with recovery instructions\n\n**Dependencies:**\n- Blocked by Phase 2 (need VCStorage implementation)\n\n**Estimated Effort:** 0.5 sprint","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-22T14:04:51.320435-07:00","updated_at":"2025-10-25T23:15:33.473975-07:00","closed_at":"2025-10-22T21:37:48.748273-07:00","dependencies":[{"issue_id":"bd-14","depends_on_id":"bd-11","type":"parent-child","created_at":"2025-10-24T13:17:40.323317-07:00","created_by":"renumber"},{"issue_id":"bd-14","depends_on_id":"bd-13","type":"blocks","created_at":"2025-10-24T13:17:40.323527-07:00","created_by":"renumber"}]} +{"id":"bd-140","title":"Clarify that humans should run bd init, not agents","description":"Current docs are ambiguous about who runs `bd init`. This leads to agents running it incorrectly, causing daemon issues, sync problems, and confusion.\n\n**Problem:** Agents struggle with:\n- Interactive prompts (git hooks)\n- Directory detection\n- Understanding when to import existing JSONL\n- Daemon startup timing\n\n**Solution:** Make it crystal clear that `bd init` is a human setup task, like `npm install` or `git init`.","design":"Update docs to emphasize:\n1. README.md - Rewrite Quick Start to show human does `bd init` first\n2. AGENTS.md - Add clear \"Human does init, agent uses bd\" section\n3. QUICKSTART.md - Update tutorial flow\n4. FAQ.md - Add Q\u0026A about who runs init","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-26T12:50:14.555803-07:00","updated_at":"2025-10-26T12:53:10.836604-07:00","closed_at":"2025-10-26T12:53:10.836604-07:00","dependencies":[{"issue_id":"bd-140","depends_on_id":"bd-141","type":"blocks","created_at":"2025-10-26T12:52:23.433758-07:00","created_by":"daemon"}]} +{"id":"bd-141","title":"Make bd init --quiet skip interactive prompts","description":"Currently `bd init --quiet` flag exists but doesn't actually skip the git hooks prompt. This makes it impossible for agents to run init non-interactively.\n\n**Problem:** Agents setting up repos can't use `bd init` because it prompts for user input.\n\n**Solution:** Make `--quiet` flag actually work:\n- Skip git hooks prompt\n- Auto-install hooks by default in quiet mode (safest)\n- No output except errors","design":"In cmd/bd/init.go, check the quiet flag before prompting:\n\n```go\nif isGitRepo() \u0026\u0026 !hooksInstalled() {\n if quiet {\n // Auto-install hooks silently in quiet mode\n _ = installGitHooks() // Ignore errors\n } else {\n // Show prompt for interactive mode\n fmt.Printf(\"Install git hooks now? [Y/n] \")\n // ... existing prompt logic\n }\n}\n```","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-10-26T12:52:19.482162-07:00","updated_at":"2025-10-26T12:52:39.295979-07:00","closed_at":"2025-10-26T12:52:39.295979-07:00"} {"id":"bd-15","title":"Phase 4: Gradual Cutover \u0026 Production Rollout","description":"Replace SQLite implementation with Beads library in production and remove legacy code.\n\n**Goal:** Complete transition to Beads library, deprecate and remove custom SQLite implementation.\n\n**Key Tasks:**\n1. Run VC executor with Beads library in CI\n2. Dogfood: Use Beads library for VC's own development\n3. Monitor for regressions and performance issues\n4. Flip feature flag: VC_USE_BEADS_LIBRARY=true by default\n5. Monitor production logs for errors\n6. Collect user feedback\n7. Add deprecation notice to CLAUDE.md\n8. Provide migration guide for users\n9. Remove legacy code: internal/storage/sqlite/sqlite.go (~1500 lines)\n10. Remove migration framework: internal/storage/migrations/\n11. Remove manual transaction management code\n12. Update all documentation\n\n**Acceptance Criteria:**\n- Beads library enabled by default in production\n- Zero production incidents related to migration\n- Performance meets or exceeds SQLite implementation\n- All tests passing with Beads library\n- Legacy SQLite code removed\n- Documentation updated\n- Celebration documented 🎉\n\n**Rollout Strategy:**\n1. Week 1: Enable for CI/testing environments\n2. Week 2: Dogfood on VC development\n3. Week 3: Enable for 50% of production (canary)\n4. Week 4: Enable for 100% of production\n5. Week 5: Remove legacy code\n\n**Monitoring:**\n- Track error rates before/after cutover\n- Monitor database query performance\n- Track issue creation/update latency\n- Monitor executor claim performance\n\n**Rollback Plan:**\n- Keep VC_FORCE_SQLITE=true escape hatch for 2 weeks post-cutover\n- Keep legacy code for 1 sprint after cutover\n- Document rollback procedure\n\n**Success Metrics:**\n- Zero data loss\n- No performance regression (\u003c 5% latency increase acceptable)\n- Reduced maintenance burden (code LOC reduction)\n- Positive developer feedback\n\n**Dependencies:**\n- Blocked by Phase 3 (need migration tooling)\n\n**Estimated Effort:** 1 sprint","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-22T14:05:07.755107-07:00","updated_at":"2025-10-25T23:15:33.474948-07:00","closed_at":"2025-10-22T21:37:48.748919-07:00","dependencies":[{"issue_id":"bd-15","depends_on_id":"bd-11","type":"parent-child","created_at":"2025-10-24T13:17:40.324637-07:00","created_by":"renumber"},{"issue_id":"bd-15","depends_on_id":"bd-14","type":"blocks","created_at":"2025-10-24T13:17:40.324851-07:00","created_by":"renumber"}]} {"id":"bd-16","title":"Add lifecycle safety docs and tests for UnderlyingDB() method","description":"The new UnderlyingDB() method exposes the raw *sql.DB connection for extensions like VC to create their own tables. While database/sql is concurrency-safe, there are lifecycle and misuse risks that need documentation and testing.\n\n**What needs to be done:**\n\n1. **Enhanced documentation** - Expand UnderlyingDB() comments to warn:\n - Callers MUST NOT call Close() on returned DB\n - Do NOT change pool/driver settings (SetMaxOpenConns, SetConnMaxIdleTime)\n - Do NOT modify SQLite PRAGMAs (WAL mode, journal, etc.)\n - Expect errors after Storage.Close() - use contexts\n - Keep write transactions short to avoid blocking core storage\n\n2. **Add lifecycle tracking** - Implement closed flag:\n - Add atomic.Bool closed field to SQLiteStorage\n - Set flag in Close(), clear in New()\n - Optional: Add IsClosed() bool method\n\n3. **Add safety tests** (run with -race):\n - TestUnderlyingDB_ConcurrentAccess - N goroutines using UnderlyingDB() during normal storage ops\n - TestUnderlyingDB_AfterClose - Verify operations fail cleanly after storage closed\n - TestUnderlyingDB_CreateExtensionTables - Create VC table with FK to issues, verify FK enforcement\n - TestUnderlyingDB_LongTxDoesNotCorrupt - Ensure long read tx doesn't block writes indefinitely\n\n**Why this matters:**\nVC will use this to create tables in the same database. Need to ensure production-ready safety without over-engineering.\n\n**Estimated effort:** S+S+S = M total (1-3h)","design":"Oracle recommends \"simple path\": enhanced docs + minimal guardrails + focused tests. See oracle output for detailed rationale on concurrency safety, lifecycle risks, and when to consider advanced path (wrapping interface).","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-22T17:07:56.812983-07:00","updated_at":"2025-10-25T23:15:33.476053-07:00","closed_at":"2025-10-22T20:10:52.636372-07:00"} {"id":"bd-17","title":"Update EXTENDING.md with UnderlyingDB() usage and best practices","description":"EXTENDING.md currently shows how to use direct sql.Open() to access the database, but doesn't mention the new UnderlyingDB() method that's the recommended way for extensions.\n\n**Update needed:**\n1. Add section showing UnderlyingDB() usage:\n ```go\n store, err := beads.NewSQLiteStorage(dbPath)\n db := store.UnderlyingDB()\n // Create extension tables using db\n ```\n\n2. Document when to use UnderlyingDB() vs direct sql.Open():\n - Use UnderlyingDB() when you want to share the storage connection\n - Use sql.Open() when you need independent connection management\n\n3. Add safety warnings (cross-reference from UnderlyingDB() docs):\n - Don't close the DB\n - Don't modify pool settings\n - Keep transactions short\n\n4. Update the VC example to show UnderlyingDB() pattern\n\n5. Explain beads.Storage.UnderlyingDB() in the API section","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-22T17:07:56.820056-07:00","updated_at":"2025-10-25T23:15:33.478579-07:00","closed_at":"2025-10-22T19:41:19.895847-07:00","dependencies":[{"issue_id":"bd-17","depends_on_id":"bd-10","type":"discovered-from","created_at":"2025-10-24T13:17:40.32522-07:00","created_by":"renumber"}]} diff --git a/AGENTS.md b/AGENTS.md index 5d53f1e9..8748a77b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -4,6 +4,23 @@ This is **beads** (command: `bd`), an issue tracker designed for AI-supervised coding workflows. We dogfood our own tool! +## Human Setup vs Agent Usage + +**IMPORTANT:** If you need to initialize bd, use the `--quiet` flag: + +```bash +bd init --quiet # Non-interactive, auto-installs git hooks, no prompts +``` + +**Why `--quiet`?** Regular `bd init` has interactive prompts (git hooks) that confuse agents. The `--quiet` flag makes it fully non-interactive: +- Automatically installs git hooks +- No prompts for user input +- Safe for agent-driven repo setup + +**If the human already initialized:** Just use bd normally with `bd create`, `bd ready`, `bd update`, `bd close`, etc. + +**If you see "database not found":** Run `bd init --quiet` yourself, or ask the human to run `bd init`. + ## Issue Tracking We use bd (beads) for issue tracking instead of Markdown TODOs or external tools. diff --git a/FAQ.md b/FAQ.md index 56dbf679..acfff03a 100644 --- a/FAQ.md +++ b/FAQ.md @@ -83,13 +83,51 @@ Follow the repo for updates and the path to 1.0! ## Usage Questions +### Should I run bd init or have my agent do it? + +**Either works!** But use the right flag: + +**Humans:** +```bash +bd init # Interactive - prompts for git hooks +``` + +**Agents:** +```bash +bd init --quiet # Non-interactive - auto-installs hooks, no prompts +``` + +**Workflow for humans:** +```bash +# Clone existing project with bd: +git clone +cd +bd init # Auto-imports from .beads/issues.jsonl + +# Or initialize new project: +cd ~/my-project +bd init # Creates .beads/, sets up daemon +git add .beads/ +git commit -m "Initialize beads" +``` + +**Workflow for agents setting up repos:** +```bash +git clone +cd +bd init --quiet # No prompts, auto-installs hooks +bd ready --json # Start using bd normally +``` + ### Do I need to run export/import manually? **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`) +- **Imports** from JSONL when it's newer than DB (e.g., after `git pull`) + +**How auto-import works:** The first bd command after `git pull` detects that `.beads/issues.jsonl` is newer than the database and automatically imports it. There's no background daemon watching for changes - the check happens when you run a bd command. **Optional**: For immediate export (no 5-second wait) and guaranteed import after git operations, install the git hooks: ```bash @@ -99,9 +137,22 @@ cd examples/git-hooks && ./install.sh **Disable auto-sync** if needed: ```bash bd --no-auto-flush create "Issue" # Disable auto-export -bd --no-auto-import list # Disable auto-import +bd --no-auto-import list # Disable auto-import check ``` +### What if my database feels stale after git pull? + +Just run any bd command - it will auto-import: + +```bash +git pull +bd ready # Automatically imports fresh data from git +bd list # Also triggers auto-import if needed +bd sync # Explicit sync command for manual control +``` + +The auto-import check is fast (<5ms) and only imports when the JSONL file is newer than the database. If you want guaranteed immediate sync without waiting for the next command, use the git hooks (see `examples/git-hooks/`). + ### Can I track issues for multiple projects? **Yes! Each project is completely isolated.** bd uses project-local databases: diff --git a/README.md b/README.md index 5453fee7..e585c069 100644 --- a/README.md +++ b/README.md @@ -76,21 +76,30 @@ brew install bd Beads is designed for **AI coding agents** to use on your behalf. Setup takes 30 seconds: +**You run this once (humans only):** ```bash -# 1. Initialize bd in your project +# In your project root: bd init -# 2. Tell your agent to configure itself +# bd will: +# - Create .beads/ directory with database +# - Import existing issues from git (if any) +# - Prompt to install git hooks (recommended: say yes) +# - Auto-start daemon for sync + +# Then tell your agent about bd: echo "BEFORE ANYTHING ELSE: run 'bd onboard' and follow the instructions" >> AGENTS.md ``` -That's it! Next time your agent starts, it will: +**Your agent does the rest:** Next time your agent starts, it will: 1. Run `bd onboard` and receive integration instructions 2. Add bd workflow documentation to AGENTS.md 3. Update CLAUDE.md with a note (if present) 4. Remove the bootstrap instruction -**Why this approach?** We leverage the agent's intelligence to naturally integrate bd into your project's documentation, rather than doing brittle string replacement. +**For agents setting up repos:** Use `bd init --quiet` for non-interactive setup (auto-installs git hooks, no prompts). + +**For new repo clones:** Run `bd init` (or `bd init --quiet` for agents) to import existing issues from `.beads/issues.jsonl` automatically. Most tasks will be created and managed by agents during conversations. You can check on things with: @@ -145,6 +154,50 @@ When you install bd on any machine with your project repo, you get: No PostgreSQL instance. No MySQL server. No hosted service. Just install bd, clone the repo, and you're connected to the "database." +### Git Workflow & Auto-Sync + +bd automatically syncs your local database with git: + +**Making changes (auto-export):** +```bash +bd create "Fix bug" -p 1 +bd update bd-42 --status in_progress +# bd automatically exports to .beads/issues.jsonl after 5 seconds + +git add .beads/issues.jsonl +git commit -m "Working on bd-42" +git push +``` + +**Pulling changes (auto-import):** +```bash +git pull +# bd automatically detects JSONL is newer and imports on next command + +bd ready # Fresh data from git! +bd list # Shows issues from other machines +``` + +**Manual sync (optional):** +```bash +bd sync # Immediately flush pending changes and import latest JSONL +``` + +**For zero-lag sync**, install the git hooks: +```bash +cd examples/git-hooks && ./install.sh +``` + +This adds: +- **pre-commit** - Immediate flush before commit (no 5-second wait) +- **post-merge** - Guaranteed import after `git pull` or `git merge` + +**Disable auto-sync** if needed: +```bash +bd --no-auto-flush create "Issue" # Skip auto-export +bd --no-auto-import list # Skip auto-import check +``` + ## Usage ### Creating Issues diff --git a/WORKFLOW.md b/WORKFLOW.md index 1d13124b..4a4f1b14 100644 --- a/WORKFLOW.md +++ b/WORKFLOW.md @@ -377,28 +377,39 @@ ls -lh project.db ## Git Workflow -### Committing the Database +### Auto-Sync Behavior -**The database IS your project state.** Commit it! +bd automatically keeps your database and git in sync: +**Making changes:** ```bash -# Add database to git -git add project.db +bd create "New task" -p 1 +bd update bd-5 --status in_progress +# bd automatically exports to .beads/issues.jsonl after 5 seconds -# Commit with meaningful message -git commit -m "Updated tracker: completed auth (bd-3), ready for API work" - -# Push +git add .beads/issues.jsonl +git commit -m "Started working on bd-5" git push ``` +**After git pull:** +```bash +git pull +# bd automatically detects JSONL is newer on next command + +bd ready # Auto-imports fresh data from git! +bd list --status in_progress # See what you were working on +``` + ### Multi-Machine Workflow **Machine 1:** ```bash -beads create "New task" -p 1 -beads update bd-5 --status in_progress -git add project.db +bd create "New task" -p 1 +bd update bd-5 --status in_progress +# Wait 5 seconds for auto-export, or run: bd sync + +git add .beads/issues.jsonl git commit -m "Started working on bd-5" git push ``` @@ -406,10 +417,18 @@ git push **Machine 2:** ```bash git pull -beads ready # Sees bd-5 is in progress -beads list --status in_progress # See what you were working on +bd ready # Auto-imports, sees bd-5 is in progress ``` +### Zero-Lag Sync (Optional) + +Install git hooks for immediate sync: +```bash +cd examples/git-hooks && ./install.sh +``` + +This eliminates the 5-second debounce and guarantees import after `git pull`. + ### Team Workflow **Each developer has their own database:** diff --git a/cmd/bd/init.go b/cmd/bd/init.go index 0f205a49..755bd591 100644 --- a/cmd/bd/init.go +++ b/cmd/bd/init.go @@ -171,22 +171,28 @@ if quiet { // Check if we're in a git repo and hooks aren't installed if isGitRepo() && !hooksInstalled() { - fmt.Printf("%s Git hooks not installed\n", yellow("⚠")) - fmt.Printf(" Install git hooks to prevent race conditions between commits and auto-flush.\n") - fmt.Printf(" Run: %s\n\n", cyan("./examples/git-hooks/install.sh")) - - // Prompt to install - fmt.Printf("Install git hooks now? [Y/n] ") - var response string - _, _ = fmt.Scanln(&response) // ignore EOF on empty input - response = strings.ToLower(strings.TrimSpace(response)) - - if response == "" || response == "y" || response == "yes" { - if err := installGitHooks(); err != nil { - fmt.Fprintf(os.Stderr, "Error installing hooks: %v\n", err) - fmt.Printf("You can install manually with: %s\n\n", cyan("./examples/git-hooks/install.sh")) - } else { - fmt.Printf("%s Git hooks installed successfully!\n\n", green("✓")) + if quiet { + // Auto-install hooks silently in quiet mode (best default for agents) + _ = installGitHooks() // Ignore errors in quiet mode + } else { + // Interactive prompt for humans + fmt.Printf("%s Git hooks not installed\n", yellow("⚠")) + fmt.Printf(" Install git hooks to prevent race conditions between commits and auto-flush.\n") + fmt.Printf(" Run: %s\n\n", cyan("./examples/git-hooks/install.sh")) + + // Prompt to install + fmt.Printf("Install git hooks now? [Y/n] ") + var response string + _, _ = fmt.Scanln(&response) // ignore EOF on empty input + response = strings.ToLower(strings.TrimSpace(response)) + + if response == "" || response == "y" || response == "yes" { + if err := installGitHooks(); err != nil { + fmt.Fprintf(os.Stderr, "Error installing hooks: %v\n", err) + fmt.Printf("You can install manually with: %s\n\n", cyan("./examples/git-hooks/install.sh")) + } else { + fmt.Printf("%s Git hooks installed successfully!\n\n", green("✓")) + } } } }