Add QualityScore *float32 field to internal/merge/merge.go to match
internal/types/types.go. Also add last-touched to .beads/.gitignore.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The close_reason and closed_by_session fields were being silently dropped
during 3-way merge operations because the simplified Issue struct in
internal/merge/merge.go was missing these fields.
Changes:
- Add CloseReason and ClosedBySession fields to merge.Issue struct
- Implement merge logic that preserves these fields when status is closed
- Use timestamp-based conflict resolution (later closed_at wins)
- Clear close metadata when status becomes non-closed
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Ensure deterministic output when merging issues. Go map iteration order
is non-deterministic, causing inconsistent merge results across runs.
Sort result slice by ID before returning, matching bd export behavior.
Fixes#853
When debug mode is enabled, the merge system now logs a message when
an expired tombstone loses to a live issue (resurrection occurs).
This helps understand why previously closed issues reappear.
Example output: "Issue bd-abc resurrected (tombstone expired)"
Changes:
- Add debug parameter to Merge3WayWithTTL and merge3Way functions
- Add debug logging in all 4 resurrection code paths
- Update tests to pass new debug parameter (bd-nl2)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Added StatusClosed constant derived from types.StatusClosed alongside
the existing StatusTombstone constant. Replaced hardcoded "closed"
strings with the constant for compile-time type checking consistency.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Strip (bd-xxx), (gt-xxx) suffixes from code comments and changelog
entries. The descriptions remain meaningful without the ephemeral
issue IDs.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Analysis found these commands are dead code:
- gt never calls `bd pin` - uses `bd update --status=pinned` instead
- Beads.Pin() wrapper exists but is never called
- bd hook functionality duplicated by gt mol status
- Code comment says "pinned field is cosmetic for bd hook visibility"
Removed:
- cmd/bd/pin.go
- cmd/bd/unpin.go
- cmd/bd/hook.go
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove omitempty from Priority field so P0 issues preserve priority:0
- Add nil check for store in createIssuesFromMarkdown
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Ensures no duplicates when left and right independently add the same
dependency (not in base). Left version is preferred.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
CRITICAL: Fixed dependency resurrection bug that caused removed/orphaned
dependencies to keep coming back after sync.
Root cause: mergeDependencies() was doing a union (additive only) and
completely ignored the base parameter. This meant any dependency present
in either left or right would be included, even if it was intentionally
removed.
Fix: Proper 3-way merge where REMOVALS ARE AUTHORITATIVE:
- If dep was in base and removed by left OR right → stays removed
- If dep wasn't in base and added by left OR right → included
- If dep was in base and both still have it → included
This fixes months of issues with orphaned parent-child relationships
being resurrected during git sync operations.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
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>