ADR-0128 A record's levels mean what its layer lets them mean
Corrected by: ADR-0129 Date: 2026-09-24 Phase: 7
Supplies the rule ADR-0121's remaining rows are decided by.
#Context
ADR-0121 found that sixteen of the component tier's thirty-seven entries had no declared variant classed anywhere, and read that as the record describing a component the rewrite replaced. It decided six rows on that basis, correctly, and left eleven undecided with a method attached: one component at a time, with the component and its stylesheet open.
Opening them shows the measurement was reading the wrong column.
Not one of the operational twenty classes its variants either. region declares set, popover declares anchored, shell-header declares persistent, loading declares pending, and no stylesheet carries a class for any of them. Those four are proved components with scenes, fixtures and passing baselines. A single variant naming the component's kind is the system's ordinary shape for a component with one mode, so "0 of 1 classed" is not a finding, it is the shape.
The column that does say something is the level list, read against the layer that owns it. Measured two ways this session, from the React render and from the fixture markup, and the two agree on every component where both speak:
| layer | what the operational set does | measured |
|---|---|---|
| Emitter | declares a range and renders a subset of it | meter records 1 to 3 and reaches 1 and 2; loading records 1 to 3 and reaches 2; staleness records 2 to 4 and reaches 2 and 4; trend records 1 to 3 and reaches 1 and 2 |
| Arbiter | declares a range and writes no data-wr-level at all | queue-item on 22 elements, table-row on 62, navigation-item on 105, none of them carrying the attribute |
| Scope | declares exactly one rung | data-table, shell-header, shell-left-panel, shell-right-panel, page-header, region, live-feed, popover, all at [1] |
Three readings fall out of that, and each is a different kind of statement:
An Emitter's level list is a capability. It holds an allocation, the allocation varies, and a rung it does not happen to render in a fixture is a rung it may hold. Four of the operational twenty are in exactly that position and none of them is defective.
An Arbiter's level list is a range it ranks over. §3 gives the Arbiter one power, the grant, and says only an Emitter holds an allocation. data-wr-level is that declaration, which is why the three operational Arbiters never write it: wr-queue-item carries its rung as a class, --ambient, --marked, --directed, and reads its tier through inline custom properties. An Arbiter writing data-wr-level declares itself an Emitter and contradicts its own record.
A Scope's level list is the one rung it owns a budget at. Every Scope in the tier but one declares a single level.
#Decision
A record's level list is read through its layer, and only an Emitter's is a capability.
- An Emitter may declare rungs it does not currently render. The list is what it may hold.
- An Arbiter declares the range it ranks over and writes no level on itself. Writing one is a layer contradiction, not a level error.
- A Scope declares one rung.
This is transcribed from the operational twenty rather than invented, because those twenty are the set with contracts, fixtures and proved-complete lists, and a rule the proved set would fail is a rule about nothing.
The consequence for ADR-0121's method: an unclassed variant is not evidence, and a level list wider than a fixture exercises is not evidence. What is evidence is a record whose level list its layer cannot mean. ADR-0121's remaining eleven rows are decided on that, and the table it carries now holds all of them.
#Consequences
Six of the eleven are correct as they stand and their rows say so: tooltip, page-header, button-group, empty-state, pagination and link. ADR-0121's measurement had them queued for a change none of them needs, and button-group is the sharpest case: it writes no level anywhere, which read as a component declaring nothing and is in fact an Arbiter behaving exactly as the three operational ones do.
Two are genuine layer contradictions and are sequenced rather than fixed here: accordion and tabs each write data-wr-level on the Arbiter's own root. Fixing it removes a declared Emitter from every scene they appear in, about thirty-two fixtures, so it moves measured budgets and both baselines and it belongs in a unit that can carry that. Scene 41 is accordion-hidden-demand and expects a failure; whether it still fails for its own reason after the declaration goes is the question that unit opens with.
One was fixed here: modal narrowed from two rungs to one, which moves no fixture and no baseline because nothing reads the level-3 tokens it stops emitting.
radio is decided and sequenced with them, and the reason is its own finding. Retiring it was attempted in this pass and self-description:check refused: 19 of 25 components state which number they are, radio sits in the middle of the list, and removing it moved every ordinal after it. Those sentences are claims about build order, so renumbering them to clear a check would make them lie. The check derives the ordinal from the entry's position in component.config.json, which is a derivation any mid-list retirement breaks, and that is the same defect in the same shape as the two above it: a check reading a column that stopped meaning what it meant.
Wrong, and ADR-0129 says how. The check has derived the ordinal from a build order with removed components counted back in since ADR-0092, out of a register in the config beside the components, and six components were already in it. The retirement failed because it was written as an object keyed by name and the register is an array. A malformed entry, read here as a broken derivation. The sentence above is left standing because a record that quietly stops having been wrong is worth less than one that says where it was.
The rule is not yet a check. It would fail on accordion and tabs today, so it lands with them rather than ahead of them. That is the same sequencing ADR-0125 used for the cascade lint and it has the same hazard: a rule written down and not enforced is the state ADR-0126 found a whole test file in. The row that closes this is the one that writes the check.
#Rejected
Narrow every record to the levels its fixtures exercise. The rule I reached for first, and the control group refuses it: meter, loading, staleness and trend would all fail, and all four are proved. It would turn a capability list into a usage log, and the next component to gain a state would fail a check for gaining it.
Read the variant column harder instead. ADR-0121's own measurement, taken further. There is nothing in it: the operational set does not class its variants either, so the column cannot separate a live record from a dead one. What a variant does carry is a generated token, and whether anything reads that token is ADR-0125's question rather than this one.
Require an Arbiter to declare no level in the record as well as in the markup. Tidier, and it would delete information. accordion ranking over 1 to 3 says what its sections may hold, which is the thing a reader of the record wants to know and the thing the three operational Arbiters also say.