ADR-0051 Acknowledgement is serialized, and the tick joins the vocabulary
#Context
ADR-0050 ended with a debt and named it:
A check is owed and is not written here. The illegal state this record creates is *level 4 with acknowledgement*, and it is a static property of a scene exactly as an over-cap scene is — so the engine could refuse it. It cannot yet: demandLive is a CSS class and the engine reads declarations, so the state is invisible to it.That record was enforced by the type system and by reading, which is one witness. This is the second.
The debt is not bookkeeping. ADR-0050's own opening is that ADR-0010's cap of one demand per View "is only humane if something clears it, and nothing does" — and what it decided is that acknowledgement clears it, by descending the demand one rung. A descent nothing can check is a descent a product can skip. The failure that would follow is the one the record opens on, arriving after the fix instead of before it: an alarm an operator has dealt with, still declaring the region maximum, still holding the only slot the next thing to go wrong needs.
#Decision
data-wr-acknowledged is a serialization-surface attribute, written in both states by the three components that can carry a demand a human could acknowledge, and the engine refuses level 4 with it.
#The attribute
ATTR.acknowledged joins core's ATTR table beside ATTR.vouched, which is the shape it copies and the record it is the companion to. The two are opposites in what they are about, and that is the whole of why both exist:
data-wr-vouched | data-wr-acknowledged | |
|---|---|---|
| A claim about | the machine — can this still be supported | the operator — has a human seen this |
| Written by | the eight components that report a condition they were told about | the three that can reach the demand rung |
What false / true does to the rung | pins it to the component's floor | caps it at Directed |
| Set by | the product's freshness wiring | the product's acknowledgement control, which is a Button (ADR-0050) |
They are independent: a reading can be acknowledged and fresh, acknowledged and stale, unacknowledged and either.
Written in both states rather than only the acknowledged one, for ADR-0048's reason: *absent* and *false* must not read alike, or a component that stopped emitting the attribute would look unacknowledged to every check while the product believed otherwise.
#The descent is a cap, and it happens in the component
Every component that takes the flag computes what it declares before it emits anything:
declaredLevel = !vouched ? FLOOR
: acknowledged && level > ACKNOWLEDGED_LEVEL ? ACKNOWLEDGED_LEVEL
: levelA cap, not a subtraction: acknowledging a Marked reading must not make it quieter than it was, and below the demand rung there is nothing to descend. ACKNOWLEDGED_LEVEL is derived per component as the rung immediately beneath its own demand rung, never written as 3 — the same construction X_UNVOUCHED_LEVEL uses, and test/discipline.test.js asserts all three land on Directed, which is what ADR-0050 names.
Withdrawal wins where both apply, and not by accident. An unvouched claim is already at its component's floor, at or below the acknowledged rung, so there is nothing further to lower. The other ordering would let an acknowledgement *raise* a withdrawn claim, which is the one direction neither record permits.
The consequence is that the illegal state is unrepresentable in the React tier, exactly as ADR-0048's was — which is why the must-fail scene carries one hand-written element, and why the engine check is not redundant with the type.
#demandLive and acknowledged are refused as a pair
Exactly one of their four combinations is a contradiction. §2 grants sustained motion to a *live* demand; acknowledgement is precisely the event that ends the liveness. An element carrying both says "a human has dealt with this" and "this is still calling for a human" in one breath.
Refused in the type, in one shared AttentionState union rather than three copies — ADR-0044's reason for refusing an adverse variant at Ambient: the token for the contradictory state does not exist either, and a missing custom property falls back silently while tsc does not.
One line was wrong before this and is corrected rather than added to. All three components computed demandIsMoving from the raw level prop rather than from declaredLevel. A withdrawn or acknowledged element given demandLive therefore carried the motion class while declaring a rung that is granted no motion. Nothing moved on screen, because each stylesheet's animation selector happens to require the level class as well — a rule two files away holding a defect shut. The expression now reads the declaration, which is what the element *is* rather than what the caller asked for.
#Three components, and modal is the argued exception
The set is status-indicator, alert and staleness — every component whose declared levels include the demand rung, except one.
modal reaches the rung and does not take an acknowledgement. For an occluding surface the acknowledgement *is* the dismissal. A modal a human has said they have seen, still open and still dimming the screen behind it, is the stuck screen ADR-0050 refuses, arriving through ADR-0037's stacking context instead of through the ration. What descends a modal's demand is closing it.
That exception is a judgement and cannot be derived, so it is not encoded as a rule. What is encoded is the half that *is* derivable — acknowledges: true requires the component to reach the demand rung, because an acknowledgement descends a demand and a component that cannot make one has nothing to descend — and the exception is printed by name on every run instead. An exception that has to be printed is an exception someone reads; a second one arriving is a line in the log rather than a silence.
staleness taking the flag is worth stating, because its own file opens by saying two things are absent from it and both are decisions. It has no vouched prop: its input is the local clock, and a staleness report that could expire would need a second staleness report about it. Acknowledgement is the opposite case — *I know line 3 is dead, I am on my way* is the ordinary sentence an operator says about it. Freshness is a claim about the machine and this component has none to make; acknowledgement is a claim about the operator, and every component that can demand has one to carry.
#The receipt, and the tick joining the shared vocabulary
The descent alone is not legible. An acknowledged demand and an ordinary Directed element resolve the same size, the same weight and the same ink, so without a mark a reader has no way to tell which of them a human already saw — the "replaced a lie with a blank" failure ADR-0048 named, from the other side.
So an acknowledged element draws a receipt beside its reading, and it may not touch the reading: the mark keeps its shape, its colour and its ink, and the copy keeps its words. The condition has not changed and nothing the component says about it may suggest otherwise.
The receipt is the checkbox's tick, vertex for vertex, and that is this record's second finding. Until now the tick was filed under ownShapes — a polygon the checkbox meant on its own — and the shared-shape table said in as many words that it was *"not a statement about attention that a second component could agree or disagree with"*. Acknowledgement is what makes that false. An operator saying I have seen this about an alarm and a reader saying yes, this one about a proposition are the same act. ADR-0028's rule is that one shape name names one geometry across the whole set, so the tick moves into the vocabulary the triangle and the octagon are in, and react:test now compares four drawings of it on every run.
No new colour role. The retraction needed one because it had to stop encoding what the reading would have said; this is the reverse — the reading still says exactly what it said — so a second role would be a fourth channel carrying a fact that is not about colour, spending emission on a state whose entire purpose is to spend less. The receipt resolves --mark, already selected on the element at the descended level.
#The engine check
salience — acknowledged: an element declaring data-wr-acknowledged="true" may not also declare the demand rung.
It is not a discount and must not be read as one. ADR-0050 rejected "count only live demands" for ADR-0040's reason — it lets a screen become compliant by an act — and this check does not reopen that. viewDemands still reads the level and consults nothing else. What makes the ration workable over a shift is that the component descends the rung *before it declares*, so by the time the engine sees the element there is nothing to discount. An element still declaring 4 while claiming acknowledgement has therefore been produced by no component in this system, and saying so is the whole check.
#Two scenes, and 49 is the one that could not be drawn
49 — a second alarm reaches the operator (must pass). The seal press went over temperature; a human acknowledged it; while they were dealing with it, conveyor 4 jammed. Two conditions on the screen, one demand, against a cap of one.
Before ADR-0050 this scene was over cap by construction, whatever the operator had done about the first alarm — the first held the View's only slot for as long as it was rendered. Every scene in the roster before it holds at most one condition worth demanding about. 49 is the first legal drawing of an ordinary shift, and the count is the claim.
The seal press alert is word-for-word what it was: same title, same message, same fix, same octagon. Only the rung moved, and the tick says why.
50 — an acknowledged demand that kept its rung (must fail). The same screen with the acknowledgement written onto an element that did not descend. It fails on salience — acknowledged and on nothing else: the View holds one demand so the cap is untouched, the forged element vouches for itself and is drawn so neither salience — vouched nor salience — hidden has anything to say. A must-fail scene that fails two rules cannot tell you which one has teeth.
One element in 50 is hand-written, for scene 48's reason and it is the finding rather than a shortcut: an acknowledged demand is capped at Directed before a class or an attribute is emitted, so a caller has no way to ask for the illegal state. Asking whether the engine refuses what the type already refuses needs markup the components will not produce.
#What widening one set found
The react discipline suite iterates a table of components, and it held 21 of the 25. The three shell Scopes and staleness were outside it, so every check in that file — one tier consumed, no raw values, no undeclared clip-path, the shared shape vocabulary, the motion collapse — had been running over a set narrower than its own subject. This is the fourth time this shape of defect has been found, and the standing lesson is to widen the set rather than patch the instance, so the table now carries all twenty-five and a completeness assertion against COMPONENT_LAYERS in both directions sits beneath it.
Adding the four rows found three real defects immediately, none of which any suite could see:
staleness.cssread--wr-staleness-sustained-easing, a token the tier never emitted. An undefined custom property resolves to nothing and the declaration drops, so the one sustained animation in the component ran on the browser's default curve while its two siblings ran on the linear one their contracts declare.- The same component's
sustained-durationcarried"property": "sustainedMs"— a grant property that does not exist. The generator readspropertynowhere, so the string was a declaration that said nothing, sitting in a declarative file, looking exactly like one that said something. The generator now refuses an unknown spelling rather than ignoring it: a key nothing reads is a key that can say anything. - The same block omitted
class: "sustained", so §5's "sustained motion below level 4 is a build failure" check had nothing to run against for this component.
And a fourth, found by grep rather than by a suite: two Storybook stories asserted the claim ADR-0050 amended — *"the acknowledged level-4 mark does not move ... while staying at level 4 because it is still the region maximum"* — above a specimen captioned level 4 · acknowledged · still that passed no acknowledgement at all and was simply a demand nobody had seen. ADR-0050 amended two stylesheet comments and missed these. Both are corrected and both specimens now acknowledge.
#Rejected options
Serialize demandLive instead of adding an attribute. Tempting, because the flag already exists. It is the wrong fact: demandLive: false at level 4 is ambiguous between *acknowledged* and *never was live*, and the illegal state this record refuses depends on telling those apart. ADR-0050 was explicit that the flag is "the rendering, not the mechanism", and a mechanism inferred from a rendering is the defect that record was written about.
Make acknowledged required and undefaulted, like vouched. Rejected because the safe direction is the opposite one. ADR-0048 required vouched because an unwired product would otherwise get confident marks it cannot support — a lie. An unwired acknowledgement leaves every demand unacknowledged: the screen stays louder than it needs to be, which costs the operator attention and costs them nothing they were owed. A default the other way would have the product silently descending demands nobody had seen, and a default is the cheapest button-press there is.
Derive acknowledges from the levels instead of declaring it. It is almost derivable, and the almost is modal. Deriving it would have silently given the modal a flag ADR-0050's reasoning refuses, and the exception would have had nowhere to be written down. Declared, checked in the direction that *is* derivable, and the exception printed by name.
A colour role for the receipt, mirroring emitter-unvouched. Rejected above: the retraction had to stop encoding what the reading would have said and this has nothing to stop encoding, so the role would carry a fact that is not about colour and spend emission on the state whose purpose is to spend less.
A fifth silhouette for the receipt. Rejected for ADR-0028's reason arriving from the useful direction: the system already had a shape meaning *a human affirmed this*, filed as private because at the time only one component made that statement. Inventing a second geometry for the same act is precisely the drift ADR-0028 exists to prevent, and it would have had to survive 4px in field-night to earn its place.
#Consequences
A probe is owed and is not written here. The attack shape is a blanket acknowledgement — an operator or a product acknowledging an alarm flood so that nothing declares the demand rung. It is not written as a gameability probe because the engine cannot answer it: a considered acknowledgement and a blanket one produce identical frames, and every check in this repository reads a frame. What the system can say is what ADR-0050 already decided — the descent is one rung and not off the ladder, the condition stays, and the copy stays — so a blanket-acknowledged screen is still a screen full of Directed alarms saying what is wrong. Naming the limit is the honest move; a probe that could not distinguish the two would be a check that passed on a lie.
One inconsistency is found and deliberately not taken. Alert builds its §6 tone records from the raw level prop rather than from declaredLevel, so a withdrawn or acknowledged alert's copy records still carry the rung the caller asked for. It is the same class of defect as the demandIsMoving line corrected above, it predates this record, and it moves nothing rendered — the records are metadata the content linter reads. Changing it reaches into a second suite's counts and belongs to a pass that can measure the result. Recorded here rather than fixed halfway.
The playbook's §10 enforcement table gains one row, Salience — acknowledged.
#Measured
data-wr-acknowledgedon 3 components, written in both states; 1 component reaching the demand rung without it, printed by name (modal).- Engine roster 45 → 47 scenes.
49-acknowledged-second-alarmpasses with 1 demand of cap 1 while carrying 2 conditions;50-acknowledged-demandfails onsalience — acknowledgedand on nothing else. - The react discipline table 21 → 25 components, with a completeness assertion against
COMPONENT_LAYERSin both directions. checkmoves from private to shared: 4 components draw it, compared vertex for vertex on every run. The shared vocabulary is now triangle ×5, octagon ×8, check ×4.stalenesstoken count 21 → 22: thesustained-easingthe stylesheet had been reading and the tier had never emitted.- Cascade audit 2900 → 2923 scene-state pairs across 180 → 182 scenes, every declared state carried by the frame.
- Themed set unchanged at 140 comparisons: the two new scenes are unthemed, composed in
field-nightlike every scene in their neighbourhood.