piece
The join: merge the two move-logs and replay the union in timestamp order.
This satisfies all three semilattice laws:
Idempotent —
piece(a, a)deduplicates equal ops (same(ts, replica)) before replay, so the result is the same asa.Commutative — the total order is deterministic regardless of which replica's log appears on which side.
Associative — follows from the set-union nature of the log merge and the determinism of the replay.
Incremental replay optimization (#728)
Rather than replaying the full merged log from scratch on every merge, we identify the earliest position at which the merged log diverges from this.log (the first op that was inserted from other). Everything before that position has already been replayed into this.effectiveParents, so we reuse that prefix and replay only from the divergence point forward.
Common case — other contains only ops with timestamps later than every op in this.log (monotone-advancing append): the divergence point equals this.log.size, so we apply only the new ops to effectiveParents. This reduces the per-merge cost from O(|merged| × depth) to O(|new| × depth).
Worst case — an op arrives with a timestamp earlier than some ops in this.log (out-of-order delivery): we replay from the insertion point, which is still correct but more expensive (up to O(|merged| × depth)). Correctness is preserved in all cases because the replay visits the identical total-order log in the identical order.