Probe rendering and modal focus boundaries in pinned browser fixture

Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a0cffe-206f-7323-89d3-b20ca4cf4bf9
This commit is contained in:
tegwick 2026-09-26 22:01:35 +02:00
parent 50c68575f1
commit 3eecd74b0d
18 changed files with 2067 additions and 0 deletions

View file

@ -0,0 +1,63 @@
# Rendering and focus boundary experiment
Executed 2026-09-26. Real React 19.3.0 / Radix Dialog 1.1.23 in a synthetic browser
fixture; no deployed application, provider inference or production requests.
[Review and interpretation](../../reviews/BoundaryRecoveryExperiment.md).
## Reproduce
From this directory:
```bash
npm ci --ignore-scripts --cache /tmp/fep-npm-cache
FEP_CHROMIUM_PATH=/path/to/chrome FEP_RESULT_PATH=/tmp/immediate.json npm test
FEP_CHROMIUM_PATH=/path/to/chrome FEP_NESTED_SETTLE_MS=100 FEP_RESULT_PATH=/tmp/settled.json npm test
```
Use a locally available Chromium executable, or omit `FEP_CHROMIUM_PATH` to use
Playwright's installed browser. The recorded runs used preinstalled Chromium
151.0.7922.34, not an assertion of compatibility with every browser. Version and
executable hash are in [provenance](provenance.json); the lockfile pins all packages
with archive integrity. Installation does not download a browser automatically here.
The runner binds an ephemeral loopback port, bundles the fixture in memory, and
closes browser/server in `finally`. No external network is used by the cases.
Output defaults to `/tmp/fep-boundary-result.json`; reviewed receipts are not
overwritten automatically. A failed obligation makes the runner exit nonzero.
The immediate nested-dialog case is known to be timing-sensitive; do not hide it
with retries or interpret a later pass as its resolution. `FEP_NESTED_SETTLE_MS`
changes only the pause after nested activation before the first Escape. It is an
experimental variable, not a proposed product fix. The browser uses React's development
build, without StrictMode. Production builds and other browsers remain untested.
## Recorded cases
| Case | Observation | Immediate / 100 ms settled |
| --- | --- | --- |
| X01 | Render fault uses inner fallback; sibling stays interactive | pass / pass |
| X02 | Event-handler exception reaches browser error reporting, not boundary | pass / pass |
| X03 | Synthetic GET returns 503; explicit catch sets request-failure state | pass / pass |
| X04 | Fault in inner fallback reaches outer boundary | pass / pass |
| X05 | Closing modal returns focus to surviving invoker | pass / pass |
| X06 | Removing invoker leaves BODY focused with default behavior | pass / pass (negative control) |
| X07 | Application close policy selects surviving next-record button | pass / pass |
| X08 | Nested close should return to parent trigger, then outer trigger | fail / pass |
[result-immediate.json](result-immediate.json) records 7/8; [result-settled.json](result-settled.json)
records 8/8 with identical code/input hashes, except the declared timing parameter.
“Pass” means an observation matched its assertion, not that the UX is acceptable:
X06 deliberately expects the missing workflow target.
[development-results.json](development-results.json) preserves three earlier runs
in order: 7/8, 8/8, 7/8. They preceded final diagnostic instrumentation; their old
runner bytes are not archived, so they are development history, not exact reproducible
snapshots. Current-code receipts above retain their matching SHA-256 input hashes.
All five runs are reported; no estimate of failure frequency is justified.
## Scope
Focus checks inspect activeElement and keyboard behavior, not screen-reader output
or full accessibility conformance. X03 handles a response error explicitly; it does
not test unhandled promises, timeouts, mutation idempotency or remote rollback.
Nested dismissal remains unresolved. Dependency/version compatibility and fixture
lifecycle effects must be separated before attributing a library defect.

View file

@ -0,0 +1,333 @@
[
{
"date": "2026-09-26T19:57:23.882Z",
"evidence": "synthetic-browser-fixture-real-libraries",
"node": "v24.11.1",
"browser": "151.0.7922.34",
"browserSelection": "explicit executable override",
"packages": {
"react": "19.3.0",
"react-dom": "19.3.0",
"@radix-ui/react-dialog": "1.1.23",
"playwright": "1.63.0",
"esbuild": "0.28.2"
},
"files": {
"fixture.jsx": "d01a78f533a8ac4c086fc93845ce5b86a5b676aee86a22ee53ac91ad2a77f936",
"experiment.mjs": "981d39a45d22503077817cb032145f1e05221821c157be18ca7a509667a5e384",
"package.json": "a0ad37e8518b0c561d6b4a091ee51f5bca90e0ce329b2be7ba75347f6dc26ae7",
"package-lock.json": "ec4b544d441f89d9c512bc9931c1818473327105d5ef9047dc04d6a721e68463"
},
"cases": [
{
"id": "X01-render-contained",
"status": "pass",
"observed": {
"caught": [
{
"boundary": "inner",
"message": "render fault"
}
],
"globalErrors": [],
"requests": []
},
"siblingUsable": true,
"browserErrors": []
},
{
"id": "X02-event-not-contained",
"status": "pass",
"observed": {
"caught": [],
"globalErrors": [
"Uncaught Error: event fault"
],
"requests": []
},
"panelPresent": true,
"browserErrors": [
"event fault"
]
},
{
"id": "X03-request-explicit-state",
"status": "pass",
"observed": {
"caught": [],
"globalErrors": [],
"requests": [
503
]
},
"state": "request failed",
"browserErrors": []
},
{
"id": "X04-fallback-escapes-inner",
"status": "pass",
"observed": {
"caught": [
{
"boundary": "outer",
"message": "fallback fault"
}
],
"globalErrors": [],
"requests": []
},
"enclosingFallback": true,
"browserErrors": []
},
{
"id": "X05-focus-existing-invoker",
"status": "pass",
"activeId": "invoker",
"browserErrors": []
},
{
"id": "X06-focus-removed-default",
"status": "pass",
"activeTag": "BODY",
"workflowTargetSelected": false,
"browserErrors": []
},
{
"id": "X07-focus-removed-explicit",
"status": "pass",
"activeId": "next",
"applicationPolicy": true,
"browserErrors": []
},
{
"id": "X08-nested-return",
"status": "fail",
"error": "page.waitForFunction: Timeout 5000ms exceeded.",
"browserErrors": []
}
],
"passed": 7,
"total": 8
},
{
"date": "2026-09-26T19:57:42.875Z",
"evidence": "synthetic-browser-fixture-real-libraries",
"node": "v24.11.1",
"browser": "151.0.7922.34",
"browserSelection": "explicit executable override",
"packages": {
"react": "19.3.0",
"react-dom": "19.3.0",
"@radix-ui/react-dialog": "1.1.23",
"playwright": "1.63.0",
"esbuild": "0.28.2"
},
"files": {
"fixture.jsx": "d01a78f533a8ac4c086fc93845ce5b86a5b676aee86a22ee53ac91ad2a77f936",
"experiment.mjs": "5268d5cfefedb6186333bcc014080757821f2bb4820f70397b22474bd3264414",
"package.json": "a0ad37e8518b0c561d6b4a091ee51f5bca90e0ce329b2be7ba75347f6dc26ae7",
"package-lock.json": "ec4b544d441f89d9c512bc9931c1818473327105d5ef9047dc04d6a721e68463"
},
"cases": [
{
"id": "X01-render-contained",
"status": "pass",
"observed": {
"caught": [
{
"boundary": "inner",
"message": "render fault"
}
],
"globalErrors": [],
"requests": []
},
"siblingUsable": true,
"browserErrors": []
},
{
"id": "X02-event-not-contained",
"status": "pass",
"observed": {
"caught": [],
"globalErrors": [
"Uncaught Error: event fault"
],
"requests": []
},
"panelPresent": true,
"browserErrors": [
"event fault"
]
},
{
"id": "X03-request-explicit-state",
"status": "pass",
"observed": {
"caught": [],
"globalErrors": [],
"requests": [
503
]
},
"state": "request failed",
"browserErrors": []
},
{
"id": "X04-fallback-escapes-inner",
"status": "pass",
"observed": {
"caught": [
{
"boundary": "outer",
"message": "fallback fault"
}
],
"globalErrors": [],
"requests": []
},
"enclosingFallback": true,
"browserErrors": []
},
{
"id": "X05-focus-existing-invoker",
"status": "pass",
"activeId": "invoker",
"browserErrors": []
},
{
"id": "X06-focus-removed-default",
"status": "pass",
"activeTag": "BODY",
"workflowTargetSelected": false,
"browserErrors": []
},
{
"id": "X07-focus-removed-explicit",
"status": "pass",
"activeId": "next",
"applicationPolicy": true,
"browserErrors": []
},
{
"id": "X08-nested-return",
"status": "pass",
"innerReturn": "nested-invoker",
"outerReturn": "invoker",
"browserErrors": []
}
],
"passed": 8,
"total": 8
},
{
"date": "2026-09-26T19:58:16.005Z",
"evidence": "synthetic-browser-fixture-real-libraries",
"node": "v24.11.1",
"browser": "151.0.7922.34",
"browserSelection": "explicit executable override",
"packages": {
"react": "19.3.0",
"react-dom": "19.3.0",
"@radix-ui/react-dialog": "1.1.23",
"playwright": "1.63.0",
"esbuild": "0.28.2"
},
"files": {
"fixture.jsx": "d01a78f533a8ac4c086fc93845ce5b86a5b676aee86a22ee53ac91ad2a77f936",
"experiment.mjs": "df9912cacd5b01b10fdc70a45d50b36d91202c44c0f57358334a1d3c41b4c88d",
"package.json": "a0ad37e8518b0c561d6b4a091ee51f5bca90e0ce329b2be7ba75347f6dc26ae7",
"package-lock.json": "ec4b544d441f89d9c512bc9931c1818473327105d5ef9047dc04d6a721e68463"
},
"cases": [
{
"id": "X01-render-contained",
"status": "pass",
"observed": {
"caught": [
{
"boundary": "inner",
"message": "render fault"
}
],
"globalErrors": [],
"requests": []
},
"siblingUsable": true,
"browserErrors": []
},
{
"id": "X02-event-not-contained",
"status": "pass",
"observed": {
"caught": [],
"globalErrors": [
"Uncaught Error: event fault"
],
"requests": []
},
"panelPresent": true,
"browserErrors": [
"event fault"
]
},
{
"id": "X03-request-explicit-state",
"status": "pass",
"observed": {
"caught": [],
"globalErrors": [],
"requests": [
503
]
},
"state": "request failed",
"browserErrors": []
},
{
"id": "X04-fallback-escapes-inner",
"status": "pass",
"observed": {
"caught": [
{
"boundary": "outer",
"message": "fallback fault"
}
],
"globalErrors": [],
"requests": []
},
"enclosingFallback": true,
"browserErrors": []
},
{
"id": "X05-focus-existing-invoker",
"status": "pass",
"activeId": "invoker",
"browserErrors": []
},
{
"id": "X06-focus-removed-default",
"status": "pass",
"activeTag": "BODY",
"workflowTargetSelected": false,
"browserErrors": []
},
{
"id": "X07-focus-removed-explicit",
"status": "pass",
"activeId": "next",
"applicationPolicy": true,
"browserErrors": []
},
{
"id": "X08-nested-return",
"status": "fail",
"error": "Expected focus nested-invoker; got {\"id\":\"invoker\",\"tag\":\"BUTTON\",\"dialogs\":0}: page.waitForFunction: Timeout 5000ms exceeded.",
"browserErrors": []
}
],
"passed": 7,
"total": 8
}
]

View file

@ -0,0 +1,124 @@
import {build} from 'esbuild';
import {chromium} from 'playwright';
import {createServer} from 'node:http';
import {once} from 'node:events';
import {readFile, writeFile} from 'node:fs/promises';
import {createHash} from 'node:crypto';
import {fileURLToPath} from 'node:url';
import assert from 'node:assert/strict';
const dir = fileURLToPath(new URL('.', import.meta.url));
const bundle = await build({entryPoints: [dir + 'fixture.jsx'], bundle: true, write: false,
define: {'process.env.NODE_ENV': '"development"'}, format: 'iife'});
const server = createServer((req, res) => {
if (req.url === '/bundle.js') {
res.writeHead(200, {'Content-Type': 'application/javascript'}); res.end(bundle.outputFiles[0].contents);
} else if (req.url === '/failure') {
res.writeHead(503, {'Content-Type': 'text/plain'}); res.end('synthetic unavailable');
} else {
res.writeHead(200, {'Content-Type': 'text/html'});
res.end('<!doctype html><html lang="en"><head><title>Boundary probe</title></head><body><div id="root"></div><script src="/bundle.js"></script></body></html>');
}
});
server.listen(0, '127.0.0.1'); await once(server, 'listening');
const url = `http://127.0.0.1:${server.address().port}`;
let browser;
const cases = [];
async function probe(id, query, action) {
const page = await browser.newPage();
page.setDefaultTimeout(5000);
const browserErrors = [];
page.on('pageerror', e => browserErrors.push(e.message));
try {
await page.goto(url + query);
await page.getByRole('button').first().waitFor();
const observed = await action(page);
cases.push({id, status: 'pass', ...observed, browserErrors});
} catch (error) {
cases.push({id, status: 'fail', error: error.message, observed: await page.evaluate(() => window.observed).catch(() => null), browserErrors});
} finally {await page.close();}
}
async function active(page, id) {
try { await page.waitForFunction(id => document.activeElement?.id === id, id, {timeout: 5000}); }
catch (error) { throw new Error(`Expected focus ${id}; got ${await page.evaluate(() => ({id: document.activeElement?.id, tag: document.activeElement?.tagName, dialogs: document.querySelectorAll('[role=dialog]').length})).then(JSON.stringify)}: ${error.message}`); }
}
try {
browser = await chromium.launch({headless: true,
...(process.env.FEP_CHROMIUM_PATH ? {executablePath: process.env.FEP_CHROMIUM_PATH} : {})});
await probe('X01-render-contained', '/', async page => {
await page.getByText('Break render', {exact: true}).click();
await page.getByTestId('inner').waitFor();
await page.getByText('Sibling 0', {exact: true}).click();
await page.getByText('Sibling 1', {exact: true}).waitFor();
const o = await page.evaluate(() => window.observed);
assert(o.caught.some(x => x.boundary === 'inner' && x.message === 'render fault'));
assert.equal(await page.getByTestId('outer').count(), 0);
return {observed: o, siblingUsable: true};
});
await probe('X02-event-not-contained', '/', async page => {
await page.getByText('Break event', {exact: true}).click();
await page.waitForFunction(() => window.observed.globalErrors.some(x => x.includes('event fault')));
const o = await page.evaluate(() => window.observed);
assert.equal(o.caught.length, 0); assert.equal(await page.getByTestId('panel').count(), 1);
return {observed: o, panelPresent: true};
});
await probe('X03-request-explicit-state', '/', async page => {
await page.getByText('Fail request', {exact: true}).click();
await page.getByRole('status').filter({hasText: 'request failed'}).waitFor();
const o = await page.evaluate(() => window.observed);
assert.deepEqual(o.requests, [503]); assert.equal(o.caught.length, 0);
return {observed: o, state: 'request failed'};
});
await probe('X04-fallback-escapes-inner', '/?brokenFallback=1', async page => {
await page.getByText('Break render', {exact: true}).click();
await page.getByTestId('outer').waitFor();
const o = await page.evaluate(() => window.observed);
assert(o.caught.some(x => x.boundary === 'outer' && x.message === 'fallback fault'));
return {observed: o, enclosingFallback: true};
});
await probe('X05-focus-existing-invoker', '/?mode=focus', async page => {
await page.locator('#invoker').focus(); await page.keyboard.press('Enter');
await active(page, 'remove'); await page.keyboard.press('Escape'); await active(page, 'invoker');
return {activeId: await page.evaluate(() => document.activeElement.id)};
});
await probe('X06-focus-removed-default', '/?mode=focus', async page => {
await page.locator('#invoker').focus(); await page.keyboard.press('Enter'); await active(page, 'remove');
await page.keyboard.press('Enter'); await page.getByRole('dialog').waitFor({state: 'detached'});
await page.waitForFunction(() => document.activeElement === document.body);
// Negative control: default restoration cannot choose a workflow target for the removed trigger.
assert.equal(await page.locator('#invoker').count(), 0);
return {activeTag: await page.evaluate(() => document.activeElement.tagName), workflowTargetSelected: false};
});
await probe('X07-focus-removed-explicit', '/?mode=focus&explicit=1', async page => {
await page.locator('#invoker').focus(); await page.keyboard.press('Enter'); await active(page, 'remove');
await page.keyboard.press('Enter'); await active(page, 'next');
return {activeId: await page.evaluate(() => document.activeElement.id), applicationPolicy: true};
});
await probe('X08-nested-return', '/?mode=focus', async page => {
await page.locator('#invoker').focus(); await page.keyboard.press('Enter'); await active(page, 'remove');
await page.keyboard.press('Tab'); await active(page, 'nested-invoker');
await page.keyboard.press('Enter'); await active(page, 'nested-close');
// Experimental timing variable, not a hidden retry: compare immediate versus settled Escape.
if (Number(process.env.FEP_NESTED_SETTLE_MS)) await page.waitForTimeout(Number(process.env.FEP_NESTED_SETTLE_MS));
await page.keyboard.press('Escape'); await active(page, 'nested-invoker');
assert.equal(await page.getByRole('dialog').count(), 1);
await page.keyboard.press('Escape'); await active(page, 'invoker');
return {innerReturn: 'nested-invoker', outerReturn: 'invoker', observed: await page.evaluate(() => window.observed)};
});
const files = {};
for (const name of ['fixture.jsx', 'experiment.mjs', 'package.json', 'package-lock.json']) {
files[name] = createHash('sha256').update(await readFile(dir + name)).digest('hex');
}
const result = {date: new Date().toISOString(), evidence: 'synthetic-browser-fixture-real-libraries',
node: process.version, browser: browser.version(), nestedSettleMs: Number(process.env.FEP_NESTED_SETTLE_MS || 0),
browserSelection: process.env.FEP_CHROMIUM_PATH ? 'explicit executable override' : 'playwright bundled',
packages: JSON.parse(await readFile(dir + 'package.json')).dependencies,
files, cases, passed: cases.filter(x => x.status === 'pass').length, total: cases.length};
const output = process.env.FEP_RESULT_PATH || '/tmp/fep-boundary-result.json';
await writeFile(output, JSON.stringify(result, null, 2) + '\n');
console.log(JSON.stringify({output, passed: result.passed, total: result.total, cases}, null, 2));
if (result.passed !== result.total) process.exitCode = 1;
} finally {
if (browser) await browser.close();
await new Promise(resolve => server.close(resolve));
}

View file

@ -0,0 +1,81 @@
import React, {useState, useRef} from 'react';
import {createRoot} from 'react-dom/client';
import * as Dialog from '@radix-ui/react-dialog';
window.observed = {caught: [], globalErrors: [], requests: [], dialogTransitions: []};
window.addEventListener('error', e => window.observed.globalErrors.push(e.message));
class Boundary extends React.Component {
state = {failed: false};
static getDerivedStateFromError() { return {failed: true}; }
componentDidCatch(error) { window.observed.caught.push({boundary: this.props.name, message: error.message}); }
render() {
if (this.state.failed) return this.props.brokenFallback
? <BrokenFallback /> : <p role="alert" data-testid={this.props.name}>Region unavailable</p>;
return this.props.children;
}
}
function BrokenFallback() { throw new Error('fallback fault'); }
function Panel() {
const [broken, setBroken] = useState(false);
const [request, setRequest] = useState('idle');
if (broken) throw new Error('render fault');
return <section data-testid="panel">
<button onClick={() => setBroken(true)}>Break render</button>
<button onClick={() => {throw new Error('event fault');}}>Break event</button>
<button onClick={async () => {
setRequest('pending');
try {
const r = await fetch('/failure');
window.observed.requests.push(r.status);
if (!r.ok) throw new Error('request rejected');
setRequest('accepted');
} catch {setRequest('request failed');}
}}>Fail request</button>
<p role="status">{request}</p>
</section>;
}
function FailureFixture() {
const [clicks, setClicks] = useState(0);
const brokenFallback = new URLSearchParams(location.search).has('brokenFallback');
return <main>
<button onClick={() => setClicks(clicks + 1)}>Sibling {clicks}</button>
<Boundary name="outer"><Boundary name="inner" brokenFallback={brokenFallback}>
<Panel />
</Boundary></Boundary>
</main>;
}
function Modal({children, title}) {
return <Dialog.Portal><Dialog.Overlay />
<Dialog.Content aria-describedby={undefined}>
<Dialog.Title>{title}</Dialog.Title>{children}
</Dialog.Content>
</Dialog.Portal>;
}
function FocusFixture() {
const [open, setOpen] = useState(false);
const [present, setPresent] = useState(true);
const next = useRef(null);
const explicit = new URLSearchParams(location.search).has('explicit');
return <main>
<button id="next" ref={next}>Next record</button>
<Dialog.Root open={open} onOpenChange={value => {window.observed.dialogTransitions.push({dialog: "outer", open: value}); setOpen(value);}}>
{present && <Dialog.Trigger id="invoker">Open task</Dialog.Trigger>}
<Dialog.Portal><Dialog.Overlay />
<Dialog.Content aria-describedby={undefined} onCloseAutoFocus={event => {
if (explicit && !present) {event.preventDefault(); next.current?.focus();}
}}>
<Dialog.Title>Record task</Dialog.Title>
<button id="remove" onClick={() => {setPresent(false); setOpen(false);}}>Remove invoking record</button>
<Dialog.Root onOpenChange={value => window.observed.dialogTransitions.push({dialog: "inner", open: value})}>
<Dialog.Trigger id="nested-invoker">Nested task</Dialog.Trigger>
<Modal title="Nested task"><Dialog.Close id="nested-close">Close nested</Dialog.Close></Modal>
</Dialog.Root>
<Dialog.Close id="close">Close task</Dialog.Close>
</Dialog.Content>
</Dialog.Portal>
</Dialog.Root>
</main>;
}
createRoot(document.getElementById('root')).render(
new URLSearchParams(location.search).get('mode') === 'focus' ? <FocusFixture /> : <FailureFixture />
);

View file

@ -0,0 +1,989 @@
{
"name": "fep-boundary-recovery",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "fep-boundary-recovery",
"dependencies": {
"@radix-ui/react-dialog": "1.1.23",
"esbuild": "0.28.2",
"playwright": "1.63.0",
"react": "19.3.0",
"react-dom": "19.3.0"
}
},
"node_modules/@esbuild/aix-ppc64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.2.tgz",
"integrity": "sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==",
"cpu": [
"ppc64"
],
"license": "MIT",
"optional": true,
"os": [
"aix"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/android-arm": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.2.tgz",
"integrity": "sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==",
"cpu": [
"arm"
],
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/android-arm64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.2.tgz",
"integrity": "sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/android-x64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.2.tgz",
"integrity": "sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/darwin-arm64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.2.tgz",
"integrity": "sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/darwin-x64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.2.tgz",
"integrity": "sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/freebsd-arm64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.2.tgz",
"integrity": "sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/freebsd-x64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.2.tgz",
"integrity": "sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-arm": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.2.tgz",
"integrity": "sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==",
"cpu": [
"arm"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-arm64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.2.tgz",
"integrity": "sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-ia32": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.2.tgz",
"integrity": "sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==",
"cpu": [
"ia32"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-loong64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.2.tgz",
"integrity": "sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==",
"cpu": [
"loong64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-mips64el": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.2.tgz",
"integrity": "sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==",
"cpu": [
"mips64el"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-ppc64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.2.tgz",
"integrity": "sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==",
"cpu": [
"ppc64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-riscv64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.2.tgz",
"integrity": "sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==",
"cpu": [
"riscv64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-s390x": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.2.tgz",
"integrity": "sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==",
"cpu": [
"s390x"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-x64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.2.tgz",
"integrity": "sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/netbsd-arm64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.2.tgz",
"integrity": "sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"netbsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/netbsd-x64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.2.tgz",
"integrity": "sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"netbsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/openbsd-arm64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.2.tgz",
"integrity": "sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"openbsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/openbsd-x64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.2.tgz",
"integrity": "sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"openbsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/openharmony-arm64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.2.tgz",
"integrity": "sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"openharmony"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/sunos-x64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.2.tgz",
"integrity": "sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"sunos"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/win32-arm64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.2.tgz",
"integrity": "sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/win32-ia32": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.2.tgz",
"integrity": "sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==",
"cpu": [
"ia32"
],
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/win32-x64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.2.tgz",
"integrity": "sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@radix-ui/primitive": {
"version": "1.1.7",
"resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.7.tgz",
"integrity": "sha512-rqWnm76nYT8HoNNqEjpgJ7Pw/DrBj5iBTrmEPo6HTX5+VJyBNOqTdv4g89G63HuR5g0AaENoAcH7Is5fF2kZ8Q==",
"license": "MIT"
},
"node_modules/@radix-ui/react-compose-refs": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.5.tgz",
"integrity": "sha512-+48PbAAbq3didjJxa+OaWY2ZwgAKsNiRGyeHKszblZMQ+kcpd9pAaT11cMkGEie0vsOi3QdeTE6d5Fe3Gn61kA==",
"license": "MIT",
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-context": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.2.2.tgz",
"integrity": "sha512-RHCUGwKHDr0hDGg4X7ma4JG4/+12qxw8rkh5QKdDldlCvtja6nUx1Ef/8HVrJze81lEsgLQlqjzjGNHantgnQA==",
"license": "MIT",
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-dialog": {
"version": "1.1.23",
"resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.23.tgz",
"integrity": "sha512-Ksw4WeROkO4rC9k/onilX/Ao2Cr1ku1unMNH+XSCcP4jSXYu7HDsg9n4ojMjVb22XpYjAQ9qfrFlVbru1vXDUA==",
"license": "MIT",
"dependencies": {
"@radix-ui/primitive": "1.1.7",
"@radix-ui/react-compose-refs": "1.1.5",
"@radix-ui/react-context": "1.2.2",
"@radix-ui/react-dismissable-layer": "1.1.19",
"@radix-ui/react-focus-guards": "1.1.6",
"@radix-ui/react-focus-scope": "1.1.16",
"@radix-ui/react-id": "1.1.4",
"@radix-ui/react-portal": "1.1.17",
"@radix-ui/react-presence": "1.1.10",
"@radix-ui/react-primitive": "2.1.10",
"@radix-ui/react-slot": "1.3.3",
"@radix-ui/react-use-controllable-state": "1.2.6",
"@radix-ui/react-use-layout-effect": "1.1.4",
"aria-hidden": "^1.2.4",
"react-remove-scroll": "^2.7.2"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-dismissable-layer": {
"version": "1.1.19",
"resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.19.tgz",
"integrity": "sha512-8g4pfOL9HoKKLWGiypT+dphVqjFfmcXO5GBnhsG6zI+lxAx/8feQpr+1LSN8Re3hiZ+XkLNS4O9ztK11/LzQ6w==",
"license": "MIT",
"dependencies": {
"@radix-ui/primitive": "1.1.7",
"@radix-ui/react-compose-refs": "1.1.5",
"@radix-ui/react-primitive": "2.1.10",
"@radix-ui/react-use-callback-ref": "1.1.4",
"@radix-ui/react-use-effect-event": "0.0.5"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-focus-guards": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.6.tgz",
"integrity": "sha512-RNOJjfZMTyBM6xYmV3IVGXkPjIhcBAuv48POevAXwrGJhkWZ9p1rFoIS1JFooPuT193AZmRsCPhpoVJxx6OPoQ==",
"license": "MIT",
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-focus-scope": {
"version": "1.1.16",
"resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.16.tgz",
"integrity": "sha512-wmRZ2WWLvmt6KHy2rNPOdPUjwq5xOHY02+m+udwJTn0aNIox/rkskAvJTyTLGhPK6KgrUjlJUJpgmx/+wFiFIQ==",
"license": "MIT",
"dependencies": {
"@radix-ui/react-compose-refs": "1.1.5",
"@radix-ui/react-primitive": "2.1.10",
"@radix-ui/react-use-callback-ref": "1.1.4"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-id": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.4.tgz",
"integrity": "sha512-TMQp2llA+RYn7JcjnrMnz7wN4pcVttPZnRZo52PLQsoLVKzNlVwUeHmfePgTgRluXFvlD3GD5g5MOVVTJCO0qA==",
"license": "MIT",
"dependencies": {
"@radix-ui/react-use-layout-effect": "1.1.4"
},
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-portal": {
"version": "1.1.17",
"resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.17.tgz",
"integrity": "sha512-vKQLcWypUnwZVvfV7UkGahH2g6ySe8M8R+zYBwPrv5byZ9QAW6cQVvNKo7GgmD+p8aYb6D9JBuvy8/WhOno2wQ==",
"license": "MIT",
"dependencies": {
"@radix-ui/react-primitive": "2.1.10",
"@radix-ui/react-use-layout-effect": "1.1.4"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-presence": {
"version": "1.1.10",
"resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.10.tgz",
"integrity": "sha512-3wyzCQ6+ubRA+D4uv9m95JYLXxmOHp05qjrkjeA7uKHHtjpPggQzc6DAb0URl7j67oR0K2foO4ip27TiX037Bw==",
"license": "MIT",
"dependencies": {
"@radix-ui/react-use-layout-effect": "1.1.4"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-primitive": {
"version": "2.1.10",
"resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.10.tgz",
"integrity": "sha512-MucOnzh6hR5mid6VpkbglRAMYMjKLqRnGBbjXkzjK52fuQDd1qbkx78a5P40mkcnVXJdEVxm26E9OPAiUq7nBg==",
"license": "MIT",
"dependencies": {
"@radix-ui/react-slot": "1.3.3"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-slot": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.3.3.tgz",
"integrity": "sha512-qx7oqnYbxnK9kYI9m317qmFmEgo6ywqWvbTogdj7cL9p3/yx4M48p7Rnw5z3H890cL/ow/EeWJsuTykeZVXP5Q==",
"license": "MIT",
"dependencies": {
"@radix-ui/react-compose-refs": "1.1.5"
},
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-use-callback-ref": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.4.tgz",
"integrity": "sha512-R6OUY2e2fA6Yn6s+VSx5KBV6Nx8LQEhu+cz7LCej18rQ1HLyg9PSC9jP/ZNx0o6FAIK9c0F1kHylzSxKsdlkrQ==",
"license": "MIT",
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-use-controllable-state": {
"version": "1.2.6",
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.6.tgz",
"integrity": "sha512-uEQJGT97ZA/TgP/Hydw47lHu+/vQj6z/0jA+WeTbK1o9Rx45GImjpD0tc3W5ad3D6XTSR6e1yEO0FvGq6WQfVQ==",
"license": "MIT",
"dependencies": {
"@radix-ui/primitive": "1.1.7",
"@radix-ui/react-use-effect-event": "0.0.5",
"@radix-ui/react-use-layout-effect": "1.1.4"
},
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-use-effect-event": {
"version": "0.0.5",
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.5.tgz",
"integrity": "sha512-7cshFL8HGS/7HEiHH+9kL9HBwp2sa9yX18Knwek6KYWmXwM7pegMgta2AXMQKI+rq3JnfSj9x8wYqFMTdG1Jgg==",
"license": "MIT",
"dependencies": {
"@radix-ui/react-use-layout-effect": "1.1.4"
},
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-use-layout-effect": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.4.tgz",
"integrity": "sha512-K20DkRkUwDnxEYMBPcg3Y6voLkEy5p5QQmszZgLngKKiC7dzBR/aEuK3w1qlx2JWDUNH6FluahYdgR3BP+QbYw==",
"license": "MIT",
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/aria-hidden": {
"version": "1.2.6",
"resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz",
"integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==",
"license": "MIT",
"dependencies": {
"tslib": "^2.0.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/detect-node-es": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz",
"integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==",
"license": "MIT"
},
"node_modules/esbuild": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.2.tgz",
"integrity": "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==",
"hasInstallScript": true,
"license": "MIT",
"bin": {
"esbuild": "bin/esbuild"
},
"engines": {
"node": ">=18"
},
"optionalDependencies": {
"@esbuild/aix-ppc64": "0.28.2",
"@esbuild/android-arm": "0.28.2",
"@esbuild/android-arm64": "0.28.2",
"@esbuild/android-x64": "0.28.2",
"@esbuild/darwin-arm64": "0.28.2",
"@esbuild/darwin-x64": "0.28.2",
"@esbuild/freebsd-arm64": "0.28.2",
"@esbuild/freebsd-x64": "0.28.2",
"@esbuild/linux-arm": "0.28.2",
"@esbuild/linux-arm64": "0.28.2",
"@esbuild/linux-ia32": "0.28.2",
"@esbuild/linux-loong64": "0.28.2",
"@esbuild/linux-mips64el": "0.28.2",
"@esbuild/linux-ppc64": "0.28.2",
"@esbuild/linux-riscv64": "0.28.2",
"@esbuild/linux-s390x": "0.28.2",
"@esbuild/linux-x64": "0.28.2",
"@esbuild/netbsd-arm64": "0.28.2",
"@esbuild/netbsd-x64": "0.28.2",
"@esbuild/openbsd-arm64": "0.28.2",
"@esbuild/openbsd-x64": "0.28.2",
"@esbuild/openharmony-arm64": "0.28.2",
"@esbuild/sunos-x64": "0.28.2",
"@esbuild/win32-arm64": "0.28.2",
"@esbuild/win32-ia32": "0.28.2",
"@esbuild/win32-x64": "0.28.2"
}
},
"node_modules/get-nonce": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz",
"integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==",
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/playwright": {
"version": "1.63.0",
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.63.0.tgz",
"integrity": "sha512-+7ziBLidS4NaNCdt57SUDT+wYmmd5fmiQejUic/kb+YsYSCPyOOE9sebzMjNmQrsnNpDJqd4WHvV/8lfKfUDUg==",
"license": "Apache-2.0",
"dependencies": {
"playwright-core": "1.63.0"
},
"bin": {
"playwright": "cli.js"
},
"engines": {
"node": ">=20"
}
},
"node_modules/playwright-core": {
"version": "1.63.0",
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.63.0.tgz",
"integrity": "sha512-rYCsBF/M5HjUch52bbtVONEFjv6Xu8sm8h72dNlR5bzIE1fvC/bxgspzkjSfU+MweEMmPM8KJebG6nnyxo5mCg==",
"license": "Apache-2.0",
"bin": {
"playwright-core": "cli.js"
},
"engines": {
"node": ">=20"
}
},
"node_modules/react": {
"version": "19.3.0",
"resolved": "https://registry.npmjs.org/react/-/react-19.3.0.tgz",
"integrity": "sha512-E8LUcbtBWt20bbl2YoHfx4ZDBdxVTfOKtCZn9cDSJ4l6/nuoApcpIBcj47t2wZoVX8g2ZHuMHbiShgCR1T5Sog==",
"license": "MIT",
"peer": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/react-dom": {
"version": "19.3.0",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.3.0.tgz",
"integrity": "sha512-JDk8dgif51OjFoDE70+OT9ICyYr+69HlmihNwp1+Nsfbna3t5sIiCa9ZJktDmQ4/1b/rn26hIAR2uYXDMr5r0Q==",
"license": "MIT",
"peer": true,
"dependencies": {
"scheduler": "^0.28.0"
},
"peerDependencies": {
"react": "^19.3.0"
}
},
"node_modules/react-remove-scroll": {
"version": "2.7.2",
"resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.2.tgz",
"integrity": "sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==",
"license": "MIT",
"dependencies": {
"react-remove-scroll-bar": "^2.3.7",
"react-style-singleton": "^2.2.3",
"tslib": "^2.1.0",
"use-callback-ref": "^1.3.3",
"use-sidecar": "^1.1.3"
},
"engines": {
"node": ">=10"
},
"peerDependencies": {
"@types/react": "*",
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/react-remove-scroll-bar": {
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz",
"integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==",
"license": "MIT",
"dependencies": {
"react-style-singleton": "^2.2.2",
"tslib": "^2.0.0"
},
"engines": {
"node": ">=10"
},
"peerDependencies": {
"@types/react": "*",
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/react-style-singleton": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz",
"integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==",
"license": "MIT",
"dependencies": {
"get-nonce": "^1.0.0",
"tslib": "^2.0.0"
},
"engines": {
"node": ">=10"
},
"peerDependencies": {
"@types/react": "*",
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/scheduler": {
"version": "0.28.0",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.28.0.tgz",
"integrity": "sha512-juorfCmIkIw8tT+p5BXSm6PJjQF/ycEYmKyzURCIt/RaZIhL+PulbQ9Yu2z1HdOJDdqDTlxA1+xKBmHXJsczAw==",
"license": "MIT"
},
"node_modules/tslib": {
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
"license": "0BSD"
},
"node_modules/use-callback-ref": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz",
"integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==",
"license": "MIT",
"dependencies": {
"tslib": "^2.0.0"
},
"engines": {
"node": ">=10"
},
"peerDependencies": {
"@types/react": "*",
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/use-sidecar": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz",
"integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==",
"license": "MIT",
"dependencies": {
"detect-node-es": "^1.1.0",
"tslib": "^2.0.0"
},
"engines": {
"node": ">=10"
},
"peerDependencies": {
"@types/react": "*",
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
}
}
}

View file

@ -0,0 +1,13 @@
{
"name": "fep-boundary-recovery",
"private": true,
"type": "module",
"scripts": {"test": "node experiment.mjs"},
"dependencies": {
"react": "19.3.0",
"react-dom": "19.3.0",
"@radix-ui/react-dialog": "1.1.23",
"playwright": "1.63.0",
"esbuild": "0.28.2"
}
}

View file

@ -0,0 +1,57 @@
{
"date": "2026-09-26",
"source_id": "SRC-0029",
"packages": {
"node_modules/react": {
"version": "19.3.0",
"resolved": "https://registry.npmjs.org/react/-/react-19.3.0.tgz",
"integrity": "sha512-E8LUcbtBWt20bbl2YoHfx4ZDBdxVTfOKtCZn9cDSJ4l6/nuoApcpIBcj47t2wZoVX8g2ZHuMHbiShgCR1T5Sog=="
},
"node_modules/react-dom": {
"version": "19.3.0",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.3.0.tgz",
"integrity": "sha512-JDk8dgif51OjFoDE70+OT9ICyYr+69HlmihNwp1+Nsfbna3t5sIiCa9ZJktDmQ4/1b/rn26hIAR2uYXDMr5r0Q=="
},
"node_modules/@radix-ui/react-dialog": {
"version": "1.1.23",
"resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.23.tgz",
"integrity": "sha512-Ksw4WeROkO4rC9k/onilX/Ao2Cr1ku1unMNH+XSCcP4jSXYu7HDsg9n4ojMjVb22XpYjAQ9qfrFlVbru1vXDUA=="
},
"node_modules/@radix-ui/react-focus-scope": {
"version": "1.1.16",
"resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.16.tgz",
"integrity": "sha512-wmRZ2WWLvmt6KHy2rNPOdPUjwq5xOHY02+m+udwJTn0aNIox/rkskAvJTyTLGhPK6KgrUjlJUJpgmx/+wFiFIQ=="
},
"node_modules/playwright": {
"version": "1.63.0",
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.63.0.tgz",
"integrity": "sha512-+7ziBLidS4NaNCdt57SUDT+wYmmd5fmiQejUic/kb+YsYSCPyOOE9sebzMjNmQrsnNpDJqd4WHvV/8lfKfUDUg=="
},
"node_modules/esbuild": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.2.tgz",
"integrity": "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA=="
},
"node_modules/@radix-ui/react-dismissable-layer": {
"version": "1.1.19",
"resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.19.tgz",
"integrity": "sha512-8g4pfOL9HoKKLWGiypT+dphVqjFfmcXO5GBnhsG6zI+lxAx/8feQpr+1LSN8Re3hiZ+XkLNS4O9ztK11/LzQ6w=="
}
},
"inspected_files": {
"@radix-ui/react-dialog/dist/index.mjs": {
"sha256": "a37daaef3f67c502500404ee93f60a04fdf05d2b0ce4783c858b1027c7f54792"
},
"@radix-ui/react-focus-scope/dist/index.mjs": {
"sha256": "798184fbe00268a6c4a539fd2073b85b6dfef6d89bd2cd547d9a66ae1024e55d"
},
"@radix-ui/react-dismissable-layer/dist/index.mjs": {
"sha256": "01df449a23d65bab1f2f2215a953cba74741419496ebd9a7932533f267cc873d"
}
},
"browser": {
"version": "151.0.7922.34",
"executable_sha256": "0b20b130e7edd9dd51873be867761295fe0cfad490c2b9a64f95bd3cfc08fa71",
"selection": "preinstalled Chromium build 1234, explicit executable override; not claimed to be Playwright 1.63 bundled revision"
}
}

View file

@ -0,0 +1,134 @@
{
"date": "2026-09-26T19:58:51.268Z",
"evidence": "synthetic-browser-fixture-real-libraries",
"node": "v24.11.1",
"browser": "151.0.7922.34",
"nestedSettleMs": 0,
"browserSelection": "explicit executable override",
"packages": {
"react": "19.3.0",
"react-dom": "19.3.0",
"@radix-ui/react-dialog": "1.1.23",
"playwright": "1.63.0",
"esbuild": "0.28.2"
},
"files": {
"fixture.jsx": "3dd538006affc9bcdb69c8b5cd1bb06ac335499f1143b91f06f1d455a127c525",
"experiment.mjs": "33ea08bcbd8fda533dc4bb44d5369b5453fd8e23940116597658435296d834fb",
"package.json": "a0ad37e8518b0c561d6b4a091ee51f5bca90e0ce329b2be7ba75347f6dc26ae7",
"package-lock.json": "ec4b544d441f89d9c512bc9931c1818473327105d5ef9047dc04d6a721e68463"
},
"cases": [
{
"id": "X01-render-contained",
"status": "pass",
"observed": {
"caught": [
{
"boundary": "inner",
"message": "render fault"
}
],
"globalErrors": [],
"requests": [],
"dialogTransitions": []
},
"siblingUsable": true,
"browserErrors": []
},
{
"id": "X02-event-not-contained",
"status": "pass",
"observed": {
"caught": [],
"globalErrors": [
"Uncaught Error: event fault"
],
"requests": [],
"dialogTransitions": []
},
"panelPresent": true,
"browserErrors": [
"event fault"
]
},
{
"id": "X03-request-explicit-state",
"status": "pass",
"observed": {
"caught": [],
"globalErrors": [],
"requests": [
503
],
"dialogTransitions": []
},
"state": "request failed",
"browserErrors": []
},
{
"id": "X04-fallback-escapes-inner",
"status": "pass",
"observed": {
"caught": [
{
"boundary": "outer",
"message": "fallback fault"
}
],
"globalErrors": [],
"requests": [],
"dialogTransitions": []
},
"enclosingFallback": true,
"browserErrors": []
},
{
"id": "X05-focus-existing-invoker",
"status": "pass",
"activeId": "invoker",
"browserErrors": []
},
{
"id": "X06-focus-removed-default",
"status": "pass",
"activeTag": "BODY",
"workflowTargetSelected": false,
"browserErrors": []
},
{
"id": "X07-focus-removed-explicit",
"status": "pass",
"activeId": "next",
"applicationPolicy": true,
"browserErrors": []
},
{
"id": "X08-nested-return",
"status": "fail",
"error": "Expected focus nested-invoker; got {\"id\":\"invoker\",\"tag\":\"BUTTON\",\"dialogs\":0}: page.waitForFunction: Timeout 5000ms exceeded.",
"observed": {
"caught": [],
"globalErrors": [],
"requests": [],
"dialogTransitions": [
{
"dialog": "outer",
"open": true
},
{
"dialog": "inner",
"open": true
},
{
"dialog": "outer",
"open": false
}
]
},
"browserErrors": []
}
],
"passed": 7,
"total": 8
}

View file

@ -0,0 +1,139 @@
{
"date": "2026-09-26T19:58:59.954Z",
"evidence": "synthetic-browser-fixture-real-libraries",
"node": "v24.11.1",
"browser": "151.0.7922.34",
"nestedSettleMs": 100,
"browserSelection": "explicit executable override",
"packages": {
"react": "19.3.0",
"react-dom": "19.3.0",
"@radix-ui/react-dialog": "1.1.23",
"playwright": "1.63.0",
"esbuild": "0.28.2"
},
"files": {
"fixture.jsx": "3dd538006affc9bcdb69c8b5cd1bb06ac335499f1143b91f06f1d455a127c525",
"experiment.mjs": "33ea08bcbd8fda533dc4bb44d5369b5453fd8e23940116597658435296d834fb",
"package.json": "a0ad37e8518b0c561d6b4a091ee51f5bca90e0ce329b2be7ba75347f6dc26ae7",
"package-lock.json": "ec4b544d441f89d9c512bc9931c1818473327105d5ef9047dc04d6a721e68463"
},
"cases": [
{
"id": "X01-render-contained",
"status": "pass",
"observed": {
"caught": [
{
"boundary": "inner",
"message": "render fault"
}
],
"globalErrors": [],
"requests": [],
"dialogTransitions": []
},
"siblingUsable": true,
"browserErrors": []
},
{
"id": "X02-event-not-contained",
"status": "pass",
"observed": {
"caught": [],
"globalErrors": [
"Uncaught Error: event fault"
],
"requests": [],
"dialogTransitions": []
},
"panelPresent": true,
"browserErrors": [
"event fault"
]
},
{
"id": "X03-request-explicit-state",
"status": "pass",
"observed": {
"caught": [],
"globalErrors": [],
"requests": [
503
],
"dialogTransitions": []
},
"state": "request failed",
"browserErrors": []
},
{
"id": "X04-fallback-escapes-inner",
"status": "pass",
"observed": {
"caught": [
{
"boundary": "outer",
"message": "fallback fault"
}
],
"globalErrors": [],
"requests": [],
"dialogTransitions": []
},
"enclosingFallback": true,
"browserErrors": []
},
{
"id": "X05-focus-existing-invoker",
"status": "pass",
"activeId": "invoker",
"browserErrors": []
},
{
"id": "X06-focus-removed-default",
"status": "pass",
"activeTag": "BODY",
"workflowTargetSelected": false,
"browserErrors": []
},
{
"id": "X07-focus-removed-explicit",
"status": "pass",
"activeId": "next",
"applicationPolicy": true,
"browserErrors": []
},
{
"id": "X08-nested-return",
"status": "pass",
"innerReturn": "nested-invoker",
"outerReturn": "invoker",
"observed": {
"caught": [],
"globalErrors": [],
"requests": [],
"dialogTransitions": [
{
"dialog": "outer",
"open": true
},
{
"dialog": "inner",
"open": true
},
{
"dialog": "inner",
"open": false
},
{
"dialog": "outer",
"open": false
}
]
},
"browserErrors": []
}
],
"passed": 8,
"total": 8
}