What shipped
- Unread conversations always surface. The inbox previously loaded a recency window of conversations, so an unread chat whose last message was older than the window was invisible until you paged down to it. The first inbox page now runs a bounded second query for all unread, non-archived conversations and merges them in — backed by a new partial database index so the query stays fast at any workspace size.
- Virtualized conversation list. The sidebar list now renders through a windowed virtualizer: only visible rows exist in the DOM, so lists of thousands of conversations scroll smoothly. Loading more is triggered as you approach the end of the list.
- Realtime refreshes preserve your place. Background refreshes previously reset the list to the newest page, silently dropping conversations you had scrolled in. Older conversations you paged in now survive refreshes.
- Load-more robustness. Paging now skips past pages that contain only already-loaded conversations (possible when unread overlay rows overlap the paging window), so infinite scroll can't stall.
Data & privacy
No new data is collected. The unread overlay query is workspace-scoped, respects archive state, and is capped. The new index contains only currently-unread, non-archived conversation references.
Verification
pnpm --filter @repo/database test— 718 passedpnpm vitest run(inbox workspace, sidebar, page suites) — 97 passedapps/appfulltsc --noEmit— cleanpnpm lint— cleanpnpm release:hygiene