A still-busy background session (one the user toggled away from) keeps
emitting updateSessionState() heartbeats — stream deltas, and especially
the 'session busy' prompt-rejection errors from auto-drained queued turns.
Each call invoked syncSessionStateToView() unconditionally, staging that
session's messages into the shared $messages view.
flushPendingViewState() guarded against the wrong session reaching the
view, but only one requestAnimationFrame is scheduled per frame and
pendingViewStateRef holds just the latest writer. So within a single
frame a background write could overwrite an already-pending foreground
write, and the stale background transcript (e.g. the red 'session busy'
rows) would render on top of whatever session the user switched to —
appearing to 'bleed' into every session.
Guard at the staging site: a session may only stage into the view when
it is the currently-active session. Background sessions still update
their own cache entry; they just never touch $messages. Pure render
fix, no behavior change to queuing, interrupt, or drain.