fix(web): thread switches show only selected thread messages#21560

merged3
main
composer-chat-14/thread-switch
opened10d agobyJJulius Marminge
View on GitHubTwo-way sync enabledPR last imported 9d ago

Switching to a thread whose history is still loading could display the previous thread’s messages beneath the newly selected title. The timeline now uses the selected thread’s cached messages, or stays empty/loading until that thread’s data arrives.

Removed only the foreign-thread fallback. The bounded selected-thread cache and current find, handoff, and paint-only guards remain intact. Rebuilt from the original contribution by @artile and @tao-io in #17142. The original fork advertises maintainer edits, but GitHub rejected the push with HTTP 403, so this is a one-layer replacement on origin. Compared the original diff against this rebuild: selected-thread caching is retained; removal of newer find, handoff, and paint-only guards is intentionally omitted.

Verification:

  • Two independent full-diff review rounds with Claude Opus 5.5 and Codex GPT-6-Sol: no code blockers. Optional removal of now-inert paint guards remains outside this fix.

  • Consolidated the thread-switch coverage from 138 to 137 cases in the existing ChatView.logic.test.ts; the cold-switch regression fails on main.

  • Focused ChatView.logic and MessagesTimeline.logic suites: 304 passed / 1 failed before the fix → 305 passed after it.

  • Four focused files including the affected browser fixtures: 311 passed. A fresh-cache, single-CPU run of the browser pair passed all 6 tests. The initial CI run exposed two existing lazy-module/highlighter fixture races; the tests now await those resources inside React act, with assertions, timeouts, and test counts unchanged.

  • Web typecheck and scoped formatting pass. Scoped lint passes with four unchanged unused-import warnings in the test file.

  • Linux web: selected B while its actual bounded-history request was held; main displayed A’s messages under B, while this revision displayed B’s loading state. Releasing the request displayed B’s transcript. Returning to cached A and B showed each selected thread’s own messages.

Matching 1280×800 captures use isolated fixture threads and a local font substitute; no transcript contents were altered in the browser. Before production matches main 1451e7c; after production is identical to final head 2c97895; the final follow-up only fixes the two browser fixtures.

Before — B selected, A’s transcript remains

Before: Thread A messages beneath the selected Thread B title

After — B selected, only B’s loading state

After: Thread B loading without Thread A messages

Before recording · After recording

Not verified: macOS, Windows, iOS, Android, Electron desktop, remote/relay/tunnel connections, or live provider handoffs. The change is in the web timeline selection path; it changes no provider or wire contracts.

Implementation: Codex GPT-6.1-Sol; tests: Codex GPT-6-Astra; independent reviews: Claude Opus 5.5 and Codex GPT-6-Sol, through T3 Code.

Checks

21 successful · 12 skipped
All checks passed
63124cc

Added 1 commit

  • fix(web): thread switches show only selected thread messages1d5341f
Synced from GitHub

Approvability

Verdict: Approved at 2c97895

Macroscope's review found this PR approvable — The production change is a small, well-scoped fix that prevents the previously viewed thread from being shown while the selected thread loads, while preserving the selected thread’s own cached timeline behavior. The remaining changes are test-only resource waits and updated coverage.

Notes:

  • No code objects were reviewed. Approvability was decided on eligibility alone.

No code changes detected at 63124cc. Prior analysis still applies.

You can add or adjust custom eligibility rules. Learn more.

Synced from GitHub

Thread transfer impact

⚠️ The latest CI run did not produce a thread transfer result for 1d5341f.

This comment will update automatically after the next completed run.

Synced from GitHub

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Path: .coderabbit.config.ts
  • Review profile: CHILL
  • Plan: Team
  • Run ID: aebc356f-aca3-4c72-8b49-615c67e0e6aa
📥 Commits

Reviewing files that changed from the base of the PR and between 2c9789522b1da66cbc31f2d47c337821889a2cc8 and 63124cc7038a13f0a1fc6a71d79364004813e507.

📒 Files selected for processing: 2
  • apps/web/src/components/ChatView.logic.ts
  • apps/web/src/components/chat/WorkflowOpeningBlock.browser.test.tsx
💤 Files with no reviewable changes: 1
  • apps/web/src/components/ChatView.logic.ts

Limit details: You’ve used all 10 included reviews currently available.

📝 Walkthrough

An uncached active thread now displays its own empty timeline while history loads. Browser tests wait for asynchronous rendering dependencies before asserting highlighted code or renewed-URL content.

Changes: Thread timeline loading

Layer / File(s)Summary
Destination-thread loading timeline
apps/web/src/components/ChatView.logic.ts, apps/web/src/components/ChatView.logic.test.ts
The resolver no longer displays another thread’s cached timeline while the active thread loads. The test expects empty entries under the destination thread’s display key and removes the remount-retention assertion.

Browser test readiness

Layer / File(s)Summary
Wait for asynchronous rendering dependencies
apps/web/src/components/chat/WorkflowOpeningBlock.browser.test.tsx, apps/web/src/components/files/AttachmentFilePreview.browser.test.tsx
The workflow test waits for the JavaScript syntax highlighter before checking highlighted code. The attachment preview test awaits the ReadOnlySourcePreview import inside act before checking the renewed URL fetch and rendered HTML.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

Possibly related PRs

  • pingdotgg/t3code#21626: Changes the same thread-switch timeline resolver behavior and its tests, using per-thread remembered entries.

Suggested reviewers: shivamhwp

Merge Risk: ⚪ Minimal · up to 63124

Switching threads no longer shows the previous thread's messages while the selected thread loads. The test changes are harmless. No merge-blocking risk was found.

Pre-merge checks: Passed 4
Check nameStatusExplanation
Title checkPassedThe title clearly and concisely describes the main web timeline fix: thread switches now show only messages from the selected thread.
Description checkPassedThe description clearly explains the problem, implementation, scope, verification results, screenshots, recordings, and unverified environments. It provides sufficient detail for review, although it d…
Linked Issues checkPassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes checkPassedCheck skipped because no linked issues were found for this pull request.
Full details: Description check

Explanation

The description clearly explains the problem, implementation, scope, verification results, screenshots, recordings, and unverified environments. It provides sufficient detail for review, although it does not use the template headings explicitly.

✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Usage-based review receipt

Note

This review was completed with usage-based billing: files reviewed beyond your plan's included limits are billed at $0.25/file. View usage-based billing.

Comment @coderabbitai help to get the list of available commands.

Added 1 commit

  • test(web): await preview and syntax highlighting resources2c97895
Synced from GitHub

Evidence for the WorkflowOpeningBlock highlighter wait in this PR, since the race doesn't reproduce on a fast machine:

  • Impact on main: all 8 of main's 8 failed CI runs among the latest 20 fail on WorkflowOpeningBlock.browser.test.tsx:103, and so do 42 of the 47 failures since 2026-10-18 20:06Z. Several open PRs are blocked on it, including #20086.
  • Timing in CI: in a failing run's log, the test started rendering at 16.58 s, and React's "A suspended resource finished loading inside a test, but the event was not wrapped in act(...)" warning arrived at 17.52 s. The cold javascript highlighter took about 0.94 s, inside vi.waitFor's 1 s window, before the block could reveal.
  • Reproduction: delaying getSharedHighlighter from @pierre/diffs by 940 ms in a copy of this test fails the unchanged test 3 of 3 runs with CI's expected null not to be null. Awaiting getSyntaxHighlighterPromise("javascript") first passes 3 of 3 with the same delay.

The full web suite (529 files) passes on 2 pinned cores on main without the delay, which is why it only shows up on CI.

Added 1 commit

  • Merge remote-tracking branch 'origin/main' into HEAD63124cc