[Bug]: Session import offers T3 Code's own scratch folders as projects when the T3 home is a symlink#23727

opened18d agobySsiddham-jain

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

  1. Make the T3 home reachable through a symlink, for example move it to another disk and link it back: mv ~/.t3 /Volumes/Data/t3 && ln -s /Volumes/Data/t3 ~/.t3 (a T3CODE_HOME that points at a symlink works the same way).
  2. Start a chat without a project and send a message with Claude or Codex. It runs in ~/.t3/scratch/<id>.
  3. Open /welcome and go to "Import your projects".

A focused test reproduces this without a real install: the config base dir is a symlink, and a Claude transcript records a scratch/<id> folder under the real base dir.

Expected behavior

T3 Code's own folders (projectless chat sandboxes under scratch/, managed worktrees, anything under the T3 home) are never offered as projects to import, whichever way the T3 home is spelled.

Actual behavior

Every projectless chat's scratch folder is listed under "Other folders" as a project to import.

Claude Code and Codex record the resolved working directory, so a transcript says /Volumes/Data/t3/scratch/<id>. AgentSessionScanner checks each candidate a second time with links resolved ("check again with links resolved"), but it compares that resolved path against baseDir and worktreesDir, which are only path.resolved and still use the symlinked spelling (apps/server/src/project/AgentSessionScanner.ts:642-668). The prefix check never matches. Scratch folders are not git repos, so the worktree .git check does not catch them either, and the /.t3/worktrees/ fallback does not apply to the real path.

The existing test excludes sandboxes reached through a symlink into the worktrees dir hits the same bug. It fails on macOS today because the test temp dir /var/folders/... resolves to /private/var/folders/.... It passes on Linux CI, where tmp is not a symlink.

Impact

Minor bug or occasional failure

Version or commit

0.1.1, main @ 60b35a1ee

Environment

macOS 27.0.1, Node 24.13. Not provider-specific: Claude Code and Codex transcripts both record the resolved cwd.

Logs or stack traces

shell
1$ vp test run src/project/AgentSessionScanner.test.ts -t symlink
2 × excludes sandboxes reached through a symlink into the worktrees dir
3 path: '/var/folders/.../t3code-scanner-links-cnZHtw/innocent-project'
4 × excludes T3 Code's own folders when its home is reached through a symlink
5 path: '/private/var/folders/.../t3code-scanner-base-491GN2/scratch/2026-01-01-quiet-fox'
6AssertionError: expected [ { …(7) } ] to deeply equal []

Workaround

Point T3CODE_HOME at the real path instead of the symlink, or untick the scratch folders in the import list.