cmux-next: chats reopen where you left them after a relaunch (cx-6bgzj)

Merged
TE
1mo ago
+380-4

Summary

Every agent chat reopened at its latest message after any relaunch (kill -9 of the app, a reboot, a normal quit), so a reader who had scrolled up lost their place. Terminals and browsers already keep theirs. Found on a fleet DEV build: I scrolled a 31-turn chat up to turn 21, ran kill -9 on the app, and it came back at the bottom.

  • Page: VirtualTranscript reports where it rests once a scroll settles (400 ms): the top row's id and the offset into it, or null at the latest message. It opens at such a place instead of the latest message when that row is loaded. Row ids come from event seqs, so they are stable across attaches. A place whose row is gone (older than the loaded window) opens at the latest message, as before.
  • App: the page sends chat.scrollAnchor with the chat's session id. The page provider answers it, the same way it answers pane.edit, and keeps the place per chat in agent-scroll-anchors.json beside the launch snapshot, capped at the 500 most recent chats. Before it attaches, the page reads the place back with chat.scrollAnchor.get, so the first rows open there.

AgentPaneModel is over its type budget on base, so it is untouched: the ops never reach the model.

Testing

  • webviews/test/transcript-scroll-restore.test.tsx: a scrolled-up transcript reports its place, a new transcript opened there shows the same offset, and back at the latest message the place is forgotten. A missing row opens at the latest message. Red before the page change (1 fail), green after.
  • ChatScrollRestoreTests (CmuxNextAgentPaneTests) goes through the page ops AgentPageProvider serves. A chat.scrollAnchor from one run comes back from disk through the next run's chat.scrollAnchor.get for the same chat. It does not come back for another chat, it is forgotten at the latest message, and an op without a chat is refused. Fleet Swift suites: red on the test commit, green on the head (receipts below).
  • bun run check, bun run typecheck, test/ui-rules.test.ts, and the jump-to-latest, range and unsent-draft tests all pass.

Changelog

  • Fixed: Agent chats reopen where you left them after a relaunch or a crash, instead of at the latest message.

🤖 Generated with Claude Code