Repository navigation
Description
Before submitting
- I searched existing issues and did not find a duplicate.
- I included enough detail to reproduce or investigate the problem.
Area
apps/web
Steps to reproduce
- In a thread for a git repo, send a prompt so the agent starts working.
- While the turn is running, open the Diff panel (it opens on "Changes").
- Expand a few files.
- Pick "Uncommitted" in the scope dropdown.
- Wait a few seconds without touching anything.
Expected behavior
The panel stays on "Uncommitted" until I pick another scope, and files I expanded stay expanded.
Actual behavior
A few seconds later the dropdown switches back to "Changes" on its own (about 8s in the attached recording, with no input from me). This keeps happening for as long as the turn runs, so "Uncommitted" is basically unusable mid-turn. The files I expanded also collapse again every time.
Likely cause
This looks like it came in with d1034d6 (#15005). In ChatView.tsx:
const activeThreadRef = useMemo(
() => (activeThread ? scopeThreadRef(activeThread.environmentId, activeThread.id) : null),
[activeThread],
);
// ...
useLayoutEffect(() => {
const explicitThreadRef = explicitDiffOpenRef.current;
explicitDiffOpenRef.current = null;
// Generic openings always show Changes, including tab fallbacks and thread changes.
if (diffOpen && activeThreadRef && explicitThreadRef !== activeThreadRef) {
useDiffPanelStore.getState().selectGitScope(activeThreadRef, "branch");
}
}, [activeThreadRef, diffOpen]);activeThreadRef is memoized on the whole activeThread object, and that object gets a new identity on every thread update while a turn is streaming. So each update creates a new ref, the layout effect runs again and calls selectGitScope(..., "branch"), even though the panel was already open and the thread didn't change.
The collapse reset is probably a side effect of the same thing: in DiffPanel.tsx, collapseScopeKey / codeViewMountKey are derived from the selected scope, so getting forced back to branch swaps the collapse state and remounts the code view.
Keying the memo/effect on environmentId + threadId (or activeThreadKey) instead of the thread object should make it fire only when the panel opens or the thread actually changes.
Impact
Major degradation or frequent failure
Version or commit
T3 Code (Nightly) 0.0.46-nightly.20261003.2638 (source checked at main @ a21702d)
Environment
macOS 27.2, desktop app
Logs or stack traces
Screenshots, recordings, or supporting files
Screen.Recording.2026-10-04.at.00.42.42.mov
Workaround
Wait for the turn to finish, then switch to "Uncommitted".
Activity
juliusmarminge commentedon Oct 3, 2026
Note
Grok responding on behalf of Julius.
Triage
Thanks for the clear report and the recording, @fatalist! This reproduces on current
main(8d84666), your read of the cause is right, and I didn't find a duplicate.What happens
In
ChatView(apps/web/src/components/ChatView.tsx, around line 2169),activeThreadRefis memoized on the whole thread shell object:A running turn keeps committing events, and each coalesced shell delta replaces the shell object, so the memo creates a new
{ environmentId, threadId }even though the ids haven't changed. That new ref re-runs the layout effect that forces the Changes scope (around line 2222). Its guard compares references, andexplicitDiffOpenRefis only set by a timeline click, so after you pick Uncommitted the next shell update callsselectGitScope(..., "branch"). The few seconds' delay in your recording is just the wait for the next delta.The collapsed files come from the same reset.
DiffPanelkeys the code view on acollapseScopeKeythat includes the scope, so switching back to Changes remounts it. The same effect also clears a selected turn (Latest turn or Turn N).Merged #15005 didn't add the re-run itself. It changed the forced scope from
unstagedtobranch, which is why Uncommitted is now the choice that gets overwritten.Likely fix area
activeThreadRefmemo onenvironmentIdandthreadId, the wayrouteThreadRefandChatHeaderalready do, so the effect runs only when the panel opens or the thread changes.A maintainer will decide on the fix direction.
kyrylofranko commentedon Oct 6, 2026
+1