Skip to contentWolf-Rayet

Decision records

ADR-0037 Occlusion reorders the demand queue, and the scrim suspends a demand rather than hiding one

Accepted2026-09-02Phase 4

#Context

Fourteen components are built and every one of them is an Emitter or an Arbiter. None has owned a budget, so the Scope tier has been exercised only by hand-authored fixture sections — 05-overlay.html raises an overlay Scope with a composited scrim and passes in all four themes, and it carries, in its own words, "Zero level-4 elements — an overlay is a statement about interactivity, not a demand for attention."

That sentence is a fixture comment, not a decision, and the modal is the component that turns it into one.

Two rules meet here and have never had to agree. ADR-0014 made the scrim a fact about pixels: the engine composites the alpha layer and measures the rendered result, so a covered element's emission is already reduced by the scrim without anything being told about it. ADR-0010 made the demand cap a fact about declarations: engine.js collects dom.nodes.filter((n) => n.rendered && n.level === DEMAND_LEVEL && !n.inExemptSlot) and compares the count to VIEW_DEMAND_CAP. There is no notion of occlusion anywhere in that filter. A demand behind a scrim counts exactly like a demand in front of one, because no scene has ever contained one — the two fixtures that raise an overlay are deliberately demand-free, so the engine's implicit answer has never been tested and was never chosen.

Applying ADR-0010's stated arbitration to the overlay case makes the disagreement worse rather than resolving it. Arrival order holds a late demand at Directed and promotes it "when a slot frees". A modal opening over a Scope that already holds a demand arrives second by construction, so it is held at Directed for as long as the background demand persists — and the background demand persists behind a scrim the reader cannot reach. The screen that results ranks an unreachable thing above the thing the reader just opened and is looking at. That is the ladder inverted, which is the failure ADR-0005's salience-share check exists to catch, arriving through the one door that check does not watch.

ADR-0010 knew it had not finished this. Its own consequences say the arbitration "is stated here and implemented nowhere, because there is no runtime yet. It is a Phase 4 obligation on the first component that can escalate, and stating it now is what stops that component inventing its own rule." This is that component, and this is that record rather than an invention inside it.

#Decision

The scrim dims light. It does not lower a declaration. A Demanded element under an overlay's scrim keeps its declared level and keeps counting against the View's demand cap. There is no occlusion exemption in the salience channel, and the engine's filter is correct as written.

Occlusion reorders the queue ADR-0010 orders by arrival. An overlay Scope requesting Demanded takes the View's slot from the demand it covers, rather than being held behind it. Arrival order governs Scopes that compete on one plane; it does not govern a Scope that occludes another, because the covered Scope is not competing for attention — it has been withdrawn from interaction by the overlay, and ranking it above what replaced it is the inversion above.

The covered demand is suspended, not exempted. Taking the slot re-declares the covered element at Directed for the overlay's lifetime and restores it to Demanded when the overlay closes. Suspension is a change of level, with everything that follows from it: level-3 roles, level-3 tone, level-3 emission. It is ADR-0010's own deferral mechanism — "held at Directed and promoted when a slot frees" — applied in the direction occlusion dictates instead of the direction arrival dictates.

A static scene showing both at Demanded is a build failure, naming both Scopes, the View and this rule. There is no runtime in a fixture to suspend anything, so a scene drawn that way is wrong at the point it was written, exactly as ADR-0010 says of every other over-cap scene.

An overlay Scope declares its own level, and its floor is Directed. A Scope carries data-wr-level — the four existing overlay fixtures already do — and for an occluding one that declaration may not sit below §2's Directed. Occlusion *is* a claim to be the local focus: a surface that dims the whole view and then declares itself "resting content" has a declaration contradicting its own stacking context, and no check in the system would catch the contradiction because each half is legal alone. So the floor is the stacking context's consequence rather than a taste value, and the ceiling is Demanded, taken under the ordering rule above.

#Rejected options

Leave it implicit — the engine already counts covered demands, so ship the modal and let the filter answer. Merit: no new record, no new machinery, and the behaviour is arguably already correct on the laundering question. Lost because the modal's own required scene has no defined verdict under it. A modal over a live alarm either fails the build or opens permanently quieter than the thing it covers, and which of those happens would have been decided by the order of two lines in engine.js rather than by anyone. The unwritten answer is also the one nobody can find: the next person to hit it reads a filter, not a decision.

Exempt covered demands from the View cap — the scrim hides them. Merit: it is the intuitive reading of occlusion, it makes modals trivially composable over any screen, and it needs no suspension mechanism at all. Lost because it is a laundering device with a stacking context for a lid. A second demand becomes free the moment something is drawn over it, which is precisely the substrate laundering ADR-0009 refuses at the content boundary and ADR-0026 refuses at the portal boundary, arriving a third time through the scrim. It also contradicts ADR-0014 in the same breath it invokes it: that record says the covered scene "remains visible, dimmed" and that occlusion "is a statement about interactivity, not a disappearance." An exemption treats it as a disappearance.

Hold the overlay at Directed, per ADR-0010's arrival order, unchanged. Merit: it is the existing rule applied without amendment, it needs no new concept, and §2's Directed — "clearly the local focus. Imperative. Names the next action." — is a genuinely good description of most modals. Lost on the inversion. A destructive confirmation is the case that breaks it: "Delete 4,471 records. This cannot be undone" is §2's Demanded exactly — imperative, consequence stated, short — and a rule that caps it at Directed because something is beeping behind a scrim has ranked the two backwards. The merit is real and is kept: an overlay that does not need Demanded takes Directed, and most will.

Forbid Demanded inside an overlay Scope entirely — a scope demand cap of zero for overlay. Merit: the cleanest rule in the set, it removes the arbitration question rather than answering it, and it has a real argument behind it — occlusion is already an attention act, so spending a demand slot on top of it is paying twice for the same interruption. Lost on the same destructive-confirmation case, from the other side. It also makes SCOPE_DEMAND_CAP a function of stacking context, which is new machinery bought to avoid a decision rather than to enforce one.

Give the View a second slot while an overlay is open. Merit: both demands keep their declared level, nothing is suspended, and no existing rule is amended. Lost because it is ADR-0010's rejected cap-of-2 wearing a condition. That option was refused because "two simultaneous demands is the exact condition the thesis calls a failure of the interface to answer *what needs me now*", and a cap that rises whenever a modal opens makes the central claim optional on the most common interaction in a product.

Let an overlay Scope rest at Ambient, like every Scope section in the existing fixtures. Merit: it is what the four committed overlay fixtures already declare, it needs no floor rule, and it has a real reading behind it — the scrim and the sheet are chrome under ADR-0009, and chrome is not an allocation. Lost because those fixtures are generic Scopes that happen to raise an overlay, not modals, and because Ambient is §2's "resting content". A component that dims the entire view and simultaneously declares itself resting has stated two incompatible things, and the system would pass it: the stacking declaration and the level declaration are each legal alone and nothing compares them. It also puts the component's copy under the level-1 length ceiling of 20 characters, which is the bootstrap measured from real level-1 strings and is a ceiling for labels, not for a three-part §6 message.

#Consequences

What this makes easier. The modal's three required scenes now have declared verdicts that come from a record rather than from a filter: a calm modal passes, a modal holding one demand passes, and a modal over a Scope whose demand is still declared Demanded fails on Salience — view. The third is the must-fail sibling ADR-0013 asked for from a different direction, and it is the first scene in the set that fails the View check for a reason the Scope check cannot see.

What this makes harder, stated plainly. The suspension half needs a runtime, and there is still no runtime. What ships with this record is the static half — the declaration, the failing scene, and the contract that forbids a modal from declaring Demanded while what it covers does. The transition from Demanded to Directed and back is a Phase 4 obligation on the first component that can escalate at runtime, which is not this one: a modal hosts a demand, it does not become one. This ADR is what stops that component inventing its own rule, which is the service ADR-0010 performed for this one.

What is not decided here. Nothing about level 3. Two Directed elements, one under a scrim and one over it, is ADR-0005's undecided case and stays undecided; a View cap on level 4 does not answer it, and neither does occlusion. ADR-0010 is amended by this record on the ordering question only, not superseded: its cap, its default, its zero-is-valid rule and its static-analysis rule are untouched and are cited above rather than restated.

Enforcement table. Touches Salience — view, whose rule gains an ordering clause and whose failure text now names occlusion when the over-cap pair straddles a scrim. Adds no new check kind. Emission load is untouched — ADR-0014 already governs what the scrim costs, and suspension changes a level, which the existing per-level roles already price.