Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a0cffe-206f-7323-89d3-b20ca4cf4bf9
113 lines
6.5 KiB
Markdown
113 lines
6.5 KiB
Markdown
# 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.
|
|
|
|
## Follow-up: nested ownership isolation
|
|
|
|
[Review](../../reviews/NestedDismissalIsolation.md) and [48-trial receipt](isolation-results.json)
|
|
compare development/production, Chromium/Firefox and four explicit variants. The
|
|
original experiment and receipts above remain unchanged. Follow-up reports 43/48
|
|
obligations met, including failures; it is a research runner, not a green CI gate.
|
|
|
|
```bash
|
|
PLAYWRIGHT_BROWSERS_PATH=/tmp/fep-playwright-browsers node node_modules/playwright/cli.js install firefox
|
|
PLAYWRIGHT_BROWSERS_PATH=/tmp/fep-playwright-browsers FEP_CHROMIUM_PATH=/path/to/chrome node isolation.mjs
|
|
```
|
|
|
|
Runs three trials per browser/build/variant, without automatic retries. Default
|
|
output is `/tmp/fep-isolation.json`; `FEP_RESULT_PATH` overrides it. A separate
|
|
`/tmp/fep-isolation-checkpoint.json` preserves completed trials if a later launch
|
|
fails. Launch failures abort; completed matrices retain assertion failures in JSON.
|
|
A sandbox prevented Firefox accessing its temporary profile here; the recorded
|
|
completed matrix ran outside that sandbox. Firefox build and limitations are in
|
|
[isolation-provenance.json](isolation-provenance.json).
|
|
|
|
Instrumentation and an experimental guard are applied in memory during bundling;
|
|
installed vendor files are not modified. The readiness variant observes private
|
|
listener state and is not a proposed public readiness API. The guard can lose input
|
|
and is not a validated fix. Do not replace raw failures with readiness passes.
|
|
|
|
## Follow-up: experimental routing
|
|
|
|
[Routing design](routing-design.md), [review](../../reviews/NestedOwnershipRouting.md)
|
|
and [corrected results](routing-results.json) compare a single document router with
|
|
unmodified behavior. Six scenarios across two browsers/builds: routed 24/24, raw
|
|
20/24. This is a research patch, not a production repair or published dependency fork.
|
|
|
|
```bash
|
|
PLAYWRIGHT_BROWSERS_PATH=/tmp/fep-playwright-browsers FEP_CHROMIUM_PATH=/path/to/chrome node routing.mjs
|
|
```
|
|
|
|
Uses the same installed dependencies/browsers as isolation.mjs. Outputs
|
|
`/tmp/fep-routing.json` (override with `FEP_RESULT_PATH`) and an incomplete checkpoint
|
|
at `/tmp/fep-routing-checkpoint.json`. No sleep, readiness wait or automatic retry.
|
|
The transform changes Escape routing only in memory and verifies the pinned source
|
|
hash before use. `routing-fixture.jsx` explicitly controls both dialogs, so its
|
|
results cannot be pooled with the earlier uncontrolled-inner fixture as matched trials.
|
|
|
|
The initial [development results](routing-development-results.json) used an incorrect
|
|
accessibility-exposed dialog count for cancellation. Their original `routing.mjs`
|
|
bytes are retained as [routing-development-runner.mjs](routing-development-runner.mjs)
|
|
for hash verification; that archived file is provenance, not the reproduction entry.
|
|
The corrected runner counts hidden parents and checks listener cleanup. Both runs
|
|
are retained, and the earlier faulty cancellation scores are excluded from conclusions.
|