Group-as-event, part A — explicit groupId membership, FORM/BREAK on snap drop
Replaces proximity-inferred grouping (computeGroups union-find) with event-driven membership. groupId on TileLayoutEntry is the source of truth; a group forms when a tile snaps flush on drop, breaks when dragged >BREAK_TOL away from all group mates.
v101.0.4a2026-06-01
·groupId?: string added to TileLayoutEntry — tiles sharing a groupId are one persistent cluster
·deriveGroups(tiles): geometry-from-membership (same TileGroup shape); membership from groupId buckets, not union-find adjacency inference
·reconcileMembershipOnDrop: BREAK (>30px from all group mates → clear groupId, dissolve if 1 remaining) + FORM (flush-adjacent to non-member → join/create/merge via crypto.randomUUID())
·FloatingTile.onUp calls reconcileMembershipOnDrop after snap commit (positions final)
·computeGroups deleted; tileGrouping feature flag removed (had no remaining consumer)