ADR-0062 An obstruction is not an alarm, and the states are the fields
#Context
ADR-0061 audited section B's five remaining rows together and let four stand. progress-indicator stood on two dimensions against tabs — three states per member rather than two, and an order Carbon makes a constraint rather than a layout, refusing the component outright *"when the process may be completed in any order"*. This record builds it, and everything below follows from those two sentences.
#Decision: the three states are the three fields
tabs splits its panels into before, selected and after to make "exactly one selected" unrepresentable — ADR-0054's move for an ordered set. Here the same split does a second job for free.
Everything in before is complete. current is current. Everything in after is not started. There is no way to spell a completed step that sits after an unstarted one, because there is no field it could go in. The linearity Carbon states as a usage rule is the shape of the props, checked by the compiler at every call site rather than by a runtime assertion nobody reads.
A step therefore declares no state and no level. Its state is where it sits in the props, and its rung is the Arbiter's grant — which is what makes this an Arbiter rather than a row the caller has already ranked.
#Complete and awaiting take the same rung, and are told apart by form
The grant is button-group's and tabs' function shape, third instance: the current step takes the set's rung, every other step takes the rung beneath, floored at Ambient. Complete and awaiting are not separated by light.
What separates them is the fill of the node and the weight of the line reaching it — position and form, the table row's encoding, and the channels that survive field-night where hue carries nothing. A second rung would have spent emission to repeat what the line already says, and at Ambient there is no second rung to spend.
#The node is a circle, and the set rule lives in the contract rather than on the variant axis
ADR-0028: a checkbox is square because several of its set may be picked, a radio button is a circle because exactly one may be. Exactly one step is current, so the node is round — the radio button's rule of the set one tier up, at the Arbiter that makes the choice rather than at the control reporting it.
tabs put that rule on its variant axis and named the variant exclusive, because it had nothing else to put there. This component has a real variant axis — a process is advancing or it is blocked — so the set rule goes where ADR-0028 specifies it, in setRule. The circle is a border-radius of 50% and not a clip-path, so this component declares shapes: {} and inherits the gap that record names about itself: the most load-bearing shape decision here is one the polygon check cannot see.
#An error can only be on the current step, so it is the indicator's variant
Carbon's anatomy gives a step an error state. In a linear process it can be nowhere else: a step that failed is a step the reader has not got past, and a process that advanced beyond a failed step is not linear — which is the case Carbon refuses this component for in the first place.
So blocked describes the indicator, not a step, and there is no per-step error flag to place inconsistently. blocked is adverse under ADR-0044 and has no Ambient rung: §2's level 1 is resting content and a live obstruction is not resting. The floor is read from the ladder rather than spelled, and variant="blocked" level={1} does not compile.
#disabled is not a state on this ladder
Carbon lists one. Button and InputField already decided it: *"a disabled control competes for no attention at all, which is an interaction affordance rather than a fact this component's allocation could describe."* A step that cannot be reached is a step the reader has not been to — which is awaiting — plus a claim about the future no component can keep.
#And it does not move the reader through the process
interactive: false. It reports where the reader is; the control that advances a process is a Button. That is ADR-0050's split — *"the control that performs an acknowledgement is a Button"* — and Carbon's own pagination page says the same from the other side: use buttons *"to navigate forward and backward"*. No turned corner (ADR-0045).
#What the generator refused, before anything shipped
The first build declared both variants' marks and nothing else, and tokens:verify rejected it:
progress-indicator: "advancing" and "blocked" at level 2 differ only in mark role ("emitter-marked" vs "status-caution"), and those roles share a lightness in 4 theme(s)All four themes. ADR-0039's Rule B, catching a component whose two states would have been told apart by hue alone — which is nothing at all in field-night, the theme §4 says this component is designed in first. The two roles are 0.6195 against 0.6195 in interior-light, 0.8742 in interior-dark, 0.285 in field-day, 0.6218 in field-night.
The fix is a pattern rather than a second colour, and it draws what it means: an advancing process closes each step behind it, and a blocked one has a step it could not close, so the ring is open. border-style: dashed on the current node under .wr-progress-indicator--blocked, and not a change of shape — the circle is the rule of the set and belongs to every step in every variant, so changing it would say the set had changed its rule when only the process had stopped.
The generator's own checks are load-bearing, which the handoff into this session already said in those words about two earlier refusals — a border token that did not exist, and a size ladder with a flat rung in a component whose whole subject is a ranking. This is another, and it is not counted here because no file in the repository counts them: a tally of past refusals is a claim about history that nothing derives, and ADR-0049 is why this record does not make one.
#Measured: scene 57
A commissioning process that cannot proceed, beside a line reporting normally.
| Scope | emission | ceiling |
|---|---|---|
#shell | 0.058307 | 0.128641 |
#scope-work | 0.029783 | 0.128641 |
#scope-line | 0.046967 | 0.128641 |
The screen holds no demand at all, and that is the claim the scene is a record of. A process that has stopped is not an emergency; ADR-0010 rations the demand rung to one per View precisely so it is available when something actually is on fire. The obstruction sits at Marked — §2's *"distinguishable, not attention-seeking"* — and ADR-0044's floor is what stops the same variant sitting at Ambient where it would be resting content.
No must-fail twin, for ADR-0054's reason: this component's illegal state is blocked at Ambient, and the correlated union refuses it in the props before anything is drawn. A fixture that cannot be authored is not a fixture that passes.
Scene 57 is the third to hold its Scopes as <Region> (ADR-0058) and the first to compose two Arbiters side by side inside one Scope — the indicator and the rows — which is legal because neither contains the other.
#Rejected options
Give complete and awaiting different rungs. The obvious reading of "three states": three levels. Rejected because the grant has two outputs and a third would need a rung the ladder does not have below Ambient, and because the difference is already drawn. The line into a completed step and the line into an unstarted one differ in weight; the nodes differ in fill. Spending a second rung to restate that is the emission this system exists to refuse, and at Ambient there is no rung to spend.
Make error a flag on a step rather than the indicator's variant. What Carbon does, and it is more flexible. Rejected because the flexibility is the defect: a per-step flag can be placed on a step the reader has already passed, which describes a process that advanced beyond a failure — a process Carbon's own page refuses this component for. Putting it on the indicator makes the inconsistent case unspellable.
Carry Carbon's disabled step state. Rejected on Button's and InputField's existing decision rather than on a new argument, which is the point: the ladder has no rung for an affordance, and a component that invented one here would have made disabled mean something different in its thirty-first appearance than in its twelfth.
Take the steps as children rather than as data. Rejected on ADR-0054's finding, third instance: a component that accepted <Step level={2}/> could not grant anything, because the caller would already have decided.
#Consequences
Roster 52, built 30 → 31. Section B has three rows left — pagination, tree-view, file-uploader — and tree-view still carries ADR-0061's open question against §5.
The third Arbiter to use §3's grant, and the function is the same shape all three times. That is now a pattern rather than a coincidence, and it is worth naming: §3 gives the tier one power, and three components exercising it three identical ways is the tier behaving like a tier.
blocked is the fourth adverse variant in the set and the first on an Arbiter. ADR-0044's correlation, the adverseVariants declaration and the existsAtLevel specimen rule all applied unchanged, which is the mechanism doing what it was generalised for.
No new check kind; playbook §10 stands at 26. What grows is one scene, one discipline row and one must-fail fixture.
linux-x64 is short by exactly the one new scene, three Scope values.
#Measured
tokens:verifyrefusing the first build: two variants sharing a lightness at level 2 in 4 of 4 themes — *darwin-arm64, this pass*.progress-indicator: 24 component tier tokens, 40 APCA floor checks all met, worst |Lc| 16.23 against aninterior-lightAmbient floor of 15.- Scene 57: 0 demands against a cap of 1, three Scopes, worst emission 0.058307 against a
field-nightceiling of 0.128641. - Roster 52, built 30 → 31.
pnpm battery— the verdict this pass is measured by.