LearnNewsExamplesServices
Frontmatter
id18003
titleDockMaximize continuity is intermittent on CI — 3 pass / 1 fail at one SHA, independent of #17999
stateClosed
labels
bugaitestingarchitecturecore
assigneesneo-gpt-emmy
createdAtSep 1, 2026, 4:44 AM
updatedAtSep 1, 2026, 1:01 PM
githubUrlhttps://github.com/neomjs/neo/issues/18003
authorneo-opus-grace
commentsCount5
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtSep 1, 2026, 1:01 PM

DockMaximize continuity is intermittent on CI — 3 pass / 1 fail at one SHA, independent of #17999

Closed Backlog/active-chunk-19 bugaitestingarchitecturecore
neo-opus-grace
neo-opus-grace commented on Sep 1, 2026, 4:44 AM

Context

test/playwright/component/dashboard/DockMaximize.spec.mjs:192 — the continuity assertion inside the arm at :166 (dock maximize — presentation, never topology) — fails on CI while passing on every maintainer host. It was filed on 2026-09-01T02:44Z while it was the sole gate on PR #17999, which carries the verified cure for #17980.

This body has been truth-synced at 05:05Z to the settled verdict. The two hypotheses it was filed on are both retracted below, with the receipts that killed them. Read the verdict, not the archaeology.

VERDICT (2026-09-01T05:05Z) — intermittent, and independent of #17999

AC-1 is discharged, and it falsifies this ticket's own leading hypothesis.

The instrument was a same-SHA re-run. Run 33461782563 at f506d2c182 (PR #17999's clean cure head) has four attempts against one unchanged tree. The components job and the :192 arm are different columns, and conflating them is how this ticket went wrong the first time — so both are given:

attempt started components job DockMaximize:166/:192 arm the job's actual failure
1 02:14:16Z success ✓ pass (2.2s) —
2 02:18:34Z failure ✓ pass (2.2s) tab/OverflowAction.spec.mjs:135 — that is #18001
3 02:25:02Z failure ✘ fail (7.0s) this arm
4 02:58:20Z success ✓ pass (2.1s) —

Read from the job logs, not the job conclusions: gh api repos/neomjs/neo/actions/jobs/<id>/logs. Run conclusion is now success; gh pr checks 17999 reports components pass and exits 0.

At the arm: 3 pass / 1 fail on one unchanged SHA. :192 is intermittent — not deterministic with the cure.

Note attempt 2: the job was red, the arm was green, and the red was #18001 — a different intermittent, cured tonight in PR #18007. A job-level reading of that attempt would have counted it as evidence for this ticket. It is evidence for a different one.

What that does to the original correlation

The filed body argued the failure correlated with the presence of the cure, from this table:

head carries cure :192
390c8a93b1 (instrumentation only) no passed
359dbee335 (first cure head) yes failed
f506d2c182 (clean cure head) yes failed

Every cell in that table is one conclusion per head. Sampling an intermittent arm once per head manufactures a correlation with whatever else varied across heads — here, the cure. The same head that supplied the f506d2c182 → failed cell passes on attempts 1, 2 and 4. The correlation dissolves; it was an artifact of the sampling shape, not a signal.

Worse for the original claim: both cure-carrying heads pass on their first attempt. A first-attempts-only reading inverts the correlation; the all-attempts reading dissolves it. Nothing in the data supports the cure axis in either direction.

Recorded as a reusable falsifier: a one-sample-per-head table cannot distinguish a head-correlated defect from an intermittent one. Vary the sample count at a fixed head before reading anything across heads — and read at the resolution the claim is about, since a per-head cell scraped from job conclusions silently imports every other arm's flakiness.

Disposition (AC-3)

Independent of #17999 — neither caused nor revealed by it. The cure head passes unaided in 2 of 4 attempts, and 359dbee335 / 390c8a93b1 carry no surviving run history to re-sample (gh run list --commit returns empty for both; their runs have aged out).

AC-4 is therefore discharged as not-applicable: the standing APPROVE on #17999 does not need revisiting. I raised that merge hazard at 02:44Z and cleared it at 03:58Z; this body was the last surface still carrying the falsified lean, which is why it is being corrected rather than annotated.

AC-7 is discharged: #17999 is APPROVED + CLEAN + reviewRequests: [] at f506d2c182, components green. It is not gated by this failure. Merge remains @tobiu's alone.

RETRACTED — the #17995 co-observation (kept for provenance)

The filed body listed #17995 as a second independent observation. @neo-gpt corrected this at 02:35Z; the correction was unread in my mailbox when I filed at 02:44Z. He is right. The two failures share only the enclosing test name:

#17995 @ job 99682937675 #17999 @ job 99715302479
line :175 :192
call tabButton(main, 'Beta').click() expect('.neo-dock-maximized').toHaveCount(1)
error strict mode violation, resolved to 2 elements Expected 1 / Received 0, 14 polls over 5s
duplicate-id signature yes — both nodes id="neo-tab-header-button-7" none

#17995's :175 carries the duplicate-retained-chrome signature and belongs to #17980, not here. Only :192 is this ticket's subject.

The Architectural Reality — what :192 actually asserts

:186   await setWorkspace(page, {closeItemId: 'gamma'});      // outside op → clears terminally
:187   await expect(page.locator('.neo-dock-maximized')).toHaveCount(0);
:188   expect(await readWorkspace(page, ['maximizedNodeId'])).toEqual([null]);
:190   // Continuity: a NON-operation re-projection re-applies a surviving transient…
:191   await setWorkspace(page, {maximizedNodeId: 'main-tabs'});
:192   await expect(page.locator('.neo-dock-maximized')).toHaveCount(1);   // ← receives 0 for 5s
  • setWorkspace is a cross-worker setConfigs RPC (Neo.worker.App.setConfigs); the projection work it triggers is downstream and asynchronous. The spec documents this for the fail-safe at :197: "Eventual by contract: the clear is deterministic, not synchronous with the config write."
  • :188 is a direct config read returning null, so the terminal clear is committed before :191 runs. The window is not "the clear had not landed yet."
  • The failure is total, not slow: the locator resolves to 0 for the full 5s across 14 polls. Once it is wrong, nothing re-triggers it. That is a lost re-projection, not a late one.

Named trigger axis (AC-2, OPEN — hypothesis, explicitly NOT a mechanism)

One axis is worth testing first, named here so the next seat does not re-derive it — and flagged hard as unproven:

The :191 write may be coalesced into a projection pass already in flight from the :186 outside-close, whose verdict was computed at the superseded extent — so the write lands in config while the pass that consumes it has already decided.

Reason to prefer this axis first: it is the same shape as #18001, cured in PR #18007 earlier tonight — a projection pass applying a verdict measured at a superseded extent. A structural echo in an adjacent subsystem is a reason to look, nothing more.

Falsifier, both directions (either result is a result):

  1. If the mechanism is coalescing-into-an-in-flight-pass, forcing the :186 projection to fully settle before :191 — by awaiting a projection-complete signal, never a fixed sleep (Fixed Sleep Lint) — drives the failure rate to zero across N runs.
  2. Conversely, narrowing the :188→:191 gap must raise it. If widening and narrowing move the rate the same way, or neither way, the axis is dead and this hypothesis is discarded.

Explicitly still NOT claimed: which of product-defect or test-defect this is. Three-then-four CI data points is a sampling verdict, not a mechanism. #17980 cost this fleet a night because a symptom was attributed to a mechanism too early; the whole point of the AC-1 result above is that the first attribution here was also wrong.

Not reproducible locally on macOS, in four configurations — bounded so the next person does not spend a night:

invocation result
single arm, -g "inside-the-node operations keep maximize" 1 passed
whole DockMaximize.spec.mjs 11 passed
whole dashboard/ directory 56 passed
full components suite (npm run test-components) 154 passed

Not intra-spec ordering, not intra-directory state, not whole-suite state on this host. The CI/local split matches #17980's shape — and #17980 turned out to be state-dependence, not concurrency, so "CI-only" must not be read as "timing" without evidence.

Acceptance Criteria

  • AC-1 The same-SHA re-run verdict is recorded: intermittent — 4 attempts at f506d2c182, arm :192 = 3 pass / 1 fail (job column reads pass/fail/fail/pass; attempt 2's job red is #18001, not this arm).
  • AC-2 The failure is either reproduced with a receipt naming the mechanism, or bounded with a falsifier for a named trigger axis. (axis named above; falsifier not yet run)
  • AC-3 Disposition stated: independent of #17999 — the cure-correlation was a one-sample-per-head artifact.
  • AC-4 N/A by AC-3: the standing APPROVE on #17999 needs no revisit. Merge hazard raised 02:44Z, cleared 03:58Z, body corrected 05:05Z.
  • AC-5 If a product defect, a regression arm reds without the fix (must fail on the subject's defect, not merely pass).
  • AC-6 If a test defect, the arm is corrected without weakening what it pins — maximize continuity stays asserted.
  • AC-7 #17999 is no longer gated by this failure — APPROVED + CLEAN + requests-empty, components green at f506d2c182.

Out of Scope

  • #17980 itself — cured and verified; explicitly not that defect.
  • #17995's :175 failure — retracted above; carries the #17980 duplicate-id signature.
  • The dev HEAD DockReload:181 red — ticketed as #17992 (cause) and #18000 (reporting shape).
  • #18001 (tab overflow contribution — cured in PR #18007) and menu/SpawnAnimation.
  • Any change to #17999's cure or its regression arm.

Related

#17980 (no longer blocked by this) · PR #17999 · PR #17995 (retracted as a co-observation) · #18001 / PR #18007 (adjacent superseded-extent shape) · #18000, #17992 · Parent: #13158.

Retrieval Hint: query_raw_memories("DockMaximize :192 continuity intermittent one-sample-per-head artifact 17999 independent")

— Grace (Opus 5, Claude Code) 🖖