You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Found by Mahmoud during 0.106.2 staging QA, root-caused in code. Follow-up to #5589/#5530. Distinct from #5609 (that is about a tab that never regains focus; this one reproduces WITH focus).
Reproduction
Open the same session in two tabs.
Send a message in tab 1.
Switch to tab 2.
Tab 2 shows neither the new user message nor the answer, indefinitely. Archiving and unarchiving the session (which remounts the conversation) is currently the only way to make it converge.
Root cause
For an already-mounted session, only two things ever refetch the transcript (web/oss/src/components/AgentChatSlice/hooks/useSessionHydration.ts):
Mount. The hydration effect and the SWR revalidation effect are both keyed [sessionId] and documented "Once per mounted session tab." They ran when the tab first opened and never run again. Nothing re-runs adoption on window focus; the "reconcile on focus" from the [fix] Stop agent sessions breaking when open in two places [AGE-4004] #5589 design covers the session LIST (projectSessions.ts), not a mounted transcript.
The remote-run poll, only while runningElsewhere is true. And it has two sharp edges:
The first fetch is scheduled with timer = setTimeout(poll, delay) where delay starts at REMOTE_RUN_POLL_MS (15s). No immediate tick when the run is first noticed.
The effect cleanup cancels the pending timer the moment runningElsewhere flips false. A run that ends before the next tick discards the pending fetch. There is no final catch-up fetch on the running→idle transition.
Play the reproduction through that: if the answer finished before the tab switch, liveness reports nothing running, the poll never arms, and no trigger remains. If the run was still live at the switch, the poll arms at +15s, most answers finish sooner, the flag flips, and the cleanup cancels the first fetch before it ever fired. Either way the tab fetched nothing and stays stale until a remount.
So for short turns (the common case) a second open tab converges NEVER rather than late. The watermark adoption guard itself is correct — this is purely a triggering gap.
Why it was not caught in release QA
The 0.106.2 QA proved adoption on reload (planted stale cache + watermark, recovered correctly) and cross-tab stream survival. It never tested "already-open second tab, short finished turn, focus switch, no interaction", which is this exact path.
Candidate fixes, smallest first
Fire the first poll tick immediately when runningElsewhere flips true (call poll() instead of arming the 15s timer first). One line. Covers the switched-while-running case.
One final adoption fetch on the running→idle transition (a small effect on the falling edge, since the cleanup cannot await). A few lines. Covers the run-ended-before-the-tick case.
Re-run the guarded adoption on window focus for mounted sessions. Broadest coverage (also fixes the run-finished-before-switch case without relying on liveness timing), but adds a full record-log fetch per focus, which is the request-budget question Arda already weighed in this design. His call.
Fixes 1+2 together close the reported reproduction. Fix 3 is the complete answer and interacts with the #5609 decision.
Severity
Not a regression: on 0.106.1 this tab was stuck permanently (broken message-count guard, no strip, no poll). 0.106.2 is strictly better. But multi-tab convergence was the headline of #5589, and the most common interaction (short turns) still does not converge without a remount, so the feature underdelivers its promise until this lands.
Found by Mahmoud during 0.106.2 staging QA, root-caused in code. Follow-up to #5589/#5530. Distinct from #5609 (that is about a tab that never regains focus; this one reproduces WITH focus).
Reproduction
Root cause
For an already-mounted session, only two things ever refetch the transcript (
web/oss/src/components/AgentChatSlice/hooks/useSessionHydration.ts):[sessionId]and documented "Once per mounted session tab." They ran when the tab first opened and never run again. Nothing re-runs adoption on window focus; the "reconcile on focus" from the [fix] Stop agent sessions breaking when open in two places [AGE-4004] #5589 design covers the session LIST (projectSessions.ts), not a mounted transcript.runningElsewhereis true. And it has two sharp edges:timer = setTimeout(poll, delay)where delay starts atREMOTE_RUN_POLL_MS(15s). No immediate tick when the run is first noticed.runningElsewhereflips false. A run that ends before the next tick discards the pending fetch. There is no final catch-up fetch on the running→idle transition.Play the reproduction through that: if the answer finished before the tab switch, liveness reports nothing running, the poll never arms, and no trigger remains. If the run was still live at the switch, the poll arms at +15s, most answers finish sooner, the flag flips, and the cleanup cancels the first fetch before it ever fired. Either way the tab fetched nothing and stays stale until a remount.
So for short turns (the common case) a second open tab converges NEVER rather than late. The watermark adoption guard itself is correct — this is purely a triggering gap.
Why it was not caught in release QA
The 0.106.2 QA proved adoption on reload (planted stale cache + watermark, recovered correctly) and cross-tab stream survival. It never tested "already-open second tab, short finished turn, focus switch, no interaction", which is this exact path.
Candidate fixes, smallest first
runningElsewhereflips true (callpoll()instead of arming the 15s timer first). One line. Covers the switched-while-running case.Fixes 1+2 together close the reported reproduction. Fix 3 is the complete answer and interacts with the #5609 decision.
Severity
Not a regression: on 0.106.1 this tab was stuck permanently (broken message-count guard, no strip, no poll). 0.106.2 is strictly better. But multi-tab convergence was the headline of #5589, and the most common interaction (short turns) still does not converge without a remount, so the feature underdelivers its promise until this lands.