After sync completion, orphan .base.jsonl and .left.jsonl files were
remaining in .beads/ directory. These are merge artifacts that should be
cleaned up after successful sync.
The fix adds SnapshotManager.Cleanup() call to createSyncFunc in
daemon_sync.go after successful import, matching the behavior of the CLI
sync command. Supports both single-repo and multi-repo modes.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add .base.jsonl, .left.jsonl, and .right.jsonl patterns to the skip list
in CheckLegacyJSONLFilename. These are legitimate git merge conflict
artifacts that should not trigger a warning about multiple JSONL files.
Fixes: bd-nsb
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add CloseReason field to Issue struct
- Add GetCloseReason and GetCloseReasonsForIssues queries
- Batch-load close reasons in scanIssues for efficiency
- Display close reason in bd show output
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Auto-import was allowing git history backfill to run, which could
incorrectly purge issues. The fix adds NoGitHistory=true to all
auto-import code paths:
- autoimport.go (importFromGit)
- autoflush.go (autoImportIfNewer)
- daemon_sync.go (importToJSONLWithStore)
Git history backfill is designed to detect deletions that happened
after a local DB was created. During auto-import, there is no local
work to protect - we are importing from the authoritative JSONL source.
Also adds comprehensive tests for NoGitHistory behavior.
Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
When opening a database that exists but is missing issue_prefix config
(typical in fresh clone scenarios), show a helpful error message instead
of cryptic migration invariant errors.
The new message:
- Explains the database needs initialization
- Detects if a JSONL file exists and shows the issue count
- Suggests the exact command to run: bd import -i <path>
- Falls back to suggesting bd init --prefix if no JSONL exists
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
When --auto-merge is used, performMerge now automatically:
1. Closes source issues with "Duplicate of <target>" reason
2. Links each source to target with a "related" dependency
Closes bd-hdt
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Changed gitCommitBeadsDir to explicitly stage only sync files
(issues.jsonl, deletions.jsonl, metadata.json) instead of the
entire .beads/ directory.
This prevents staging gitignored snapshot files (beads.*.jsonl,
*.meta.json) that may still be tracked from before they were
added to .gitignore, which could cause merge conflicts when
multiple polecats run bd sync concurrently.
- Fix doctor to treat empty deletions.jsonl as valid (0 entries OK status)
- Fix HydrateDeletionsManifest to create empty file when no deletions found
- Add --parent flag documentation to onboard command
- Add CLI --help tip throughout onboard documentation
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Short tests were timing out after 13+ minutes due to:
1. TestZFCSkipsExportAfterImport spawning subprocess that tried to
auto-start daemon - now skipped in short mode
2. TestVersionFlag taking 5+ seconds because --version flag did not
skip PersistentPreRun daemon startup - added early return
3. TestGetVersionsSince* had hardcoded version expectations that
became stale - made tests dynamic using versionChanges array
Short tests now complete in ~8 seconds instead of timing out.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Two fixes to prevent git pull --rebase from failing:
1. Skip hook execution during rebase operations by detecting
.git/rebase-merge or .git/rebase-apply directories
2. Use --no-git-history flag to prevent git-history-backfill
from writing to deletions.jsonl during imports
The root cause was that post-checkout hooks were running during
rebase, triggering the git-history-backfill which appends to
deletions.jsonl. This created uncommitted changes that blocked
the rebase from continuing.
Bump hooks version to 0.26.0 (requires bd version bump to take effect).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- autoImportIfNewer() now directly checks noAutoImport flag
- Ensures auto-import is blocked even if caller forgets to check autoImportEnabled
- Added TestAutoImportIfNewer_NoAutoImportFlag test to verify the fix
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
The staleness check compares last_import_time against JSONL file mtime.
File mtime has nanosecond precision, but last_import_time was stored with
only second precision (RFC3339). This caused a race condition where the
stored time could be slightly earlier than the file mtime, triggering
false "Database out of sync" errors - particularly in git worktrees.
Changed all 6 locations that set last_import_time to use RFC3339Nano.
The CheckStaleness parser already handles both formats, so this is
backward compatible.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Fixes bd-0b2: The git history backfill mechanism was causing data loss
during JSONL filename migrations (beads.jsonl → issues.jsonl). When issues
existed in the old filename's git history, the backfill incorrectly treated
them as "deleted" and purged them from the database.
Changes:
- Add NoGitHistory field to importer.Options and ImportOptions structs
- Modify purgeDeletedIssues() to skip git history check when flag is set
- Add --no-git-history flag to bd import command
- Add --no-git-history flag to bd sync command
- Update purge_test.go to pass Options argument
Usage:
bd import -i .beads/issues.jsonl --no-git-history
bd sync --no-git-history
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- bd init now preserves existing metadata.json settings instead of
overwriting with defaults (bd-zai)
- bd init detects existing JSONL filename (beads.jsonl vs issues.jsonl)
when creating new metadata.json
- bd import now correctly reports prefix source ("issues" vs "directory")
- bd import avoids using ".beads" as prefix when run from inside .beads/
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Change default JSONL filename from beads.jsonl to issues.jsonl
- Add bd doctor check and fix to auto-migrate legacy beads.jsonl configs
- Update FindJSONLPath to prefer issues.jsonl over beads.jsonl
- Add CheckLegacyJSONLConfig and CheckLegacyJSONLFilename checks
- Add LegacyJSONLConfig fix to rename files and update config
- Update .gitattributes to reference issues.jsonl
- Fix tests to expect new canonical filename
- Add bd-6xd to v0.25.1 release notes
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- TestVersionChangesCoverage: Add missing 3rd changelog entry for v0.25.1
- TestDefaultPath: Use filepath.Join for cross-platform path handling
- TestDebouncer_CancelWithNoPendingAction: Increase sleep from 60ms to 100ms
to account for Windows timer imprecision
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Previously, bd sync would commit ALL staged files when committing beads
changes. This could lead to unintended commits of work-in-progress code
that users had staged but weren't ready to commit.
Changed gitCommitBeadsDir to use pathspec (-- .beads/) to explicitly
limit the commit to only .beads/ files.
Also added in previous commit (bd-pbj):
- New Untracked Files check in bd doctor for untracked .beads/*.jsonl
- bd doctor --fix can now stage and commit untracked JSONL files
Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
The pre-commit and pre-push hooks were only staging beads.jsonl and
issues.jsonl, but not deletions.jsonl. This caused deletions.jsonl
to remain untracked after bd cleanup or bd delete operations.
Updated all hook locations:
- cmd/bd/templates/hooks/pre-commit
- cmd/bd/templates/hooks/pre-push
- examples/git-hooks/pre-commit
- examples/git-hooks/pre-push
- .beads-hooks/pre-commit
- .beads-hooks/pre-push
Users with existing hooks should run: bd hooks install
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
git config --global core.excludesfile may return paths like ~/...
which Go does not expand. This caused setupGlobalGitIgnore to fail
when users had configured their gitignore with a tilde path.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
After write operations in git worktrees, subsequent reads failed with
"Database out of sync with JSONL" even though the hash check passed.
Root cause: flushToJSONLWithState() updated last_import_hash but not
last_import_time after export. CheckStaleness() compares last_import_time
against JSONL mtime, so after export the JSONL appeared "newer" than the
last import.
Additional issue: RFC3339 only has second precision but file mtimes have
nanosecond precision, causing false positives when times were within the
same second.
Fix:
- Update last_import_time after export in flushToJSONLWithState()
- Use RFC3339Nano format for nanosecond precision
- Update CheckStaleness() to parse both formats for backward compatibility
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
The multiple JSONL files check was incorrectly flagging deletions.jsonl
as a problem, even though it is a valid system file for tracking deleted
issues. Added deletions.jsonl to the skip list alongside backups and
merge artifacts.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Removes global gitattributes setup from stealth mode, keeping only the global gitignore configuration. CI failures are pre-existing (TestZFCSkipsExportAfterImport timeout).
- bd-b8h: Extract getCheckHealthDBPath() to DRY up path resolution
- bd-xyc: Open DB once in runCheckHealth, pass connection to check functions
- bd-2em: checkHooksQuick now verifies all 4 hooks (pre-commit, post-merge,
pre-push, post-checkout) instead of just post-merge
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add --check-health flag for quick, silent health checks (exit 0 on success)
- Check version mismatch (CLI vs database), sync.branch config, outdated hooks
- Add hints.doctor config option to suppress doctor hints globally
- Update post-merge/post-checkout hooks to call bd doctor --check-health
- Suggest running bd doctor in upgrade notification
- Modernize post-checkout hook (bash→sh, use bd sync instead of bd import)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add JSONL sanitization after git pull to remove deleted issues that
git's 3-way merge may resurrect. Also add bd doctor check to hydrate
deletions.jsonl from git history for pre-v0.25.0 deletions.
Changes:
- Add sanitizeJSONLWithDeletions() in sync.go (Step 3.6)
- Add checkDeletionsManifest() in doctor.go (Check 18)
- Add HydrateDeletionsManifest() fix in doctor/fix/deletions.go
- Add looksLikeIssueID() validation to prevent false positives
- Add comprehensive tests for sanitization logic
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
bd sync was only committing beads.jsonl, leaving other tracked files
like metadata.json unstaged. This caused 'git pull --rebase' to fail
with 'You have unstaged changes' error.
Now checks and commits the entire .beads/ directory to ensure a clean
worktree before pulling.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
When running on a branch with no upstream (e.g., gastown polecats), output
different SESSION CLOSE PROTOCOL instructions:
- Use 'bd sync --from-main' instead of 'bd sync'
- Skip git push step (branch is local-only)
- Update Sync & Collaboration section to show --from-main
- Update Completing work workflow accordingly
Detection: git rev-parse --abbrev-ref --symbolic-full-name @{u} returns
error if no upstream configured.
Closes bd-4l5
Completes the deletion propagation epic (bd-imj) with all 9 subtasks:
- Cross-clone deletion propagation via deletions.jsonl
- bd deleted command for audit trail
- Auto-compact during sync (opt-in)
- Git history fallback with timeout and regex escaping
- JSON output for pruning results
- Integration tests for deletion scenarios
- Documentation in AGENTS.md, README.md, and docs/DELETIONS.md
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add Count function to deletions package for fast line counting
- Add maybeAutoCompactDeletions to sync (opt-in via deletions.auto_compact config)
- Fix regex escaping in batchCheckGitHistory (bd-bgs)
- Add 30s timeout to git history commands (bd-f0n)
- Use git rev-parse --show-toplevel for proper repo root detection (bd-bhd)
- Add tests for Count and auto-compact functionality
Closes: bd-qsm, bd-bgs, bd-f0n, bd-bhd
Adds `bd init --stealth` to enable beads usage without affecting repo collaborators:
- Global gitattributes: configures beads merge driver across all repos
- Global gitignore: prevents .beads/ and .claude/settings.local.json from being committed
- Claude Code integration: adds 'bd onboard' instruction automatically
- Respects existing global git config files, only creates when necessary
Perfect for personal experimentation or contributing to repos where not everyone uses beads.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-authored-by: Claude <noreply@anthropic.com>
Enables bd sync to work with local-only branches that don't have
upstream tracking. Auto-detects this case and syncs beads from
origin/main instead of requiring an upstream branch.
Also fixes hasJSONLConflict() to recognize both issues.jsonl and
beads.jsonl filenames.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implements two P1 tasks for the deletions manifest epic:
bd-v2x: Add deletions pruning to bd compact
- PruneDeletions function removes records older than retention period
- Default retention: 7 days (configurable via metadata.json)
- CLI --retention flag for override
- Atomic file rewrite prevents corruption
- Called automatically during all compact operations
bd-pnm: Add git history fallback for pruned deletions
- Catches deletions where manifest entry was pruned
- Uses git log -S to search for ID in JSONL history
- Batches multiple IDs for efficiency (git -G regex)
- Self-healing: backfills manifest on hit
- Conservative: keeps issue if git check fails (shallow clone)
Tests added for both features with edge cases covered.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Global daemon support has been deprecated for most of the project's
lifetime. This change removes the dead code entirely:
- Remove --global and --migrate-to-global daemon flags
- Remove runGlobalDaemon() and migrateToGlobalDaemon() functions
- Remove shouldUseGlobalDaemon() and getGlobalBeadsDir() functions
- Simplify functions that had global bool parameters
- Remove warning about old global socket in getSocketPath()
This reduces code complexity and removes 238 net lines of unused code.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>