The test was picking up global git config when checking that --skip-merge-driver
didn't set the merge.beads.driver config locally.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
After adding close_reason column to issues table, two functions still
called GetCloseReason() to fetch from events table after already
scanning the column. Removed the redundant code.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add migration 017_close_reason_column.go to create the column
- Update all INSERT statements to include close_reason
- Update all SELECT statements to include close_reason
- Update doctor.go to check for close_reason in schema validation
- Remove workaround code that batch-loaded close reasons from events table
- Fix migrations_test.go to include close_reason in test table schema
This fixes sync loops where close_reason values were silently dropped
because the DB lacked the column despite the struct having the field.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
In multi-repo mode, non-primary repos incorrectly wrote ALL issues to their
local issues.jsonl, including foreign issues from other repos. This caused
prefix mismatch errors on subsequent imports.
The fix adds prefix filtering in flushToJSONLWithState() when:
1. Multi-repo mode is configured (repos.primary set)
2. Current repo is not the primary repo
3. The repo has a configured issue_prefix
Issues not matching the local prefix are filtered out before writing to JSONL.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add CLI support for the estimated_minutes field that was already in the
Issue schema but had no way to be set from the command line.
Changes:
- Add --estimate flag to bd create (set estimated time on new issues)
- Add --estimate flag to bd update (modify estimated time on existing issues)
- Add EstimatedMinutes field to RPC CreateArgs and UpdateArgs
- Add handling in daemon RPC handlers for the new field
Example usage:
bd create --title "Task" --estimate 60 # 60 minutes estimate
bd update bd-abc --estimate 120 # update to 2 hours
Fixes GH #443🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Extract shared performSync implementation with skipGit parameter:
- createSyncFunc and createLocalSyncFunc now delegate to performSync
- Follows same pattern as performExport and performAutoImport
- Reduces ~80 lines of duplicated code
Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
Add documentation for users experiencing npm postinstall failures in Claude Code web environments due to network restrictions.
Closes: bd-8q0
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Adds --foreground flag to 'bd daemon --start' that runs the daemon in
foreground instead of forking to background. This enables management by
process supervisors like systemd, supervisord, or similar tools.
Usage: bd daemon --start --foreground
Closes#438🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Consolidate createSyncFunc and createLocalSyncFunc into a shared
performSync function, following the same pattern used for:
- performExport (used by createExportFunc and createLocalExportFunc)
- performAutoImport (used by createAutoImportFunc and createLocalAutoImportFunc)
The new performSync takes a skipGit bool parameter that skips all git
operations (commits, pulls, pushes) and 3-way merge when true.
This reduces ~60 lines of duplicated code and provides a single
implementation to maintain.
Closes: bd-73u
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Fix DEPENDENCIES.md: correct parent-child syntax (child depends on parent)
- Update bd show: display Children instead of Blocks for parent-child deps
- Group dependents by type with distinct labels
Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
- Create docs/UNINSTALLING.md with comprehensive uninstall steps
- Add link to UNINSTALLING.md from INSTALLING.md
- Cover: daemon, hooks, merge driver, .beads dir, worktree cleanup
Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
Fixes#441. The JIRA REST API v2 /search endpoint has been deprecated
and returns HTTP 410 Gone. Migrate to API v3 /search/jql endpoint.
Changes:
- Update API endpoint from /rest/api/2/search to /rest/api/3/search/jql
- Add URL encoding for JQL query parameter (Python 3.14 compatibility)
- Add reference to Atlassian migration guide
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
When sync.branch is configured, the sync command:
1. Exports changes to JSONL
2. Commits to sync branch via worktree
3. Pulls from sync branch
4. Restores .beads/ from HEAD to keep working directory clean
But PersistentPostRun's flushManager.Shutdown() was re-exporting to JSONL,
undoing the restore and leaving modified files.
Fix: Set skipFinalFlush flag when sync.branch mode completes successfully.
This prevents the final export in PersistentPostRun.
Also: Skip push to main branch when sync.branch is configured - all
pushes should go through the sync branch worktree.
When sync.branch is configured, the main branch's .beads/ directory was
showing as modified after every sync, even though the data was correctly
synced to the sync branch worktree.
This happened because:
1. Export writes to main's .beads/
2. Files are copied to worktree and committed there
3. But main's .beads/ now differs from what's committed on main
Fix: After sync completes, restore .beads/ from HEAD to keep the working
directory clean. The actual beads data lives on the sync branch; the main
branch's .beads/ is just a snapshot that should match what's committed.
Add detection for when the current branch is the configured sync branch.
This is a misconfiguration that causes bd sync to fail with:
fatal: 'beads-sync' is already used by worktree
The doctor now reports this as an error with a clear fix:
Switch to your main working branch: git checkout main
Also shows current branch info in the OK case for better visibility.
Add a new command that encapsulates all the work needed to migrate a clone
to use the sync.branch workflow for multi-clone setups like Gas Town:
- Validates current state (not on sync branch, not already configured)
- Creates sync branch if it doesn't exist (from remote or locally)
- Sets up git worktree for the sync branch
- Syncs current beads data to worktree
- Commits initial state to sync branch
- Sets sync.branch configuration
- Pushes sync branch to remote
Usage:
bd migrate-sync beads-sync # Basic migration
bd migrate-sync beads-sync --dry-run # Preview changes
bd migrate-sync beads-sync --force # Reconfigure even if set
Extract performExport() and performAutoImport() shared implementations:
- createExportFunc() and createLocalExportFunc() now use performExport()
with skipGit parameter
- createAutoImportFunc() and createLocalAutoImportFunc() now use performAutoImport()
with skipGit parameter
- createLocalSyncFunc() kept as-is (different flow from createSyncFunc)
Reduces daemon_sync.go by 89 lines (1003 -> 914) while maintaining
identical behavior and test coverage.
All existing tests pass. New shared functions use conditional logic
to skip git operations when skipGit=true, eliminating the need for
separate implementations.
* feat(daemon): add --local flag for git-free operation
Add --local mode to the daemon that allows it to run without a git
repository. This decouples the daemon's core functionality (auto-flush
to JSONL, auto-import from JSONL) from git synchronization.
Changes:
- Add --local flag to daemon command
- Skip git repo check when --local is set
- Add validation that --auto-commit and --auto-push cannot be used with --local
- Create local-only sync functions that skip git operations:
- createLocalSyncFunc: export-only for polling mode
- createLocalExportFunc: export without git commit/push
- createLocalAutoImportFunc: import without git pull
- Update startup message to indicate LOCAL mode
- Update event loop to use local functions when in local mode
This enables use cases like:
- Single-machine issue tracking without git
- Auto-flush to JSONL for backup purposes
- Running daemon in environments without git access
Multi-machine sync still requires git (as expected).
* fix(daemon): skip fingerprint validation in local mode
validateDatabaseFingerprint() calls beads.ComputeRepoID() which
executes git commands. This fails in non-git directories even
with --local flag.
Skip fingerprint validation entirely when running in local mode
since there's no git repository to validate against.
* test(daemon): add comprehensive test coverage for --local mode
Add tests for:
- Flag validation (--local incompatible with --auto-commit/--auto-push)
- Git check skip logic in local mode
- createLocalSyncFunc, createLocalExportFunc, createLocalAutoImportFunc
- Fingerprint validation skip in local mode
- Full integration test in non-git directory
- Export/import round-trip test
---------
Co-authored-by: Claude <noreply@anthropic.com>
When a clone gets reset (git reset --hard origin/main), the
git-history-backfill logic was incorrectly marking ALL issues as
deleted since they appeared in git history but not in the current
JSONL. This caused the entire database to be purged.
Fix:
- Add 50% threshold check: abort if git-history-backfill would delete
more than 50% of issues (likely a reset scenario, not deletions)
- Add warning when >10 issues would be deleted via backfill
- Print helpful message about manual deletion if needed
Test:
- Added TestMassDeletionSafetyGuard that simulates JSONL reset and
verifies the safety guard prevents mass deletion
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
When importing JSONL that contains issues in the deletions manifest,
import now:
- Filters out deleted issues before import
- Prints per-issue warning with deletion details (date, actor)
- Shows count of skipped issues in summary
- Suggests --ignore-deletions flag to force import
The new --ignore-deletions flag allows importing issues that are in the
deletions manifest, useful for recovering accidentally deleted issues.
Fixes bd-4zy
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Previously, bd init blocked when JSONL existed with issues but no database,
telling users to run 'bd doctor --fix'. But doctor --fix just ran bd migrate
which requires an existing database - creating a circular dependency.
Now:
- bd init allows fresh clones (JSONL exists, no database) to proceed
- bd init creates the database and imports from JSONL automatically
- bd doctor --fix runs bd init (not migrate) when there's no database
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Lower minimum hash length from 4 to 3 characters
- Update hash validation to support base36 (0-9, a-z) instead of just hex
- Require at least one digit to distinguish hashes from English words
- Fixes prefix extraction for hyphenated prefixes with 3-char hashes
e.g., 'document-intelligence-0sa' now correctly extracts 'document-intelligence'
- Add test cases for 3-char hashes with multi-part prefixes
- Resolves bd sync failures with 'prefix mismatch detected' errors
Adds a lightweight redirect mechanism that allows a stub .beads directory
to point to the actual beads location. This solves the workspace problem
where an AI agent runs in one directory but needs to operate on beads
stored elsewhere.
The redirect file is a simple text file containing a path (relative or
absolute) to the target .beads directory. Comments (lines starting with #)
are supported. Redirect chains are prevented - only one level is followed.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Test isJiraExternalRef helper with various URL patterns
- Test stats struct initialization
- Test result struct fields
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>