Since widget cells became content-measured (packVertically in client/src/components/dashboard/DashboardGrid.jsx), y and h carry two contradictory jobs. The renderer packs in PIXELS and treats y as reading order only; but placeAndCompact still resolves rectangle collisions on {x,y,w,h}, reflowToOrder still tracks rowMaxH, and GRID_ROW_MAX still clamps y as a position. toPackSpace exists purely to reconcile the two, so every gesture round-trips pixels → rows → compact → rows to keep them agreeing. Not a correctness bug — the round-trip is what makes them agree — but anyone touching drag has to hold both models at once.
Fix shape: demote the persisted shape to { id, x, w, order, h?, fixedH? }, delete overlaps + the y-compaction entirely, and let the pack own vertical placement outright. Keep h as the first-paint/older-client fallback (that compatibility story is the reason it survives at all — see the fixedH note in the dashboard CLAUDE.md). It needs a migration in scripts/migrations/ that rewrites each stored layout's grid to the new shape (data/dashboard-layouts.json, plus the seven DEFAULT_LAYOUTS/INTENT_LAYOUTS grids in server/services/dashboardLayouts.js) and a version-gated read so an install that has not upgraded still gets usable geometry.
Surfaced by the /simplify altitude review.
Migrated from PLAN.md by /do:replan --issues.
Since widget cells became content-measured (
packVerticallyinclient/src/components/dashboard/DashboardGrid.jsx),yandhcarry two contradictory jobs. The renderer packs in PIXELS and treatsyas reading order only; butplaceAndCompactstill resolves rectangle collisions on{x,y,w,h},reflowToOrderstill tracksrowMaxH, andGRID_ROW_MAXstill clampsyas a position.toPackSpaceexists purely to reconcile the two, so every gesture round-trips pixels → rows → compact → rows to keep them agreeing. Not a correctness bug — the round-trip is what makes them agree — but anyone touching drag has to hold both models at once.Fix shape: demote the persisted shape to
{ id, x, w, order, h?, fixedH? }, deleteoverlaps+ the y-compaction entirely, and let the pack own vertical placement outright. Keephas the first-paint/older-client fallback (that compatibility story is the reason it survives at all — see thefixedHnote in the dashboard CLAUDE.md). It needs a migration inscripts/migrations/that rewrites each stored layout's grid to the new shape (data/dashboard-layouts.json, plus the sevenDEFAULT_LAYOUTS/INTENT_LAYOUTSgrids inserver/services/dashboardLayouts.js) and a version-gated read so an install that has not upgraded still gets usable geometry.Surfaced by the /simplify altitude review.
Migrated from PLAN.md by /do:replan --issues.