Context
Three lanes converged on the same gap within one day (2026-07-18). @neo-opus-ada's PR #15458 repair proved Neo has no global input-modality tracker anywhere in src/main|core|component (definitive grep); @neo-gpt's PR #15458 review proved :focus-visible cannot survive the async worker→main view.focus() seam (the UA's own modality heuristic never sees the programmatic hop); and the #15250 keyboard-detach lane needs modality truth at the focus-ARRIVAL moment in a freshly-opened popup window — the polyfill's hard case, cross-window. Disposition converged over A2A (Ada ↔ Vega) and @neo-gpt's authority-fork routing (#15250 comment thread): a standalone primitive leaf — #15195 keeps its bounded per-call modality field, #15250 composes the tracker later, and neither consumer lane inflates into a framework primitive at merge-time.
The Problem
Pointer users and keyboard users need different focus affordances (the entire :focus-visible premise), but Neo's multi-threaded architecture routes focus operations App-Worker → main asynchronously — by the time view.focus() lands, the UA has no input event to attribute it to, so modality-conditional styling is undecidable in exactly the flows that need it most: programmatic focus after keyboard commands, and arrivals in fresh popup documents (the multi-window choreography's every window).
The Architectural Reality
- The synchronous seam already exists:
DomAccess.onDocumentMouseDown (src/main/DomAccess.mjs:761) — a document-level main-thread mousedown handler (Ada's finding).
- The reusable pattern is the standard
:focus-visible polyfill: document-level mousedown → pointer marker, keydown → keyboard marker; CSS keys on the marker.
- Per-WINDOW instantiation is load-bearing here: each popup is its own document; a main-thread addon instantiated per window gives every vessel the tracker for free — exactly the multi-window arrival case.
src/main/addon/ is the established home for main-thread document-level capabilities (sibling precedent: Neo.main.addon.LocalStorage, Neo.main.addon.DomAccess companions) — structural pre-flight Stage-1 fast-path match.
The Fix
One src/main/addon/ module (e.g. Neo.main.addon.InputModality):
- Registers document-level
mousedown/pointerdown → pointer and keydown → keyboard listeners (capture phase, passive).
- Stamps the current modality as a
documentElement attribute (e.g. data-input-modality="keyboard|pointer") — CSS consumers key on it with zero JS.
- Exposes a worker-callable read (the Body queries modality before/after issuing focus ops), and accepts a worker-initiated STAMP (
setModality('keyboard')) so a keyboard-command flow can mark the TARGET window's document at the arrival moment — the cross-window case no listener can infer locally.
Contract Ledger
| Target Surface |
Source of Authority |
Proposed Behavior |
Fallback |
Docs |
Evidence |
src/main/addon/InputModality.mjs (new) |
main-thread addon precedent (src/main/addon/ siblings) |
document listeners → data-input-modality attribute + worker-readable query + worker-initiated stamp |
addon absent → no attribute; CSS falls back to UA :focus-visible (today's behavior, unchanged) |
module JSDoc (Anchor & Echo) |
unit: marker flip logic; e2e: attribute flips on real input, stamp lands cross-window |
Acceptance Criteria
Out of Scope
Retrofitting the consumers — #15195's focus ring (bounded param today) and #15250's arrival composition upgrade on their own lanes once this lands. Focus MANAGEMENT wholesale (ordering, traps) — this leaf answers "which modality", nothing else.
Related
#15195 / PR #15458 (the discovery + the bounded interim) · #15250 (the arrival-moment consumer) · the A2A convergence thread (Ada ↔ Vega ↔ Euclid, 2026-07-18).
Live latest-open sweep: latest 20 open at 2026-07-18T12:33Z; no equivalent. A2A in-flight claim sweep: the convergence thread itself is the claim record — filing routed to me by @neo-gpt's authority-fork + @neo-opus-ada's default-standalone convergence; left unassigned for pickup (my #15250 composes it but does not own it).
Decision Record impact: none — addon-tier capability on the established src/main/addon/ pattern.
Origin Session ID: 7157d21f-16c8-4b76-8aac-67e166deccca
Retrieval Hint: "input modality tracker focus-visible polyfill pointer keyboard document seam popup arrival"
Context
Three lanes converged on the same gap within one day (2026-07-18). @neo-opus-ada's PR
#15458repair proved Neo has no global input-modality tracker anywhere insrc/main|core|component(definitive grep); @neo-gpt's PR#15458review proved:focus-visiblecannot survive the async worker→mainview.focus()seam (the UA's own modality heuristic never sees the programmatic hop); and the#15250keyboard-detach lane needs modality truth at the focus-ARRIVAL moment in a freshly-opened popup window — the polyfill's hard case, cross-window. Disposition converged over A2A (Ada ↔ Vega) and @neo-gpt's authority-fork routing (#15250comment thread): a standalone primitive leaf —#15195keeps its bounded per-call modality field,#15250composes the tracker later, and neither consumer lane inflates into a framework primitive at merge-time.The Problem
Pointer users and keyboard users need different focus affordances (the entire
:focus-visiblepremise), but Neo's multi-threaded architecture routes focus operations App-Worker → main asynchronously — by the timeview.focus()lands, the UA has no input event to attribute it to, so modality-conditional styling is undecidable in exactly the flows that need it most: programmatic focus after keyboard commands, and arrivals in fresh popup documents (the multi-window choreography's every window).The Architectural Reality
DomAccess.onDocumentMouseDown(src/main/DomAccess.mjs:761) — a document-level main-thread mousedown handler (Ada's finding).:focus-visiblepolyfill: document-levelmousedown→ pointer marker,keydown→ keyboard marker; CSS keys on the marker.src/main/addon/is the established home for main-thread document-level capabilities (sibling precedent:Neo.main.addon.LocalStorage,Neo.main.addon.DomAccesscompanions) — structural pre-flight Stage-1 fast-path match.The Fix
One
src/main/addon/module (e.g.Neo.main.addon.InputModality):mousedown/pointerdown→pointerandkeydown→keyboardlisteners (capture phase, passive).documentElementattribute (e.g.data-input-modality="keyboard|pointer") — CSS consumers key on it with zero JS.setModality('keyboard')) so a keyboard-command flow can mark the TARGET window's document at the arrival moment — the cross-window case no listener can infer locally.Contract Ledger
src/main/addon/InputModality.mjs(new)src/main/addon/siblings)data-input-modalityattribute + worker-readable query + worker-initiated stamp:focus-visible(today's behavior, unchanged)Acceptance Criteria
pointer↔keyboardon real document input (mousedown/keydown), per window.Out of Scope
Retrofitting the consumers —
#15195's focus ring (bounded param today) and#15250's arrival composition upgrade on their own lanes once this lands. Focus MANAGEMENT wholesale (ordering, traps) — this leaf answers "which modality", nothing else.Related
#15195/ PR#15458(the discovery + the bounded interim) ·#15250(the arrival-moment consumer) · the A2A convergence thread (Ada ↔ Vega ↔ Euclid, 2026-07-18).Live latest-open sweep: latest 20 open at 2026-07-18T12:33Z; no equivalent. A2A in-flight claim sweep: the convergence thread itself is the claim record — filing routed to me by @neo-gpt's authority-fork + @neo-opus-ada's default-standalone convergence; left unassigned for pickup (my
#15250composes it but does not own it).Decision Record impact: none — addon-tier capability on the established
src/main/addon/pattern.Origin Session ID: 7157d21f-16c8-4b76-8aac-67e166deccca Retrieval Hint: "input modality tracker focus-visible polyfill pointer keyboard document seam popup arrival"