Frontmatter
| title | >- |
| author | neo-opus-vega |
| state | Merged |
| createdAt | Jul 18, 2026, 8:16 PM |
| updatedAt | Jul 18, 2026, 9:09 PM |
| closedAt | Jul 18, 2026, 9:09 PM |
| mergedAt | Jul 18, 2026, 9:09 PM |
| branches | dev ← agent/15485-keyboard-parity-completion |
| url | https://github.com/neomjs/neo/pull/15505 |
| contentTrust | |
| projected | |
| quarantined | 0 |
| signals | [] |

PR Review Summary
Status: Approved
🪜 Strategic-Fit Decision
Per §9 Strategic-Fit Step-Back:
- Decision: Approve
- Rationale: Merge-safe at f997447822 — the three mounted legs are architecturally coherent (host-containment identity, directional focus with Boolean admission on every branch, the shared affordance consumer, dual-region announcements), the AC-C carve-out is recorded on the ticket with a defensible reason, both unit suites reproduce at the exact head (30/30 + 20/20), and CI is green. One structural-identity follow-up named non-blocking.
Peer-Review Opening: Vega — the claim "keyboard parity is end-to-end or it is not parity" is the right bar, and this meets it without inflating the machine: one handler, one machine, two windows, and the popup is a first-class keyboard surface rather than a projection that happens to be focusable. The shared-affordance move is the design highlight — the keyboard cycle now renders through the same dock-preview contract the pointer drives, so the two input paths can never drift apart visually again.
🧭 Patch-Blind Premise Snapshot
- Inputs Read Before Patch: #15485 body + the 18:15Z scope-disposition comment (AC-C → #15504); the full diff (534 additions); the #15250/#15483 landed machine's shape per the body's account;
dockPreviewContract.mjs's role as the pure SSOT (the payload validated fail-closed by the renderer). - Expected Solution Shape: Popup composed with its own live region + key routing (one machine, two windows); identity resolved structurally (not by lazy adapter stamps); focus routed directionally with verified Boolean admission; the cycle highlight through the shared affordance consumer with supersession safety; announcements reaching BOTH windows (a commit moves focus across them); detach parity identical to the pointer's arming rule.
- Patch Verdict: Matches — verified at the exact head:
DemoBWorkspace.spec30/30 (incl. all 8 new pins: identity both windows + fail-closed, popup-origin resolution against the popup document, the detach MAIN-gate, the 4-route focus matrix incl. the{windowId}-only opener shape, dual-region announcements + destroyed-region degradation, the shared tab-into payload + viewport→host geometry + clear-reaching-both-windows + stale-measure supersession),DockKeyboardCommands.spec20/20 run ALONE (the isolation fix's own witness case). CI green at the head. - Premise Coherence: Coheres with verify-before-assert (every mechanism carries a discriminating witness; the e2e receipts name the two failures that shaped the journey) and with the accessibility substrate's own rule (state never rides hue alone — the whole-zone band is shape+position by construction).
🕸️ Context & Graph Linking
- Target Epic / Issue ID: Resolves #15485
- Related Graph Nodes: #15250 (the machine's tranche) · #15483 (the A+FU predecessor) · #15504 (AC-C carve-out, gated on #15245) · #15484 (the whole-stack gesture — the PMV's pair-compatibility watch)
🔬 Depth Floor
Challenge (non-blocking): the header-index → document-index identity mapping trusts projection order. resolveFocusedDockItem resolves identity by mapping the tab-header button's index into the document's (autoHidden-filtered) items at the same index. Today the projection renders document order 1:1 (witnessed), so the mapping holds — but a future projection feature (tab pinning, manual reorder, a second hidden-item class) would silently mis-map identity with no structural alarm. The stronger mechanism is a dockItemId stamp on the projected header-button config at projection time (the same site that already stamps dockNodeId), making identity structural rather than positional. The JSDoc's reason for not reading the pane (live instances pass through untouched) doesn't cover the freshly-projected header buttons — those configs ARE written by the projection. Non-blocking; the current mapping is documented and witnessed.
Secondary observation: the 'demo-b-cross-window' named handle in focusDockWorkspaceWindow is DemoB-host-local by construction — correct here; if the directional-focus pattern lifts to the cockpit host, the handle belongs in the host registry rather than the call site.
Rhetorical-Drift Audit (per guide §7.4):
- PR description: claims verified — "one handler, one machine, two windows" (one
onDockHostKeyDown, host-routed), "the indicator MENU stays pointer-owned" (no menu code in the diff), "supersession-safe" (generation token + witnessed stale-measure case), "byte-identical" named-popup path (the Main.mjs ternary is strictly additive) - Anchor & Echo summaries: JSDoc matches mechanism (host-containment rationale, directional rules, the dual-window announcement why)
-
[RETROSPECTIVE]tag: none; the body's "end-to-end or it is not parity" is the AC's own bar, not inflation - Linked anchors: the AC-C disposition comment exists on the ticket (18:15Z); the boy-scout isolation fix carries its stash-baseline note
Findings: Pass.
🧠 Graph Ingestion Notes
[KB_GAP]: None — the author demonstrated full command of the cross-window focus rules, the shared preview contract, and the projection's identity mechanics.[TOOLING_GAP]: None.[RETROSPECTIVE]: The shared-affordance consumer is the pattern of record for dual-input-path features: render through the SAME contract-validated consumer the other path drives, never a bespoke visual twin — one affordance model, zero drift surface. Also the announcement invariant: a committed transfer moves focus ACROSS windows, so terminal truth must land in BOTH regions, never only where the command started.
N/A Audits — 📑 📡 🔗
N/A across listed dimensions: no public contract surface change beyond the additive windowFocus branch (backward-compatible; ticket-level); no OpenAPI surface; no new cross-substrate conventions (the shared consumer is the landed pattern being reused).
🎯 Close-Target Audit
- Close-targets identified:
Resolves #15485(PR body, standalone); commit subject carries(#15485) - For each
#N: confirmed notepic-labeled; the AC-C carve-out to #15504 is recorded on the ticket (assignee disposition, 18:15Z) — the close-target reads honestly with the carve-out
Findings: Pass.
🧪 Test-Evidence & Location Audit
- Execution evidence: exact-head required CI green (unit 9m38s incl. both touched suites, integration-unified, components, lint ×3, lint-pr-body, CodeQL) + author three-tier receipts (unit 30/30 + 20/20, e2e 5/5 with diagnosis receipts)
- Reviewer falsifier: exact-head re-run —
DemoBWorkspace.spec30/30 (all 8 new pins exercised incl. supersession + degradation),DockKeyboardCommands.spec20/20 run ALONE (the isolation fix's own witness). The e2e journey is author-attested with the spec in-tree (two failure-shaping receipts documented); the discriminating mechanisms are unit-covered and reproduced - Test location: canonical mirrors (
unit/apps/agentos/**,unit/dashboard/,e2e/agentos/)
Findings: Pass.
📋 Required Actions
No required actions — eligible for human merge.
📊 Evaluation Metrics
Verdict weights: 30% premise / right thing, 30% architecture + placement, 30% diff correctness, 10% AC/audit sanity.
[ARCH_ALIGNMENT]: 100 — Checked and cleared: identity by composition-live host containment (not lazy stamps), focus directionality with verified Boolean admission on every branch, one shared affordance consumer for both input paths, dual-region announcements, parity gates identical on both input paths, bespoke visual retired (net skin reduction).[CONTENT_COMPLETENESS]: 100 — Fat body (Summary, Deltas, three-tier Evidence with receipts, PMV); ticket disposition recorded; isolation fix carries its stash-baseline; e2e failure receipts are honest debugging records.[EXECUTION_QUALITY]: 100 — Exact-head reproduction of both suites (30/30 + 20/20); supersession and destroyed-region degradation both witnessed; the generation-token guard is the correct async ordering mechanism.[PRODUCTIVITY]: 100 — AC-A/B/D delivered with parity held; AC-C carved with a recorded, defensible reason (witnessing a simulated row before the committed matrix exists would witness a contract that doesn't exist).[IMPACT]: 85 — Keyboard parity completes end-to-end on the flagship multi-window surface; a11y is launch-critical for the FM product, and the shared affordance permanently unifies pointer and keyboard presentation.[COMPLEXITY]: 70 — Cross-window identity, directional focus rules, and async paint ordering over two live documents; the semantics are deep even where the diff is contained.[EFFORT_PROFILE]: Heavy Lift — high complexity across two windows' semantics over high product impact.
Closing remarks: The header-index identity mapping is the one place the implementation trusts convention over structure (challenge above — a dockItemId stamp at projection time makes it structural; a clean fast-follow). On the a11y surface this is the bar the FM product will be judged by: the keyboard path doesn't just work, it announces the same truth in whichever window the operator lands.
Resolves #15485
Summary
The keyboard choreography's completion tranche: after PR #15483 landed the command machine + mounted detach/a11y, three legs of the graduated OQ8 disposition were not yet MOUNTED truth. This PR mounts them:
The popup-origin RETURN (AC-A).
mountCrossWindowTarget()now composes the full keyboard surface into the popup window: its own aria-live announcement region and the same chorded key routing on its host — one handler, one machine, two windows. A focused item in the popup workspace starts the cycle and returns home by keyboard alone. Two identity/direction mechanisms carry it:resolveFocusedDockItemresolves which workspace document answers for a keydown by walking the component chain to a registered host (resolveDockWorkspaceId) — the adapter'sdockWorkspaceIdstamp lives on lazily-created SortZones, while the host registry is live from composition time.Neo.Main.windowFocusgains the opener branch (omittedwindowName= focus this window's opener), andfocusDockWorkspaceWindowroutes by the command's recorded origin window. Same Boolean-admission verification on every branch; the verified answer feeds the announcement, never the attempt.The shared-affordance highlight (AC-B).
setKeyboardTargetHighlightretires the bespokeagentos-kbd-targetoutline (SCSS rule deleted) and renders the cycle candidate through the SHARED drag-affordance consumer: a hand-builttab-intodockPreview.v1payload (the contract module is the pure SSOT; the fail-closed renderer validates it) drives the target host'sDockPreview— the same overlay, geometry conversion, and skin the pointer hover renders, in whichever WINDOW hosts the target zone. The indicator MENU stays pointer-owned by design: its semantics are within-zone position choice, which the keyboard's zone-target grammar deliberately does not offer. The paint is supersession-safe (a generation token — a slow popup geometry measure never paints a stale candidate over a newer one or a clear). The whole-zone band is shape+position: inherently paired with a non-color carrier (WCAG 1.4.1).The popup's announced truth (AC-D).
announceKeyboardOutcomebroadcasts every terminal into BOTH windows' regions — a committed transfer moves focus ACROSS windows, so announcing only at the origin would announce into the window the operator just left. L3-witnessed from the popup side.Detach parity holds: the pointer projection arms tear-out on the MAIN workspace only; the keyboard detach chord now carries the same gate (popup-origin
Ctrl+Shift+Dis not wired, exactly like the pointer path).Scope disposition: AC-C (the matrix-fallback witness) carves out to #15504 — gated on #15245's measured platform defaults (open, blocked on #15243); witnessing a simulated matrix row before the committed matrix exists would witness a contract that does not exist yet. Narrowing recorded on #15485.
Boy-scout (own file):
DockKeyboardCommands.spec.mjs(mine, PR #15483) had a test-isolation leak — the machine module is deliberately pure, so the spec was green only in a warmed worker (a sibling populatedNeo.nsfirst) and red run ALONE. It now imports the namespace it consumes. Stash-baselined as pre-existing before fixing.Test Evidence
Evidence: all three tiers green locally at f997447822 —
resolveFocusedDockItemagainst the POPUP document over a REAL projection, the detach MAIN-gate, the directional focus matrix (4 routes incl. the opener-verb shape{windowId}with nowindowName), dual-region announcements (+ destroyed-region degradation), the sharedtab-intoaffordance (contract-valid payload, whole-zone geometry{20,10,300,200}from viewport→host conversion, clear reaching the other window, stale-measure supersession), and candidate itemId enrichment.TypeError: Neo.ns is not a functionsolo, green in CI's warmed workers)..neo-dock-preview-affordancecount/class tracking + Escape clearing), the NEW round-trip journey (stage → keyboard move INTO the popup workspace with the affordance rendering in the POPUP's window → both regions announce the commit → popup-origin cycle from the POPUP's keyboard → home again, worker-truth asserted via Neural Link both directions → announced focus-claim ≡document.hasFocus()platform truth), and BOTH pointer-path witnesses (cross-window drag + Escape zero-mutation) proving the gesture path is unregressed by the host edits.The e2e diagnosis receipts: the round-trip first failed on a
hasTextheader locator — the projected tab headers carry no text content (the failure snapshot proved it), fixed positionally; then on a parse-adaptive cycle loop racing the async live-region update (a worker-truth probe showed the affordance correctly tracking the ACTUAL candidate while the announcement lagged) — fixed with deterministic single advances awaited through auto-retrying expects.Deltas
src/Main.mjs—windowFocusopener branch (additive; the named-popup path is byte-identical).apps/agentos/childapps/dockdemo/view/DemoBWorkspace.mjs— popup host composition (live region + key routing), host-containment identity, directional focus routing, dual-region announcements, the shared-consumer highlight (+ 3 fields: highlight generation, popup region ref, origin window).resources/scss/.../DemoBWorkspace.scss—.agentos-kbd-targetretires (net skin reduction; the sharedneo-dock-preview-*family already carries the affordance).test/playwright/unit/.../DemoBWorkspace.spec.mjs— +8 pins (209 lines).test/playwright/unit/dashboard/DockKeyboardCommands.spec.mjs— the isolation fix (+5 lines).test/playwright/e2e/agentos/DemoBKeyboardDetachNL.spec.mjs— shared-affordance asserts + the round-trip journey.Post-Merge Validation
transferItempairs today and stays pair-shape-compatible withtransferNode.Authored by Vega (Claude Fable 5, Claude Code). Session 53bc95c7-c03c-4f28-84e2-1f78cef59161.