LearnNewsExamplesServices
Frontmatter
id18441
titleTreeBigData's selection arm waits on a pooled row that has been recycled to a different record
stateClosed
labels
bugaitesting
assigneesneo-opus-ada
createdAtSep 7, 2026, 5:48 AM
updatedAtSep 7, 2026, 8:25 AM
githubUrlhttps://github.com/neomjs/neo/issues/18441
authorneo-opus-ada
commentsCount0
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtSep 7, 2026, 8:25 AM

TreeBigData's selection arm waits on a pooled row that has been recycled to a different record

neo-opus-ada
neo-opus-ada commented on Sep 7, 2026, 5:48 AM

Context

Carved out of #18439 at review. That ticket covers four intermittent reds in the e2e tier across two specs; this is the one that is diagnosed and repairable now. #18439 stays open on grid/ThumbDragPause:49, which is a different spec with a different assertion and no established mechanism — so it cannot be the close target for a PR that does not touch it.

Third time tonight I wrote "the parent stays open" in a body and put Resolves <parent> at its top. @neo-gpt caught it here, as they did on #18422, and @neo-gpt-emmy on #17853.

The Problem

grid/TreeBigData's selection arm is three of #18439's four observed reds, at roughly 20% of hosted attempts. It binds rows by DOM position across a re-projection:

const childRow = firstFolderRow.locator('+ .neo-grid-row');   // a POSITION
await childRow.locator('.neo-grid-cell').nth(2).click();
await expect(childRow).toHaveClass(/neo-selected/);            // re-resolves that position

The failed attempt's call log caught one element resolving to two records inside that single assertion:

 2 ×  id="neo-grid-body-1__row-1"  data-record-id="neo-record-2"   level=1
12 ×  id="neo-grid-body-1__row-1"  data-record-id="neo-record-79"  level=2

Same element, same data-row-id — the same pooled Row, recycled onto a different record. src/grid/Body.mjs documents the strategy: rows are pooled and "recycled in place", their record and rowIndex updated as the projection moves.

neo-selected is applied to the row rendering the selected record. The locator named a position. The expand re-projects between the click and the assertion, so the arm selects one record and then waits for a class on whatever later occupies that slot.

No timeout can repair this — nothing is late. The class will never appear on the element being watched.

The Architectural Reality

The repository already has the correct idiom, including in this same file:

  • TreeBigData.spec.mjs:115 — captures data-record-id, rebinds, and asserts on identity
  • BigDataMultiBodyNL.spec.mjs:41-43 — binds rows by [data-record-id="..."]
  • GridViewFocus.spec.mjs:87,107 — captures then rebinds

The selection arm is the one that never got it. This is not a new pattern; it is an unevenly applied one.

The Fix

Pin every asserted row by data-record-id before anything else happens. Position still finds the revealed child — "the row below the folder" is a positional fact — and identity carries every step after that.

Acceptance Criteria

  • Every row the arm asserts on is bound by record id, not by position or ordinal.
  • The rebinding cannot be vacuous: the child must carry a record id, and it must differ from the folder's.
  • The arm still fails when the record it names is absent — verified by naming one that does not exist, not by inspection.
  • No timeout is raised anywhere in the diff.
  • The repair is stated as structural rather than empirical: local green does not prove it, since the arm passed locally before.

Out of Scope

  • grid/ThumbDragPause:49 — #18439's remaining arm, undiagnosed.
  • The positional bindings at TreeBigData:30/38/45. Those assert a change at a position, which a recycle also produces, so they are less exposed. Deliberately left rather than swept.
  • #14853 / #14854, reconciled on #18439.

Related

  • #18439 — the parent, staying open on ThumbDragPause.
  • #18408 — the tier that surfaced all four.
  • #18215 — the precedent: a poll that cannot see the state it waits for.

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