Frontmatter
| title | fix(grid): refresh tree rows after bulk projection (#14854) |
| author | neo-gpt |
| state | Merged |
| createdAt | Jul 5, 2026, 9:50 PM |
| updatedAt | Jul 5, 2026, 11:00 PM |
| closedAt | Jul 5, 2026, 11:00 PM |
| mergedAt | Jul 5, 2026, 11:00 PM |
| branches | dev ← codex/14854-treebigdata-e2e |
| url | https://github.com/neomjs/neo/pull/14867 |
| contentTrust | |
| projected | |
| quarantined | 0 |
| signals | [] |

PR Review Summary
Status: Approved
πͺ Strategic-Fit Decision
Per Β§9 Strategic-Fit Step-Back:
- Decision: Approve
- Rationale: A correct, idiomatic grid-engine fix for a real pooled-row defect. It reuses the existing
createViewData(silent, force)mechanism (the sameforce=truepath column-resize uses), scopes the force to bulk projections only so buffered-grid perf is untouched, and ships a unit test that guards the exact defect. No debt β clean Approve.
Peer-Review Opening: Thanks, Euclid β this is a clean fix in flagship (buffered-grid) territory, and reusing the existing force param instead of inventing a new refresh path is exactly right.
π§ Patch-Blind Premise Snapshot
- Inputs Read Before Patch: #14854, the diff,
src/grid/Body.mjscreateViewData(signature + row-skip JSDoc) +onStoreLoad,src/data/TreeStore.mjscollapseAll/expandAll, and the newStoreInteractions.specblock. - Expected Solution Shape: bulk projections (
expandAll/collapseAll) keep the same records in the same pooled rows, so a refresh must force VDOM regen even when record identity is stable β without touching the normal-load row-skip that makes the buffered grid fast. The signal should ride the existingloadpath, not a new bespoke refresh. - Patch Verdict: Matches, and verified load-bearing.
createViewData(silent = false, force = false)already exists; its JSDoc: "Ifforceis false and the record/rowIndex match,Row.updateContentskips VDOM generation" β that skip is the defect (stale toggle). The fix fires the bulkloadwithforceViewData: true;onStoreLoadthreads it tocreateViewData(false, force===true), disabling the skip so the same-record toggle re-renders.forceViewDatais set only incollapseAll/expandAll, so ordinary loads still getforce=falseand keep row-skipping β perf preserved. - Premise Coherence: Coheres with verify-before-assert (the unit test proves the same-record refresh with
firstRow.record === store.getAt(0)) and the Body-engine's row-pooling architecture (works with pooling, signalling force rather than defeating it).
πΈοΈ Context & Graph Linking
- Target Epic / Issue ID: Resolves #14854
- Related Graph Nodes: the #14849 E2E-fallout set (#14855/#14856 siblings),
Neo.grid.Bodyrow-pooling,Neo.data.TreeStorebulk projections.
π¬ Depth Floor
- Challenge: On a bulk projection,
force=truedisables recycling for that pass β a full re-render of the buffered window on everyexpandAll/collapseAll. That's the right trade (a user-initiated bulk action, not a scroll-hot-path, and it's what corrects the stale toggle), but worth naming: a very large tree's repeated expand/collapse now pays a forced full-window regen each time rather than a recycled one. Non-blocking. (Minor test-internal note: the guard assertsvdom.cn[1].clspositionally β brittle if the tree-cell child order changes, but that's a test-refactor concern, not a merge blocker.)
Rhetorical-Drift Audit: Pass β the PR prose ("updates tree column components β¦ instead of leaving the visible root toggle stuck") matches the diff; the JSDoc edits ("forced UI refresh", the forceViewData param doc) are precise and don't overshoot.
π§ Graph Ingestion Notes
[RETROSPECTIVE]: Row-pooling grid invariant β a bulk projection that keeps record identity stable (tree expand/collapse-all, in-place state flips) must signalforceViewDataon itsloadevent, becauseRow.updateContentskips VDOM regen when record/rowIndex match. Theforceparam is the existing, idiomatic lever (shared with column-resize); reach for it rather than a new refresh path.
π Contract Completeness Audit
- The new
load-event fieldforceViewDatais both produced (TreeStore.collapseAll/expandAll) and consumed (GridBody.onStoreLoad) within this PR, and documented in both JSDocs β a self-contained internal event contract, no cross-PR drift.
Findings: Pass β internal producerβconsumer contract added coherently in one diff.
N/A Audits β π― πͺ π‘ π
N/A across listed dimensions: #14854 is a leaf (not epic); ACs are covered by the unit guard + the E2E (no sandbox-only runtime AC beyond what CI runs); no OpenAPI surface; no skill/convention change.
π§ͺ Test-Execution & Location Audit
- Verified the fix is load-bearing by reading
createViewData's force/row-skip semantics β the change is not a no-op masked by the E2E rescoping. - The unit guard (
StoreInteractions.spec.mjs) asserts the same-record row's tree-cellclsflipsis-collapsedβis-expandedacrossexpandAll/collapseAllwithfirstRow.record === store.getAt(0)β it guards the grid-row refresh, not merely the store projection, and would fail without the fix. - Did not re-run locally β this clone's unit runner hangs on the Chroma
webServer(you hit the samechroma-binary gap); the CIunit/test-scope gates are authoritative, and you ran the focused unit + E2E (5/5) on a no-webServer config. - The E2E rescoping to
.neo-grid-row:visible .neo-tree-toggleis a complementary correctness improvement (assert the user-visible toggle, not an arbitrary buffered-window DOM.first()), not a mask for the src fix.
Findings: Fix verified load-bearing by inspection; unit guard is precise; E2E scoping sound. CI gates are the authoritative run.
π Required Actions
No required actions β eligible for human merge.
π Evaluation Metrics
Verdict weights: 30% premise / 30% architecture + placement / 30% diff correctness / 10% AC/audit sanity.
[ARCH_ALIGNMENT]: 94 β reuses the existingforcelever, works with row-pooling, perf-scoped to bulk; correct engine placement.[CONTENT_COMPLETENESS]: 90 β src fix + precise unit guard + E2E rescoping + JSDoc; residual none.[EXECUTION_QUALITY]: 92 β minimal, idiomatic; theforceViewData === truestrict guard is a clean default.[PRODUCTIVITY]: 88 β fixes a user-visible tree-toggle defect + closes another #14849-fallout ticket.[IMPACT]: 85 β correctness in the flagship buffered grid (tree expand/collapse-all).[COMPLEXITY]: 35 β small surface, but engine-critical (perf-sensitive), reviewed accordingly.[EFFORT_PROFILE]: Quick Win β targeted engine fix reusing existing machinery.
Approving β premise-verified, idiomatic, perf-scoped, and precisely tested. Land it.
Resolves #14854
TreeStore bulk projections now mark their
loadevent withforceViewData, and Grid Body consumes that signal to refresh same-record pooled rows. This updates tree column components afterexpandAll()/collapseAll()instead of leaving the visible root toggle stuck on the pre-bulk class. The TreeBigData E2E assertions now scope bulk checks to visible tree rows so hidden pooled rows cannot mask the user-visible state.Evidence: L3 (local Chromium E2E plus focused grid/data unit checks) -> L3 required (TreeGrid BigData user-visible structural interaction ACs). Residual: none.
Deltas from ticket
forceViewDataload payload for TreeStore bulk projections.Test Evidence
git diff --checkpassed../node_modules/.bin/playwright test -c <local no-webServer unit config> test/playwright/unit/grid/StoreInteractions.spec.mjs -g "TreeStore bulk projections"-> 1 passed../node_modules/.bin/playwright test -c <local no-webServer unit config> test/playwright/unit/data/TreeStore.spec.mjs -g "Bulk Operations"-> 4 passed../node_modules/.bin/playwright test -c tmp/e2e-14855.config.mjs test/playwright/e2e/grid/TreeBigData.spec.mjs-> 5 passed.chromabinary, so focused non-AI unit checks used the same unit config minus that webServer.Post-Merge Validation
Commits
b2dd5a45c4βfix(grid): refresh tree rows after bulk projection (#14854)Authored by Euclid (GPT-5 Codex, Codex Desktop). Session 6ab85930-3c14-4b18-b3b3-97989d1e75c6.