LearnNewsExamplesServices
Frontmatter
id18410
titleWorkstationTabOverflowCapNL measures a collapsed reveal''s pin strip, because the heavy header it documents no longer stages a cap
stateClosed
labels
bugaitesting
assigneesneo-opus-ada
createdAtSep 7, 2026, 1:22 AM
updatedAtSep 7, 2026, 8:27 AM
githubUrlhttps://github.com/neomjs/neo/issues/18410
authorneo-opus-ada
commentsCount0
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtSep 7, 2026, 8:27 AM

WorkstationTabOverflowCapNL measures a collapsed reveal's pin strip, because the heavy header it documents no longer stages a cap

Closed Backlog/active-chunk-21 bugaitesting
neo-opus-ada
neo-opus-ada commented on Sep 7, 2026, 1:22 AM

The Symptom

WorkstationTabOverflowCapNL fails on dev at the staging guard:

Error: the heavy header must stage a multi-action trailing partition
expect(received).toBeGreaterThan(expected)
  Expected: > 1
  Received:   1

Two mechanisms were proposed and both are dead. @neo-opus-vega bisected it: the same failure reproduces byte-identically against ac93c04e3c, the commit immediately before #18306, so HeaderActionPolicy is exonerated. Vega then hypothesised nesting — actions wrapped one level deeper would stop matching the spec's :scope > query while the count collapsed with nothing removed. That is also falsified, below.

What the DOM Actually Contains

Probed the live app at the spec's own viewport (1180×840). Eight .neo-tab-header-toolbar elements:

kind actions capped overflow ctrl tabs clientW scrollW activeW
reveal 1 1 – 1 0 0 0
reveal 1 1 – 1 0 0 0
header 1 0 – 1 180 180 58
header 1 0 – 1 413 413 78
header 2 0 ✔ 1 276 276 149
header 1 0 – 2 220 220 55
header 1 0 – 1 220 220 63
header 1 0 – 1 1156 1156 114

Nesting is out: :scope > .neo-toolbar-action and .neo-toolbar-action return the same count on every toolbar. Nothing moved deeper.

Three facts decide it:

  1. No header overflows. scrollWidth === clientWidth on all six. The widest active tab is 149px in a 276px strip. The docblock's premise — "twelve canonical titles in a narrow pane" — is not what the app boots into; every header holds one or two tabs.
  2. No heavy header carries a cap. .neo-tab-overflow-capped count is zero on all six.
  3. The only capped elements in the document are the titles of two collapsed reveal headers, and they are zero-width. A reveal has exactly one trailing action — the pin — by design.

The Mechanism

document.querySelector('.neo-tab-overflow-capped') returns the first match in document order. The heavy headers stage none, so it returns a collapsed reveal's title, and every downstream measurement — toolbar, actions, clusterWidth, the cap identity — describes the reveal's one-pin strip instead of the heavy header's trailing cluster. actionCount === 1 is then the correct answer to the wrong question, which is why no source change explains it and why it predates #18306.

This is also why the loud-failure guard did not fire. Its message reads "if no cap exists, the stage no longer exercises this branch and the spec must fail loudly" — but a cap did exist. A selector that substitutes a different surface defeats a guard written against absence.

Why It Matters Beyond This Spec

The spec depends on an app's incidental boot composition to stage its degenerate case. When the composition drifted, the spec did not report a missing stage; it silently retargeted and reported a product defect that does not exist — costing two peers a bisect and a mechanism hunt tonight.

The same shape plausibly explains the three WorkstationPaletteBridgeNL timeouts, which wait for a visible .neo-tab-header-button while the capped candidates measure zero width. Stated as the next thing to check, not as a finding — no probe has been run against that spec.

Acceptance Criteria

  • The spec stages the over-wide active tab itself rather than inheriting it from app boot defaults.
  • Its capped-button selection cannot resolve to a reveal header, and cannot resolve to a zero-width element.
  • With the stage absent, the spec fails naming the missing stage — verified by removing the staging step and reading the message, not by inspection.
  • The actionCount > 1 guard measures the surface the assertions then use; a red states which header it measured.
  • Re-running against ac93c04e3c no longer reproduces the failure, closing Vega's bisect.

Out of Scope

  • Whether the app should boot a twelve-title narrow pane. The spec must not depend on the answer either way.
  • WorkstationPaletteBridgeNL and WorkstationStarvedGeometryNL, which stay unowned until probed.
  • The GPU exclusion of this tier from CI — that is #18408.

Related

  • #17988 — created the cluster reserve and the > 1 guard this ticket repairs.
  • #18306 — exonerated by bisect; recorded so the next reader does not re-open it.
  • #18408 — the CI tier that excludes these specs.

Origin Session ID: 95f9ff6e-1ba5-43b6-860a-208fbf7f4442