⊕ crdt merge
generation-counting merge state visualizer
Fetching Pyodide runtime (~12 MB)…
⊕ merge state viz
CRDT-like versioned merge engine · live Python via Pyodide
● loading
scenario →
Branch A
edit the textarea, then apply
— entries
Document text one line per line
Live lines count is odd → present in document 0
—
State entries (content:str, depth:int, anchored_right:bool, count:int) 0
live (odd count)
deleted (even count)
hover row for details
d
anc
count
content
Edit history click to inspect any snapshot
no edits yet
Branch B
edit independently of A
— entries
Document text one line per line
Live lines count is odd → present in document 0
—
State entries (content:str, depth:int, anchored_right:bool, count:int) 0
live (odd count)
deleted (even count)
hover row for details
d
anc
count
content
Edit history click to inspect any snapshot
no edits yet
Merge A ⊕ B
deterministic, commutative — merge(A,B) = merge(B,A)
—
Merged live lines 0
run merge first
Merged state entries all entries incl. deleted 0
d
anc
count
content
Conflict-annotated output git-style diff markers
—
Conflict key
added left — line inserted only in A
added right — line inserted only in B
added both — same insertion in both branches
deleted left — line deleted in A, kept in B
deleted right — line deleted in B, kept in A
How generation counting works
Every state entry carries a count field.
Odd count = line is live (present).
Even count = line is deleted.
Adding re-increments count: 1→2→3→…
On merge, max(countA, countB) wins — so a re-add (count=3) beats a delete (count=2). The parity of the max determines the final state.
Anchor direction
◂ left-anchored: line was inserted above its parent in the tree.
▸ right-anchored: line was inserted below its parent in the tree.
This resolves insertion-order ambiguity when two branches add lines in the same position.
Hover over any state row for a full explanation of that entry's fields.
Based on Manyana by Bram Cohen. Source on GitHub.