- Refactored upsertIssues to match by content hash first, then by ID
- Added buildHashMap, buildIDMap, and handleRename helper functions
- Import now detects and handles renames (same content, different ID)
- Importing same data multiple times is idempotent (reports Unchanged)
- Exported BuildReplacementCache and ReplaceIDReferencesWithCache for reuse
- All 30+ existing import tests pass
- Improved convergence for N-way collision scenarios
Changes:
- internal/importer/importer.go: Content-first matching in upsertIssues
- internal/storage/sqlite/collision.go: Exported helper functions
- internal/storage/sqlite/collision_test.go: Updated function names
Amp-Thread-ID: https://ampcode.com/threads/T-3df96ad8-7c0e-4190-87b5-6d5327718f0a
Co-authored-by: Amp <amp@ampcode.com>
After 2 weeks of collision/stale-data fixes, reviewed all changes to identify
spurious code that is no longer needed after content-hash resolution was implemented.
**Removed:**
1. countReferences() function from collision.go (lines 274-328)
- Was used for reference-count based collision scoring
- Completely unused after switching to content-hash based resolution (commit 2e87329)
- Still exists in duplicates.go for deduplication (different use case)
2. ReferenceScore field from CollisionDetail struct
- Marked as DEPRECATED but never removed
- No longer used by ScoreCollisions() which now uses content hashing
3. TestCountReferences and TestCountReferencesWordBoundary tests
- Tested the now-deleted countReferences() function
- No longer relevant
**Fixed:**
- Updated CheckpointWAL comments to remove misleading "staleness detection" claim
- Staleness detection uses metadata (last_import_time), NOT file mtime
- CheckpointWAL is still valuable for data persistence and WAL size reduction
- Comments now accurately reflect actual benefits
**Verified:**
- All tests pass (internal/storage/sqlite)
- Content-hash collision resolution still works correctly
- No behavioral changes, just cleanup
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add RenameDetail type to track content matches with different IDs
- Remove deletion logic from DetectCollisions (now read-only)
- Create ApplyCollisionResolution to handle all modifications
- Update importer.go to use two-phase approach (detect then apply)
- Fix dependency preservation in RemapCollisions
- Collect all dependencies before CASCADE DELETE
- Recreate with updated IDs after remapping
- Add tests: TestDetectCollisionsReadOnly, TestApplyCollisionResolution
- Update collision tests for content-hash scoring behavior
- Create bd-100 to track fixing autoimport tests
- Add SetConfig('issue_prefix', 'bd') to collision tests (bd-166)
- Update test cases to use 'bd-' prefix instead of invalid custom IDs (bd-177)
- Fixes 5 test failures in TestDetectCollisions, TestScoreCollisions, TestRemapCollisions, TestCreateIssues
All tests now pass.
Amp-Thread-ID: https://ampcode.com/threads/T-b2413b0e-2720-45b1-9b3d-acaa7d4cf9b4
Co-authored-by: Amp <amp@ampcode.com>
- Added testUserAlice constant for 'alice' in test files
- Added windowsOS constant for 'windows' in test files
- Added testIssueBD1/testIssueBD2 constants for 'bd-1'/'bd-2' in test files
- Added testVersion100 constant for '1.0.0' in version tests
- Added testIssueCustom1 constant for 'custom-1' in lazy init tests
Closes bd-54
Amp-Thread-ID: https://ampcode.com/threads/T-0a4e5d44-2d95-4948-8f4a-d8facf8657c7
Co-authored-by: Amp <amp@ampcode.com>
Bug: updateDependencyReferences() was incorrectly updating ALL dependencies
in the database during collision resolution with --resolve-collisions,
including dependencies belonging to existing issues.
Root cause: The function checked if dep.IssueID was in idMapping keys
(old imported IDs like 'bd-1'), but those are also the IDs of existing
database issues. This caused existing dependencies to be incorrectly
modified or deleted.
Fix: Changed logic to only update dependencies where IssueID is in
idMapping VALUES (new remapped IDs like 'bd-295'). This ensures only
dependencies from remapped issues are updated, not existing ones.
During normal import flow, this is effectively a no-op since imported
dependencies haven't been added to the database yet when RemapCollisions
runs (they're added later in Phase 5 of import_shared.go).
Changes:
- Updated updateDependencyReferences() in collision.go to build a set
of new remapped IDs and only update dependencies with those IDs
- Added comprehensive documentation explaining the correct semantics
- Added regression tests: TestRemapCollisionsRemapsImportedNotExisting
and TestRemapCollisionsDoesNotUpdateNonexistentDependencies
- Skipped 3 tests that expected the old buggy behavior with clear
notes about why they need to be rewritten
Real-world impact: In one case, 125 dependencies were incorrectly
deleted from 157 existing issues during collision resolution.
Fixes https://github.com/steveyegge/beads/issues/120
Fixes bd-56
Implements --resolve-collisions flag for import command to safely handle ID
collisions during branch merges. When enabled, colliding issues are remapped
to new IDs and all text references and dependencies are automatically updated.
Also adds comprehensive tests, branch-merge example, and documentation.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add reference scoring to prioritize which colliding issues should be
renumbered during collision resolution. Issues with fewer references
are renumbered first to minimize total update work.
Changes to collision.go:
- Add ReferenceScore field to CollisionDetail
- scoreCollisions() calculates scores and sorts collisions ascending
- countReferences() counts text mentions + dependency references
- Uses word-boundary regex (\b) to match exact IDs (bd-10 not bd-100)
New tests in collision_test.go:
- TestCountReferences: validates reference counting logic
- TestScoreCollisions: verifies scoring and sorting behavior
- TestCountReferencesWordBoundary: ensures exact ID matching
Reference score = text mentions (desc/design/notes/criteria) + deps
Sort order: fewest references first (minimizes renumbering impact)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add collision detection infrastructure to identify conflicts during
JSONL import when branches diverge and create issues with the same ID.
New files:
- internal/storage/sqlite/collision.go: Core collision detection logic
- detectCollisions() categorizes issues as exact matches, collisions, or new
- compareIssues() identifies which fields differ between issues
- CollisionDetail provides detailed collision reporting
- internal/storage/sqlite/collision_test.go: Comprehensive test suite
- Tests exact matches, new issues, and various collision scenarios
- Tests multi-field conflicts and edge cases
- All tests passing
This lays the foundation for bd-13 through bd-17 (reference scoring,
ID remapping, CLI flags, and documentation).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>