LiveConnection WS Client
src/lib/offline/live.ts is the client end of event push (ADR-011). It holds the live WebSocket to the user’s SyncInbox and, on each signal, triggers the existing delta-read reconcilers — the socket replaces the polling timer, not the data path.
Key pieces
Section titled “Key pieces”createLiveConnection(deps)— opens/closes the socket on lifecycle (foreground + online + signed-in), runs a catch-up?sinceread on connect, and reconnects with backoff.reconnectDelayMs(...)— backoff with jitter, capped atRECONNECT_CAP_MS(30 s).createSignalCoalescer(...)— debounces bursts per surface (~500 ms) so many signals collapse into one refresh.mapSurfaceTags(tags, active)— maps signal surface tags to the surfaces the client should refresh.- Self-mutation suppression —
noteLocalMutation(tags)records the surfaces a local write just touched;takeUnsuppressedTags(tags)filters those out of an incoming signal so a client does not redundantly re-read its own change.SYNC_STREAM_PATHis/api/v1/sync/stream. - State —
getLiveState()/subscribeLiveState(listener)expose transport state (live / reconnecting-fallback / offline) for the status UI.
Fallback
Section titled “Fallback”While the socket is down, a slow polling fallback (PollController, src/lib/offline/poll.ts) drives refreshes, and every reconnect performs a catch-up read — so convergence and offline-first are preserved regardless of socket health (ADR-006 → ADR-011).
Related: SyncInbox Durable Object (the server end), Sync-Core Reconcilers (what a signal triggers), Poll Controller (the fallback).