Root cause: The merge driver matched issues by IssueKey (ID+CreatedAt+CreatedBy).
When timestamp precision differed (e.g., with/without nanoseconds), the same
issue was treated as two different issues, causing both tombstone and closed
versions to appear in the merge result.
Fix: Added ID-based fallback matching in merge3WayWithTTL. When key-based
matching fails but the same ID exists in the other side, use that for merging.
Also track processed IDs to prevent duplicates.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add bd migrate-tombstones command (bd-8f9) to convert legacy
deletions.jsonl entries to inline tombstones in issues.jsonl
- Supports --dry-run to preview changes
- Supports --verbose for detailed progress
- Archives deletions.jsonl with .migrated suffix after migration
- Update bd compact to prune expired tombstones (bd-okh)
- All compact modes now prune tombstones older than 30-day TTL
- Reports count of pruned tombstones in output
- Add resurrection merge test (bd-bob)
- Tests scenario where base is tombstone but both left/right resurrect
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add TestIsExpiredTombstone with edge cases for merge package
- Add TestImportIssues_LegacyDeletionsConvertedToTombstones for importer
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- bd-ki14: Preserve tombstones when other side implicitly deleted
In merge3WayWithTTL(), implicit deletion cases now check if the
remaining side is a tombstone and preserve it instead of dropping.
- bd-ig5: Remove duplicate constants from merge package
StatusTombstone, DefaultTombstoneTTL, and ClockSkewGrace now
reference the types package to avoid duplication.
- bd-6x5: Handle empty DeletedAt in mergeTombstones()
Added explicit handling for edge cases where one or both tombstones
have empty DeletedAt fields with deterministic behavior.
- bd-1sn: Copy tombstone fields in mergeIssue() safety fallback
When status becomes tombstone via mergeStatus safety fallback,
tombstone fields are now copied from the appropriate side.
Added comprehensive tests for all fixed edge cases.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- bd-dtm: Changed stderr printing to use SafetyWarnings in worktree.go
- bd-ciu: Fixed non-deterministic output order in formatVanishedIssues
- bd-dmd: Removed duplicate safety check message in sync.go
- bd-k2n: PushSyncBranch now recreates worktree if cleaned up
- bd-c5m: Fixed string(rune()) in tests to use strconv.Itoa
- bd-8uk: Added test for SafetyWarnings population
- bd-1kf: Fixed mergePriority to handle negative priorities
- bd-xo9: Documented sync.require_confirmation_on_mass_delete config
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
CHANGES:
1. Merge logic (internal/merge/merge.go):
- Added mergeStatus() enforcing closed ALWAYS wins over open
- Fixed closed_at handling: only set when status='closed'
- Changed deletion handling: deletion ALWAYS wins over modification
2. Deletion tracking (cmd/bd/snapshot_manager.go):
- Updated ComputeAcceptedDeletions to accept all merge deletions
- Removed "unchanged locally" check (deletion wins regardless)
3. FK constraint helper (internal/storage/sqlite/util.go):
- Added IsForeignKeyConstraintError() for bd-koab
- Detects FK violations for graceful import handling
TESTS UPDATED:
- TestMergeStatus: comprehensive status merge tests
- TestIsForeignKeyConstraintError: FK constraint detection
- bd-pq5k test: validates no invalid state (status=open with closed_at)
- Deletion tests: reflect new deletion-wins behavior
- All tests pass ✓
This ensures issues never get stuck in invalid states and prevents
the insane situation where issues never die!
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Added merge_test.go with 797 lines of test coverage
- Tests for field merging, dependency merging, timestamp handling
- Tests for deletion detection and conflict generation
- Integration tests for merge driver auto-config in bd init
- Test helpers for git repository setup
Closes bd-kazt
All tests pass: go test ./internal/merge/... -v
Amp-Thread-ID: https://ampcode.com/threads/T-f0fe7c4c-13e7-486b-b073-fc64b81eeb4b
Co-authored-by: Amp <amp@ampcode.com>
- Check error returns from Fprintln and Sync
- Remove unused 'merged' parameter from hasConflict
- Remaining gosec G304 warnings are baseline (file paths from git, not user input)
- Vendored beads-merge algorithm into internal/merge/ with full MIT license attribution
- Created bd merge command as native wrapper (no external binary needed)
- Updated bd init to auto-configure git merge driver (both interactive and --quiet)
- Removed obsolete test files that were incompatible with vendored version
- Added merge to noDbCommands list so it can run standalone
- Tested: successful merge and conflict detection work correctly
Closes bd-bzfy
Thanks to @neongreen for permission to vendor!
See: https://github.com/neongreen/mono/issues/240
Original: https://github.com/neongreen/mono/tree/main/beads-merge
Amp-Thread-ID: https://ampcode.com/threads/T-f0fe7c4c-13e7-486b-b073-fc64b81eeb4b
Co-authored-by: Amp <amp@ampcode.com>