Context
The operator asked for more tests of menu hover and keyboard navigation, submenus included (2026-09-18). Scratch Playwright arms against dev@3f859a4803 measured the paths below as correct today. None has an arm. @neo-opus-ada, who built the menu stack, cross-checked each gap by grepping component/menu, unit/menu and component/button/Base.spec.mjs. The defects the same probes found are filed separately.
| # |
path |
measured |
| 1 |
Arrowing past a parent faster than subMenuHoverDelay |
never previews (maximum levels observed: 1), while resting on it previews (2). This is the debounce contract of the focus rest (#18780) |
| 2 |
Arrow keys over a disabled row and a separator |
skipped both ways |
| 3 |
A pointer rest on a disabled parent |
previews nothing |
| 4 |
Hover to depth 3, then a rest on a root leaf |
the whole branch goes in one step: level counts [3, 1] |
| 5 |
A click on a leaf inside a hover preview that focus never entered |
every level closes, and the item's route fires exactly once |
| 6 |
Enter on a leaf two levels down |
every level closes together ([3, 0]), and the route fires once |
| 7 |
Escape from depth 3 |
walks back one level per press, focusing each parent item, then dismisses |
| 8 |
Arrowing inside a submenu |
previews and drops that submenu's own child level, never closing itself |
| 9 |
Tab out of a submenu |
dismisses the whole floating cascade |
| 10 |
The pointer leaving the menu while a preview shows |
the preview stays |
| 11 |
A press on dead space in a form.field.ComboBox's bound list (added after #18854, at @neo-opus-vega's review note) |
the input keeps focus. This is the one Navigator consumer whose focus lives outside the subject, so the walk's subject.parentNode limit is what the arm witnesses |
The Problem
The 09-16 stack (#18758 → #18804) pinned what it changed. Everything above works because of how those pieces compose, and a regression in any of them would ship green. Row 1 is the most exposed: the focus-rest arms use subMenuHoverDelay 0 or 1000, never a pass-through faster than the delay.
The Architectural Reality
- The fixtures already exist in
test/playwright/component/menu/List.spec.mjs: createMenu(page, config), the three-level items tree, restItems, recordLevelCounts / levelCounts and focusedItem. A route on a leaf gives an exactly-once witness: count hashchange events, because Neo.Main.setRoute writes location.hash.
- Absence needs a bounded wait before it is read, the way the existing arms "outlast the delay". Presence polls.
The Fix
Add one arm per row to test/playwright/component/menu/List.spec.mjs, reusing its fixtures. It is a test-only change.
Acceptance Criteria
Out of Scope
- Touch or pen "rest" and RTL arrow semantics, which are design questions first (Ada's gaps 5 and 6).
- The End / skipped-row-click defect (#18846) and the focus hand-back defect (#18847).
Related
#18846 · #18847 · #18758 · #18759 · #18760 · #18780 · #18795 · #18803
Live latest-open sweep: latest 20 open issues read at 2026-09-18T11:01:41Z, plus an all-state title search (menu focus body / Navigator End / last-of-type / disabled menu): no equivalent (nearest: #17851 separator + disabled field, closed; #17825 outside-pointer dismissal, closed). A2A sweep: latest 30 messages. @neo-opus-vega posted a lane-intent on menu non-interactive rows at 10:39Z and stood down at 10:54Z in my favour; no other claim. Memory Core sweep, on the problem's nouns: no prior decision. Own-assignment sweep: 8 open, none on menus or focus.
Origin Session ID: 0a997d38-ccdb-4352-ac21-566606a6ab2d
Retrieval Hint: "menu witness arms fast arrowing debounce disabled separator depth three hover cascade route exactly once"
Context
The operator asked for more tests of menu hover and keyboard navigation, submenus included (2026-09-18). Scratch Playwright arms against
dev@3f859a4803measured the paths below as correct today. None has an arm. @neo-opus-ada, who built the menu stack, cross-checked each gap by greppingcomponent/menu,unit/menuandcomponent/button/Base.spec.mjs. The defects the same probes found are filed separately.subMenuHoverDelay[3, 1]routefires exactly once[3, 0]), and the route fires onceform.field.ComboBox's bound list (added after #18854, at @neo-opus-vega's review note)subject.parentNodelimit is what the arm witnessesThe Problem
The 09-16 stack (#18758 → #18804) pinned what it changed. Everything above works because of how those pieces compose, and a regression in any of them would ship green. Row 1 is the most exposed: the focus-rest arms use
subMenuHoverDelay0 or 1000, never a pass-through faster than the delay.The Architectural Reality
test/playwright/component/menu/List.spec.mjs:createMenu(page, config), the three-levelitemstree,restItems,recordLevelCounts/levelCountsandfocusedItem. A route on a leaf gives an exactly-once witness: counthashchangeevents, becauseNeo.Main.setRoutewriteslocation.hash.The Fix
Add one arm per row to
test/playwright/component/menu/List.spec.mjs, reusing its fixtures. It is a test-only change.Acceptance Criteria
Rows 1–11 each have an arm, green on
dev(row 11 once #18854 is ondev, which it is).Rows 1 and 4 each fail under a one-line source mutation that breaks the behaviour they claim, recorded in the PR:
startRestignoressubMenuHoverDelayunmount()stops hiding its own submenuRow 3 has two independent guards, the row's
pointer-events: noneand the hover delegate'snonInteractiveItemClscheck, so no single mutation reddens it. The PR says so rather than claiming one.No arm asserts a process-global or timing-sensitive count, and each absence is read after a bounded wait.
Out of Scope
Related
#18846 · #18847 · #18758 · #18759 · #18760 · #18780 · #18795 · #18803
Live latest-open sweep: latest 20 open issues read at 2026-09-18T11:01:41Z, plus an all-state title search (menu focus body / Navigator End / last-of-type / disabled menu): no equivalent (nearest: #17851 separator + disabled field, closed; #17825 outside-pointer dismissal, closed). A2A sweep: latest 30 messages. @neo-opus-vega posted a lane-intent on menu non-interactive rows at 10:39Z and stood down at 10:54Z in my favour; no other claim. Memory Core sweep, on the problem's nouns: no prior decision. Own-assignment sweep: 8 open, none on menus or focus.
Origin Session ID: 0a997d38-ccdb-4352-ac21-566606a6ab2d Retrieval Hint: "menu witness arms fast arrowing debounce disabled separator depth three hover cascade route exactly once"