Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a0cffe-206f-7323-89d3-b20ca4cf4bf9
67 lines
4.6 KiB
Markdown
67 lines
4.6 KiB
Markdown
# Boundary recovery observations — 2026-09-26
|
||
|
||
Status: executed synthetic browser fixture, editorial interpretation by Codex.
|
||
WP-0003 T01; SRC-0029 pinned packages and SRC-0030 Radix documentation. This advances
|
||
implementation evidence for Failure Boundary and Focus Return, not full-pattern
|
||
recurrence, application validation or the M1/M2 gates. Sixteen hypotheses remain.
|
||
|
||
[Runner, fixture and raw results](../experiments/boundary-recovery/README.md) use
|
||
React 19.3.0, Radix Dialog 1.1.23 and Chromium 151.0.7922.34. Package archives,
|
||
inspected implementation hashes and browser provenance are recorded. Sources of
|
||
injected faults and application focus policy are our own fixture, not vendor examples.
|
||
No live model calls; future inference remains through llm-connect.
|
||
|
||
## Observations and implications
|
||
|
||
| Evidence | Executed observation | Bounded interpretation |
|
||
| --- | --- | --- |
|
||
| X01 | Inner boundary catches render fault; sibling button remains usable | Local rendering containment works for this subtree and fault |
|
||
| X02 | Event-handler exception is globally reported; no boundary catch | Do not promise catch-all UI recovery from a rendering boundary |
|
||
| X03 | GET /failure returns 503; explicit application catch displays failure state | Request state is separate; this does not establish behavior of unhandled async errors |
|
||
| X04 | Broken inner fallback reaches outer fallback | Recovery UI can fail and needs an enclosing policy |
|
||
| X05 | Escape returns focus to surviving trigger | A partial implementation of ordinary modal return |
|
||
| X06 | Removing the trigger and closing leaves BODY focused | A generic trigger reference cannot choose the next workflow target |
|
||
| X07 | Application onCloseAutoFocus override selects next record | A narrow application policy repairs this removed-trigger case |
|
||
| X08 | Immediate Escape after nested activation closed outer dialog in the recorded final immediate run; 100 ms pause preserved inner-then-outer return | Activation/focus arrival alone is insufficient evidence of stable dismissal ownership; timing cause remains unproven |
|
||
|
||
## Source inspection and uncertainty
|
||
|
||
[Radix Dialog docs](https://www.radix-ui.com/primitives/docs/components/dialog)
|
||
expose close-autofocus customization and describe Escape dismissal. Inspected package
|
||
code `@radix-ui/react-dialog/dist/index.mjs` lines 154–156 cancels the default unmount
|
||
focus action and attempts focus on the trigger reference. Our explicit target in X07
|
||
is an application addition, not a built-in workflow-selection guarantee.
|
||
|
||
In the pinned `@radix-ui/react-focus-scope/dist/index.mjs`, lines 94–103 defer unmount
|
||
focus handling. The pinned dismissable-layer module, lines 90–120, selects the highest
|
||
layer and registers Escape listeners/layers through effects. These are plausible
|
||
places to investigate the timing discrepancy, not a demonstrated causal diagnosis.
|
||
See [file hashes and transitive versions](../experiments/boundary-recovery/provenance.json).
|
||
|
||
The failing X08 transition log is outer-open, inner-open, outer-close; it does not
|
||
show inner-close before outer-close. The final settled run shows the intended order.
|
||
Three earlier development runs also alternated fail/pass/fail. Do not describe this
|
||
as an unconditional nested-focus guarantee, estimate a rate from five exploratory
|
||
runs, or prescribe a 100 ms sleep as a fix. Current result files record identical
|
||
fixture/runner/lock hashes, with the timing parameter explicitly different.
|
||
|
||
## Candidate revisions and remaining work
|
||
|
||
[Failure Boundary](../candidates/FailureBoundary.md) gains executed partial support
|
||
and concrete exclusions. [Focus Return](../candidates/FocusReturn.md) gains a negative
|
||
control, a conditional recovery policy and an unresolved nested-lifecycle case.
|
||
Both stay hypotheses. One synthetic fixture is not an independent application use.
|
||
|
||
Next under [WP-0003 T01](../../workplans/FEP-WP-0003-contrasting-schools.md): isolate
|
||
nested dismissal with event/effect timing instrumentation and compare production
|
||
build plus another browser before assigning cause. Preserve the immediate path as
|
||
a regression probe; test explicit readiness/ownership rather than adding a delay.
|
||
Screen-reader behavior remains untested. Feature/release coupling inspection and
|
||
navigation/history/cache checks remain separate pending work.
|
||
|
||
## Follow-up disposition
|
||
|
||
[Nested isolation](NestedDismissalIsolation.md) now captures the stale-listener
|
||
interval and compares builds/browsers. The mechanism is located in an instrumented
|
||
fixture; a complete product remedy remains open. This supersedes the earlier lack
|
||
of timing diagnosis, while preserving the original receipts and their limitations.
|