fix: reattach SSE on session-switch return and preserve live progress (closes #2924)#3005
Closed
franksong2702 wants to merge 22 commits into
Closed
fix: reattach SSE on session-switch return and preserve live progress (closes #2924)#3005franksong2702 wants to merge 22 commits into
franksong2702 wants to merge 22 commits into
Conversation
3e268f1 to
b929d33
Compare
added 10 commits
May 28, 2026 18:58
57437ed to
11533ae
Compare
added 6 commits
May 28, 2026 19:10
13ec8ef to
e15f827
Compare
3 tasks
Contributor
Author
|
Closing this draft in favor of the cleaner follow-up path. #2924 was closed by #3038, and the remaining live-to-final / reattach / replay / Activity lifecycle work has been repackaged into #3401 with a smaller current-master diff, updated tests, manual screenshot evidence, and green CI. This PR is now stale/conflicting and too broad to remain the active review vehicle. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Thinking Path
/api/session.runtime_journaleven though that is not an applied-SSE cursor; the backend could skip buffered queue items whenreplay=1was requested but no journal replay was available; duplicate interim boundaries with no new visible text could create Activity burst ids that had no text anchor; and final settled rendering could drop live burst metadata when final messages carried their own tool metadata.Contract Routing
Task type: runtime / streaming / recovery fix with chat-rendering UI behavior.
Touched areas:
static/sessions.jsandstatic/messages.js.api/routes.py.static/ui.js.Relevant public docs:
AGENTS.mdCONTRIBUTING.mddocs/CONTRACTS.mddocs/rfcs/README.mddocs/rfcs/webui-run-state-consistency-contract.mddocs/rfcs/turn-journal.mddocs/UIUX-GUIDE.mdDESIGN.mdContract families exercised:
Scope boundaries:
Evidence needed before Ready for review:
What Changed
Response interrupteddiagnostics out of active stream replay while preserving dead-stream behavior.recordActivityBoundary()incremented the next tool burst id but left the current text DOM stamped with the old id.activityBurstId,duration, andstarted_atas auxiliary metadata when the final message owns the settled tool metadata, without violating message-windowing ownership.tool_callsback to the previous visible assistant progress segment, so final settled rendering and session-switch reattach do not split one tool burst into multiple orphaned Activity groups.segmentStartfrom the last recorded burst anchor, select the last projected live segment, and force a fresh segment when reconnect resumes exactly at a boundary with no tail yet.INFLIGHT.lastRunJournalSeqfrom/api/session.runtime_journal; that summary is diagnostic state, not proof that the frontend applied every SSE event through that seq.Why It Matters
A long-running WebUI turn should keep the same visible timeline while the user switches sessions: progress text, the tools that followed that text, more progress text, then later tools. Reattaching should not blank the interim text, duplicate it, skip not-yet-consumed journal events, or pile all Activity groups into one unrelated block.
Verification
node --check static/ui.js static/messages.js static/sessions.jspytest -q tests/test_live_activity_timeline.py tests/test_tool_call_persistence.py tests/test_streaming_markdown.py tests/test_inflight_stream_reuse.py tests/test_run_journal_routes.py tests/test_ui_tool_call_cleanup.py tests/test_issue734_message_windowing.py— local clean heade15f8270: 131 passed.python3 -m pytest tests/test_live_activity_timeline.py tests/test_inflight_stream_reuse.py tests/test_streaming_race_fix.py -q— local clean head1a8379d9: 41 passed.python3 -m pytest tests/test_live_activity_timeline.py tests/test_inflight_stream_reuse.py tests/test_streaming_race_fix.py -q— local clean head5c2c83a2: 42 passed.python3 -m pytest tests/test_inflight_stream_reuse.py tests/test_live_activity_timeline.py tests/test_streaming_race_fix.py -q— local clean head886e7548: 46 passed.node --check static/messages.js static/ui.js static/sessions.js— local clean head886e7548: passed.pytest -q --ignore=tests/test_passkey_auth.py— local machine before the final cursor/empty-burst/final-metadata follow-up patches: 6624 passed, 62 skipped, 3 xpassed; 2 unrelatedtests/test_workspace_git.pyfailures caused by local git default branch not beingmaster.test (3.11),test (3.12), andtest (3.13)pass on commite15f8270.886e7548are pending after the latest follow-up push.Risks / Follow-ups
Model Used
OpenAI GPT-5 Codex. AI assistance was used to inspect runtime evidence, split PR scope, implement the focused fixes, run contract verification, and verify the clean branch.