LiveInboxPreview.tsxfeat(onboarding): a setup flow that shows you the product while you configure it Adds `/onboarding-setup` — a sidebar-driven flow over the four surfaces a new user actually has to configure (Inbox, sub-inboxes, Tasks, Pipeline), each step paired with a live preview of the real product rather than a screenshot of it. Reachable from the profile menu as "Set up Cedar". Two inbox-creation races surfaced by clicking through the template gallery are fixed on the way, since the flow leans on that path hard: - Per-mutation `invalidateQueries` lost rows. Create #1's refetch was issued after #2 had written its optimistic row, so a server list predating #2 landed last and overwrote it — the row vanished and the template card flipped back to unselected. Now the last create to settle does the single refetch. - Two adds fired back to back both read the cache before either had written to it and claimed the same position, so a run of template clicks piled up at one index and the tab strip reordered itself on refetch. Positions are now issued from a carried-forward high-water mark. A failed create drops only its own row instead of restoring a whole snapshot, and `removeInbox` no longer swallows the rejection — callers holding their own selected-state need to hear about it, or the row returns while the card stays deselected. Co-Authored-By: Claude Opus 5 (1M context) <<email>>Aug 31, 2026, 10:48 PMmock-threads.tsfeat(onboarding): a setup flow that shows you the product while you configure it Adds `/onboarding-setup` — a sidebar-driven flow over the four surfaces a new user actually has to configure (Inbox, sub-inboxes, Tasks, Pipeline), each step paired with a live preview of the real product rather than a screenshot of it. Reachable from the profile menu as "Set up Cedar". Two inbox-creation races surfaced by clicking through the template gallery are fixed on the way, since the flow leans on that path hard: - Per-mutation `invalidateQueries` lost rows. Create #1's refetch was issued after #2 had written its optimistic row, so a server list predating #2 landed last and overwrote it — the row vanished and the template card flipped back to unselected. Now the last create to settle does the single refetch. - Two adds fired back to back both read the cache before either had written to it and claimed the same position, so a run of template clicks piled up at one index and the tab strip reordered itself on refetch. Positions are now issued from a carried-forward high-water mark. A failed create drops only its own row instead of restoring a whole snapshot, and `removeInbox` no longer swallows the rejection — callers holding their own selected-state need to hear about it, or the row returns while the card stays deselected. Co-Authored-By: Claude Opus 5 (1M context) <<email>>Aug 31, 2026, 10:48 PMPreviewInbox.tsxfeat(onboarding): a setup flow that shows you the product while you configure it Adds `/onboarding-setup` — a sidebar-driven flow over the four surfaces a new user actually has to configure (Inbox, sub-inboxes, Tasks, Pipeline), each step paired with a live preview of the real product rather than a screenshot of it. Reachable from the profile menu as "Set up Cedar". Two inbox-creation races surfaced by clicking through the template gallery are fixed on the way, since the flow leans on that path hard: - Per-mutation `invalidateQueries` lost rows. Create #1's refetch was issued after #2 had written its optimistic row, so a server list predating #2 landed last and overwrote it — the row vanished and the template card flipped back to unselected. Now the last create to settle does the single refetch. - Two adds fired back to back both read the cache before either had written to it and claimed the same position, so a run of template clicks piled up at one index and the tab strip reordered itself on refetch. Positions are now issued from a carried-forward high-water mark. A failed create drops only its own row instead of restoring a whole snapshot, and `removeInbox` no longer swallows the rejection — callers holding their own selected-state need to hear about it, or the row returns while the card stays deselected. Co-Authored-By: Claude Opus 5 (1M context) <<email>>Aug 31, 2026, 10:48 PM