Appearance
ADR-0071: The gaps read's coverage union and its precedence are a contract, not an implementation detail
Status: Accepted — amends ADR-0068, which stands Date: 2026-09-20
Decisions
D-148 The coverage union has four members and one precedence order, and both are fixed
The four members, and four is the whole set: GAPS_OUTSTANDING, NO_RESTRICTION, NOTHING_SELECTED, EVERY_PAIR_JUDGED. A fifth is a new ADR, not a new case.
The precedence, in order — the order is the rule, not an artefact of how the conditions happened to be written:
- a non-empty gaps list is
GAPS_OUTSTANDING; - else a document holding no Restriction is
NO_RESTRICTION; - else a document from which nothing has been selected is
NOTHING_SELECTED; - else
EVERY_PAIR_JUDGED.
NO_RESTRICTION outranks NOTHING_SELECTED on a wholly uncurated document, and that is the judgement in this ruling. With no Restriction, selecting spans produces no pair either, so a page that told the curator to go and select first would be sending them to do work that changes nothing on this surface.
What this amendment touches
ADR-0068 — D-144 stands. Its two facts and its compose-nothing rule are unchanged. What this adds is that the encoding of the case is fixed rather than free: ADR-0068 ruled the intent and left the shape open, and the shape has since crossed the repository boundary. ADR-0068 is Accepted and is not edited.
Correcting ADR-0068's Decision paragraph. It reads "The reconcile page states the case those facts determine", which permits what the ruling forbade: a page deriving its sentence from two booleans and
gaps.lengthis composing the case, which is the precise thingcoverageexists to prevent. ADR-0068's Context has the stricter reading — "The fix is not a better sentence; it is a payload that determines the answer", and D-124's server-decides rule — so the Decision paragraph is under-written rather than in conflict. Read it as: the server decides the case and sends it; the page words the case it is given and determines nothing.Correcting ADR-0068's stated cost. Its Consequences claim "one more query on a read that already runs per document". There is no extra query —
readCuratedDocumentalready returned the document's Restrictions and the record's attachments, so both facts were in hand. The fixture half of that cost is real and stands. A cost that was written and then not paid should not stand as if it were.
Context
ADR-0068 rules that the gaps read carries two facts and that the page composes no claim the payload does not carry. It does not name a union and it does not order one. The build settled both, and both now cross the boundary between the two repositories: the server decides the case, the page words it, and a golden fixture carries one body per member so a page cannot receive a value it has no wording for.
A closed union that two repositories key off, gated by a fixture per member, is already a contract in everything but authority. This ruling supplies the authority.
Five fixture cases against four members, and that is correct. EVERY_PAIR_JUDGED carries two wordings, separated by pairCount under the judged-count ruling (D-145): a document with pairs says every pair was judged, and one with none says there were none to judge. That is one member with two wordings, not two members. The count is what splits it for a reader, which is exactly why D-145 rejected making it a fifth member. Do not reconcile the five cases down to four, and do not promote the second wording into the union.
Decision
The coverage union's four members and their precedence order are a contract between the two repositories. Changing either is an ADR.
Rejected options
- Leaving the union as implementation detail — rejected. D-144 rules the intent, and the fixture already stops a member shipping without a wording, so it looks covered. But a fixture records a shape; it does not rule one. The next agent to reshape the union would take the fixture with it, both repositories would stay green, and the contract would have changed with nothing to notice. That is the green-for-the-wrong-reason class this project keeps finding, one level up again: the gate that was supposed to catch the drift moves along with it.
- Ordering
NOTHING_SELECTEDaboveNO_RESTRICTION— rejected because on a wholly uncurated document it sends the curator to select spans, which produces no pair and changes nothing on this surface. The instruction would be true about the document and useless about the task. - Deriving the case on the page from the facts and the list length — rejected as the shape ADR-0068 already refused. It is also what the under-written Decision paragraph appeared to permit, which is why this ADR corrects it.
This ruling may not be re-decided
If a change contradicts this ADR: stop and raise it. Do not implement over it.
Specifically: do not add a fifth member, do not reorder the precedence, do not let the page decide the case from the facts it was sent, and do not collapse the five fixture cases to four. Each of those is an ADR.
Consequences
What becomes true. A reshaped union fails review against a ruling rather than passing a fixture it brought with it. The precedence question that was settled by the order the conditions were written in is now settled by a decision, and the uncurated-document case has a stated reason.
What this costs. A fifth member — or a reordering — now costs an ADR, including the cases where it would be obviously right. The fixture stays the enforcement, so it is still regenerated on both sides whenever the union legitimately changes.
What is closed off. Any growth of the union by implementation, and any page-side derivation of the case.
Coverage
| Upstream | Landed in | Evidence | Note |
|---|---|---|---|
| D-144 | D-148 | ADR-0068 ruled the intent and named no union; this fixes the encoding that the build settled and both repositories now key off | ADR-0068, amended here and standing |
| D-145 | D-148 | the judged count splits one member into two wordings, which is why there are five fixture cases and four members | ADR-0069; D-145 is untouched and its rejected fifth member stays rejected |
| D-124 | D-148 | the server decides every per-field value and the client derives nothing from it; the union is that rule's encoding on the curator-side read | ADR-0053; the golden fixture is the same cross-repository instrument |
| D-44 | D-148 | the members describe states of the reconciliation rule's pairs, which is what makes the set closed at four | ADR-0022 |