prevLengthRef.current was never zeroed when conversationId changed,
so the first batch of messages in a new (shorter) conversation would
not trigger scrollIntoView. Reset it in the polling useEffect cleanup.
- Finding 1: add AppState::authed_get/authed_post helpers that attach
Bearer token when present; all 4 commands now use them
- Finding 2: MessageInput accepts onSent callback, calls it after
successful send; ChatPage passes refreshKey bump as onSent
- Finding 3: MessageList useEffect uses cancellation flag so stale
in-flight responses cannot overwrite a newly selected conversation
- Finding 4: scrollIntoView moved to separate effect keyed on
messages.length so scroll only fires when new messages arrive