feat(sync): add per-field merge strategies for conflict resolution
Implements configurable per-field merge strategies (hq-ew1mbr.11):
- Add FieldStrategy type with strategies: newest, max, union, manual
- Add conflict.fields config section for per-field overrides
- compaction_level defaults to "max" (highest value wins)
- estimated_minutes defaults to "manual" (flags for user resolution)
- labels defaults to "union" (set merge)
Manual conflicts are displayed during sync with resolution options:
bd sync --ours / --theirs, or bd resolve <id> <field> <value>
Config example:
conflict:
strategy: newest
fields:
compaction_level: max
estimated_minutes: manual
labels: union
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
committed by
Steve Yegge
parent
e0dc3a37c3
commit
9a9704b451
@@ -572,6 +572,11 @@ func doPullFirstSync(ctx context.Context, jsonlPath string, renameOnImport, noGi
|
||||
fmt.Printf(" Local wins: %d, Remote wins: %d, Same: %d, Conflicts (LWW): %d\n",
|
||||
localCount, remoteCount, sameCount, mergeResult.Conflicts)
|
||||
|
||||
// Display manual conflicts that need user resolution
|
||||
if len(mergeResult.ManualConflicts) > 0 {
|
||||
displayManualConflicts(mergeResult.ManualConflicts)
|
||||
}
|
||||
|
||||
// Step 6: Import merged state to DB
|
||||
// First, write merged result to JSONL so import can read it
|
||||
fmt.Println("→ Writing merged state to JSONL...")
|
||||
@@ -1071,6 +1076,11 @@ func resolveSyncConflicts(ctx context.Context, jsonlPath string, strategy config
|
||||
// Re-run merge with the resolved conflicts
|
||||
mergeResult := MergeIssues(baseIssues, localIssues, remoteIssues)
|
||||
|
||||
// Display any remaining manual conflicts
|
||||
if len(mergeResult.ManualConflicts) > 0 {
|
||||
displayManualConflicts(mergeResult.ManualConflicts)
|
||||
}
|
||||
|
||||
// Write merged state
|
||||
if err := writeMergedStateToJSONL(jsonlPath, mergeResult.Merged); err != nil {
|
||||
return fmt.Errorf("writing merged state: %w", err)
|
||||
@@ -1177,7 +1187,7 @@ func resolveSyncConflictsManually(ctx context.Context, jsonlPath, beadsDir strin
|
||||
local := localMap[id]
|
||||
remote := remoteMap[id]
|
||||
base := baseMap[id]
|
||||
merged, _ := MergeIssue(base, local, remote)
|
||||
merged, _, _ := MergeIssue(base, local, remote)
|
||||
if merged != nil {
|
||||
mergedIssues = append(mergedIssues, merged)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user