test(e2e): tell an open modal from a blank viewport in the boot-continuity coverage rule - #7305

Merged
yinlianghui merged 1 commit into
mainfrom
claude/issue-6578-boot-coverage-discriminator
Sep 2, 2026
Merged

test(e2e): tell an open modal from a blank viewport in the boot-continuity coverage rule#7305
yinlianghui merged 1 commit into
mainfrom
claude/issue-6578-boot-coverage-discriminator

Conversation

@yinlianghui

Copy link
Copy Markdown
Collaborator

Fixes#6578

The Console boot continuity coverage rule read an open modal dialog as a blank
viewport, on every sample for as long as the modal was open. This adds the
discriminator the card said was not established, after measuring three candidates
through the card's own four control arms.

Measurement first, per the 2026-08-27 triage ruling: nothing was written until a
candidate was shown to stay RED on the genuinely-blank arm and GREEN on the modal arm.

Instrument

Production console bundle (VITE_BASE_PATH=/console/ pnpm turbo run build --filter=@object-ui/console,
35 tasks, exit 0) served by vite preview on :4173. Signed-out /login boot with
this spec's own endpoint mocks. Arms are page.evaluate DOM mutations applied after
the boot completes, so the only variable per arm is the DOM shape. Sampling cadence
is unchanged (every mutation and every animation frame after React's first commit),
settle 1500 ms, n=3 per arm. Chromium 141.0.7390.37.

Pixel ledger alongside every row: CDP Page.startScreencast at everyNthFrame: 1,
each frame classified by objectui#6378's white rule (no colour channel below 242),
correlated with the DOM ledger on a shared performance.timeOrigin.

Candidate table (four arms, post-arm samples, n=3)

Uncovered-sample counts. RED on the blank arm and GREEN on the modal arms is what a
candidate has to show.

armsamplestop rule (current)full-stack rule(a) host holds the point + rendered content(c) portal-aware hit test(b) white frames / post-arm framesmin channel
untouched — must read covered91-9200000 / 1-20
#root emptied + splash removed — must read uncovered91919191911 / 1246
body-level overlay, app hit-testable underneath90-9290-920000 / 30
overlay + body{pointer-events:none} (Radix modal shape)929292000 / 1-30

Row 2 reproduces #6570's number exactly: min channel 246, the bare page background.
Rows 3-4 are a fully rendered, fully visible app that both DOM rules call empty.

All three candidates clear both arms on these four. The fifth shape below is what
separates them.

Portal survey — and the measurement that decided it

Shapes derived one-for-one from the real component sources in
packages/components/src/ui/. dropdown-menu.tsx and popover.tsx pass no modal
prop, so Radix's defaults apply (DropdownMenu modal, Popover not).

shapetop rulefull-stack(a)(c)white framesmin channel
modal DropdownMenu — portal off-centre, no overlay, body{pointer-events:none}87-9187-91087-910 / 1-40
non-modal Popover00000 / 2-30
Tooltip00000 / 1-30
Toast viewport / sonner, bottom-right00000 / 1-20

Two things this establishes that the card left open:

  1. The false positive is not confined to the dialog shape. A modal
    DropdownMenu produces it too, and there the centre element is the bare html
    rather than any portal — Radix parks pointer-events: none on the body for every
    modal layer, whether or not that layer renders a full-screen overlay.
    AlertDialog, Sheet and CommandDialog are the dialog shape by source
    (fixed inset-0 z-50 bg-black/80 overlay inside a portal), so they read as row 4.
  2. Popovers, tooltips and toasts are benign. None of them covers the viewport
    centre and none is modal, so the hit test still lands inside #root.

What ships, and why the other two were rejected

Shipped — (a) a named host still holds the sample point with something rendered in
it.
When the hit test says "uncovered", the rule asks the second question the
defect is actually about. objectui#6378's window is an empty#root, which answers
no and stays red. It is consulted only after the hit test has already failed, so it
can only reclassify a sample the old rule called uncovered — never the reverse — and
costs nothing on a covered sample.

Rejected — (c) portal-aware hit test. It reads 87-91 uncovered on the modal
DropdownMenu shape: with no overlay under the sample point there is no portal at the
point to recognise, so the false positive survives. It also keys the gate to one
component library's attribute spellings, which a Radix major could rename while the
gate stayed green.

Rejected for the gate, kept as the arbiter — (b) the pixel ledger. It separates
every arm correctly and is why this PR can claim the blank arm is genuinely blank
(min channel 246) and the modal arms are genuinely painted (min channel 0). It is a
bad gate for the reason this file already states about #6378: it needs a CDP
session, so it is chromium-only where this spec runs five projects, and it decides on
frames the compositor happens to swap. Measured here: on the blank arm it had one
post-arm frame to decide 1500 ms on, where the DOM rule had 91 samples.

Ablation

The probe is extracted from e2e/console-boot-indicator.spec.tson disk and
transpiled, so mutating the file really changes what is measured.

Mutation const ok = hit || appStillHoldsPoint(cx, cy); to const ok = hit;,
confirmed on disk before the run: deleted-text count 1 to 0, injected-text count 0 to
1, blob 147c6cdd to 0c0a2971. The extracted probe that ran carries
const ok = hit; at line 106.

armshipped rule (uncovered)discriminator removed (uncovered)
untouched0
#root emptied + splash removed91-92 (stays RED)92-94
body-level overlay089-91
overlay + body{pointer-events:none}091-92
modal DropdownMenu089-93

Restore proven by state, not by an exit code: on-disk blob back to 147c6cdd
(equal to the HEAD blob), git diff HEAD empty, git status --porcelain empty.
The mutation ran under trap ... EXIT INT TERM with absolute paths.

The spec's own run

Running 4 tests using 2 workers
ok 2 [chromium] > console-boot-indicator.spec.ts:47:3 > ships the indicator in the HTML document, not in a JS chunk (276ms)
ok 1 [chromium] > console-boot-indicator.spec.ts:86:3 > renders the indicator with the app bundle blocked (478ms)
ok 3 [chromium] > console-boot-indicator.spec.ts:119:3 > paints content BEFORE React mounts, and hands over without a gap (2.2s)
ok 4 [chromium] > console-boot-indicator.spec.ts:285:3 > never hands the viewport to an empty document between splash and destination (2.7s)
4 passed (4.3s)

The signed-out boot this spec runs never opens a modal, so its own reading is
unchanged at 0 uncovered — the change is for the signed-in scenarios the campaign
wants to add next, which is where the false positive bites.

Gates, at the final commit

git rev-parse --short HEAD = 5e61d0e96, and every reading below is from that tree.

gateverdict
pnpm type-check:e2eexit 0
npx eslint e2e/console-boot-indicator.spec.tsexit 0, 0 errors, 0 warnings
pnpm check:control-bytescheck-control-bytes: OK (scanned 6008 tracked text file(s); skipped 85 binary)
node scripts/check-changeset-presence.mjsNo source or published contract of a released package changed in this range, so no changeset is owed.
pnpm exec vitest run scripts/__tests__/e2e-type-check.test.ts1 file passed, 14 tests passed
Playwright, this file, chromium4 passed

Declared deviations

Scope

One file, e2e/console-boot-indicator.spec.ts. No apps/console or
packages/app-shell source, no change to the splash, no timeout raised, no test
skipped or quarantined, no live-e2e / import-harness config touched, and no shared
helper added (an addInitScript callback is serialised, so it cannot import one).

🤖 Generated with Claude Code

https://claude.ai/code/session_01BGMDbrVa8JjZcCQ7DWYH1b


Generated by Claude Code

…nuity rule
The `Console boot continuity` coverage rule read an open modal dialog as an
empty viewport, on every sample for as long as the modal was open. A Radix
`DialogPortal` renders the overlay and the dialog as body-level siblings of
`#root`, so the centre hit test lands outside both named hosts; and
`DismissableLayer` parks `pointer-events: none` on the body while a modal layer
is open, which drops `#root` and its whole subtree out of hit testing, so
reading the full `elementsFromPoint` stack does not rescue it either.
When the hit test says "uncovered", the rule now asks the second question the
defect is actually about: does a named host still hold the sample point with
something rendered inside it? objectui#6378's window is an EMPTY `#root`, which
answers no and stays red.
Consulted only after the hit test has already failed, so it can only reclassify
a sample the old rule called uncovered, never the other way round.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BGMDbrVa8JjZcCQ7DWYH1b
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

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

2 participants

@yinlianghui@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

test(e2e): tell an open modal from a blank viewport in the boot-continuity coverage rule - #7305

Merged
yinlianghui merged 1 commit into
mainfrom
claude/issue-6578-boot-coverage-discriminator
Sep 2, 2026
Merged

test(e2e): tell an open modal from a blank viewport in the boot-continuity coverage rule#7305
yinlianghui merged 1 commit into
mainfrom
claude/issue-6578-boot-coverage-discriminator

Conversation

@yinlianghui

Copy link
Copy Markdown
Collaborator

Fixes#6578

The Console boot continuity coverage rule read an open modal dialog as a blank
viewport, on every sample for as long as the modal was open. This adds the
discriminator the card said was not established, after measuring three candidates
through the card's own four control arms.

Measurement first, per the 2026-08-27 triage ruling: nothing was written until a
candidate was shown to stay RED on the genuinely-blank arm and GREEN on the modal arm.

Instrument

Production console bundle (VITE_BASE_PATH=/console/ pnpm turbo run build --filter=@object-ui/console,
35 tasks, exit 0) served by vite preview on :4173. Signed-out /login boot with
this spec's own endpoint mocks. Arms are page.evaluate DOM mutations applied after
the boot completes, so the only variable per arm is the DOM shape. Sampling cadence
is unchanged (every mutation and every animation frame after React's first commit),
settle 1500 ms, n=3 per arm. Chromium 141.0.7390.37.

Pixel ledger alongside every row: CDP Page.startScreencast at everyNthFrame: 1,
each frame classified by objectui#6378's white rule (no colour channel below 242),
correlated with the DOM ledger on a shared performance.timeOrigin.

Candidate table (four arms, post-arm samples, n=3)

Uncovered-sample counts. RED on the blank arm and GREEN on the modal arms is what a
candidate has to show.

armsamplestop rule (current)full-stack rule(a) host holds the point + rendered content(c) portal-aware hit test(b) white frames / post-arm framesmin channel
untouched — must read covered91-9200000 / 1-20
#root emptied + splash removed — must read uncovered91919191911 / 1246
body-level overlay, app hit-testable underneath90-9290-920000 / 30
overlay + body{pointer-events:none} (Radix modal shape)929292000 / 1-30

Row 2 reproduces #6570's number exactly: min channel 246, the bare page background.
Rows 3-4 are a fully rendered, fully visible app that both DOM rules call empty.

All three candidates clear both arms on these four. The fifth shape below is what
separates them.

Portal survey — and the measurement that decided it

Shapes derived one-for-one from the real component sources in
packages/components/src/ui/. dropdown-menu.tsx and popover.tsx pass no modal
prop, so Radix's defaults apply (DropdownMenu modal, Popover not).

shapetop rulefull-stack(a)(c)white framesmin channel
modal DropdownMenu — portal off-centre, no overlay, body{pointer-events:none}87-9187-91087-910 / 1-40
non-modal Popover00000 / 2-30
Tooltip00000 / 1-30
Toast viewport / sonner, bottom-right00000 / 1-20

Two things this establishes that the card left open:

  1. The false positive is not confined to the dialog shape. A modal
    DropdownMenu produces it too, and there the centre element is the bare html
    rather than any portal — Radix parks pointer-events: none on the body for every
    modal layer, whether or not that layer renders a full-screen overlay.
    AlertDialog, Sheet and CommandDialog are the dialog shape by source
    (fixed inset-0 z-50 bg-black/80 overlay inside a portal), so they read as row 4.
  2. Popovers, tooltips and toasts are benign. None of them covers the viewport
    centre and none is modal, so the hit test still lands inside #root.

What ships, and why the other two were rejected

Shipped — (a) a named host still holds the sample point with something rendered in
it.
When the hit test says "uncovered", the rule asks the second question the
defect is actually about. objectui#6378's window is an empty#root, which answers
no and stays red. It is consulted only after the hit test has already failed, so it
can only reclassify a sample the old rule called uncovered — never the reverse — and
costs nothing on a covered sample.

Rejected — (c) portal-aware hit test. It reads 87-91 uncovered on the modal
DropdownMenu shape: with no overlay under the sample point there is no portal at the
point to recognise, so the false positive survives. It also keys the gate to one
component library's attribute spellings, which a Radix major could rename while the
gate stayed green.

Rejected for the gate, kept as the arbiter — (b) the pixel ledger. It separates
every arm correctly and is why this PR can claim the blank arm is genuinely blank
(min channel 246) and the modal arms are genuinely painted (min channel 0). It is a
bad gate for the reason this file already states about #6378: it needs a CDP
session, so it is chromium-only where this spec runs five projects, and it decides on
frames the compositor happens to swap. Measured here: on the blank arm it had one
post-arm frame to decide 1500 ms on, where the DOM rule had 91 samples.

Ablation

The probe is extracted from e2e/console-boot-indicator.spec.tson disk and
transpiled, so mutating the file really changes what is measured.

Mutation const ok = hit || appStillHoldsPoint(cx, cy); to const ok = hit;,
confirmed on disk before the run: deleted-text count 1 to 0, injected-text count 0 to
1, blob 147c6cdd to 0c0a2971. The extracted probe that ran carries
const ok = hit; at line 106.

armshipped rule (uncovered)discriminator removed (uncovered)
untouched0
#root emptied + splash removed91-92 (stays RED)92-94
body-level overlay089-91
overlay + body{pointer-events:none}091-92
modal DropdownMenu089-93

Restore proven by state, not by an exit code: on-disk blob back to 147c6cdd
(equal to the HEAD blob), git diff HEAD empty, git status --porcelain empty.
The mutation ran under trap ... EXIT INT TERM with absolute paths.

The spec's own run

Running 4 tests using 2 workers
ok 2 [chromium] > console-boot-indicator.spec.ts:47:3 > ships the indicator in the HTML document, not in a JS chunk (276ms)
ok 1 [chromium] > console-boot-indicator.spec.ts:86:3 > renders the indicator with the app bundle blocked (478ms)
ok 3 [chromium] > console-boot-indicator.spec.ts:119:3 > paints content BEFORE React mounts, and hands over without a gap (2.2s)
ok 4 [chromium] > console-boot-indicator.spec.ts:285:3 > never hands the viewport to an empty document between splash and destination (2.7s)
4 passed (4.3s)

The signed-out boot this spec runs never opens a modal, so its own reading is
unchanged at 0 uncovered — the change is for the signed-in scenarios the campaign
wants to add next, which is where the false positive bites.

Gates, at the final commit

git rev-parse --short HEAD = 5e61d0e96, and every reading below is from that tree.

gateverdict
pnpm type-check:e2eexit 0
npx eslint e2e/console-boot-indicator.spec.tsexit 0, 0 errors, 0 warnings
pnpm check:control-bytescheck-control-bytes: OK (scanned 6008 tracked text file(s); skipped 85 binary)
node scripts/check-changeset-presence.mjsNo source or published contract of a released package changed in this range, so no changeset is owed.
pnpm exec vitest run scripts/__tests__/e2e-type-check.test.ts1 file passed, 14 tests passed
Playwright, this file, chromium4 passed

Declared deviations

Scope

One file, e2e/console-boot-indicator.spec.ts. No apps/console or
packages/app-shell source, no change to the splash, no timeout raised, no test
skipped or quarantined, no live-e2e / import-harness config touched, and no shared
helper added (an addInitScript callback is serialised, so it cannot import one).

🤖 Generated with Claude Code

https://claude.ai/code/session_01BGMDbrVa8JjZcCQ7DWYH1b


Generated by Claude Code

…nuity rule
The `Console boot continuity` coverage rule read an open modal dialog as an
empty viewport, on every sample for as long as the modal was open. A Radix
`DialogPortal` renders the overlay and the dialog as body-level siblings of
`#root`, so the centre hit test lands outside both named hosts; and
`DismissableLayer` parks `pointer-events: none` on the body while a modal layer
is open, which drops `#root` and its whole subtree out of hit testing, so
reading the full `elementsFromPoint` stack does not rescue it either.
When the hit test says "uncovered", the rule now asks the second question the
defect is actually about: does a named host still hold the sample point with
something rendered inside it? objectui#6378's window is an EMPTY `#root`, which
answers no and stays red.
Consulted only after the hit test has already failed, so it can only reclassify
a sample the old rule called uncovered, never the other way round.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BGMDbrVa8JjZcCQ7DWYH1b
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

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

2 participants

@yinlianghui@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

test(e2e): tell an open modal from a blank viewport in the boot-continuity coverage rule - #7305

Merged
yinlianghui merged 1 commit into
mainfrom
claude/issue-6578-boot-coverage-discriminator
Sep 2, 2026
Merged

test(e2e): tell an open modal from a blank viewport in the boot-continuity coverage rule#7305
yinlianghui merged 1 commit into
mainfrom
claude/issue-6578-boot-coverage-discriminator

Conversation

@yinlianghui

Copy link
Copy Markdown
Collaborator

Fixes#6578

The Console boot continuity coverage rule read an open modal dialog as a blank
viewport, on every sample for as long as the modal was open. This adds the
discriminator the card said was not established, after measuring three candidates
through the card's own four control arms.

Measurement first, per the 2026-08-27 triage ruling: nothing was written until a
candidate was shown to stay RED on the genuinely-blank arm and GREEN on the modal arm.

Instrument

Production console bundle (VITE_BASE_PATH=/console/ pnpm turbo run build --filter=@object-ui/console,
35 tasks, exit 0) served by vite preview on :4173. Signed-out /login boot with
this spec's own endpoint mocks. Arms are page.evaluate DOM mutations applied after
the boot completes, so the only variable per arm is the DOM shape. Sampling cadence
is unchanged (every mutation and every animation frame after React's first commit),
settle 1500 ms, n=3 per arm. Chromium 141.0.7390.37.

Pixel ledger alongside every row: CDP Page.startScreencast at everyNthFrame: 1,
each frame classified by objectui#6378's white rule (no colour channel below 242),
correlated with the DOM ledger on a shared performance.timeOrigin.

Candidate table (four arms, post-arm samples, n=3)

Uncovered-sample counts. RED on the blank arm and GREEN on the modal arms is what a
candidate has to show.

armsamplestop rule (current)full-stack rule(a) host holds the point + rendered content(c) portal-aware hit test(b) white frames / post-arm framesmin channel
untouched — must read covered91-9200000 / 1-20
#root emptied + splash removed — must read uncovered91919191911 / 1246
body-level overlay, app hit-testable underneath90-9290-920000 / 30
overlay + body{pointer-events:none} (Radix modal shape)929292000 / 1-30

Row 2 reproduces #6570's number exactly: min channel 246, the bare page background.
Rows 3-4 are a fully rendered, fully visible app that both DOM rules call empty.

All three candidates clear both arms on these four. The fifth shape below is what
separates them.

Portal survey — and the measurement that decided it

Shapes derived one-for-one from the real component sources in
packages/components/src/ui/. dropdown-menu.tsx and popover.tsx pass no modal
prop, so Radix's defaults apply (DropdownMenu modal, Popover not).

shapetop rulefull-stack(a)(c)white framesmin channel
modal DropdownMenu — portal off-centre, no overlay, body{pointer-events:none}87-9187-91087-910 / 1-40
non-modal Popover00000 / 2-30
Tooltip00000 / 1-30
Toast viewport / sonner, bottom-right00000 / 1-20

Two things this establishes that the card left open:

  1. The false positive is not confined to the dialog shape. A modal
    DropdownMenu produces it too, and there the centre element is the bare html
    rather than any portal — Radix parks pointer-events: none on the body for every
    modal layer, whether or not that layer renders a full-screen overlay.
    AlertDialog, Sheet and CommandDialog are the dialog shape by source
    (fixed inset-0 z-50 bg-black/80 overlay inside a portal), so they read as row 4.
  2. Popovers, tooltips and toasts are benign. None of them covers the viewport
    centre and none is modal, so the hit test still lands inside #root.

What ships, and why the other two were rejected

Shipped — (a) a named host still holds the sample point with something rendered in
it.
When the hit test says "uncovered", the rule asks the second question the
defect is actually about. objectui#6378's window is an empty#root, which answers
no and stays red. It is consulted only after the hit test has already failed, so it
can only reclassify a sample the old rule called uncovered — never the reverse — and
costs nothing on a covered sample.

Rejected — (c) portal-aware hit test. It reads 87-91 uncovered on the modal
DropdownMenu shape: with no overlay under the sample point there is no portal at the
point to recognise, so the false positive survives. It also keys the gate to one
component library's attribute spellings, which a Radix major could rename while the
gate stayed green.

Rejected for the gate, kept as the arbiter — (b) the pixel ledger. It separates
every arm correctly and is why this PR can claim the blank arm is genuinely blank
(min channel 246) and the modal arms are genuinely painted (min channel 0). It is a
bad gate for the reason this file already states about #6378: it needs a CDP
session, so it is chromium-only where this spec runs five projects, and it decides on
frames the compositor happens to swap. Measured here: on the blank arm it had one
post-arm frame to decide 1500 ms on, where the DOM rule had 91 samples.

Ablation

The probe is extracted from e2e/console-boot-indicator.spec.tson disk and
transpiled, so mutating the file really changes what is measured.

Mutation const ok = hit || appStillHoldsPoint(cx, cy); to const ok = hit;,
confirmed on disk before the run: deleted-text count 1 to 0, injected-text count 0 to
1, blob 147c6cdd to 0c0a2971. The extracted probe that ran carries
const ok = hit; at line 106.

armshipped rule (uncovered)discriminator removed (uncovered)
untouched0
#root emptied + splash removed91-92 (stays RED)92-94
body-level overlay089-91
overlay + body{pointer-events:none}091-92
modal DropdownMenu089-93

Restore proven by state, not by an exit code: on-disk blob back to 147c6cdd
(equal to the HEAD blob), git diff HEAD empty, git status --porcelain empty.
The mutation ran under trap ... EXIT INT TERM with absolute paths.

The spec's own run

Running 4 tests using 2 workers
ok 2 [chromium] > console-boot-indicator.spec.ts:47:3 > ships the indicator in the HTML document, not in a JS chunk (276ms)
ok 1 [chromium] > console-boot-indicator.spec.ts:86:3 > renders the indicator with the app bundle blocked (478ms)
ok 3 [chromium] > console-boot-indicator.spec.ts:119:3 > paints content BEFORE React mounts, and hands over without a gap (2.2s)
ok 4 [chromium] > console-boot-indicator.spec.ts:285:3 > never hands the viewport to an empty document between splash and destination (2.7s)
4 passed (4.3s)

The signed-out boot this spec runs never opens a modal, so its own reading is
unchanged at 0 uncovered — the change is for the signed-in scenarios the campaign
wants to add next, which is where the false positive bites.

Gates, at the final commit

git rev-parse --short HEAD = 5e61d0e96, and every reading below is from that tree.

gateverdict
pnpm type-check:e2eexit 0
npx eslint e2e/console-boot-indicator.spec.tsexit 0, 0 errors, 0 warnings
pnpm check:control-bytescheck-control-bytes: OK (scanned 6008 tracked text file(s); skipped 85 binary)
node scripts/check-changeset-presence.mjsNo source or published contract of a released package changed in this range, so no changeset is owed.
pnpm exec vitest run scripts/__tests__/e2e-type-check.test.ts1 file passed, 14 tests passed
Playwright, this file, chromium4 passed

Declared deviations

Scope

One file, e2e/console-boot-indicator.spec.ts. No apps/console or
packages/app-shell source, no change to the splash, no timeout raised, no test
skipped or quarantined, no live-e2e / import-harness config touched, and no shared
helper added (an addInitScript callback is serialised, so it cannot import one).

🤖 Generated with Claude Code

https://claude.ai/code/session_01BGMDbrVa8JjZcCQ7DWYH1b


Generated by Claude Code

…nuity rule
The `Console boot continuity` coverage rule read an open modal dialog as an
empty viewport, on every sample for as long as the modal was open. A Radix
`DialogPortal` renders the overlay and the dialog as body-level siblings of
`#root`, so the centre hit test lands outside both named hosts; and
`DismissableLayer` parks `pointer-events: none` on the body while a modal layer
is open, which drops `#root` and its whole subtree out of hit testing, so
reading the full `elementsFromPoint` stack does not rescue it either.
When the hit test says "uncovered", the rule now asks the second question the
defect is actually about: does a named host still hold the sample point with
something rendered inside it? objectui#6378's window is an EMPTY `#root`, which
answers no and stays red.
Consulted only after the hit test has already failed, so it can only reclassify
a sample the old rule called uncovered, never the other way round.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BGMDbrVa8JjZcCQ7DWYH1b
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

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

2 participants

@yinlianghui@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

test(e2e): tell an open modal from a blank viewport in the boot-continuity coverage rule - #7305

Merged
yinlianghui merged 1 commit into
mainfrom
claude/issue-6578-boot-coverage-discriminator
Sep 2, 2026
Merged

test(e2e): tell an open modal from a blank viewport in the boot-continuity coverage rule#7305
yinlianghui merged 1 commit into
mainfrom
claude/issue-6578-boot-coverage-discriminator

Conversation

@yinlianghui

Copy link
Copy Markdown
Collaborator

Fixes#6578

The Console boot continuity coverage rule read an open modal dialog as a blank
viewport, on every sample for as long as the modal was open. This adds the
discriminator the card said was not established, after measuring three candidates
through the card's own four control arms.

Measurement first, per the 2026-08-27 triage ruling: nothing was written until a
candidate was shown to stay RED on the genuinely-blank arm and GREEN on the modal arm.

Instrument

Production console bundle (VITE_BASE_PATH=/console/ pnpm turbo run build --filter=@object-ui/console,
35 tasks, exit 0) served by vite preview on :4173. Signed-out /login boot with
this spec's own endpoint mocks. Arms are page.evaluate DOM mutations applied after
the boot completes, so the only variable per arm is the DOM shape. Sampling cadence
is unchanged (every mutation and every animation frame after React's first commit),
settle 1500 ms, n=3 per arm. Chromium 141.0.7390.37.

Pixel ledger alongside every row: CDP Page.startScreencast at everyNthFrame: 1,
each frame classified by objectui#6378's white rule (no colour channel below 242),
correlated with the DOM ledger on a shared performance.timeOrigin.

Candidate table (four arms, post-arm samples, n=3)

Uncovered-sample counts. RED on the blank arm and GREEN on the modal arms is what a
candidate has to show.

armsamplestop rule (current)full-stack rule(a) host holds the point + rendered content(c) portal-aware hit test(b) white frames / post-arm framesmin channel
untouched — must read covered91-9200000 / 1-20
#root emptied + splash removed — must read uncovered91919191911 / 1246
body-level overlay, app hit-testable underneath90-9290-920000 / 30
overlay + body{pointer-events:none} (Radix modal shape)929292000 / 1-30

Row 2 reproduces #6570's number exactly: min channel 246, the bare page background.
Rows 3-4 are a fully rendered, fully visible app that both DOM rules call empty.

All three candidates clear both arms on these four. The fifth shape below is what
separates them.

Portal survey — and the measurement that decided it

Shapes derived one-for-one from the real component sources in
packages/components/src/ui/. dropdown-menu.tsx and popover.tsx pass no modal
prop, so Radix's defaults apply (DropdownMenu modal, Popover not).

shapetop rulefull-stack(a)(c)white framesmin channel
modal DropdownMenu — portal off-centre, no overlay, body{pointer-events:none}87-9187-91087-910 / 1-40
non-modal Popover00000 / 2-30
Tooltip00000 / 1-30
Toast viewport / sonner, bottom-right00000 / 1-20

Two things this establishes that the card left open:

  1. The false positive is not confined to the dialog shape. A modal
    DropdownMenu produces it too, and there the centre element is the bare html
    rather than any portal — Radix parks pointer-events: none on the body for every
    modal layer, whether or not that layer renders a full-screen overlay.
    AlertDialog, Sheet and CommandDialog are the dialog shape by source
    (fixed inset-0 z-50 bg-black/80 overlay inside a portal), so they read as row 4.
  2. Popovers, tooltips and toasts are benign. None of them covers the viewport
    centre and none is modal, so the hit test still lands inside #root.

What ships, and why the other two were rejected

Shipped — (a) a named host still holds the sample point with something rendered in
it.
When the hit test says "uncovered", the rule asks the second question the
defect is actually about. objectui#6378's window is an empty#root, which answers
no and stays red. It is consulted only after the hit test has already failed, so it
can only reclassify a sample the old rule called uncovered — never the reverse — and
costs nothing on a covered sample.

Rejected — (c) portal-aware hit test. It reads 87-91 uncovered on the modal
DropdownMenu shape: with no overlay under the sample point there is no portal at the
point to recognise, so the false positive survives. It also keys the gate to one
component library's attribute spellings, which a Radix major could rename while the
gate stayed green.

Rejected for the gate, kept as the arbiter — (b) the pixel ledger. It separates
every arm correctly and is why this PR can claim the blank arm is genuinely blank
(min channel 246) and the modal arms are genuinely painted (min channel 0). It is a
bad gate for the reason this file already states about #6378: it needs a CDP
session, so it is chromium-only where this spec runs five projects, and it decides on
frames the compositor happens to swap. Measured here: on the blank arm it had one
post-arm frame to decide 1500 ms on, where the DOM rule had 91 samples.

Ablation

The probe is extracted from e2e/console-boot-indicator.spec.tson disk and
transpiled, so mutating the file really changes what is measured.

Mutation const ok = hit || appStillHoldsPoint(cx, cy); to const ok = hit;,
confirmed on disk before the run: deleted-text count 1 to 0, injected-text count 0 to
1, blob 147c6cdd to 0c0a2971. The extracted probe that ran carries
const ok = hit; at line 106.

armshipped rule (uncovered)discriminator removed (uncovered)
untouched0
#root emptied + splash removed91-92 (stays RED)92-94
body-level overlay089-91
overlay + body{pointer-events:none}091-92
modal DropdownMenu089-93

Restore proven by state, not by an exit code: on-disk blob back to 147c6cdd
(equal to the HEAD blob), git diff HEAD empty, git status --porcelain empty.
The mutation ran under trap ... EXIT INT TERM with absolute paths.

The spec's own run

Running 4 tests using 2 workers
ok 2 [chromium] > console-boot-indicator.spec.ts:47:3 > ships the indicator in the HTML document, not in a JS chunk (276ms)
ok 1 [chromium] > console-boot-indicator.spec.ts:86:3 > renders the indicator with the app bundle blocked (478ms)
ok 3 [chromium] > console-boot-indicator.spec.ts:119:3 > paints content BEFORE React mounts, and hands over without a gap (2.2s)
ok 4 [chromium] > console-boot-indicator.spec.ts:285:3 > never hands the viewport to an empty document between splash and destination (2.7s)
4 passed (4.3s)

The signed-out boot this spec runs never opens a modal, so its own reading is
unchanged at 0 uncovered — the change is for the signed-in scenarios the campaign
wants to add next, which is where the false positive bites.

Gates, at the final commit

git rev-parse --short HEAD = 5e61d0e96, and every reading below is from that tree.

gateverdict
pnpm type-check:e2eexit 0
npx eslint e2e/console-boot-indicator.spec.tsexit 0, 0 errors, 0 warnings
pnpm check:control-bytescheck-control-bytes: OK (scanned 6008 tracked text file(s); skipped 85 binary)
node scripts/check-changeset-presence.mjsNo source or published contract of a released package changed in this range, so no changeset is owed.
pnpm exec vitest run scripts/__tests__/e2e-type-check.test.ts1 file passed, 14 tests passed
Playwright, this file, chromium4 passed

Declared deviations

Scope

One file, e2e/console-boot-indicator.spec.ts. No apps/console or
packages/app-shell source, no change to the splash, no timeout raised, no test
skipped or quarantined, no live-e2e / import-harness config touched, and no shared
helper added (an addInitScript callback is serialised, so it cannot import one).

🤖 Generated with Claude Code

https://claude.ai/code/session_01BGMDbrVa8JjZcCQ7DWYH1b


Generated by Claude Code

…nuity rule
The `Console boot continuity` coverage rule read an open modal dialog as an
empty viewport, on every sample for as long as the modal was open. A Radix
`DialogPortal` renders the overlay and the dialog as body-level siblings of
`#root`, so the centre hit test lands outside both named hosts; and
`DismissableLayer` parks `pointer-events: none` on the body while a modal layer
is open, which drops `#root` and its whole subtree out of hit testing, so
reading the full `elementsFromPoint` stack does not rescue it either.
When the hit test says "uncovered", the rule now asks the second question the
defect is actually about: does a named host still hold the sample point with
something rendered inside it? objectui#6378's window is an EMPTY `#root`, which
answers no and stays red.
Consulted only after the hit test has already failed, so it can only reclassify
a sample the old rule called uncovered, never the other way round.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BGMDbrVa8JjZcCQ7DWYH1b
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

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

2 participants

@yinlianghui@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

test(e2e): tell an open modal from a blank viewport in the boot-continuity coverage rule - #7305

Merged
yinlianghui merged 1 commit into
mainfrom
claude/issue-6578-boot-coverage-discriminator
Sep 2, 2026
Merged

test(e2e): tell an open modal from a blank viewport in the boot-continuity coverage rule#7305
yinlianghui merged 1 commit into
mainfrom
claude/issue-6578-boot-coverage-discriminator

Conversation

@yinlianghui

Copy link
Copy Markdown
Collaborator

Fixes#6578

The Console boot continuity coverage rule read an open modal dialog as a blank
viewport, on every sample for as long as the modal was open. This adds the
discriminator the card said was not established, after measuring three candidates
through the card's own four control arms.

Measurement first, per the 2026-08-27 triage ruling: nothing was written until a
candidate was shown to stay RED on the genuinely-blank arm and GREEN on the modal arm.

Instrument

Production console bundle (VITE_BASE_PATH=/console/ pnpm turbo run build --filter=@object-ui/console,
35 tasks, exit 0) served by vite preview on :4173. Signed-out /login boot with
this spec's own endpoint mocks. Arms are page.evaluate DOM mutations applied after
the boot completes, so the only variable per arm is the DOM shape. Sampling cadence
is unchanged (every mutation and every animation frame after React's first commit),
settle 1500 ms, n=3 per arm. Chromium 141.0.7390.37.

Pixel ledger alongside every row: CDP Page.startScreencast at everyNthFrame: 1,
each frame classified by objectui#6378's white rule (no colour channel below 242),
correlated with the DOM ledger on a shared performance.timeOrigin.

Candidate table (four arms, post-arm samples, n=3)

Uncovered-sample counts. RED on the blank arm and GREEN on the modal arms is what a
candidate has to show.

armsamplestop rule (current)full-stack rule(a) host holds the point + rendered content(c) portal-aware hit test(b) white frames / post-arm framesmin channel
untouched — must read covered91-9200000 / 1-20
#root emptied + splash removed — must read uncovered91919191911 / 1246
body-level overlay, app hit-testable underneath90-9290-920000 / 30
overlay + body{pointer-events:none} (Radix modal shape)929292000 / 1-30

Row 2 reproduces #6570's number exactly: min channel 246, the bare page background.
Rows 3-4 are a fully rendered, fully visible app that both DOM rules call empty.

All three candidates clear both arms on these four. The fifth shape below is what
separates them.

Portal survey — and the measurement that decided it

Shapes derived one-for-one from the real component sources in
packages/components/src/ui/. dropdown-menu.tsx and popover.tsx pass no modal
prop, so Radix's defaults apply (DropdownMenu modal, Popover not).

shapetop rulefull-stack(a)(c)white framesmin channel
modal DropdownMenu — portal off-centre, no overlay, body{pointer-events:none}87-9187-91087-910 / 1-40
non-modal Popover00000 / 2-30
Tooltip00000 / 1-30
Toast viewport / sonner, bottom-right00000 / 1-20

Two things this establishes that the card left open:

  1. The false positive is not confined to the dialog shape. A modal
    DropdownMenu produces it too, and there the centre element is the bare html
    rather than any portal — Radix parks pointer-events: none on the body for every
    modal layer, whether or not that layer renders a full-screen overlay.
    AlertDialog, Sheet and CommandDialog are the dialog shape by source
    (fixed inset-0 z-50 bg-black/80 overlay inside a portal), so they read as row 4.
  2. Popovers, tooltips and toasts are benign. None of them covers the viewport
    centre and none is modal, so the hit test still lands inside #root.

What ships, and why the other two were rejected

Shipped — (a) a named host still holds the sample point with something rendered in
it.
When the hit test says "uncovered", the rule asks the second question the
defect is actually about. objectui#6378's window is an empty#root, which answers
no and stays red. It is consulted only after the hit test has already failed, so it
can only reclassify a sample the old rule called uncovered — never the reverse — and
costs nothing on a covered sample.

Rejected — (c) portal-aware hit test. It reads 87-91 uncovered on the modal
DropdownMenu shape: with no overlay under the sample point there is no portal at the
point to recognise, so the false positive survives. It also keys the gate to one
component library's attribute spellings, which a Radix major could rename while the
gate stayed green.

Rejected for the gate, kept as the arbiter — (b) the pixel ledger. It separates
every arm correctly and is why this PR can claim the blank arm is genuinely blank
(min channel 246) and the modal arms are genuinely painted (min channel 0). It is a
bad gate for the reason this file already states about #6378: it needs a CDP
session, so it is chromium-only where this spec runs five projects, and it decides on
frames the compositor happens to swap. Measured here: on the blank arm it had one
post-arm frame to decide 1500 ms on, where the DOM rule had 91 samples.

Ablation

The probe is extracted from e2e/console-boot-indicator.spec.tson disk and
transpiled, so mutating the file really changes what is measured.

Mutation const ok = hit || appStillHoldsPoint(cx, cy); to const ok = hit;,
confirmed on disk before the run: deleted-text count 1 to 0, injected-text count 0 to
1, blob 147c6cdd to 0c0a2971. The extracted probe that ran carries
const ok = hit; at line 106.

armshipped rule (uncovered)discriminator removed (uncovered)
untouched0
#root emptied + splash removed91-92 (stays RED)92-94
body-level overlay089-91
overlay + body{pointer-events:none}091-92
modal DropdownMenu089-93

Restore proven by state, not by an exit code: on-disk blob back to 147c6cdd
(equal to the HEAD blob), git diff HEAD empty, git status --porcelain empty.
The mutation ran under trap ... EXIT INT TERM with absolute paths.

The spec's own run

Running 4 tests using 2 workers
ok 2 [chromium] > console-boot-indicator.spec.ts:47:3 > ships the indicator in the HTML document, not in a JS chunk (276ms)
ok 1 [chromium] > console-boot-indicator.spec.ts:86:3 > renders the indicator with the app bundle blocked (478ms)
ok 3 [chromium] > console-boot-indicator.spec.ts:119:3 > paints content BEFORE React mounts, and hands over without a gap (2.2s)
ok 4 [chromium] > console-boot-indicator.spec.ts:285:3 > never hands the viewport to an empty document between splash and destination (2.7s)
4 passed (4.3s)

The signed-out boot this spec runs never opens a modal, so its own reading is
unchanged at 0 uncovered — the change is for the signed-in scenarios the campaign
wants to add next, which is where the false positive bites.

Gates, at the final commit

git rev-parse --short HEAD = 5e61d0e96, and every reading below is from that tree.

gateverdict
pnpm type-check:e2eexit 0
npx eslint e2e/console-boot-indicator.spec.tsexit 0, 0 errors, 0 warnings
pnpm check:control-bytescheck-control-bytes: OK (scanned 6008 tracked text file(s); skipped 85 binary)
node scripts/check-changeset-presence.mjsNo source or published contract of a released package changed in this range, so no changeset is owed.
pnpm exec vitest run scripts/__tests__/e2e-type-check.test.ts1 file passed, 14 tests passed
Playwright, this file, chromium4 passed

Declared deviations

Scope

One file, e2e/console-boot-indicator.spec.ts. No apps/console or
packages/app-shell source, no change to the splash, no timeout raised, no test
skipped or quarantined, no live-e2e / import-harness config touched, and no shared
helper added (an addInitScript callback is serialised, so it cannot import one).

🤖 Generated with Claude Code

https://claude.ai/code/session_01BGMDbrVa8JjZcCQ7DWYH1b


Generated by Claude Code

…nuity rule
The `Console boot continuity` coverage rule read an open modal dialog as an
empty viewport, on every sample for as long as the modal was open. A Radix
`DialogPortal` renders the overlay and the dialog as body-level siblings of
`#root`, so the centre hit test lands outside both named hosts; and
`DismissableLayer` parks `pointer-events: none` on the body while a modal layer
is open, which drops `#root` and its whole subtree out of hit testing, so
reading the full `elementsFromPoint` stack does not rescue it either.
When the hit test says "uncovered", the rule now asks the second question the
defect is actually about: does a named host still hold the sample point with
something rendered inside it? objectui#6378's window is an EMPTY `#root`, which
answers no and stays red.
Consulted only after the hit test has already failed, so it can only reclassify
a sample the old rule called uncovered, never the other way round.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BGMDbrVa8JjZcCQ7DWYH1b
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

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

2 participants

@yinlianghui@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

test(e2e): tell an open modal from a blank viewport in the boot-continuity coverage rule - #7305

Merged
yinlianghui merged 1 commit into
mainfrom
claude/issue-6578-boot-coverage-discriminator
Sep 2, 2026
Merged

test(e2e): tell an open modal from a blank viewport in the boot-continuity coverage rule#7305
yinlianghui merged 1 commit into
mainfrom
claude/issue-6578-boot-coverage-discriminator

Conversation

@yinlianghui

Copy link
Copy Markdown
Collaborator

Fixes#6578

The Console boot continuity coverage rule read an open modal dialog as a blank
viewport, on every sample for as long as the modal was open. This adds the
discriminator the card said was not established, after measuring three candidates
through the card's own four control arms.

Measurement first, per the 2026-08-27 triage ruling: nothing was written until a
candidate was shown to stay RED on the genuinely-blank arm and GREEN on the modal arm.

Instrument

Production console bundle (VITE_BASE_PATH=/console/ pnpm turbo run build --filter=@object-ui/console,
35 tasks, exit 0) served by vite preview on :4173. Signed-out /login boot with
this spec's own endpoint mocks. Arms are page.evaluate DOM mutations applied after
the boot completes, so the only variable per arm is the DOM shape. Sampling cadence
is unchanged (every mutation and every animation frame after React's first commit),
settle 1500 ms, n=3 per arm. Chromium 141.0.7390.37.

Pixel ledger alongside every row: CDP Page.startScreencast at everyNthFrame: 1,
each frame classified by objectui#6378's white rule (no colour channel below 242),
correlated with the DOM ledger on a shared performance.timeOrigin.

Candidate table (four arms, post-arm samples, n=3)

Uncovered-sample counts. RED on the blank arm and GREEN on the modal arms is what a
candidate has to show.

armsamplestop rule (current)full-stack rule(a) host holds the point + rendered content(c) portal-aware hit test(b) white frames / post-arm framesmin channel
untouched — must read covered91-9200000 / 1-20
#root emptied + splash removed — must read uncovered91919191911 / 1246
body-level overlay, app hit-testable underneath90-9290-920000 / 30
overlay + body{pointer-events:none} (Radix modal shape)929292000 / 1-30

Row 2 reproduces #6570's number exactly: min channel 246, the bare page background.
Rows 3-4 are a fully rendered, fully visible app that both DOM rules call empty.

All three candidates clear both arms on these four. The fifth shape below is what
separates them.

Portal survey — and the measurement that decided it

Shapes derived one-for-one from the real component sources in
packages/components/src/ui/. dropdown-menu.tsx and popover.tsx pass no modal
prop, so Radix's defaults apply (DropdownMenu modal, Popover not).

shapetop rulefull-stack(a)(c)white framesmin channel
modal DropdownMenu — portal off-centre, no overlay, body{pointer-events:none}87-9187-91087-910 / 1-40
non-modal Popover00000 / 2-30
Tooltip00000 / 1-30
Toast viewport / sonner, bottom-right00000 / 1-20

Two things this establishes that the card left open:

  1. The false positive is not confined to the dialog shape. A modal
    DropdownMenu produces it too, and there the centre element is the bare html
    rather than any portal — Radix parks pointer-events: none on the body for every
    modal layer, whether or not that layer renders a full-screen overlay.
    AlertDialog, Sheet and CommandDialog are the dialog shape by source
    (fixed inset-0 z-50 bg-black/80 overlay inside a portal), so they read as row 4.
  2. Popovers, tooltips and toasts are benign. None of them covers the viewport
    centre and none is modal, so the hit test still lands inside #root.

What ships, and why the other two were rejected

Shipped — (a) a named host still holds the sample point with something rendered in
it.
When the hit test says "uncovered", the rule asks the second question the
defect is actually about. objectui#6378's window is an empty#root, which answers
no and stays red. It is consulted only after the hit test has already failed, so it
can only reclassify a sample the old rule called uncovered — never the reverse — and
costs nothing on a covered sample.

Rejected — (c) portal-aware hit test. It reads 87-91 uncovered on the modal
DropdownMenu shape: with no overlay under the sample point there is no portal at the
point to recognise, so the false positive survives. It also keys the gate to one
component library's attribute spellings, which a Radix major could rename while the
gate stayed green.

Rejected for the gate, kept as the arbiter — (b) the pixel ledger. It separates
every arm correctly and is why this PR can claim the blank arm is genuinely blank
(min channel 246) and the modal arms are genuinely painted (min channel 0). It is a
bad gate for the reason this file already states about #6378: it needs a CDP
session, so it is chromium-only where this spec runs five projects, and it decides on
frames the compositor happens to swap. Measured here: on the blank arm it had one
post-arm frame to decide 1500 ms on, where the DOM rule had 91 samples.

Ablation

The probe is extracted from e2e/console-boot-indicator.spec.tson disk and
transpiled, so mutating the file really changes what is measured.

Mutation const ok = hit || appStillHoldsPoint(cx, cy); to const ok = hit;,
confirmed on disk before the run: deleted-text count 1 to 0, injected-text count 0 to
1, blob 147c6cdd to 0c0a2971. The extracted probe that ran carries
const ok = hit; at line 106.

armshipped rule (uncovered)discriminator removed (uncovered)
untouched0
#root emptied + splash removed91-92 (stays RED)92-94
body-level overlay089-91
overlay + body{pointer-events:none}091-92
modal DropdownMenu089-93

Restore proven by state, not by an exit code: on-disk blob back to 147c6cdd
(equal to the HEAD blob), git diff HEAD empty, git status --porcelain empty.
The mutation ran under trap ... EXIT INT TERM with absolute paths.

The spec's own run

Running 4 tests using 2 workers
ok 2 [chromium] > console-boot-indicator.spec.ts:47:3 > ships the indicator in the HTML document, not in a JS chunk (276ms)
ok 1 [chromium] > console-boot-indicator.spec.ts:86:3 > renders the indicator with the app bundle blocked (478ms)
ok 3 [chromium] > console-boot-indicator.spec.ts:119:3 > paints content BEFORE React mounts, and hands over without a gap (2.2s)
ok 4 [chromium] > console-boot-indicator.spec.ts:285:3 > never hands the viewport to an empty document between splash and destination (2.7s)
4 passed (4.3s)

The signed-out boot this spec runs never opens a modal, so its own reading is
unchanged at 0 uncovered — the change is for the signed-in scenarios the campaign
wants to add next, which is where the false positive bites.

Gates, at the final commit

git rev-parse --short HEAD = 5e61d0e96, and every reading below is from that tree.

gateverdict
pnpm type-check:e2eexit 0
npx eslint e2e/console-boot-indicator.spec.tsexit 0, 0 errors, 0 warnings
pnpm check:control-bytescheck-control-bytes: OK (scanned 6008 tracked text file(s); skipped 85 binary)
node scripts/check-changeset-presence.mjsNo source or published contract of a released package changed in this range, so no changeset is owed.
pnpm exec vitest run scripts/__tests__/e2e-type-check.test.ts1 file passed, 14 tests passed
Playwright, this file, chromium4 passed

Declared deviations

Scope

One file, e2e/console-boot-indicator.spec.ts. No apps/console or
packages/app-shell source, no change to the splash, no timeout raised, no test
skipped or quarantined, no live-e2e / import-harness config touched, and no shared
helper added (an addInitScript callback is serialised, so it cannot import one).

🤖 Generated with Claude Code

https://claude.ai/code/session_01BGMDbrVa8JjZcCQ7DWYH1b


Generated by Claude Code

…nuity rule
The `Console boot continuity` coverage rule read an open modal dialog as an
empty viewport, on every sample for as long as the modal was open. A Radix
`DialogPortal` renders the overlay and the dialog as body-level siblings of
`#root`, so the centre hit test lands outside both named hosts; and
`DismissableLayer` parks `pointer-events: none` on the body while a modal layer
is open, which drops `#root` and its whole subtree out of hit testing, so
reading the full `elementsFromPoint` stack does not rescue it either.
When the hit test says "uncovered", the rule now asks the second question the
defect is actually about: does a named host still hold the sample point with
something rendered inside it? objectui#6378's window is an EMPTY `#root`, which
answers no and stays red.
Consulted only after the hit test has already failed, so it can only reclassify
a sample the old rule called uncovered, never the other way round.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BGMDbrVa8JjZcCQ7DWYH1b
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

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

2 participants

@yinlianghui@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

test(e2e): tell an open modal from a blank viewport in the boot-continuity coverage rule - #7305

Merged
yinlianghui merged 1 commit into
mainfrom
claude/issue-6578-boot-coverage-discriminator
Sep 2, 2026
Merged

test(e2e): tell an open modal from a blank viewport in the boot-continuity coverage rule#7305
yinlianghui merged 1 commit into
mainfrom
claude/issue-6578-boot-coverage-discriminator

Conversation

@yinlianghui

Copy link
Copy Markdown
Collaborator

Fixes#6578

The Console boot continuity coverage rule read an open modal dialog as a blank
viewport, on every sample for as long as the modal was open. This adds the
discriminator the card said was not established, after measuring three candidates
through the card's own four control arms.

Measurement first, per the 2026-08-27 triage ruling: nothing was written until a
candidate was shown to stay RED on the genuinely-blank arm and GREEN on the modal arm.

Instrument

Production console bundle (VITE_BASE_PATH=/console/ pnpm turbo run build --filter=@object-ui/console,
35 tasks, exit 0) served by vite preview on :4173. Signed-out /login boot with
this spec's own endpoint mocks. Arms are page.evaluate DOM mutations applied after
the boot completes, so the only variable per arm is the DOM shape. Sampling cadence
is unchanged (every mutation and every animation frame after React's first commit),
settle 1500 ms, n=3 per arm. Chromium 141.0.7390.37.

Pixel ledger alongside every row: CDP Page.startScreencast at everyNthFrame: 1,
each frame classified by objectui#6378's white rule (no colour channel below 242),
correlated with the DOM ledger on a shared performance.timeOrigin.

Candidate table (four arms, post-arm samples, n=3)

Uncovered-sample counts. RED on the blank arm and GREEN on the modal arms is what a
candidate has to show.

armsamplestop rule (current)full-stack rule(a) host holds the point + rendered content(c) portal-aware hit test(b) white frames / post-arm framesmin channel
untouched — must read covered91-9200000 / 1-20
#root emptied + splash removed — must read uncovered91919191911 / 1246
body-level overlay, app hit-testable underneath90-9290-920000 / 30
overlay + body{pointer-events:none} (Radix modal shape)929292000 / 1-30

Row 2 reproduces #6570's number exactly: min channel 246, the bare page background.
Rows 3-4 are a fully rendered, fully visible app that both DOM rules call empty.

All three candidates clear both arms on these four. The fifth shape below is what
separates them.

Portal survey — and the measurement that decided it

Shapes derived one-for-one from the real component sources in
packages/components/src/ui/. dropdown-menu.tsx and popover.tsx pass no modal
prop, so Radix's defaults apply (DropdownMenu modal, Popover not).

shapetop rulefull-stack(a)(c)white framesmin channel
modal DropdownMenu — portal off-centre, no overlay, body{pointer-events:none}87-9187-91087-910 / 1-40
non-modal Popover00000 / 2-30
Tooltip00000 / 1-30
Toast viewport / sonner, bottom-right00000 / 1-20

Two things this establishes that the card left open:

  1. The false positive is not confined to the dialog shape. A modal
    DropdownMenu produces it too, and there the centre element is the bare html
    rather than any portal — Radix parks pointer-events: none on the body for every
    modal layer, whether or not that layer renders a full-screen overlay.
    AlertDialog, Sheet and CommandDialog are the dialog shape by source
    (fixed inset-0 z-50 bg-black/80 overlay inside a portal), so they read as row 4.
  2. Popovers, tooltips and toasts are benign. None of them covers the viewport
    centre and none is modal, so the hit test still lands inside #root.

What ships, and why the other two were rejected

Shipped — (a) a named host still holds the sample point with something rendered in
it.
When the hit test says "uncovered", the rule asks the second question the
defect is actually about. objectui#6378's window is an empty#root, which answers
no and stays red. It is consulted only after the hit test has already failed, so it
can only reclassify a sample the old rule called uncovered — never the reverse — and
costs nothing on a covered sample.

Rejected — (c) portal-aware hit test. It reads 87-91 uncovered on the modal
DropdownMenu shape: with no overlay under the sample point there is no portal at the
point to recognise, so the false positive survives. It also keys the gate to one
component library's attribute spellings, which a Radix major could rename while the
gate stayed green.

Rejected for the gate, kept as the arbiter — (b) the pixel ledger. It separates
every arm correctly and is why this PR can claim the blank arm is genuinely blank
(min channel 246) and the modal arms are genuinely painted (min channel 0). It is a
bad gate for the reason this file already states about #6378: it needs a CDP
session, so it is chromium-only where this spec runs five projects, and it decides on
frames the compositor happens to swap. Measured here: on the blank arm it had one
post-arm frame to decide 1500 ms on, where the DOM rule had 91 samples.

Ablation

The probe is extracted from e2e/console-boot-indicator.spec.tson disk and
transpiled, so mutating the file really changes what is measured.

Mutation const ok = hit || appStillHoldsPoint(cx, cy); to const ok = hit;,
confirmed on disk before the run: deleted-text count 1 to 0, injected-text count 0 to
1, blob 147c6cdd to 0c0a2971. The extracted probe that ran carries
const ok = hit; at line 106.

armshipped rule (uncovered)discriminator removed (uncovered)
untouched0
#root emptied + splash removed91-92 (stays RED)92-94
body-level overlay089-91
overlay + body{pointer-events:none}091-92
modal DropdownMenu089-93

Restore proven by state, not by an exit code: on-disk blob back to 147c6cdd
(equal to the HEAD blob), git diff HEAD empty, git status --porcelain empty.
The mutation ran under trap ... EXIT INT TERM with absolute paths.

The spec's own run

Running 4 tests using 2 workers
ok 2 [chromium] > console-boot-indicator.spec.ts:47:3 > ships the indicator in the HTML document, not in a JS chunk (276ms)
ok 1 [chromium] > console-boot-indicator.spec.ts:86:3 > renders the indicator with the app bundle blocked (478ms)
ok 3 [chromium] > console-boot-indicator.spec.ts:119:3 > paints content BEFORE React mounts, and hands over without a gap (2.2s)
ok 4 [chromium] > console-boot-indicator.spec.ts:285:3 > never hands the viewport to an empty document between splash and destination (2.7s)
4 passed (4.3s)

The signed-out boot this spec runs never opens a modal, so its own reading is
unchanged at 0 uncovered — the change is for the signed-in scenarios the campaign
wants to add next, which is where the false positive bites.

Gates, at the final commit

git rev-parse --short HEAD = 5e61d0e96, and every reading below is from that tree.

gateverdict
pnpm type-check:e2eexit 0
npx eslint e2e/console-boot-indicator.spec.tsexit 0, 0 errors, 0 warnings
pnpm check:control-bytescheck-control-bytes: OK (scanned 6008 tracked text file(s); skipped 85 binary)
node scripts/check-changeset-presence.mjsNo source or published contract of a released package changed in this range, so no changeset is owed.
pnpm exec vitest run scripts/__tests__/e2e-type-check.test.ts1 file passed, 14 tests passed
Playwright, this file, chromium4 passed

Declared deviations

Scope

One file, e2e/console-boot-indicator.spec.ts. No apps/console or
packages/app-shell source, no change to the splash, no timeout raised, no test
skipped or quarantined, no live-e2e / import-harness config touched, and no shared
helper added (an addInitScript callback is serialised, so it cannot import one).

🤖 Generated with Claude Code

https://claude.ai/code/session_01BGMDbrVa8JjZcCQ7DWYH1b


Generated by Claude Code

…nuity rule
The `Console boot continuity` coverage rule read an open modal dialog as an
empty viewport, on every sample for as long as the modal was open. A Radix
`DialogPortal` renders the overlay and the dialog as body-level siblings of
`#root`, so the centre hit test lands outside both named hosts; and
`DismissableLayer` parks `pointer-events: none` on the body while a modal layer
is open, which drops `#root` and its whole subtree out of hit testing, so
reading the full `elementsFromPoint` stack does not rescue it either.
When the hit test says "uncovered", the rule now asks the second question the
defect is actually about: does a named host still hold the sample point with
something rendered inside it? objectui#6378's window is an EMPTY `#root`, which
answers no and stays red.
Consulted only after the hit test has already failed, so it can only reclassify
a sample the old rule called uncovered, never the other way round.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BGMDbrVa8JjZcCQ7DWYH1b
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

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

2 participants

@yinlianghui@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

test(e2e): tell an open modal from a blank viewport in the boot-continuity coverage rule - #7305

Merged
yinlianghui merged 1 commit into
mainfrom
claude/issue-6578-boot-coverage-discriminator
Sep 2, 2026
Merged

test(e2e): tell an open modal from a blank viewport in the boot-continuity coverage rule#7305
yinlianghui merged 1 commit into
mainfrom
claude/issue-6578-boot-coverage-discriminator

Conversation

@yinlianghui

Copy link
Copy Markdown
Collaborator

Fixes#6578

The Console boot continuity coverage rule read an open modal dialog as a blank
viewport, on every sample for as long as the modal was open. This adds the
discriminator the card said was not established, after measuring three candidates
through the card's own four control arms.

Measurement first, per the 2026-08-27 triage ruling: nothing was written until a
candidate was shown to stay RED on the genuinely-blank arm and GREEN on the modal arm.

Instrument

Production console bundle (VITE_BASE_PATH=/console/ pnpm turbo run build --filter=@object-ui/console,
35 tasks, exit 0) served by vite preview on :4173. Signed-out /login boot with
this spec's own endpoint mocks. Arms are page.evaluate DOM mutations applied after
the boot completes, so the only variable per arm is the DOM shape. Sampling cadence
is unchanged (every mutation and every animation frame after React's first commit),
settle 1500 ms, n=3 per arm. Chromium 141.0.7390.37.

Pixel ledger alongside every row: CDP Page.startScreencast at everyNthFrame: 1,
each frame classified by objectui#6378's white rule (no colour channel below 242),
correlated with the DOM ledger on a shared performance.timeOrigin.

Candidate table (four arms, post-arm samples, n=3)

Uncovered-sample counts. RED on the blank arm and GREEN on the modal arms is what a
candidate has to show.

armsamplestop rule (current)full-stack rule(a) host holds the point + rendered content(c) portal-aware hit test(b) white frames / post-arm framesmin channel
untouched — must read covered91-9200000 / 1-20
#root emptied + splash removed — must read uncovered91919191911 / 1246
body-level overlay, app hit-testable underneath90-9290-920000 / 30
overlay + body{pointer-events:none} (Radix modal shape)929292000 / 1-30

Row 2 reproduces #6570's number exactly: min channel 246, the bare page background.
Rows 3-4 are a fully rendered, fully visible app that both DOM rules call empty.

All three candidates clear both arms on these four. The fifth shape below is what
separates them.

Portal survey — and the measurement that decided it

Shapes derived one-for-one from the real component sources in
packages/components/src/ui/. dropdown-menu.tsx and popover.tsx pass no modal
prop, so Radix's defaults apply (DropdownMenu modal, Popover not).

shapetop rulefull-stack(a)(c)white framesmin channel
modal DropdownMenu — portal off-centre, no overlay, body{pointer-events:none}87-9187-91087-910 / 1-40
non-modal Popover00000 / 2-30
Tooltip00000 / 1-30
Toast viewport / sonner, bottom-right00000 / 1-20

Two things this establishes that the card left open:

  1. The false positive is not confined to the dialog shape. A modal
    DropdownMenu produces it too, and there the centre element is the bare html
    rather than any portal — Radix parks pointer-events: none on the body for every
    modal layer, whether or not that layer renders a full-screen overlay.
    AlertDialog, Sheet and CommandDialog are the dialog shape by source
    (fixed inset-0 z-50 bg-black/80 overlay inside a portal), so they read as row 4.
  2. Popovers, tooltips and toasts are benign. None of them covers the viewport
    centre and none is modal, so the hit test still lands inside #root.

What ships, and why the other two were rejected

Shipped — (a) a named host still holds the sample point with something rendered in
it.
When the hit test says "uncovered", the rule asks the second question the
defect is actually about. objectui#6378's window is an empty#root, which answers
no and stays red. It is consulted only after the hit test has already failed, so it
can only reclassify a sample the old rule called uncovered — never the reverse — and
costs nothing on a covered sample.

Rejected — (c) portal-aware hit test. It reads 87-91 uncovered on the modal
DropdownMenu shape: with no overlay under the sample point there is no portal at the
point to recognise, so the false positive survives. It also keys the gate to one
component library's attribute spellings, which a Radix major could rename while the
gate stayed green.

Rejected for the gate, kept as the arbiter — (b) the pixel ledger. It separates
every arm correctly and is why this PR can claim the blank arm is genuinely blank
(min channel 246) and the modal arms are genuinely painted (min channel 0). It is a
bad gate for the reason this file already states about #6378: it needs a CDP
session, so it is chromium-only where this spec runs five projects, and it decides on
frames the compositor happens to swap. Measured here: on the blank arm it had one
post-arm frame to decide 1500 ms on, where the DOM rule had 91 samples.

Ablation

The probe is extracted from e2e/console-boot-indicator.spec.tson disk and
transpiled, so mutating the file really changes what is measured.

Mutation const ok = hit || appStillHoldsPoint(cx, cy); to const ok = hit;,
confirmed on disk before the run: deleted-text count 1 to 0, injected-text count 0 to
1, blob 147c6cdd to 0c0a2971. The extracted probe that ran carries
const ok = hit; at line 106.

armshipped rule (uncovered)discriminator removed (uncovered)
untouched0
#root emptied + splash removed91-92 (stays RED)92-94
body-level overlay089-91
overlay + body{pointer-events:none}091-92
modal DropdownMenu089-93

Restore proven by state, not by an exit code: on-disk blob back to 147c6cdd
(equal to the HEAD blob), git diff HEAD empty, git status --porcelain empty.
The mutation ran under trap ... EXIT INT TERM with absolute paths.

The spec's own run

Running 4 tests using 2 workers
ok 2 [chromium] > console-boot-indicator.spec.ts:47:3 > ships the indicator in the HTML document, not in a JS chunk (276ms)
ok 1 [chromium] > console-boot-indicator.spec.ts:86:3 > renders the indicator with the app bundle blocked (478ms)
ok 3 [chromium] > console-boot-indicator.spec.ts:119:3 > paints content BEFORE React mounts, and hands over without a gap (2.2s)
ok 4 [chromium] > console-boot-indicator.spec.ts:285:3 > never hands the viewport to an empty document between splash and destination (2.7s)
4 passed (4.3s)

The signed-out boot this spec runs never opens a modal, so its own reading is
unchanged at 0 uncovered — the change is for the signed-in scenarios the campaign
wants to add next, which is where the false positive bites.

Gates, at the final commit

git rev-parse --short HEAD = 5e61d0e96, and every reading below is from that tree.

gateverdict
pnpm type-check:e2eexit 0
npx eslint e2e/console-boot-indicator.spec.tsexit 0, 0 errors, 0 warnings
pnpm check:control-bytescheck-control-bytes: OK (scanned 6008 tracked text file(s); skipped 85 binary)
node scripts/check-changeset-presence.mjsNo source or published contract of a released package changed in this range, so no changeset is owed.
pnpm exec vitest run scripts/__tests__/e2e-type-check.test.ts1 file passed, 14 tests passed
Playwright, this file, chromium4 passed

Declared deviations

Scope

One file, e2e/console-boot-indicator.spec.ts. No apps/console or
packages/app-shell source, no change to the splash, no timeout raised, no test
skipped or quarantined, no live-e2e / import-harness config touched, and no shared
helper added (an addInitScript callback is serialised, so it cannot import one).

🤖 Generated with Claude Code

https://claude.ai/code/session_01BGMDbrVa8JjZcCQ7DWYH1b


Generated by Claude Code

…nuity rule
The `Console boot continuity` coverage rule read an open modal dialog as an
empty viewport, on every sample for as long as the modal was open. A Radix
`DialogPortal` renders the overlay and the dialog as body-level siblings of
`#root`, so the centre hit test lands outside both named hosts; and
`DismissableLayer` parks `pointer-events: none` on the body while a modal layer
is open, which drops `#root` and its whole subtree out of hit testing, so
reading the full `elementsFromPoint` stack does not rescue it either.
When the hit test says "uncovered", the rule now asks the second question the
defect is actually about: does a named host still hold the sample point with
something rendered inside it? objectui#6378's window is an EMPTY `#root`, which
answers no and stays red.
Consulted only after the hit test has already failed, so it can only reclassify
a sample the old rule called uncovered, never the other way round.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BGMDbrVa8JjZcCQ7DWYH1b
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

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

2 participants

@yinlianghui@claude