fix: resolve P2 sync noise and cleanup issues
- 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>
This commit is contained in:
@@ -181,6 +181,17 @@ func DefaultPath(beadsDir string) string {
|
||||
return filepath.Join(beadsDir, "deletions.jsonl")
|
||||
}
|
||||
|
||||
// IsTombstoneMigrationComplete checks if the tombstone migration has been completed.
|
||||
// After running `bd migrate-tombstones`, the deletions.jsonl file is archived to
|
||||
// deletions.jsonl.migrated. This function checks for that marker file.
|
||||
// When migration is complete, new deletion records should NOT be written to
|
||||
// deletions.jsonl (bd-ffr9).
|
||||
func IsTombstoneMigrationComplete(beadsDir string) bool {
|
||||
migratedPath := filepath.Join(beadsDir, "deletions.jsonl.migrated")
|
||||
_, err := os.Stat(migratedPath)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// Count returns the number of lines in the deletions manifest.
|
||||
// This is a fast operation that doesn't parse JSON, just counts lines.
|
||||
// Returns 0 if the file doesn't exist or is empty.
|
||||
|
||||
@@ -290,6 +290,38 @@ func TestDefaultPath(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsTombstoneMigrationComplete(t *testing.T) {
|
||||
t.Run("no migrated file", func(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
if IsTombstoneMigrationComplete(tmpDir) {
|
||||
t.Error("expected false when no .migrated file exists")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("migrated file exists", func(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
migratedPath := filepath.Join(tmpDir, "deletions.jsonl.migrated")
|
||||
if err := os.WriteFile(migratedPath, []byte("{}"), 0644); err != nil {
|
||||
t.Fatalf("failed to create migrated file: %v", err)
|
||||
}
|
||||
if !IsTombstoneMigrationComplete(tmpDir) {
|
||||
t.Error("expected true when .migrated file exists")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("deletions.jsonl exists without migrated", func(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
deletionsPath := filepath.Join(tmpDir, "deletions.jsonl")
|
||||
if err := os.WriteFile(deletionsPath, []byte("{}"), 0644); err != nil {
|
||||
t.Fatalf("failed to create deletions file: %v", err)
|
||||
}
|
||||
// Should return false because the .migrated marker doesn't exist
|
||||
if IsTombstoneMigrationComplete(tmpDir) {
|
||||
t.Error("expected false when only deletions.jsonl exists (not migrated)")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestLoadDeletions_EmptyLines(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
path := filepath.Join(tmpDir, "deletions.jsonl")
|
||||
|
||||
Reference in New Issue
Block a user