Close the last lineup sync gaps from review

Codex's review of c50788c..16f8ad3 left three items.

- Shared-landing undo reached the empty-group write path. Place A, place
  B onto A's landing, delete A, hydrate (the surviving landing is renamed
  to B's link id), undo: A's link came back pointing at nothing and the
  projection authored A with items: [].
  - A deletion now records every endpoint of the removed links, shared
    ones included, and an addition records both endpoints even when
    pinned. Graph-action replay only inserts what is missing, so a
    surviving landing keeps its current state and a renamed one is
    recreated under its original id (the id the projection gives it).
  - Guard: live sync never authors a lineupGroup with no items. It keeps
    what is already overlaid or queued, records the lineup as refused
    (ActivePageLiveSyncState.unsyncableLineupKeys, which puts the sync
    status in attention) and logs it once. The server's
    assertLineupPayload now rejects empty items with the existing
    INVALID_LINEUP_PAYLOAD_DATA code; the function spec and error codes
    are unchanged.
- Composite inverses. Link edits record only the scalars that changed
  plus images added and removed by id (LineUpLinkChange); visibility
  edits record only the toggles that changed (AbilityVisibilityChange).
  Undo leaves a teammate's image or toggle alone. An edit that changes
  nothing records nothing.
- Overlay cleanup ran after projection had already painted the overlay,
  so an ack refresh that already held a teammate's newer value showed the
  stale local version and the next sync wrote it back. Satisfied overlays
  (no queued, in-flight, successor, paused or attention op) are now
  dropped by dropSatisfiedOverlays before the page is projected, which
  also covers acks received while another page was active.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
c1db6b75f2Dara Adedeji committed on 9/25/2026, 5:20:33 AMparent16f8ad3
8 files changedLine totals unavailable