ADR-0026 — Conflict resolution policy
- Status: Accepted
- Date: 2026-06-11
- Related: sync/09 conflict resolution, ADR-0008, ADR-0022
Context
ADR-0008 set the principle (conflicted copies, never overwrite). The sync engine needs the full taxonomy and resolution policy — including the awkward cases (delete-vs-edit, create/create, rename, type change, case/unicode collisions) — and a guarantee that all devices reach the same outcome.
Decision
Resolve via server-anchored, deterministic policy:
- edit/edit (differ): keep both; loser →
name (conflicted copy — <device>, <ts>).ext(Syncthing/Dropbox-style). edit/edit (same content): converge, no copy. - edit vs delete: edit always wins (resurrect), delete surfaced. Never let a delete destroy an edit.
- create/create same name: hash-equal → adopt one; else conflicted copy.
- rename/rename same node: server total order wins the name; other surfaced.
- type change (file↔dir): rename one side as conflicted.
- case-only / unicode-normalization collisions: normalize; on true clash, keep both with a disambiguating suffix; surface.
- Resolution is materialized at the server (the losing optimistic commit creates a new node), so the conflicted copy fans out uniformly to all devices — exactly one copy, not N. Tie-breaks: total-order/version → timestamp → device-ID (documented, reproducible).
- Optional, opt-in 3-way text merge for mergeable types; no CRDT/OT whole-file or real-time co-editing (NG1).
Consequences
Positive
- No silent data loss; both sides of every conflict are recoverable (+ version history).
- Server-anchored determinism prevents the N-devices → N-copies explosion of naive client-side resolution.
- Edit-beats-delete removes the most common accidental-loss path.
Negative / costs
- Conflicted copies put reconciliation on the user (mitigated: clear surfacing + version history). Cross-platform name collisions need normalization machinery.
Alternatives considered
- Last-writer-wins: silently destroys an edit. Rejected (disqualifying).
- CRDT/OT for everything: solves co-editing (a non-goal), heavy, unsafe for binary. Rejected; narrow opt-in text merge only.
- Client-side resolution: non-deterministic across devices → duplicate copies. Rejected in favor of server anchoring.
Scaling
Conflict-copy creation is rate-limited/coalesced under storms; deterministic resolution keeps outcomes O(1) per conflict regardless of device count.