- bd-6pni: Auto-filter tombstoned issues with mismatched prefixes during
import instead of failing. Tombstones from contributor PRs with different
test prefixes are pollution and safe to ignore.
- bd-ffr9: Stop recreating deletions.jsonl after tombstone migration.
Added IsTombstoneMigrationComplete() check to all code paths that write
to the legacy deletions manifest.
- bd-admx: Fix perpetual "JSONL file hash mismatch" warning. Now clears
both export_hashes AND jsonl_file_hash when mismatch detected, so the
warning doesn't repeat.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Fixes 46 broken relative links across 20 documentation files in docs/.
Changes:
- Added ../ prefix for root files (README.md, AGENTS.md)
- Removed ../ prefix for sibling docs files
- Removed dead links to non-existent files
- Fixed subdirectory paths
Based on PR #574 by chrisvaillancourt.
Co-Authored-By: Chris Vaillancourt <chrisvaillancourt@users.noreply.github.com>
- bd-8v5o: When doctor --fix hydrates issues from git history, also
remove them from the deletions manifest to prevent perpetual skip
warnings during sync
- bd-wsqt: Remove verbose per-issue "Skipping bd-xxx" messages during
sync. Caller already shows summary of skipped issues.
Added RemoveDeletions() function to deletions package with tests.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When importing issues, if an incoming issue has the same content hash as an
existing issue but a DIFFERENT prefix, this should not be treated as a rename.
Cross-prefix content matches occur when importing issues from other projects
that happen to have identical content.
Previously, the importer would call handleRename which tries to create an issue
with the incoming prefix, failing prefix validation ("does not match configured
prefix" error).
The fix checks if prefixes differ before calling handleRename:
- Same prefix, different ID suffix → true rename, call handleRename
- Different prefix → skip incoming issue, keep existing unchanged
Added test: TestImportCrossPrefixContentMatch reproduces the bug scenario
where alpha-* issues exist but beta-* issues are imported with same content.
Document the intent and nuances of recent fixes:
internal/importer/utils.go:
- RenameImportedIssuePrefixes: explain the three ID formats (sequential,
hash-based, hierarchical) and how prefix renaming preserves identity
- isValidIDSuffix: document why dots are allowed (hierarchical parent-child
relationships) and what characters are rejected
cmd/bd/deletion_tracking.go:
- isIssueNotFoundError: explain why "not found" is success during merge
(issue may be tombstoned, never existed locally, or manually deleted)
- Deletion loop: document what "accepted deletions" means and why we
tolerate missing issues during the pruning phase
During sync, the 3-way merge logic tries to delete issues that were
removed remotely. If an issue is already gone (tombstoned or never
existed locally), that shouldn't be an error - the goal is just to
ensure the issue is deleted.
Changes:
- Add isIssueNotFoundError helper to detect missing issue errors
- Skip "issue not found" errors during merge deletion (count as success)
- Update stats output to show already-gone count when relevant
Update bd show command to include status information for all dependency
types (children, blocks, related, discovered). Issues now display with
format [P1 - closed] instead of just [P1].
This provides better visibility into the state of dependent issues
without needing to run bd show on each individual issue.
Changes:
- Updated daemon mode formatting for all dependency types (lines 208, 214, 220, 226)
- Updated direct mode formatting for all dependency types (lines 400, 406, 412, 418)
- Changed format from "[P%d]" to "[P%d - %s]" with dash separator
Example output:
Children (9):
↳ pma-an8: Create config.py module [P1 - closed]
↳ pma-38g: Create utils.py module [P1 - open]
Blocks (1):
← pma-uzm: Adapt validate_outputs.py [P1 - blocked]
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude <noreply@anthropic.com>
The isNumeric function was rejecting valid hierarchical hash IDs like
'6we.2' that contain dots for parent.child notation. This caused
`bd import --rename-on-import` to fail with "non-numeric suffix" errors.
Changes:
- Rename isNumeric to isValidIDSuffix for clarity
- Accept dots (.) in addition to alphanumeric for hierarchical IDs
- Update test cases to cover hierarchical ID formats
* feat: auto-disable daemon in git worktrees for safety
Implement worktree daemon compatibility as proposed in the analysis.
The daemon is now automatically disabled when running in a git worktree
unless sync-branch is configured.
Git worktrees share the same .beads directory, and the daemon commits
to whatever branch its working directory has checked out. This causes
commits to go to the wrong branch when using daemon in worktrees.
- Add shouldDisableDaemonForWorktree() helper that checks:
1. If current directory is a git worktree (via git rev-parse)
2. If sync-branch is configured (env var or config.yaml)
- Modify shouldAutoStartDaemon() to call the helper
- Modify daemon connection logic in main.go to skip connection
- Add FallbackWorktreeSafety constant for daemon status reporting
- Update warnWorktreeDaemon() to skip warning when sync-branch configured
- In worktree WITHOUT sync-branch: daemon auto-disabled, direct mode used
- In worktree WITH sync-branch: daemon enabled (commits go to dedicated branch)
- In regular repo: no change (daemon works as before)
- Added comprehensive unit tests for shouldDisableDaemonForWorktree()
- Added integration tests for shouldAutoStartDaemon() in worktree contexts
- Manual E2E testing verified correct behavior
- Updated WORKTREES.md with new automatic safety behavior
- Updated DAEMON.md with Git Worktrees section
* feat: check database config for sync-branch in worktree safety logic
Previously, the worktree daemon safety check only looked at:
- BEADS_SYNC_BRANCH environment variable
- sync-branch in config.yaml
This meant users who configured sync-branch via `bd config set sync-branch`
(which stores in the database) would still have daemon disabled in worktrees.
Now the check also reads sync.branch from the database config table,
making daemon work in worktrees when sync-branch is configured via any method.
Changes:
- Add IsConfiguredWithDB() function that checks env, config.yaml, AND database
- Add findBeadsDB() to locate database (worktree-aware via git-common-dir)
- Add getMainRepoRoot() helper using git rev-parse
- Add getConfigFromDB() for lightweight database reads
- Update shouldDisableDaemonForWorktree() to use IsConfiguredWithDB()
- Update warnWorktreeDaemon() to use IsConfiguredWithDB()
- Add test case for database config path
* refactor: use existing beads.FindDatabasePath() instead of duplicating code
Remove duplicate getMainRepoRoot() and findBeadsDB() functions from
syncbranch.go and use the existing beads.FindDatabasePath() which is
already worktree-aware.
Changes:
- Replace custom findBeadsDB() with beads.FindDatabasePath()
- Remove duplicate getMainRepoRoot() (git.GetMainRepoRoot() exists)
- Remove unused imports (exec, strings, filepath)
- Clean up debug logging in tests
---------
Co-authored-by: Charles P. Cross <cpdata@users.noreply.github.com>
The --repair flag was generating sequential IDs (sageox-9895, sageox-9896)
instead of hash-based IDs (sageox-jwnv, sageox-urtm). This fix uses the
proper GenerateIssueID function from sqlite package to generate consistent
hash-based IDs during prefix repair operations.
Changes:
- Import sqlite package for hash ID generation
- Add generateRepairHashID helper that uses sqlite.GenerateIssueID
- Track used IDs within batch to avoid collisions
- Update test to verify hash IDs instead of sequential
Contributors frequently fork the repo and accidentally include their local
.beads/issues.jsonl changes in PRs. This adds:
1. A new CI job that fails PRs containing .beads/issues.jsonl changes
2. Clear error message with fix instructions
3. Updated CONTRIBUTING.md with guidance
This should prevent the common issue of PRs including unintended database changes.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When git merge replaces the .beads/beads.db file, the daemon's
SQLite connection becomes stale (still reading deleted inode).
This adds FreshnessChecker that detects file replacement via
inode/mtime comparison and triggers automatic reconnection.
Implementation:
- freshness.go: monitors db file for replacement
- store.go: adds EnableFreshnessChecking() and reconnect()
- queries.go: calls checkFreshness() on GetIssue/SearchIssues
- daemon.go: enables freshness checking at startup
- freshness_test.go: comprehensive tests including merge scenario
Code quality (per review):
- Extract configureConnectionPool() helper to reduce duplication
- Handle Close() error in reconnect() (log but continue)
- Use t.Cleanup() pattern in tests per project conventions
- Rename setupFreshnessTest() per naming conventions
Overhead: ~2.6μs per read op (~0.8% of total query time)
Signed-off-by: Alessandro De Blasis <alex@deblasis.net>
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Setting vendorHash to placeholder to trigger CI failure with correct hash.
Go dependencies were updated.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* bd-ckej: fix orphan skip count mismatch on fresh import
When OrphanSkip mode is used during import and a child issue's parent doesn't
exist, the issue ID was cleared to '' but then regenerated anyway in
GenerateBatchIssueIDs, causing it to be created in the database. This resulted
in a count mismatch: JSONL had 824 issues but only 823 were in the database (one
orphan was counted but not created).
Fix: Filter out orphaned issues with empty IDs before batch creation and track
them in result.Skipped so the count stays accurate.
* test: add TestImportOrphanSkip_CountMismatch for bd-ckej
Adds comprehensive test that verifies orphaned issues are properly skipped
during import when orphan_handling=OrphanSkip and parent doesn't exist.
Also improves the fix to pre-filter orphaned issues before batch creation,
ensuring they're not inserted then have IDs cleared (preventing count
mismatches).
---------
Co-authored-by: Amp <amp@example.com>
Closes#566
There might be some further work to ensure that bd version still reports branch and commit hash. That'll be a separate PR.
Co-authored-by: Matt Wilkie <matt.wilkie@yukon.ca>
When bd doctor detects legacy deletions.jsonl, --fix now runs the
tombstone migration automatically instead of requiring users to
manually run bd migrate-tombstones.
This makes the migration smoother for multi-clone scenarios where
only one clone needs to do the actual migration, but other clones
may still have local deletions.jsonl files that need cleanup.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Tombstones are now stored inline in issues.jsonl.
Added deletions.jsonl to .gitignore to prevent re-tracking.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add auto-commit, auto-push, local mode, sync interval, and daemon mode
to the status output when querying a running daemon.
This helps users understand the current daemon configuration without
having to check logs or remember what flags were used at startup.
Changes:
- Add config fields to StatusResponse in protocol.go
- Add SetConfig() method to Server for daemon to set its config
- Update handleStatus() to include config in response
- Update showDaemonStatus() to query and display config via RPC
- Add comprehensive test coverage for new functionality
Co-authored-by: Christian Catalan <crcatala@gmail.com>
- Add comprehensive CHANGELOG entry for v0.30.0 (tombstone architecture)
- Add v0.30.0 to versionChanges in info.go for `bd info --whats-new`
- Acknowledge 13 community contributors
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
GH#464: Add safety guards to prevent deletion of open/in_progress issues during sync:
- Safety guard in git-history-backfill (importer.go)
- Safety guard in deletions manifest processing
- Warning when uncommitted changes detected before pull (daemon_sync.go)
- Enhanced repo ID mismatch error message
GH#545: Fix bd blocked to show status=blocked issues (sqlite/ready.go):
- Changed from INNER JOIN to LEFT JOIN to include issues without dependencies
- Added WHERE clause to include both status=blocked AND dependency-blocked issues
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Mark unused ctx parameter with underscore in getRepoRootForWorktree
- Replace exec.Command("test", "-d") with os.Stat for directory check
- Handle file.Close() errors properly in compact.go and migrate_tombstones.go
- Explicitly ignore cleanup errors with _ assignment
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Update default.nix vendorHash to match current go.mod dependencies
- Fix NewSQLiteStorage calls to include required context.Context parameter
- Rename duplicate runCmd to runGitCmd in routing_integration_test.go
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The previous bd-in7q fix had backwards logic - by EXCLUDING tombstones
from currentIDs, they appeared missing when compared to historicalIDs,
causing HydrateDeletionsManifest to erroneously add them to deletions.jsonl.
This corruption manifested when:
1. Issues were migrated to tombstones via migrate-tombstones
2. Doctor hydration ran (directly or via sync)
3. Tombstones were seen as deleted and re-added to deletions.jsonl
4. Next import skipped thousands of issues with in deletions manifest
Fix: Include ALL issues (including tombstones) in currentIDs. Tombstones
represent migrated deletions that ARE accounted for - they should not
trigger new deletion records.
Generated with Claude Code
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
GH#517: Claude uses 'medium' instead of P2/2 for priority, causing
infinite error loops. The bd prime output didn't show the --priority
flag or explain the valid format.
Fix: Add --priority=2 to the create example and add a clear note
explaining that priority must be 0-4 or P0-P4, NOT 'high/medium/low'.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>