Skip to content

finding(e2e): the boot-continuity coverage rule reads an open modal as a blank viewport #6578

Description

@claude

Found while establishing step 1 of #6570 (premise check). Recording the measurement; not proposing an implementation.

The rule

e2e/console-boot-indicator.spec.ts (Console boot continuity) defines coverage as:

const el = document.elementFromPoint(cx, cy);
const ok = !!el && !!(el.closest('#root') || el.closest('#boot-splash'));

That rule reads an open modal dialog as a blank viewport, and it does so on every sample for as long as the modal is open.

The mechanism, measured

A Radix Dialog renders DialogOverlay (fixed inset-0 z-50) and DialogContent through DialogPortal, i.e. as body-level siblings of #root. So the centre hit test lands on a div that is outside both #root and #boot-splash — the exact signature the campaign treats as a blank viewport.

Both obvious repairs fail:

  • Reading the whole hit stack (document.elementsFromPoint) does not help. Radix's DismissableLayer parks pointer-events: none on <body> while a modal is open, and elements with pointer-events: none are skipped by hit testing — so #root and its whole subtree leave the stack entirely. Measured on 20/20 boots of finding(console): /organizations leaves the viewport centre uncovered for ~453ms after the org gate has handed off #6570's fixture: body { pointer-events: none }, #root with 2 child elements, a 1280x720 box and 196 characters of rendered text, and not one element of it anywhere in the hit stack.
  • aria-hidden is not a tell either: #root's aria-hidden read null on every sample.

Reproduced deliberately with two synthetic control arms on a signed-out /login boot (n=3 each, production bundle, Chromium 141):

arm uncovered (top rule) uncovered (full-stack rule) white frames
untouched (control: covered) 0 0 0/31
#root emptied + splash removed (control: really blank) 34-36 34-36 6/34, min channel 246
body-level overlay, app hit-testable underneath 33-38 0 0/34
body-level overlay + body{pointer-events:none} (Radix modal shape) 38-42 38-42 0/33

The last row is a fully rendered, fully visible app that both DOM rules call empty.

What separates them

The pixel ledger does, and only it. CDP Page.startScreencast at everyNthFrame: 1 with objectui#6378's white rule (no colour channel below 242) fires on the genuinely blank arm (min channel 246 — the bare page background is white) and never on the modal/overlay arms (min channel 0 — the 80%-black overlay).

Why it matters

#6569 recorded the false-NEGATIVE direction: this probe cannot fail for a gate that decides after a session exists. This is the false-POSITIVE direction of the same instrument, and it bites exactly where the campaign wants to go next. Any signed-in scenario added to this spec that lands on a surface with an auto-opened dialog — /organizations for a zero-org user is one such surface, and it is the first one anyone tried — reports a multi-hundred-millisecond uncovered window with no defect present. That already happened once: it is the whole content of #6570.

What is NOT established

  • Whether a cheap DOM-only discriminator exists at all. Geometry plus rendered-text on #root would separate these cases in the samples above, but it was not built or exercised, and it has not been shown to stay red on the genuinely blank arm.
  • Whether any other body-level portal in this codebase (toasts, popovers, tooltips, command palette) produces the same reading. Only the Radix dialog shape was measured.
  • Any rate for the false positive across surfaces. One surface, one fixture.

Measurement detail, the control-arm table and the 20-boot distribution are on #6570.


Generated by Claude Code


Generated by Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

domain:devxobjectui devx stream: fix lands on .github/, scripts/ or release pipeline — devx lane cross-repo

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions