Fix bd-9bsx: Add sync validation to prevent infinite dirty loop

- Added dbNeedsExport() to check if DB and JSONL are in sync
- Only re-export after import if DB has changes that differ from JSONL
- Prevents unconditional re-export that caused infinite dirty state
- Added comprehensive tests for sync validation

Fixes recurring dirty state after merge conflicts that plagued users for weeks.

Amp-Thread-ID: https://ampcode.com/threads/T-f4f8c8c6-07bc-4334-9109-4626b4fd7a24
Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
Steve Yegge
2025-11-05 18:10:06 -08:00
parent b6fad0e618
commit 5438485fb8
3 changed files with 299 additions and 20 deletions

View File

@@ -214,27 +214,40 @@ Use --merge to merge the sync branch back to main branch.`,
}
}
// Step 4.5: Export back to JSONL if import made changes (e.g., rename detection)
// This ensures JSONL stays in sync with DB after rename detection
fmt.Println("→ Re-exporting after import to sync rename changes...")
if err := exportToJSONL(ctx, jsonlPath); err != nil {
fmt.Fprintf(os.Stderr, "Error re-exporting after import: %v\n", err)
os.Exit(1)
}
// Step 4.6: Commit the re-export if it created changes
hasPostImportChanges, err := gitHasChanges(ctx, jsonlPath)
if err != nil {
fmt.Fprintf(os.Stderr, "Error checking git status after re-export: %v\n", err)
os.Exit(1)
}
if hasPostImportChanges {
fmt.Println("→ Committing rename detection changes...")
if err := gitCommit(ctx, jsonlPath, "bd sync: apply rename detection from import"); err != nil {
fmt.Fprintf(os.Stderr, "Error committing post-import changes: %v\n", err)
os.Exit(1)
// Step 4.5: Check if DB needs re-export (only if DB differs from JSONL)
// This prevents the infinite loop: import → export → commit → dirty again
if err := ensureStoreActive(); err == nil && store != nil {
needsExport, err := dbNeedsExport(ctx, store, jsonlPath)
if err != nil {
fmt.Fprintf(os.Stderr, "Warning: failed to check if export needed: %v\n", err)
// Conservative: assume export needed
needsExport = true
}
if needsExport {
fmt.Println("→ Re-exporting after import to sync DB changes...")
if err := exportToJSONL(ctx, jsonlPath); err != nil {
fmt.Fprintf(os.Stderr, "Error re-exporting after import: %v\n", err)
os.Exit(1)
}
// Step 4.6: Commit the re-export if it created changes
hasPostImportChanges, err := gitHasChanges(ctx, jsonlPath)
if err != nil {
fmt.Fprintf(os.Stderr, "Error checking git status after re-export: %v\n", err)
os.Exit(1)
}
if hasPostImportChanges {
fmt.Println("→ Committing DB changes from import...")
if err := gitCommit(ctx, jsonlPath, "bd sync: apply DB changes after import"); err != nil {
fmt.Fprintf(os.Stderr, "Error committing post-import changes: %v\n", err)
os.Exit(1)
}
hasChanges = true // Mark that we have changes to push
}
} else {
fmt.Println("→ DB and JSONL in sync, skipping re-export")
}
hasChanges = true // Mark that we have changes to push
}
}
}