What
reconcile --auto-writeback refuses to write back a ForeignCollision item (a never-applied, pre-existing native file): writing it back would overwrite the curated canonical source with foreign content, which resolveAuto calls "the worst data-loss path", so it prints skipped (foreign-collision, would overwrite source): … — resolve interactively and counts the item as unresolved.
A confirmed bulk [W] at the interactive prompt does not get that refusal. In walk, the confirmed bulk choice is taken before the --auto-* dispatch:
action := s.bulk
if action == actionNone {
action = s.resolveAuto(it) // the only place the ForeignCollision refusal lives
}
so once the user answers y to apply 'w' to all N remaining items? [y/N], every remaining actionable item — foreign collisions included — goes to applyAction → attemptWriteBack → writeBackItem. Downstream, writeBackItem refuses only plugin-owned items; a foreign collision is written into the canonical source.
Why it matters
The confirmation names a count, not what is in it. Two keystrokes (W, y) on a queue that happens to contain a foreign collision do exactly what the non-interactive mode was taught to refuse, with no per-item warning. A per-item [w] on a foreign collision is a deliberate choice and is fine; the bulk path is the gap.
Where
Options
- Apply the same refusal to a bulk write-back: in
walk, when s.bulk == actionWriteBack and the item is a ForeignCollision (or plugin-owned), print the existing skipped (foreign-collision, would overwrite source) line, count it in autoSkipped, and continue — the bulk choice then means "write back everything that is safe to write back non-interactively", the same meaning --auto-writeback has.
- Alternatively, make the confirmation honest:
apply 'w' to all N remaining items (M are foreign collisions and would overwrite source)? [y/N].
Option 1 is the smaller change and keeps the two "sweep" modes consistent. Either way, a test: a queue with a drift item and a foreign collision, stdin Wy, assert the canonical file the foreign collision maps to is unchanged.
What
reconcile --auto-writebackrefuses to write back aForeignCollisionitem (a never-applied, pre-existing native file): writing it back would overwrite the curated canonical source with foreign content, whichresolveAutocalls "the worst data-loss path", so it printsskipped (foreign-collision, would overwrite source): … — resolve interactivelyand counts the item as unresolved.A confirmed bulk
[W]at the interactive prompt does not get that refusal. Inwalk, the confirmed bulk choice is taken before the--auto-*dispatch:so once the user answers
ytoapply 'w' to all N remaining items? [y/N], every remaining actionable item — foreign collisions included — goes toapplyAction→attemptWriteBack→writeBackItem. Downstream,writeBackItemrefuses only plugin-owned items; a foreign collision is written into the canonical source.Why it matters
The confirmation names a count, not what is in it. Two keystrokes (
W,y) on a queue that happens to contain a foreign collision do exactly what the non-interactive mode was taught to refuse, with no per-item warning. A per-item[w]on a foreign collision is a deliberate choice and is fine; the bulk path is the gap.Where
internal/cli/reconcile.go:walk(bulk precedesresolveAuto),resolveAuto(the refusal),writeBackItem(plugin-owned refusal only).309fde0(action := bulkActionahead of the auto switch). Surfaced by the round-3 adversarial review of refactor(cli): reconcileRun becomes a reconcileSession (#232) #253, whose docs now enumerate the three routes to the dest-dropped-server deletion (per-item[w], confirmed bulk[W],--auto-writeback) and made the asymmetry legible. Out of refactor(cli): reconcileRun becomes a reconcileSession (#232) #253's behaviour-preserving scope.Options
walk, whens.bulk == actionWriteBackand the item is aForeignCollision(or plugin-owned), print the existingskipped (foreign-collision, would overwrite source)line, count it inautoSkipped, and continue — the bulk choice then means "write back everything that is safe to write back non-interactively", the same meaning--auto-writebackhas.apply 'w' to all N remaining items (M are foreign collisions and would overwrite source)? [y/N].Option 1 is the smaller change and keeps the two "sweep" modes consistent. Either way, a test: a queue with a drift item and a foreign collision, stdin
Wy, assert the canonical file the foreign collision maps to is unchanged.