FA-8186 / Overlay interactions / Open access
Popover outside-interaction handling: Escape fails to dismiss the overlay · case 01
Escape fails to dismiss the overlay.
ROOT CAUSE
The escape operation uses `if event == 'escape': return opened` where the contract requires `if event == 'escape': return False`.
VERIFIED REPAIR
Implement the escape operation as `if event == 'escape': return False`.
Unsuccessful approach: Toggling Escape opens an overlay when it is already closed.
Case contract
Cancelled events preserve state; Escape closes; only pointerdown toggles triggers or dismisses outside; membership in the composed path recognizes descendants and portals.
Why this case matters
A deterministic model of popover outside-interaction handling; this isolates one interface invariant without requiring a browser.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(opened, target_path, trigger, panel, event, prevented):
if prevented: return opened
if event == 'escape': return opened
if event != 'pointerdown': return opened
if trigger in target_path: return not opened
if panel in target_path: return opened
return False
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('cancelled open', solve(True, ['outside'], 'trigger', 'panel', 'pointerdown', True), True)
check('cancelled closed', solve(False, ['outside'], 'trigger', 'panel', 'pointerdown', True), False)
check('escape open', solve(True, [], 'trigger', 'panel', 'escape', False), False)
check('escape closed', solve(False, [], 'trigger', 'panel', 'escape', False), False)
check('ignored', solve(True, [], 'trigger', 'panel', 'pointermove', False), True)
check('trigger opens', solve(False, ['icon','trigger'], 'trigger', 'panel', 'pointerdown', False), True)
check('trigger closes', solve(True, ['icon','trigger'], 'trigger', 'panel', 'pointerdown', False), False)
check('inside descendant', solve(True, ['button','panel'], 'trigger', 'panel', 'pointerdown', False), True)
check('parameterized descendant depth', solve(True, ['node'+str(i) for i in range(N)]+['panel'], 'trigger', 'panel', 'pointerdown', False), True)
for repetition in range(N):
check('repeat inside descendant', solve(True, ['button','panel'], 'trigger', 'panel', 'pointerdown', False), True)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| cancelled open | True | True | Passed |
| cancelled closed | False | False | Passed |
| escape open | True | False | Failed |
| escape closed | False | False | Passed |
| ignored | True | True | Passed |
| trigger opens | True | True | Passed |
| trigger closes | False | False | Passed |
| inside descendant | True | True | Passed |
| parameterized descendant depth | True | True | Passed |
| repeat inside descendant | True | True | Passed |
SHA-256 / 5e76bbb1d16b90bda6500877877227e14ed120ae7b776bb54895eb1e4c8b3b94
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(opened, target_path, trigger, panel, event, prevented):
if prevented: return opened
if event == 'escape': return not opened
if event != 'pointerdown': return opened
if trigger in target_path: return not opened
if panel in target_path: return opened
return False
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('cancelled open', solve(True, ['outside'], 'trigger', 'panel', 'pointerdown', True), True)
check('cancelled closed', solve(False, ['outside'], 'trigger', 'panel', 'pointerdown', True), False)
check('escape open', solve(True, [], 'trigger', 'panel', 'escape', False), False)
check('escape closed', solve(False, [], 'trigger', 'panel', 'escape', False), False)
check('ignored', solve(True, [], 'trigger', 'panel', 'pointermove', False), True)
check('trigger opens', solve(False, ['icon','trigger'], 'trigger', 'panel', 'pointerdown', False), True)
check('trigger closes', solve(True, ['icon','trigger'], 'trigger', 'panel', 'pointerdown', False), False)
check('inside descendant', solve(True, ['button','panel'], 'trigger', 'panel', 'pointerdown', False), True)
check('parameterized descendant depth', solve(True, ['node'+str(i) for i in range(N)]+['panel'], 'trigger', 'panel', 'pointerdown', False), True)
for repetition in range(N):
check('repeat inside descendant', solve(True, ['button','panel'], 'trigger', 'panel', 'pointerdown', False), True)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| cancelled open | True | True | Passed |
| cancelled closed | False | False | Passed |
| escape open | False | False | Passed |
| escape closed | True | False | Failed |
| ignored | True | True | Passed |
| trigger opens | True | True | Passed |
| trigger closes | False | False | Passed |
| inside descendant | True | True | Passed |
| parameterized descendant depth | True | True | Passed |
| repeat inside descendant | True | True | Passed |
SHA-256 / 3ee9acf3c6f55503e6d1527702f67b5ca13836c1871ba2d92011a91525501fc4
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(opened, target_path, trigger, panel, event, prevented):
if prevented: return opened
if event == 'escape': return False
if event != 'pointerdown': return opened
if trigger in target_path: return not opened
if panel in target_path: return opened
return False
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('cancelled open', solve(True, ['outside'], 'trigger', 'panel', 'pointerdown', True), True)
check('cancelled closed', solve(False, ['outside'], 'trigger', 'panel', 'pointerdown', True), False)
check('escape open', solve(True, [], 'trigger', 'panel', 'escape', False), False)
check('escape closed', solve(False, [], 'trigger', 'panel', 'escape', False), False)
check('ignored', solve(True, [], 'trigger', 'panel', 'pointermove', False), True)
check('trigger opens', solve(False, ['icon','trigger'], 'trigger', 'panel', 'pointerdown', False), True)
check('trigger closes', solve(True, ['icon','trigger'], 'trigger', 'panel', 'pointerdown', False), False)
check('inside descendant', solve(True, ['button','panel'], 'trigger', 'panel', 'pointerdown', False), True)
check('parameterized descendant depth', solve(True, ['node'+str(i) for i in range(N)]+['panel'], 'trigger', 'panel', 'pointerdown', False), True)
for repetition in range(N):
check('repeat inside descendant', solve(True, ['button','panel'], 'trigger', 'panel', 'pointerdown', False), True)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| cancelled open | True | True | Passed |
| cancelled closed | False | False | Passed |
| escape open | False | False | Passed |
| escape closed | False | False | Passed |
| ignored | True | True | Passed |
| trigger opens | True | True | Passed |
| trigger closes | False | False | Passed |
| inside descendant | True | True | Passed |
| parameterized descendant depth | True | True | Passed |
| repeat inside descendant | True | True | Passed |
SHA-256 / 7a045de732a8956f9c0381ac510e7759e33401a66e89faa24402a37a06cf6dbd
Verification & scope
This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.
Observations recorded using Python 3.12.14 at 2026-09-29T14:38:19.152984+00:00.
Case digest / 2e484b5c8bba7e83e70da177b82eb685045a1e12eae85071b36cec9e8a6eff3f