refactor: remove all deletions.jsonl code (bd-fom)

Complete removal of the legacy deletions.jsonl manifest system.
Tombstones are now the sole deletion mechanism.

Removed:
- internal/deletions/ - entire package
- cmd/bd/deleted.go - deleted command
- cmd/bd/doctor/fix/deletions.go - HydrateDeletionsManifest
- Tests for all removed functionality

Cleaned:
- cmd/bd/sync.go - removed sanitize, auto-compact
- cmd/bd/delete.go - removed dual-writes
- cmd/bd/doctor.go - removed checkDeletionsManifest
- internal/importer/importer.go - removed deletions checks
- internal/syncbranch/worktree.go - removed deletions merge
- cmd/bd/integrity.go - updated validation (warn-only on decrease)

Files removed: 12
Lines removed: ~7500

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Steve Yegge
2025-12-16 14:20:32 -08:00
parent e0528de590
commit 9f76cfda01
32 changed files with 298 additions and 7534 deletions

View File

@@ -383,8 +383,6 @@ func applyFixList(path string, fixes []doctorCheck) {
err = fix.DatabaseConfig(path)
case "JSONL Config":
err = fix.LegacyJSONLConfig(path)
case "Deletions Manifest":
err = fix.MigrateTombstones(path)
case "Untracked Files":
err = fix.UntrackedJSONL(path)
case "Sync Branch Health":
@@ -924,12 +922,7 @@ func runDiagnostics(path string) doctorResult {
result.Checks = append(result.Checks, syncBranchHealthCheck)
// Don't fail overall check for sync branch health, just warn
// Check 18: Deletions manifest (legacy, now replaced by tombstones)
deletionsCheck := checkDeletionsManifest(path)
result.Checks = append(result.Checks, deletionsCheck)
// Don't fail overall check for missing deletions manifest, just warn
// Check 19: Tombstones health (bd-s3v)
// Check 18: Tombstones health (bd-s3v)
tombstonesCheck := checkTombstones(path)
result.Checks = append(result.Checks, tombstonesCheck)
// Don't fail overall check for tombstone issues, just warn
@@ -2756,101 +2749,6 @@ func checkSyncBranchHealth(path string) doctorCheck {
}
}
func checkDeletionsManifest(path string) doctorCheck {
beadsDir := filepath.Join(path, ".beads")
// Skip if .beads doesn't exist
if _, err := os.Stat(beadsDir); os.IsNotExist(err) {
return doctorCheck{
Name: "Deletions Manifest",
Status: statusOK,
Message: "N/A (no .beads directory)",
}
}
// Check if we're in a git repository using worktree-aware detection
_, err := git.GetGitDir()
if err != nil {
return doctorCheck{
Name: "Deletions Manifest",
Status: statusOK,
Message: "N/A (not a git repository)",
}
}
deletionsPath := filepath.Join(beadsDir, "deletions.jsonl")
// Check if deletions.jsonl exists
info, err := os.Stat(deletionsPath)
if err == nil {
// File exists - count entries (empty file is valid, means no deletions)
if info.Size() == 0 {
return doctorCheck{
Name: "Deletions Manifest",
Status: statusOK,
Message: "Empty (no legacy deletions)",
}
}
file, err := os.Open(deletionsPath) // #nosec G304 - controlled path
if err == nil {
defer file.Close()
count := 0
scanner := bufio.NewScanner(file)
for scanner.Scan() {
if len(scanner.Bytes()) > 0 {
count++
}
}
// bd-s3v: Suggest migration to inline tombstones
if count > 0 {
return doctorCheck{
Name: "Deletions Manifest",
Status: statusWarning,
Message: fmt.Sprintf("Legacy format (%d entries)", count),
Detail: "deletions.jsonl is deprecated in favor of inline tombstones",
Fix: "Run 'bd migrate-tombstones' to convert to inline tombstones",
}
}
return doctorCheck{
Name: "Deletions Manifest",
Status: statusOK,
Message: "Empty (no legacy deletions)",
}
}
}
// bd-s3v: deletions.jsonl doesn't exist - this is the expected state with tombstones
// Check for .migrated file to confirm migration happened
migratedPath := filepath.Join(beadsDir, "deletions.jsonl.migrated")
if _, err := os.Stat(migratedPath); err == nil {
return doctorCheck{
Name: "Deletions Manifest",
Status: statusOK,
Message: "Migrated to tombstones",
}
}
// No deletions.jsonl and no .migrated file - check if JSONL exists
jsonlPath := filepath.Join(beadsDir, "issues.jsonl")
if _, err := os.Stat(jsonlPath); os.IsNotExist(err) {
jsonlPath = filepath.Join(beadsDir, "beads.jsonl")
if _, err := os.Stat(jsonlPath); os.IsNotExist(err) {
return doctorCheck{
Name: "Deletions Manifest",
Status: statusOK,
Message: "N/A (no JSONL file)",
}
}
}
// JSONL exists but no deletions tracking - this is fine for new repos using tombstones
return doctorCheck{
Name: "Deletions Manifest",
Status: statusOK,
Message: "Using inline tombstones",
}
}
// checkTombstones checks the health of tombstone records (bd-s3v)
// Reports: total tombstones, expiring soon (within 7 days), already expired
func checkTombstones(path string) doctorCheck {