LearnNewsExamplesServices
Frontmatter
id17581
titlelist.Buffered prunes nested pooled-item updates
stateClosed
labels
bugaitestingregressioncore
assigneesneo-gpt-emmy
createdAtAug 23, 2026, 12:03 AM
updatedAtAug 23, 2026, 2:49 AM
githubUrlhttps://github.com/neomjs/neo/issues/17581
authorneo-gpt-emmy
commentsCount0
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[x] 17550 Activity stream: scrollable buffered list, honest counts, per-row local times
closedAtAug 23, 2026, 2:49 AM

list.Buffered prunes nested pooled-item updates

Closed Backlog/active-chunk-18 bugaitestingregressioncore
neo-gpt-emmy
neo-gpt-emmy commented on Aug 23, 2026, 12:03 AM

Context

Neo.list.Buffered landed in PR #17557 and its first nested-component adoption is the Fleet activity history under #17550. The live 500-record witness exposed a second post-merge engine defect, independent of the ResizeObserver routing defect in #17579.

At branch base 2b281a7639 plus the #17550 working delta, physical pool slot 0 held the newest record (event499). Its object-cell component reported text: "event 499" and vdom.text: "event 499", while its persisted VNode—and therefore painted DOM—still contained the original fixture text.

A live one-variable falsifier then set the owning buffered list's next updateDepth from 2 to 3 and rebuilt the same mounted range. Without changing the record or child VDOM again, the VNode immediately became "event 499".

The Problem

Buffered#getPooledComponent() derives the parent list's repaint depth as:

TreeBuilder.getComponentDepth(component)

That value counts the pooled item component itself and its descendants. It does not include the one component boundary from the list to that pooled item.

For a row container with leaf child components, getComponentDepth(row) returns 2. The list update expands the row, reaches its children at depth 1, and TreeBuilder emits mounted child references with neoIgnore: true. The row's record and child VDOM advance, but the persisted VNodes and painted text stay stale.

This is not activity-row formatting and not an app timing workaround. Any list.Buffered consumer whose itemConfig creates nested components can reproduce the same boundary miss after a pool slot is recycled.

The Architectural Reality

  • src/util/vdom/TreeBuilder.mjs:105-126 defines component depth and explicitly tells ancestor callers to use distanceToComponent + getComponentDepth(component).
  • src/list/Buffered.mjs:557-611 owns pooled component creation/rebinding and the list-level repaint envelope.
  • src/grid/View.mjs:255-268 is the established bounded-depth precedent: the owner derives enough depth to reach record-derived component contents, while avoiding -1 because unbounded collision scope destabilizes unrelated updates.

The buffered list is always exactly one component boundary above its pooled item component. The correct finite bound is therefore 1 + TreeBuilder.getComponentDepth(component).

The Fix

  1. Include the list-to-pooled-item distance when deriving Buffered's update depth.
  2. Add a mounted nested-item witness that recycles a physical slot from record A to record B and asserts worker VNode plus painted text both become B.
  3. Preserve the existing bounded pool, stable physical component IDs, anchor restoration, selection, and no-insert/remove contracts.
  4. Re-run #17550's 500-event headed witness without app-local retries or deferred row updates.

Contract Ledger

Target surface Source of authority Proposed behavior Fallback Docs Evidence
Buffered#getPooledComponent() repaint envelope TreeBuilder#getComponentDepth() finite depth includes the one list-to-item boundary plus the pooled item's full nested component depth a leaf item stays at the existing minimum useful bound; invalid item config still falls back to ordinary list content inline rationale beside the derived bound nested mounted recycle witness
pooled item record rebinding Store record + configured recordProperty record, child VDOM, persisted VNode and painted DOM converge in one list update missing/invalid config keeps the existing destroy/fallback path existing class JSDoc remains authority A→B slot reuse plus 500-record activity witness

Decision Record impact

None — this restores the finite-depth contract already documented by TreeBuilder.

Acceptance Criteria

  • A mounted pooled row with nested child components reuses the same physical component IDs when rebound from record A to record B.
  • After that rebind, the child config, VDOM, persisted VNode, and painted DOM all expose record B; no organic second update is required.
  • Buffered derives a finite repaint bound from the exact list-to-item distance plus TreeBuilder.getComponentDepth(component); it does not use updateDepth: -1.
  • Existing list.Buffered scroll, resize, prepend-anchor, selection, focus, record-change, and pool-bound tests remain green.
  • #17550's 500-record headed witness shows correct newest-row text with a viewport-plus-buffer component count, on both themes.

Out of Scope

  • Initial viewport delivery; #17579 owns the ResizeObserver envelope.
  • Fixed-DOM-order recycling beyond the current no-insert/remove contract; #17563 owns that follow-up.
  • App-local timeouts, post-render retries, or a second activity-row render path.
  • Variable-height rows or a repo-wide VDOM update redesign.

Avoided Traps

  • Set the row to updateDepth: -1. The update owner is the list, and the unbounded collision behavior is already rejected by the Grid precedent.
  • Schedule a later row update. It hides the shallow parent envelope behind timing and permits a stale painted frame.
  • Flatten the activity row into raw VDOM. It evades the engine defect by abandoning the component-library composition that exposed it.

Related

#17550 · #17563 · #17579 · PR #17557

Live latest-open sweep: checked the latest 20 open issues at 2026-08-22T22:03:11.902Z; no equivalent found.
A2A in-flight sweep: checked the latest 30 all-state messages at 2026-08-22T22:03:11.902Z; no overlapping claim found.

Origin Session ID: a502fc35-3ddd-439b-9797-7d6629b3b5f3

Retrieval Hint: query_raw_memories("list.Buffered nested pooled item updateDepth stale child VNode event499")

🪡 Emmy (GPT-5.6 Sol Ultra, Codex)

tobiu referenced in commit 68505df - "feat(agentos): buffer the Fleet activity history (#17550) (#17585) on Aug 23, 2026, 2:49 AM
tobiu closed this issue on Aug 23, 2026, 2:49 AM