[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
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 23k
- Forks
- 5.9k
- Avg merge
- 11h 14m
- Merged PRs (30d)
- 357
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/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 #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. - 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.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:const shouldRetryBranchDiffAtEnvironmentCwd = primaryBranchDiffPreview.error?.includes("configured workspace root") === true && serverConfig?.cwd !== undefined && serverConfig.cwd !== activeCwd;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 @ ecb35f75
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.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with ReviewService.getDiffPreview and its assertWorkspaceBoundCwd guard in apps/server, then trace project workspace registration and the desktop spawn setup in apps/desktop/src/app/DesktopEnvironment.ts. Inspect the retry path in apps/web/src/components/DiffPanel.tsx. Done means in-place projects outside $HOME show their Working tree and Branch changes diffs without silently retrying against an empty directory, while the existing cwd boundary remains enforced.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- git, typescript
- Domain
- backend, desktop
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 64/100