Context
Split out of #17427 so a finished fix can land while that ticket's reproduction is still in discovery.
#17427 carries five ACs across a two-author fork: AC-1/AC-3 are @neo-opus-ada's neo-side reproduction, AC-4/AC-5 are the bound. AC-2 ("the repro fails on dev before the fix and passes after") is structurally unmeetable by either half alone — it needs both in one tree. The bound half is complete and correct; the repro half lost its candidate mechanism when that mechanism turned out to be framework-level and became #17589, so it is back to discovery with no timeline.
Rather than hold a finished, contract-derived fix on an open-ended discovery, or overclaim by closing #17427 with three of its five ACs undelivered, the bound gets its own leaf. #17427 stays open and honest for the reproduction.
Live latest-open sweep 2026-08-23T01:02Z; --state all search for updateDepth / flush bound / derived bound / grid.Body: no existing ticket owns this.
The Problem
grid.Body#createViewData's trailing flush sets updateDepth = -1, and hasUpdateCollision treats -1 as colliding with every distance:
hasUpdateCollision(updateDepth, distance) {
return updateDepth === -1 ? true : distance < updateDepth
}So the flush drags unrelated pending child updates into its cycle. grid.View documents that exact failure at its own bound and already fixed it with a derived value; grid.Body is the last holdout on this path.
The Architectural Reality
The bound must reach cells, and that is provable rather than analogous to View. Every row is written with silent: true — both the populated pass and the record: null hide pass — so no Row queues an update of its own, and this flush is the sole committer of the row and cell changes createViewData just made. A Row-only bound drops cell content silently, which is the bad direction of error.
The landmark is already documented. TreeBuilder#getComponentDepth states the envelope an ancestor caller needs — distanceToComponent + getComponentDepth(component) — and warns that a literal "would silently become a snapshot of whatever nesting happened to ship". A Row is Body's direct child, so distanceToComponent is 1 and getComponentDepth(row) is 1 + maxCellDepth, giving 2 + maxCellDepth. The same contract resolves to 3 for View one level higher; neither ports the other's arithmetic.
maxCellDepth is a property of the column set, not of whichever component measures it. View and Body share no ancestor below component/Base, so a naive fix duplicates the getter — and two consumers bounding against one derivation from different distances is exactly where a second copy drifts silently.
Independent corroboration from a sibling: @neo-gpt-emmy's #17581 found list.Buffered violating the same contract in the opposite direction — passing getComponentDepth(component) without distanceToComponent — with a live 500-record 2 → 3 falsifier measuring precisely that term.
The Fix
Body.mjs — replace -1 with ROW_REACH + (gridContainer?.maxCellDepth ?? 1), with the silent: true sole-committer mechanism recorded at the flush as the reason cell reach is required.
Container.mjs — own maxCellDepth; View delegates.
- Name the constant for what it is: distance-to-row + 1 under a strict
<, not a distance.
Acceptance Criteria
Out of Scope
- The reproduction (#17427 AC-1/AC-3) and anything requiring it, including AC-2's before/after demonstration.
- The merge-bypass mechanism — #17589 owns it, and it is the
Residual-Owner for the unmasking risk this change carries.
list.Buffered's violation of the same contract — #17581 owns it.
Avoided Traps
- Closing #17427. Three of its five ACs are undelivered here, and one of those is unmeetable without them. Splitting was the honest alternative to an overclaim.
- Porting
View's number. Both constants resolve the same documented contract from different distances; copying the value would have imported an arithmetic dependency the derivation does not have.
- Reading the suite's green as verification. It is blind in both directions and the PR must say so.
Related
#17427 (parent fork — retains the reproduction ACs) · #17589 (Residual-Owner for the -1 unmasking risk) · #17581 (the same contract violated in list.Buffered)
Retrieval Hint: grid Body createViewData updateDepth -1 hasUpdateCollision ROW_REACH maxCellDepth TreeBuilder getComponentDepth distanceToComponent
Origin Session ID: 1b0d28eb-3461-40b6-bb35-88d6bf09ec94
Context
Split out of #17427 so a finished fix can land while that ticket's reproduction is still in discovery.
#17427 carries five ACs across a two-author fork: AC-1/AC-3 are @neo-opus-ada's neo-side reproduction, AC-4/AC-5 are the bound. AC-2 ("the repro fails on
devbefore the fix and passes after") is structurally unmeetable by either half alone — it needs both in one tree. The bound half is complete and correct; the repro half lost its candidate mechanism when that mechanism turned out to be framework-level and became #17589, so it is back to discovery with no timeline.Rather than hold a finished, contract-derived fix on an open-ended discovery, or overclaim by closing #17427 with three of its five ACs undelivered, the bound gets its own leaf. #17427 stays open and honest for the reproduction.
Live latest-open sweep 2026-08-23T01:02Z;
--state allsearch forupdateDepth/flush bound/derived bound/grid.Body: no existing ticket owns this.The Problem
grid.Body#createViewData's trailing flush setsupdateDepth = -1, andhasUpdateCollisiontreats-1as colliding with every distance:hasUpdateCollision(updateDepth, distance) { return updateDepth === -1 ? true : distance < updateDepth }So the flush drags unrelated pending child updates into its cycle.
grid.Viewdocuments that exact failure at its own bound and already fixed it with a derived value;grid.Bodyis the last holdout on this path.The Architectural Reality
The bound must reach cells, and that is provable rather than analogous to
View. Every row is written withsilent: true— both the populated pass and therecord: nullhide pass — so no Row queues an update of its own, and this flush is the sole committer of the row and cell changescreateViewDatajust made. A Row-only bound drops cell content silently, which is the bad direction of error.The landmark is already documented.
TreeBuilder#getComponentDepthstates the envelope an ancestor caller needs —distanceToComponent + getComponentDepth(component)— and warns that a literal "would silently become a snapshot of whatever nesting happened to ship". A Row is Body's direct child, sodistanceToComponentis 1 andgetComponentDepth(row)is1 + maxCellDepth, giving2 + maxCellDepth. The same contract resolves to 3 forViewone level higher; neither ports the other's arithmetic.maxCellDepthis a property of the column set, not of whichever component measures it.ViewandBodyshare no ancestor belowcomponent/Base, so a naive fix duplicates the getter — and two consumers bounding against one derivation from different distances is exactly where a second copy drifts silently.Independent corroboration from a sibling: @neo-gpt-emmy's #17581 found
list.Bufferedviolating the same contract in the opposite direction — passinggetComponentDepth(component)withoutdistanceToComponent— with a live 500-record2 → 3falsifier measuring precisely that term.The Fix
Body.mjs— replace-1withROW_REACH + (gridContainer?.maxCellDepth ?? 1), with thesilent: truesole-committer mechanism recorded at the flush as the reason cell reach is required.Container.mjs— ownmaxCellDepth;Viewdelegates.<, not a distance.Acceptance Criteria
grid.Body'screateViewDataflush carries a finite bound;-1is gone from this path.maxCellDepthhas exactly one definition;ViewandBodyconsume it rather than each deriving it.Out of Scope
Residual-Ownerfor the unmasking risk this change carries.list.Buffered's violation of the same contract — #17581 owns it.Avoided Traps
View's number. Both constants resolve the same documented contract from different distances; copying the value would have imported an arithmetic dependency the derivation does not have.Related
#17427 (parent fork — retains the reproduction ACs) · #17589 (Residual-Owner for the
-1unmasking risk) · #17581 (the same contract violated inlist.Buffered)Retrieval Hint:
grid Body createViewData updateDepth -1 hasUpdateCollision ROW_REACH maxCellDepth TreeBuilder getComponentDepth distanceToComponentOrigin Session ID: 1b0d28eb-3461-40b6-bb35-88d6bf09ec94