Context
Graduated from the PR #12754 cross-family review (@neo-gpt REQUEST_CHANGES, empirical probes at head ca7f58049) + maintainer architectural direction: the multi-body grid SelectionModel must be grid.View-owned, NOT center-body-owned. This is the holistic version of the SM rework that #12754 only partially (and regressively) attempted.
The Problem
Container.createOrUpdateSubGrids() spreads ...me.body.initialConfig into bodyStart (Container.mjs:43-44) and bodyEnd (:78-79), so each locked body receives its own cloned selectionModel instance. The instances are kept coherent only via BaseModel.getActivePeers() fan-out + the register() "Peer State Adoption" — the fragile architecture the #9868 R&D retro condemned. Dynamic grid.body.selectionModel = <Model> changes leave the locked bodies on stale model types.
V-B-A note: user-facing multi-body selection currently works on dev — GridSelectionMultiBody.spec.mjs cross-body row-selection is green on dev (probe-confirmed, not a stale-server false-green). So this is architecture hardening, not a v13-facing regression. It is post-v13 internal architecture per #9872's "View owning body lifecycle" boundary.
gpt's empirical probes (PR #12754) — use as regression gates
{"centerType":"...RowModel","startType":"...RowModel","endType":"...RowModel","centerIsStart":false,"centerIsEnd":false}
{"afterCell":{"center":"...CellModel","start":"...RowModel","end":"...RowModel"}}The Architectural Reality + Fix
- One SelectionModel owned by
grid.View (not the center grid.Body); bodyStart/body/bodyEnd become pure render/event delegates.
createOrUpdateSubGrids() stops cloning selectionModel into the locked bodies (drop it from the initialConfig spread).
BaseModel.updateRows spans all bodies (the updateBodyRows extraction from #12754's reverted commit ca7f58049 — recover it); delete getActivePeers() + the register() Peer State Adoption.
- Rework
RowModel.onRowClick's event.body === view gating so a locked-body click is owned by the single View model.
Acceptance Criteria
Out of Scope
- Body-scroll orchestration (
syncBodies) — delivered separately (the View body-orchestration leaf / PR #12754).
Related
- Parent: #9492 (Adapt Selection Models for Split Rows). Refs #9486, #9872.
- Design: #9868 (R&D retro — the peer-SM failure analysis). Refs #9830 (the bug — works on dev today; this hardens the architecture behind it). Origin PR: #12754.
Decision Record impact
aligned-with #9868 R&D direction.
Origin Session ID: 3f9ffeb7-a284-4783-912b-f39912115d2e
Retrieval Hint: "grid.View-owned single SelectionModel eliminate per-body model construction"; PR #12754 review thread.
Context
Graduated from the PR #12754 cross-family review (@neo-gpt
REQUEST_CHANGES, empirical probes at headca7f58049) + maintainer architectural direction: the multi-body grid SelectionModel must begrid.View-owned, NOT center-body-owned. This is the holistic version of the SM rework that #12754 only partially (and regressively) attempted.The Problem
Container.createOrUpdateSubGrids()spreads...me.body.initialConfigintobodyStart(Container.mjs:43-44) andbodyEnd(:78-79), so each locked body receives its own clonedselectionModelinstance. The instances are kept coherent only viaBaseModel.getActivePeers()fan-out + theregister()"Peer State Adoption" — the fragile architecture the #9868 R&D retro condemned. Dynamicgrid.body.selectionModel = <Model>changes leave the locked bodies on stale model types.V-B-A note: user-facing multi-body selection currently works on dev —
GridSelectionMultiBody.spec.mjscross-body row-selection is green on dev (probe-confirmed, not a stale-server false-green). So this is architecture hardening, not a v13-facing regression. It is post-v13 internal architecture per #9872's "View owning body lifecycle" boundary.gpt's empirical probes (PR #12754) — use as regression gates
// Construction: all three bodies have independent RowModel instances {"centerType":"...RowModel","startType":"...RowModel","endType":"...RowModel","centerIsStart":false,"centerIsEnd":false} // Dynamic toggle (center → CellModel) leaves locked bodies stale: {"afterCell":{"center":"...CellModel","start":"...RowModel","end":"...RowModel"}}The Architectural Reality + Fix
grid.View(not the centergrid.Body);bodyStart/body/bodyEndbecome pure render/event delegates.createOrUpdateSubGrids()stops cloningselectionModelinto the locked bodies (drop it from theinitialConfigspread).BaseModel.updateRowsspans all bodies (theupdateBodyRowsextraction from #12754's reverted commitca7f58049— recover it); deletegetActivePeers()+ theregister()Peer State Adoption.RowModel.onRowClick'sevent.body === viewgating so a locked-body click is owned by the single View model.Acceptance Criteria
grid.body.selectionModelchange updates all bodies — no stale model types (gpt probe 2 inverted).GridSelectionMultiBody.spec.mjscross-body test stays green; new unit spec for body-spanningupdateRows.Out of Scope
syncBodies) — delivered separately (the View body-orchestration leaf / PR #12754).Related
Decision Record impact
aligned-with#9868 R&D direction.Origin Session ID: 3f9ffeb7-a284-4783-912b-f39912115d2e Retrieval Hint: "grid.View-owned single SelectionModel eliminate per-body model construction"; PR #12754 review thread.