LearnNewsExamplesServices
Frontmatter
id16117
titleHuman popup-over-popup drag never materializes the local proxy
stateOpen
labels
bugdesignaitestingregressioncore
assigneesneo-gpt-emmy
createdAt8:56 AM
updatedAt10:03 AM
githubUrlhttps://github.com/neomjs/neo/issues/16117
authorneo-gpt-emmy
commentsCount1
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]

Human popup-over-popup drag never materializes the local proxy

Open Backlog/active-chunk-10 bugdesignaitestingregressioncore
neo-gpt-emmy
neo-gpt-emmy commented on 8:56 AM

Context

Live operator QA on 2026-07-29 falsified the visual-completion claim made by PR #16096, which resolved #16090. During the real human gesture—drag one Workstation popup over another—the screen continues to show two fully opaque native popup windows. No target-local proxy is visible and the popup below exposes no usable drop-zone language.

PR #16096 proved a narrower mechanism: its scripted Scene 3 path found one target-window DragProxyContainer and read opacity: 0.7 from that element. That is not proof that the ordinary human gesture reaches the conversion, that the source popup yields early enough, or that the target zones are simultaneously legible. A single computed-style read at a contrived geometry cannot close this successor.

The geometry and lifecycle premises are not new: #15395 specified the dual-window conversion law and was resolved by PR #15567; #15396 specified park-don't-close and was resolved by PR #15573. The current observation is therefore a post-merge regression/integration failure. Both predecessors remain closed.

The Problem

The intended popup-over-popup grammar is not perceivable in the live product. Progressive partial overlap does not visibly transition from the native source popup to an in-app proxy. The user instead sees two real opaque windows, and the upper window obscures the target's drop zones.

A transition that occurs only at or near 100% overlap would still be the wrong interaction: by then the source has hidden the target and its choices. The conversion must become visible early, while enough target content remains visible to understand and select a drop outcome.

The trigger cannot use one window's extent or creation-time geometry. Source and target popups can have different live sizes and can be resized mid-session. #15395 established the reachable metric:

rx = overlapWidth / min(sourceWidth, targetWidth)

ry = overlapHeight / min(sourceHeight, targetHeight)

The composed score must use live rectangles, a calibrated convert-in/convert-out hysteresis pair, and pointer intent inside the target's dock-accepting region. Full overlay is neither necessary nor acceptable as the only positive point.

The current observation does not establish the exact failing owner. Candidate boundaries include the already-landed conversion sensor's production feed, claim/admission, native source parking, target-local proxy materialization, or stale/equal-size assumptions in the composed geometry path. The first deliverable is a human-path failing witness that distinguishes them.

The Architectural Reality

Current source contains the pieces, but their existence does not prove the live composition:

  • #15395 / PR #15567 owns the dual-window conversion geometry contract: live rects, smaller-extent per-axis normalization, hysteresis, and pointer gating.
  • #15396 / PR #15573 owns the in-gesture source-vessel lifecycle: park, re-show, and exact-source recovery.
  • apps/workstation/view/Workspace.mjs#resolveProxyConfig adds workstation-vessel-dragproxy only after a target-local proxy has been admitted.
  • resources/scss/src/apps/workstation/Viewport.scss assigns that proxy opacity: .7; this rule cannot affect either native popup and is irrelevant when no proxy materializes.
  • src/dashboard/DockVesselEmbodiment.mjs#createDockVesselProxyEmbodiment() owns target-local proxy stage/move/restore/promote lifecycle.
  • Workspace#parkTearOutVessel() owns the native focus → park → refocus effect and fails closed when its route or geometry contract rejects the transition.
  • Neo.manager.DragCoordinator selects and feeds the target; its native-titlebar and active pointer-drag paths are distinct.
  • PR #16096 exercised a scripted Scene 3 boundary and inspected the target DOM. It did not retain a progressive, actual-pointer visual sequence proving that the live user path transitions before target occlusion.

The repair belongs at the earliest failing owner above. Do not paper over a missing conversion with native window alpha or a second drag coordinator.

The Fix

  1. Add a headed macOS Chromium regression that uses the real dock-tab pointer gesture and real popup windows; it must not call a conversion helper directly.
  2. Retain a visual/semantic sequence across approach, pointer-gated target entry, partial overlap, proxy motion, and commit or convert-out. Record both live native rectangles, rx, ry, composed score, hysteresis state, selected target/claim, park admission, proxy census, preview/indicator state, and exact window identities at the same frames.
  3. Exercise at least small-over-large, large-over-small, near-equal, and post-resize asymmetric popup pairs. Each must reach conversion while the target remains readable.
  4. Repair the failing composition owner—sensor feed, admission, park, target proxy, or geometry use—so the source popup yields and exactly one target-local proxy moves with the pointer above still-visible drop indicators.
  5. Preserve cancel/convert-out, exact source-window restoration, commit-before-close, same-instance/store continuity, and stale-generation/disconnect cleanup.

Contract Ledger

Target surface Source of authority Required behavior Failure fallback Evidence
Dual-window conversion sensor #15395 / PR #15567 Use both live source and target rects; normalize each overlap axis by the smaller corresponding extent; apply calibrated in/out hysteresis Invalid geometry or no pointer intent remains non-converting Same-frame rects, rx, ry, composed score, pointer gate, transition
Human popup-over-popup gesture Real pointer stream + live native windows Target entry visibly transitions the dragged vessel to one target-local proxy during partial overlap Keep the exact source popup recoverable; never commit an unshown target Actual-pointer headed sequence on current dev red, fixed head green
Native source vessel #15396 / PR #15573 + Workspace#parkTearOutVessel() Yields behind the target only after the local proxy path is ready Refuse conversion and preserve/restore the same popup Identity, rect, park result, and visibility/z-order receipt
Target-local embodiment createDockVesselProxyEmbodiment() One moving proxy carries the live pane Zero proxy means the visual claim fails closed Proxy identity/window/parent/rect plus retained frames
Drop target language Existing DockDropIndicators + preview owner Indicators and preview remain legible concurrently with the proxy No visually hidden commit target DOM state plus same-frame visual proof

Acceptance Criteria

  • A focused actual-pointer headed witness fails on current merged dev with the reported two-native-popup/no-local-proxy state; no direct executor or conversion-helper call may stand in for the human gesture.
  • The witness records both live popup rectangles and proves the #15395 smaller-extent per-axis calculation for small-over-large, large-over-small, near-equal, and post-resize asymmetric cases.
  • Conversion uses distinct calibrated convert-in/convert-out thresholds and pointer intent inside the target dock surface; rect overlap alone does not arm conversion.
  • The retained sequence proves conversion during partial overlap while target choices remain readable; 100% overlay is neither required nor used as the only positive point.
  • From conversion admission through release, exactly one target-local proxy is visible and follows the pointer; the native source vessel is parked/relegated and does not obscure the target.
  • The proxy and the target's drop indicators/preview are visibly legible in the same retained frames at more than one pointer position.
  • Visual proof includes the full target window, source/proxy identity, and progression before/after conversion. A computed opacity value, DOM census, semantic receipt, or single final screenshot alone is insufficient.
  • Convert-out/cancel restores the exact same native source popup under the live pointer without reacquisition; commit retains commit-before-close and same-instance/store continuity.
  • Target unregister/disconnect and stale-generation paths retire the proxy exactly once with no DOM/native residue.
  • The regression remains green under ordinary headed execution without film flags or film-only choreography.

Out of Scope

Overflow-menu skin · ordinary tab-header drag-proxy skin · drop-indicator thickness symmetry · same-gesture re-entry freeze after initial tear-out · dragging an already-dropped native popup over the main app · popup first-paint/white-canvas defects · video production.

Avoided Traps

  • Do not reopen #15395, #15396, or #16090; this is their post-merge regression/integration successor.
  • Do not replace the two-live-rectangle metric with one-window, stale, or equal-size geometry.
  • Do not infer usability from opacity: .7 on an element the human path may never create.
  • Do not accept a full-overlay-only transition; it defeats the target-choice affordance.
  • Do not replace the in-app baseline with unsupported native popup alpha.
  • Do not use film/tour executors as the only evidence for an ordinary human interaction.

Decision Record impact

depends-on ADR 0029 §§2.3 and 2.8.2–2.8.3; no amendment expected. If the failing witness reveals that the recorded ownership state cannot express progressive target entry, stop and revalidate the ADR premise before implementation.

Related

Post-merge successor to #15395 (PR #15567), #15396 (PR #15573), and #16090 (PR #16096) · parent #15239 · QT-parity epic #13158.

Freshness evidence: Memory Core recovered the original dual-size operator exploration and exact geometry contract; live GitHub confirmed #15395 and #15396 are completed predecessors, closed by PRs #15567 and #15573. Knowledge Base semantic sweep, live current-source/PR inspection, latest 20 open GitHub issues, exact-title/scope search, and latest 30 all-state A2A messages were also checked on 2026-07-29; no equivalent open successor or competing claim was found.

Origin Session ID: abce4d75-7dcb-4145-8afc-b0ff2cdc51e6

Retrieval Hint: dual-window conversion geometry popup proxy min-axis hysteresis human path two opaque popups PR 16096