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
{{ message }}
Repository navigation
[Bug]: No project isn't recognized when its folder is the target of a symlinked ~/.t3/scratch, so Turn into project disappears and a duplicate No project is created #34439
I searched existing issues and did not find a duplicate.
I included enough detail to reproduce or investigate the problem.
Area
apps/server (also apps/web via packages/client-runtime)
Steps to reproduce
Use T3 Code until ~/.t3/scratch holds some No project threads, each in its own ~/.t3/scratch/<date>-<words>-<id> folder.
Move the scratch folder somewhere visible and symlink it back: mv ~/.t3/scratch ~/projects/t3-chats && ln -s ~/projects/t3-chats ~/.t3/scratch
Point the No project at the real folder, ~/projects/t3-chats. I did this through t3_project_update with workspaceRoot; the project settings folder field would give the same result.
Restart T3 Code and open the thread menu on one of the older No project threads. Their worktreePath is still ~/.t3/scratch/....
Both spellings name the same folder on disk.
Expected behavior
T3 Code still recognizes the project as No project, because its folder resolves to the scratch root:
The thread menu offers Turn into project.
New No project threads go to the existing No project.
Actual behavior
Turn into project is missing from the thread menu.
The server creates a second, empty "No project" rooted at ~/.t3/scratch. Settings then lists two "No project" entries on the same machine.
From code reading, ScratchThreadPromotion.promote would also refuse the thread with "Only a No project thread with its own folder can become a project.", because the parent of the thread's folder is checked with a plain string compare.
Every scratch check compares path spellings and never resolves symlinks:
apps/server/src/project/ManagedProjectFolders.ts: scratchRoot is path.resolve(baseDir, "scratch"), and isScratchRoot compares path.resolve(project.workspaceRoot) to it. path.resolve doesn't follow symlinks, so isScratchProject is false and ensureScratchProject bootstraps a new project.
packages/client-runtime/src/state/projects.ts: isScratchProject compares the project root to the advertised scratchWorkspaceRoot as text. canTurnThreadIntoProject in apps/web/src/hooks/useThreadActions.ts therefore hides the action.
Other places in the server already compare real paths, for example KnownWorkspaces and AgentSessionScanner.
Impact
Minor bug or occasional failure
A No project thread can't be turned into a project, and a duplicate No project appears. There's a manual workaround (below).
Version or commit
0.1.9-nightly.20261110.4465 (code read at main @ 479ee74)
Delete the empty duplicate No project, then set the original No project's folder back to the symlink spelling ~/.t3/scratch. Turn into project then appears again.
Activity