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
[Bug]: Diff panel Working tree/Branch scopes silently empty for every in-place project — getDiffPreview workspace-root guard compares against $HOME in packaged desktop builds #4022
I searched existing issues and did not find a duplicate.
I included enough detail to reproduce or investigate the problem.
Area
apps/server
Steps to reproduce
Install a packaged desktop build (stable 0.0.28, Windows installer). In packaged builds the backend server is spawned with cwd = $HOME (apps/desktop/src/app/DesktopEnvironment.ts: backendCwd: input.isPackaged ? homeDirectory : appRoot — documented in [Bug]: Packaged builds set server cwd to $HOME; ClaudeProvider auxiliary spawns leak it past project bindings #2867), and the spawn passes no --cwd flag, so ServerConfig.cwd resolves to process.cwd() = the home directory. Verified on the live process: the backend child's cwd is C:\Users\T9.
Add any project whose repo lives outside the home directory (e.g. D:\git\<repo>) and run a thread in place (not in a t3-managed worktree).
Open the diff panel and switch the scope dropdown to Working tree or Branch changes.
Expected behavior
The panel shows the working-tree / branch diff of the project's repository, as those scopes describe.
Actual behavior
The panel silently renders empty for every in-place project, regardless of repo size or state. Two-step failure:
ReviewService.getDiffPreview calls assertWorkspaceBoundCwd, which only accepts a cwd inside ServerConfig.cwd or config.worktreesDir. Since ServerConfig.cwd is $HOME in packaged builds, the project cwd (D:\git\<repo>) is rejected in ~2 ms:
VcsRepositoryDetectionError: VCS repository detection failed in ReviewService.getDiffPreview: D:\git\ABW\game - Review diff preview cwd must stay within the configured workspace root.
The client already knows about this failure mode — apps/web/src/components/DiffPanel.tsx has a dedicated fallback:
The retry re-queries with cwd: serverConfig.cwd — i.e. it computes the diff preview against $HOME, which is not a git repository, so the query "succeeds" with no sources and the panel shows nothing. No error ever surfaces to the user.
The only cwds that can pass the guard are t3-managed worktrees under ~/.t3/worktrees, so Working tree / Branch changes scopes only function for worktree threads. On large monorepos this leaves the diff panel with no working scope at all, because the Turn scopes are independently broken there by the checkpoint-capture timeout (#3646).
The guard itself is well-motivated — it's the validation added after #316 (arbitrary client-supplied cwd). The problem is that it validates against the server process's cwd, which in packaged desktop builds is $HOME by design, rather than against the workspace roots of registered projects. #2867 reports the same $HOME-cwd root cause from the provider-probe side; #2441 looks like this same silent-empty diff panel observed without the root cause identified.
Impact
Major degradation or frequent failure
Version or commit
0.0.28 (desktop stable, Windows installer); code paths verified identical at main @ ecb35f7
Environment
Windows 11 Pro (10.0.26200), T3 Code desktop 0.0.28, git 2.54.0.windows.1, provider claudeAgent
Logs or stack traces
server.trace.ndjson — the two spans emitted by one open of the diff panel (primary + fallback):
19:10:13 ws.rpc.review.getDiffPreview 2.0 ms Failure
VcsRepositoryDetectionError: VCS repository detection failed in
ReviewService.getDiffPreview: D:\git\ABW\game - Review diff preview cwd
must stay within the configured workspace root.
at .../app.asar/apps/server/dist/bin.mjs:37040:17
19:10:13 ws.rpc.review.getDiffPreview 437.2 ms Success (fallback at serverConfig.cwd = C:\Users\T9 — not a repo, empty result)
Backend spawn (no --cwd; ServerConfig falls back to process.cwd()):
"...\t3code\T3 Code (Alpha).exe" ...\app.asar\apps\server\dist\bin.mjs --bootstrap-fd 3
live process cwd: C:\Users\T9
Workaround
Run the thread in a t3-managed worktree (paths under ~/.t3/worktrees pass the guard). No workaround exists for in-place projects. Suggested direction: validate getDiffPreview's cwd against the registered projects' workspace roots (and thread worktree paths) instead of ServerConfig.cwd, or have the desktop app pass the project roots to the server as allowed boundaries — this would fix the diff panel while keeping the #316 hardening intact. The DiffPanel.tsx fallback should also surface an error instead of silently rendering an empty diff of the wrong directory.
Before submitting
Area
apps/server
Steps to reproduce
cwd = $HOME(apps/desktop/src/app/DesktopEnvironment.ts:backendCwd: input.isPackaged ? homeDirectory : appRoot— documented in [Bug]: Packaged builds set server cwd to $HOME; ClaudeProvider auxiliary spawns leak it past project bindings #2867), and the spawn passes no--cwdflag, soServerConfig.cwdresolves toprocess.cwd()= the home directory. Verified on the live process: the backend child's cwd isC:\Users\T9.D:\git\<repo>) and run a thread in place (not in a t3-managed worktree).Expected behavior
The panel shows the working-tree / branch diff of the project's repository, as those scopes describe.
Actual behavior
The panel silently renders empty for every in-place project, regardless of repo size or state. Two-step failure:
ReviewService.getDiffPreviewcallsassertWorkspaceBoundCwd, which only accepts a cwd insideServerConfig.cwdorconfig.worktreesDir. SinceServerConfig.cwdis$HOMEin packaged builds, the project cwd (D:\git\<repo>) is rejected in ~2 ms:VcsRepositoryDetectionError: VCS repository detection failed in ReviewService.getDiffPreview: D:\git\ABW\game - Review diff preview cwd must stay within the configured workspace root.The client already knows about this failure mode —
apps/web/src/components/DiffPanel.tsxhas a dedicated fallback:The retry re-queries with
cwd: serverConfig.cwd— i.e. it computes the diff preview against$HOME, which is not a git repository, so the query "succeeds" with no sources and the panel shows nothing. No error ever surfaces to the user.The only cwds that can pass the guard are t3-managed worktrees under
~/.t3/worktrees, so Working tree / Branch changes scopes only function for worktree threads. On large monorepos this leaves the diff panel with no working scope at all, because the Turn scopes are independently broken there by the checkpoint-capture timeout (#3646).The guard itself is well-motivated — it's the validation added after #316 (arbitrary client-supplied
cwd). The problem is that it validates against the server process's cwd, which in packaged desktop builds is$HOMEby design, rather than against the workspace roots of registered projects. #2867 reports the same$HOME-cwd root cause from the provider-probe side; #2441 looks like this same silent-empty diff panel observed without the root cause identified.Impact
Major degradation or frequent failure
Version or commit
0.0.28 (desktop stable, Windows installer); code paths verified identical at main @ ecb35f7
Environment
Windows 11 Pro (10.0.26200), T3 Code desktop 0.0.28, git 2.54.0.windows.1, provider claudeAgent
Logs or stack traces
Workaround
Run the thread in a t3-managed worktree (paths under
~/.t3/worktreespass the guard). No workaround exists for in-place projects. Suggested direction: validategetDiffPreview's cwd against the registered projects' workspace roots (and thread worktree paths) instead ofServerConfig.cwd, or have the desktop app pass the project roots to the server as allowed boundaries — this would fix the diff panel while keeping the #316 hardening intact. TheDiffPanel.tsxfallback should also surface an error instead of silently rendering an empty diff of the wrong directory.