Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Why review files never conflict

Two people review different code on different branches. Both append to .vidi/reviews.jsonl. That should collide on every merge, and if reviewing meant resolving a conflict each time, people would quietly stop reviewing.

It does not collide, and the reason is four properties stacked on top of each other.

One claim per line, never rewritten

The ledgers are JSONL: one review per line, appended. Nothing is ever edited in place, and nothing is deleted. Revoking adds a record rather than removing one.

That already removes most of the problem. Two people appending different lines are not editing the same text, so there is nothing for git to arbitrate.

The git half: merge=union

vidi init writes one line into .gitattributes:

.vidi/*.jsonl merge=union

This tells git to resolve these files by keeping every line from both sides instead of asking you to choose. No conflict markers, ever.

Writers append rather than rewrite for exactly this reason. A whole-file rewrite would clobber lines contributed on another branch, which is what union merge exists to prevent.

Why union alone would be wrong

Keeping every line says nothing about what the lines mean together. Union on its own leaves two holes:

  • the same claim can arrive twice: a replay, or one review present in both its bare and its signed form
  • a revocation and the review it kills can both be present

So the reader applies an algebra over the union (crates/vidi-core/src/ledger/store.rs):

RuleEffect
content_id dedupcontent-identical lines collapse to one entry
revoke-winsa revocation dominates its target forever, whichever arrived first
monotonereviews.jsonl only ever adds claims; revocations.jsonl only ever tightens

Order cannot change the answer

None of those rules depend on order. Two people who merge the same set of records compute the same coverage, no matter what sequence the merges happened in, and no matter where in the file a line sits.

No coordination is needed, because there is no ordering to agree on. (The formal name for this property is a monotone CRDT, if you want to look it up.)

It is also what makes re-approving after a revocation work. A revocation names one content_id and dominates it permanently. But vouching again produces a record with a different content_id, which the revocation does not name. The old claim stays dead, the new one is live, and neither outcome depends on arrival order.

Choosing which copy survives

Dedup has to keep one entry, and choosing which one is harder than it looks.

The same review can be written down three ways: plainly, wrapped in a signature, or wrapped in a signature plus a notary receipt. Same claim, different envelopes, and all three share one content_id.

So when several of them arrive, something must decide which to keep. Last-write-wins would make the survivor depend on merge order, and the whole guarantee above would collapse.

Instead the store ranks the forms (plain, then signed, then signed with a receipt) and always keeps the highest, breaking ties on the bytes themselves. The form it retains therefore depends only on which forms turned up, never on the order they arrived in.

That tie-break is also deliberately inert. The gate never reads a record’s form, receipt, or signatures, so which representative survives can never move a gate outcome. It exists only to make the answer deterministic.

A set, not a log

There is no repo-side hash chain and no sequence number. The ledger is an unordered set of claims, and any chain integrity lives notary-side only.

This is a deliberate trade. A chain would give tamper-evident ordering, but ordering is the one thing that cannot survive two people merging branches in different sequences. Vidi gives up the chain in the repository to keep the convergence.

Whitespace cannot dodge a revocation

There is a hard edge here. A content_id is computed after the surrounding whitespace is stripped, so two records that differ only in spacing get the same id (crates/vidi-core/src/ledger/codec.rs).

Without that, a whitespace twin of a revoked review would hash to a different content_id, which the revocation does not name, and the resurrected claim would read fresh. Stripping the whitespace first closes that door.

What this does not cover

The guarantee is about merging, not about agreement. Two people can hold contradictory positions on the same code, one approving and one rejecting, and the merge keeps both lines without complaint. Resolving that disagreement is a human problem; the ledger only promises that it will not lose either claim and that everyone computes the same answer from the pair.

It also depends on everyone having the .gitattributes rule. Commit that line with .vidi/. A clone missing it gets ordinary conflicting-file behavior on the one file that should never conflict.

Next

Fail-closed by default