Peira Labs

Products

Revision Agreement

A system that answers from a copy should be able to tell you which copy.

Specification
Draft 0.1.0, 2026-09-29 · CC BY 4.0
revcheck
Released v0.2.1 on 2026-09-29 · Apache-2.0 or MIT
Read it
SPEC.md · repository

1 The problem

Most systems that answer questions from a body of content keep the real content in one place and build a search index on top of it. The index is a copy, and copies lag. When they do, a healthy-looking system returns a well-formed, confident, out-of-date answer, and nothing in the answer says so.

2 Three questions

Ask them of anything that serves content through a derived copy: a search index, a projection, a cache, a replica.

  1. Does a result carry its revision?
  2. Can the copy be checked against the original?
  3. Does disagreement stop it?

A system that does all three can be checked by its callers. A system that does none has to be taken on trust.

3 Requirements and levels

R1
A read reports its revision, in the same structure as its results.
R2
There is an operation that compares every derived consumer’s revision with the source and names any that disagree.
R3
When a consumer disagrees, the read is refused, or served with a machine-readable label naming the stale consumer and both revisions.
R4
Writes advance one revision at a time, and no read sees a half-applied write.
LevelRequiresWhat it buys
0 UnverifiednoneNothing. Staleness cannot be seen from outside.
1 AttributedR1A caller can tell two answers apart.
2 CheckedR1, R2An operator can show, on demand, that the whole system is current.
3 Fail-closedR1–R3The system cannot silently serve stale content.
4 SerializedR1–R4Revisions name unambiguous states, and level 3 holds under concurrent writes.

4 revcheck

revcheck reads a JSON response and decides whether it satisfies R1. It can also compare two payloads taken before and after a write and confirm that the revision moved. Static binaries for x86_64 and aarch64 Linux are on the release page.

$ curl -sD - https://example.test/search?q=x | revcheck
level 0 (Unverified)
near-misses:
- header:Last-Modified: rejected by name (wall-clock field)
- $.results[0].updated_at: rejected by name (wall-clock field)
- $.results[0].hash: per-item scope
Example from the README at commit 58d70fa, checked 2026-10-26.

It is deliberately narrow. It tests R1 and revision advance only. R2 and R3 need the system’s own write and comparison operations and cannot be judged from a payload, so a pass establishes level 1 and nothing above it. A pass is also weaker than a failure: revcheck sees the shape of a value, not its meaning, and an API version looks the same as a content revision. Confirm a pass with revcheck advance around a real write.

5 Status

The specification is a draft, stable enough to test against and expected to change in response to implementations and counterexamples. Counterexamples are the most useful contribution: if you know a system that already returns its revision with its results, open an issue so the specification can cite it.