fix(web): keep newer titles when an untouched header rename ends#23188

open2
main
GitHub fork: r13/a012-preserve-newer-titles-after-untouched-re
opened10d agobyOonly21mil
View on GitHubTwo-way sync enabledPR last imported 3h ago

Problem

An untouched rename in the chat header can overwrite a newer thread title. Start renaming "New thread", rename the same thread to "Fix login redirect" in another client, then click away without typing. The first client restores "New thread". Enter has the same result.

The input keeps the title captured when editing began, but the commit handler compares it with the latest title. A concurrent update turns an untouched edit into a stale write. Automatic titling can produce the same sequence.

Change

Compare the submitted title with renamingTitle, the baseline already captured for the rename session. Keep the existing activeThreadTitle fallback. An untouched edit becomes a no-op; an intentional edit still saves.

Add one deterministic browser regression covering blur and Enter, plus an intentional-edit control after a concurrent update. It checks persisted title behavior without timers, frame waits or mock-call assertions.

Scope and approval

This qualifies for CONTRIBUTING.md's small, focused obvious-bug exception without a prior issue. The change reuses existing state in the header's commit handler. Web and desktop share this header; mobile uses a separate implementation. The sidebar rename editors (SidebarThreadRow and LegacySidebar) compare against the live title the same way. They keep the typed value in state with no captured baseline, so they need their own change and are not touched here.

Verification

pnpm exec vp test run src/components/chat/ChatHeader.browser.test.tsx --project browser, from apps/web: the same regression fails both cases against the base component with expected "Fix login redirect", received "New thread". Both cases pass with the candidate, including the genuine-edit control.

pnpm exec vp lint apps/web --report-unused-disable-directives, changed-file pnpm exec vp fmt --check, and pnpm --filter @t3tools/web typecheck passed. Package lint reported existing warnings outside the changed files. git diff --check passed.

Focused regression output, failing on base and passing on the candidate.

Browser regression fails on base and passes on candidate

Production builds used local commits e64766c56a (base) and cc9cf576e9 (candidate), whose ChatHeader.tsx and regression test are byte-identical to this branch's base and head.

Two real browser clients opened each build on macOS. Client 1 opened the title editor. Client 2 renamed that thread through the UI. Backend reads confirmed the update before client 1 blurred or pressed Enter. Base overwrote the newer title on both paths. Candidate retained it with the same backend update timestamp. An intentional edit propagated to client 2. No provider run was needed. Services, tabs and disposable state were cleaned up.

Base, after the concurrent update: the sidebar shows the newer title while the input still holds its captured value.

Base editor before blur

Base, after blur: the stale title returns.

Base loses the concurrent title

Candidate, after the same update and blur: the newer title survives.

Candidate preserves the concurrent title

Enter shows the same before/after difference.

Base loses the title on Enter

Candidate preserves the title on Enter

Not checked:

  • Native desktop shell, Linux production browser, mobile clients and the two sidebar rename editors (unchanged).
  • Provider-driven automatic titling; the two-client flow exercises the same concurrent metadata update.
  • Broad repository tests and candidate CI. The branch merges cleanly with current main.

Prior PRs: #11830 by Julius Marminge added the current header editor. #7817 by Utkarsh Patil introduced double-click rename. Utkarsh's closed #7822 fixed a stale-title flash after an intentional rename, a different bug; this PR reuses none of it. Nearby #21444 by Matt Stone and #22352 by Mantas Kantautas change separate menu actions. No same-fix proposal was found.

Generated with GPT-6.1 Sol in T3 Code Nightly

Checks

22 successful · 12 skipped
All checks passed
709a06e

Added 2 commits

  • test(web): blur rename into a non-button target709a06e
  • fix(web): preserve newer titles after untouched rename sessionsf05a890
Synced from GitHub

Approvability

Verdict: Approved at 709a06e

Macroscope's review found this PR approvable — This is a narrowly scoped header rename bug fix that prevents untouched edits from overwriting newer concurrent titles while retaining intentional edits. The production change is minimal and is covered by a focused browser regression test.

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

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: Advanced
  • Run ID: 7921c63d-2fe9-4bd6-a685-2f09fc85c08c
📥 Commits

Reviewing files that changed from the base of the PR and between b5a226e49c52ecab4ddc2d678a7012d97e651a6a and 709a06e1e30969b9c9363ce041345da642959021.

📒 Files selected for processing: 2
  • apps/web/src/components/chat/ChatHeader.browser.test.tsx
  • apps/web/src/components/chat/ChatHeader.tsx

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 1 remain after this review.

Walkthrough

ChatHeader now compares a rename against the active rename title when available. Browser tests cover blur and Enter behavior when a concurrent update changes the thread title.

Changes: Chat rename behavior

Layer / File(s)Summary
Rename commit and concurrency tests
apps/web/src/components/chat/ChatHeader.tsx, apps/web/src/components/chat/ChatHeader.browser.test.tsx
commitRename uses the active rename title for comparison when available. Browser tests verify that untouched renames retain concurrent title updates and edited renames persist the edited value.

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

Change: Bug fix

Suggested reviewers: juliusmarminge

Merge Risk: External image Minimal · up to 709a0

The rename change appears mergeable after normal checks; the reviewed paths preserve newer titles when an untouched rename ends.

Pre-merge checks: Passed 4
Check nameStatusExplanation
Title checkPassedThe title clearly and concisely describes the main fix: preserving newer thread titles when an untouched header rename ends.
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.
Description checkPassedThe description follows the repository template closely. It has the Problem, Change, Scope and approval, and Verification sections, and each is substantively filled in. The Problem section explains th…
Full details: Description check

Explanation

The description follows the repository template closely. It has the Problem, Change, Scope and approval, and Verification sections, and each is substantively filled in. The Problem section explains the stale-write bug with reproduction steps (start renaming "New thread", rename in another client to "Fix login redirect", then blur or press Enter). The Change section explains the baseline comparison against renamingTitle and keeps the activeThreadTitle fallback. The Scope and approval section claims the small, focused obvious-bug exception and explains why sidebar editors are excluded. The Verification section gives the exact test command, lint, format, typecheck, and diff-check results, and lists what was not checked. Before and after screenshots and a manual two-client check are included. The template asks for the model and harness at the end when an agent was used. The description ends with "Generated with GPT-6.1 Sol in T3 Code Nightly", which covers that request. The description also covers many items beyond the template, such as prior PR history. These are extra context and do not break the required structure.

Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Note

Written by gpt-6.1-sol on behalf of Maria

Verified in a real dev environment

verified as-is at 709a06e1e30969b9c9363ce041345da642959021 on a disposable linux vm. github #23171 maps to git.cafe #23188. no code changes or pushes were needed.

used the repo's playwright dependency with /usr/bin/google-chrome, a real git repository added through the app, and real codex gpt-6.1-sol turns. no mocks, fixtures, replay provider, or seeded conversation data. main and the pr used separate app state and ran one dev server at a time.

  • reproduced on github/main (32ecd71726) in ../main, after vp i: client 1 opened the header editor on Title Verification Ready; client 2 renamed it to Fix login redirect; untouched blur and Enter both restored the stale title.
  • installed and ran the exact pr head with vp i and a background vp run dev --home-dir /home/user/t3code/.t3. the same two-client blur and Enter flows retained Fix login redirect. reload confirmed persistence.
  • opened the header editor immediately after sending the real codex turn. automatic titling changed the sidebar to Title Verification while the editor retained the original prompt-derived title. untouched blur preserved the automatic title.
  • intentional edits still saved after a concurrent title update and propagated to the second client. Escape discarded a typed draft and preserved the concurrent title, including after reload.
  • the existing ChatHeader.browser.test.tsx passed both cases on blacksmith. the first attempt needed chromium installed on the remote worker; after installing it there, the focused run passed. the pr's reported CI has 34 green or skipped checks, 0 failing, 0 pending.

short runtime transcript from the real provider event log:

text
112:10:51.257Z turn/start model=gpt-6.1-sol
212:10:56.541Z item/completed text="title verification ready."
312:10:56.734Z turn/completed status=completed error=null
4blacksmith: ChatHeader.browser.test.tsx (2 tests), 1 file passed

main after untouched blur, showing the stale title restored:

main restores the stale title after blur

pr after the matching blur, showing the newer title retained:

pr preserves the newer title after blur

automatic titling while the untouched editor remains open:

real codex automatic title arrives during header editing

automatic title survives untouched blur

short recording: a second client changes the sidebar title while the header editor is untouched; blur preserves it; an intentional rename then saves. inspected the exported clip and checked playback and seeking of the uploaded video in t3's browser.

concurrent title survives blur and intentional rename still saves

Not verified

native electron shell, macos/windows, native ios/android, remote relay/tunnel connections, and other providers were not exercised on this linux vm. desktop shares this web header; mobile and the sidebar rename editors have separate implementations outside this diff. no repo-wide checks were run. this pass verifies the existing header entry point, persistence, cross-client updates, and codex automatic titling.

media rendering limitation: git.cafe renders external media as links. github displays the four screenshots inline, but its image-markdown renderer does not play the mp4 embed. the uploaded clip itself was played and seeked successfully in t3's browser.