LearnNewsExamplesServices
Frontmatter
id19375
titleA tear-out's outer size has no runtime witness that it equals the tab body it replaced
stateClosed
labels
enhancementaitestingdashboard
assigneesneo-opus-vega
createdAtOct 3, 2026, 9:01 AM
updatedAtOct 3, 2026, 10:52 AM
githubUrlhttps://github.com/neomjs/neo/issues/19375
authorneo-opus-vega
commentsCount0
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[x] 18532 Native vessel re-show has no runtime witness that the outer footprint is preserved (mechanism mapped, preconditions measured)
blocking[]
closedAtOct 3, 2026, 10:52 AM

A tear-out's outer size has no runtime witness that it equals the tab body it replaced

Closed v13.2.0/archive-v13-2-0-chunk-24 enhancementaitestingdashboard
neo-opus-vega
neo-opus-vega commented on Oct 3, 2026, 9:01 AM

Context

#18532 named this invariant beside its own ("Related invariant, worth covering while the harness is open"): the popup a tab tears out into must have the outer size of the tab body it replaced, so neighbouring items are not overlapped — the content is legitimately smaller by the chrome. The #18532 witness ships without it: its stage resizes both vessels to a small rig width right after the pop-out (the display budget forces it), and the shared pop-out helper returns no tab-body rect, so the assertion was not a three-line addition. The ticket's own rule applies: not cheap, so its own ticket rather than silent omission.

The Problem

Neo.Main#resizeWindow verifies the requested size against outerWidth/outerHeight, so the engine half is self-consistent. Nothing at runtime relates that outer size back to the tab body's rect at the moment of the tear-out. A regression that handed the body's rect to a content-sized call would pass every unit test that supplies the numbers, and the popup would come up one chrome short on screen.

Fact corrected while building the arm (2026-10-03)

The engine sizes the vessel to the tabs node the pane leaves — header strip and body together (HeaderActions#measureDockPaneRect measures the tab container; Main#windowOpen then resizeTos the OUTER frame to that rect under useTotalHeight). Measured on real chrome: node 425×635, body alone 425×599 (a 36 px header strip), popup outer 425×635, chrome 67 px. "Tab body" in the title and below reads as that footprint; the invariant and the arm hold against the node's rect, and the receipt records the body beside it.

The Architectural Reality

  • The tear-out path opens the vessel from the dragged tab's body rect (Workstation VesselWorkspace, the native vessel open in NativeVesselTransaction), and the window manager publishes both innerRect and outerRect per window (manager/Window.mjs, outerRect = innerRect − chrome).
  • The sibling e2e specs (WorkstationNativeTitlebarDragNL, WorkstationNativePopupOverPopupNL) already pop panes out through the real header action with viewport: null on real chrome; test/playwright/e2e/utils/workstationPopOut.mjs is the shared choreography.
  • The Brain-gated NL e2e set does not run in CI (NEO_AGENTOS_RUNTIME_ROOT unset there), so the receipt is a local real-chrome run, as for #18532.

The Fix

One e2e arm, in the Workstation native spec whose rig already holds a real popup: read the tab body's bounding rect in the main window immediately before the pop-out, read the popup's outerWidth/outerHeight (OS) and manager.Window's outerRect immediately after adoption and before any rig resize, assert equality within the platform tolerance. Extend workstationPopOut.mjs to return the pre-pop-out body rect so the arm does not re-derive it. Chrome is read from the real window, never supplied.

Acceptance Criteria

  • The arm asserts popup outer size == the tabs node's size (width and height) within tolerance, on real chrome, before any rig resize; the receipt records the body rect beside it.
  • Mutation-proven: removing the engine's outer-size correction (Main#windowOpen's resizeTo under useTotalHeight) turns the arm red on the size line with the frame one chrome taller, not on a collateral failure.
  • The pop-out helper returns the node rect and the body rect it measured; no spec re-measures them.
  • A headless run (chrome 0) skips the arm with a stated reason, as #18532's arm does.

Out of Scope

The re-show footprint (#18532). Any change to Main's resize route or to the tear-out sizing itself.

Related

Sibling of #18532 (same harness, the other half of the operator-stated multi-window size contract). Decision Record impact: none — test coverage for existing behaviour.

unowned-rationale: lands on the #18532 harness once its PR merges; whoever next opens that spec file takes it.

Live latest-open sweep: latest 20 open neo issues read at 2026-10-03T07:00:09Z; no equivalent. gh issue list --search "tear-out popup outer size tab body" returned only #18532. A2A sweep (30 rows, 06:30–07:00Z): no claim on this scope. Memory Core sweep on the invariant's nouns: the #18532 lineage and Clio's G3 conversion-geometry leaves, no prior witness or decision. Own-assignment sweep: #18532 (this ticket's parent harness), nothing else on the surface.

Origin Session ID: 075e6b2a-b93a-4972-b143-0fca9e7c06d8 Retrieval Hint: "tear-out outer size equals tab body witness"

tobiu referenced in commit e91ec8a - "test(workstation): a popped-out pane is born at the outer size of the tabs node it left, witnessed on real chrome (#19375) (#19379)" on Oct 3, 2026, 10:52 AM
tobiu closed this issue on Oct 3, 2026, 10:52 AM