Conflict resolution
Skill almasumdev/awesome-mobile-agent-skills/.github/skills/offline/conflict-resolution
Stack-agnostic agent skills and workflows shared across iOS, Android, Flutter, React Native, and KMP.
npx -y skills add almasumdev/awesome-mobile-agent-skills --skill conflict-resolutionAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Pragmatic conflict resolution for mobile sync - last-write-wins, field-level merge, three-way merge, vector clocks, and CRDT basics. Use when two clients can modify the same record offline.
SKILL.md
5.5 KB, as published. Nobody here has run it
Conflict Resolution
Instructions
Any bidirectional sync has conflicts. The question is not "will we have them" but "how do we resolve them predictably". Pick a policy per entity, make it explicit, and show pending or conflicted states in the UI.
1. Conflict Models
| Model | Works by | Good for |
|---|---|---|
| Last-write-wins (LWW) | Highest timestamp wins per record | Settings, profile fields, simple data |
| Field-level LWW | Per-field timestamps merge | User profile with independently edited fields |
| Three-way merge | Base + ours + theirs -> merged | Documents, code-like content |
| Vector clocks | Track causality | Systems with unreliable clocks |
| CRDTs | Conflict-free data types | Collaborative docs, shared sets |
| Manual | Ask the user | Irreducible conflicts, high-stakes data |
2. Last-Write-Wins
The easiest policy. Each update carries a server-authoritative timestamp or revision.
data class Article(val id: String, val title: String, val body: String, val rev: Long, val updatedAt: Instant)
fun resolve(local: Article, remote: Article): Article =
if (remote.rev >= local.rev) remote else local
Trap: naive wall-clock LWW drops edits when devices have skewed clocks. Use server-assigned revisions or hybrid logical clocks (HLC).
3. Field-Level LWW
Good when different fields are edited on different devices.
record: { title: {v:"A", ts:t1}, body: {v:"B", ts:t2} }
On merge, pick the higher timestamp per field. Keep the change envelope small by sending only changed fields.
4. Three-Way Merge
When you know the base version the client started from, the server can merge:
merge(base, ours, theirs) =
if ours == base: theirs
elif theirs == base: ours
elif ours == theirs: ours
else: conflict -> policy (prefer ours, prefer theirs, prompt user)
For text, use a diff/patch library. For structured records, do it field-by-field.
5. Vector Clocks
When wall clocks cannot be trusted and causality matters:
- Each replica keeps a vector
{replicaId: counter}. - On update, increment the local replica's counter.
- On merge, compare vectors:
- If A <= B (every component), B is newer.
- If neither dominates, concurrent -> conflict.
Vector clocks detect conflicts; they do not resolve them. Pair with a resolution policy.
6. CRDTs (Conflict-Free Replicated Data Types)
CRDTs guarantee automatic merge without conflicts:
- Counters (G-Counter, PN-Counter) -- increments merge by summing per replica.
- Sets (OR-Set, LWW-Set) -- add/remove operations merge deterministically.
- Text (RGA, Yjs, Automerge) -- concurrent edits merge into a consistent sequence.
- Maps -- nested CRDTs.
Use Yjs, Automerge, or a language-native port. Cost: payload growth from metadata, operation history, and garbage collection.
7. Pragmatic Recipe for Most Apps
- Default to server-assigned revisions + LWW at the record level.
- Switch to field-level LWW for profile-like entities with independent edits.
- Switch to three-way merge for documents with structured content.
- Reserve CRDTs for truly collaborative content (multi-cursor docs, shared boards).
- Always have a manual fallback for high-stakes data (medical, financial).
8. Client UI for Conflicts
Do not fail silently. Conflicts need affordances:
- Pending state: local change sent, awaiting ack.
- Synced state: server ack received.
- Conflict state: show both versions, let the user pick, or default to policy with undo.
- Keep an in-app history/log of conflict resolutions for 7-30 days.
enum SyncState: Equatable {
case synced
case pending
case conflict(local: Article, remote: Article)
case failed(reason: String)
}
9. Deterministic Behavior
- Every merge function is pure and testable. Write unit tests that exercise LWW, concurrent edits, and deletions.
- Deletes need special handling: use tombstones so a delete does not get resurrected by a stale offline edit.
- Document idempotency: applying the same resolution twice must yield the same state.
10. Anti-Patterns
- Silent server overwrites. The user loses work without signal.
- Client-side timestamps as the source of truth without clock validation.
- Mixing CRDTs and LWW within one entity.
- Resolving conflicts in UI code. Keep the policy in a domain function; the UI presents outcomes.
- Letting tombstones accumulate forever. Garbage collect.
11. Testing Conflicts
- Simulate two clients editing the same record offline, then reconnecting in either order.
- Property-based tests for merge commutativity (
merge(a,b) == merge(b,a)) where applicable. - Fuzz the resolution function with random histories.
- In CI, run an end-to-end scenario with two emulated devices against a test server.
Checklist
- A conflict policy is chosen and documented per entity.
- Server-assigned revisions or HLCs are used, not wall clocks alone.
- Delete operations use tombstones with a GC policy.
- Merge functions are pure, unit-tested, and idempotent.
- UI surfaces pending, synced, and conflict states.
- CRDTs are used only where justified; not as a default.
- Conflict rate is monitored per entity; spikes trigger review.
- End-to-end scenarios simulate concurrent offline edits.