What a conflict object actually holds
The stored shape: three sides, two change ids, a status, and a resolution.
Written By Dustin
Last updated About 3 hours ago
Worth knowing, because almost every surprising thing about TOVIO conflicts follows from the shape of the object.
The fields
Typed conflicts carry their own detail alongside this: a rename conflict records both divergent target paths, a mode conflict records the two modes, an entry-kind conflict records what each side thought the entry was. Resolution never has to guess it back from an address.
Landing several lanes at once can produce a conflict with more than two contributors. The object has room for the extra sides, so an n-way conflict is stored as one conflict rather than being flattened into a pairwise approximation.
The contributor set is sorted
Contributors are ordered by change id before the object is stored, so the same disagreement gets the same address regardless of which lane you happened to name first. Merging A into B and B into A produce one object, not two.
Detection time is deliberately absent
There is no "when was this detected" field in the object. That is not an oversight — a conflict is content-addressed, and a clock-derived field would give the same conflict a different address on every machine. When detection time is surfaced it comes from the op-log or the audit chain, which are allowed to carry injected time.
Once you resolve it, the recorded resolution does carry who resolved it and when. That timestamp arrives from the edge, not from the core: the merge engine itself never reads a clock.
The merge graph is not stored
The line-level structure behind a content conflict is recomputed on demand from the three sides and the two change ids. It is never persisted as a second source of truth, because two sources of truth is how a merge engine starts disagreeing with itself.
The one thing that is persisted is the resolution — because a resolution is a free human or agent decision that cannot be recovered from the snapshots no matter how carefully you recompute.
Protected paths
When a path is policy-protected, its content is protected everywhere it appears: the conflict's sides are sealed under the path's policy, as are the cached region fingerprints and edit structure, which reveal what a file says almost as readily as the file does. Error messages about a protected conflict are plaintext-free by rule.
Be precise about the boundary, though. What is protected is the content, not the fact. A peer who syncs the repository without holding the policy key still sees that a conflict exists and at which path — they simply cannot read any of its three sides.