Conversation lab (Mac): bound the loaded window as messages arrive, not only on scroll
Summary
The Chief chat on the Mac only trimmed its loaded message window when the reader finished a scroll. A chat left open at the bottom never scrolls, so every arriving message stayed loaded, and each update walks the whole window. It slows down the longer the chat stays open.
Now a live arrival past ConversationStore.windowTrimThreshold (1500) schedules the same resting-reader trim (trimHistoryIfResting) on the next main-actor turn. It keeps the newest 1000. The trim is unchanged: it refuses while the reader is scrolled up, sending, replying, editing or has a thread open, and it keeps quoted, unread and unacknowledged messages.
This is the leftover from the "Paginate unbounded lists" task (a16 report, "Chief chat (iOS and Mac): loaded window only grows"). The iOS half went straight to feat-cmux-next under the iOS rule.
Changelog
Fixed: A Chief chat left open on the Mac no longer gets slower as messages arrive.
Tests
MacConversationWindowBoundTests.liveArrivalsWhileRestingAtTheBottomBoundTheWindow: applies 1510 live messages to an open conversation resting at the bottom, then checks the window is back to 1000 or fewer.
- Red on 099e5723 (test only): see the fleet receipt below.
- Green on the head: see the fleet receipt below.
Observed / Not run
Fleet receipts are posted as comments. Not run: a live Chief chat open for days on a real Mac.
HOLD: user dogfoods before merge.
🤖 Generated with Claude Code
![Autofix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark-3x.png)
Open in [code]smith · Need help on this PR? Tag @codesmith-bot with what you need.
Summary by cubic
Fixes the Chief chat on Mac trimming the loaded message window only at scroll end, so a chat left open at the bottom grew without limit as messages arrived and every update walked the whole window.
Live arrivals past ConversationStore.windowTrimThreshold (1500) now schedule the same resting-reader trim (trimHistoryIfResting) on the next main-actor turn, keeping the newest 1000. The trim still backs off while the reader is scrolled up, sending, replying, editing, or has a thread open, and preserves quoted, unread, and unacknowledged messages. Adds a regression test for an open conversation resting at the bottom receiving 1510 live messages.