@@ -67,6 +67,7 @@ import {
6767 setPendingConnectionError ,
6868 useSavedRemoteConnections ,
6969} from "../../state/use-remote-environment-registry" ;
70+ import { vcsEnvironment } from "../../state/vcs" ;
7071import { EnvironmentProject } from "@t3tools/client-runtime/state/shell" ;
7172import { type VcsRef } from "@t3tools/client-runtime/state/vcs" ;
7273import {
@@ -81,6 +82,7 @@ import {
8182 resolveNewTaskBranchWorktreePath ,
8283 resolveNewTaskLocalWorkspaceSelection ,
8384} from "./new-task-context-presentation" ;
85+ import { resolveProjectThreadWorkspaceSelection } from "./projectThreadCreationValidation" ;
8486
8587type WorkspaceMode = "local" | "worktree" ;
8688
@@ -124,6 +126,7 @@ type NewTaskFlowContextValue = {
124126 readonly selectedEnvironmentId : EnvironmentId | null ;
125127 readonly selectedProjectKey : string | null ;
126128 readonly selectedModelKey : string | null ;
129+ readonly isGitRepo : boolean ;
127130 readonly workspaceMode : WorkspaceMode ;
128131 readonly selectedBranchName : string | null ;
129132 readonly selectedWorktreePath : string | null ;
@@ -348,6 +351,17 @@ export function NewTaskFlowProvider(props: React.PropsWithChildren) {
348351 const selectedEnvironmentServerConfig = useEnvironmentServerConfig (
349352 selectedProject ?. environmentId ?? null ,
350353 ) ;
354+ const gitStatus = useEnvironmentQuery (
355+ selectedProject !== null && selectedProject . workspaceRoot . length > 0
356+ ? vcsEnvironment . status ( {
357+ environmentId : selectedProject . environmentId ,
358+ input : { cwd : selectedProject . workspaceRoot } ,
359+ } )
360+ : null ,
361+ ) ;
362+ // Match web/desktop: assume git only while status is unresolved so the
363+ // composer controls do not flicker away during the initial query.
364+ const isGitRepo = gitStatus . data ?. isRepo ?? true ;
351365 // While a queued pending task is being edited its draft lives under a key
352366 // scoped to the queued message, so per-project new-task drafts stay intact.
353367 const selectedProjectDraftKey = editingPendingTask
@@ -387,9 +401,15 @@ export function NewTaskFlowProvider(props: React.PropsWithChildren) {
387401 projectSetting : selectedProject ?. defaultThreadEnvMode ,
388402 projectFilePending : t3ProjectFileQuery . isPending ,
389403 } ) ;
390- const workspaceMode = selectedProjectDraft . workspaceSelection ?. mode ?? defaultWorkspaceMode ;
391- const selectedBranchName = selectedProjectDraft . workspaceSelection ?. branch ?? null ;
392- const selectedWorktreePath = selectedProjectDraft . workspaceSelection ?. worktreePath ?? null ;
404+ const workspaceSelection = resolveProjectThreadWorkspaceSelection ( {
405+ isGitRepo,
406+ environmentMode : selectedProjectDraft . workspaceSelection ?. mode ?? defaultWorkspaceMode ,
407+ branch : selectedProjectDraft . workspaceSelection ?. branch ?? null ,
408+ worktreePath : selectedProjectDraft . workspaceSelection ?. worktreePath ?? null ,
409+ } ) ;
410+ const workspaceMode = workspaceSelection . environmentMode ;
411+ const selectedBranchName = workspaceSelection . branch ;
412+ const selectedWorktreePath = workspaceSelection . worktreePath ;
393413 // Keep the user's explicit choice separate from the resolved display value:
394414 // only the explicit flag is ever written back to the draft, so the resolved
395415 // value keeps tracking the server setting when the config loads late.
@@ -530,12 +550,12 @@ export function NewTaskFlowProvider(props: React.PropsWithChildren) {
530550 const debouncedBranchQuery = useDebouncedValue ( branchQuery , BRANCH_SEARCH_DEBOUNCE_MS ) ;
531551 const branchTarget = useMemo (
532552 ( ) => ( {
533- environmentId : selectedProject ?. environmentId ?? null ,
553+ environmentId : isGitRepo ? ( selectedProject ?. environmentId ?? null ) : null ,
534554 // `|| null` also skips the stand-in project's empty workspaceRoot.
535- cwd : selectedProject ?. workspaceRoot || null ,
555+ cwd : isGitRepo ? selectedProject ?. workspaceRoot || null : null ,
536556 query : debouncedBranchQuery ,
537557 } ) ,
538- [ debouncedBranchQuery , selectedProject ?. environmentId , selectedProject ?. workspaceRoot ] ,
558+ [ debouncedBranchQuery , isGitRepo , selectedProject ?. environmentId , selectedProject ?. workspaceRoot ] ,
539559 ) ;
540560 const branchState = usePaginatedBranches ( branchTarget ) ;
541561 const branchSearchIsDebouncing = branchQuery . trim ( ) !== debouncedBranchQuery . trim ( ) ;
@@ -725,12 +745,12 @@ export function NewTaskFlowProvider(props: React.PropsWithChildren) {
725745 const refreshBranches = branchState . refresh ;
726746 const loadMoreBranches = branchState . loadNext ;
727747 const loadBranches = useCallback ( ( ) => {
728- if ( ! selectedProject ) {
748+ if ( ! selectedProject || ! isGitRepo ) {
729749 return ;
730750 }
731751 setPendingConnectionError ( null ) ;
732752 refreshBranches ( ) ;
733- } , [ refreshBranches , selectedProject ] ) ;
753+ } , [ isGitRepo , refreshBranches , selectedProject ] ) ;
734754
735755 useEffect ( ( ) => {
736756 if (
@@ -824,10 +844,15 @@ export function NewTaskFlowProvider(props: React.PropsWithChildren) {
824844 if ( text . length === 0 || ! draftModelSelection ) {
825845 return null ;
826846 }
827- const workspaceSelection = draft . workspaceSelection ;
828- // Fall back to the resolved mode (server default) so queued tasks drain
847+ // Fall back to the resolved default mode so queued tasks drain
829848 // with the same mode the composer displayed.
830- const mode = workspaceSelection ?. mode ?? workspaceMode ;
849+ const workspaceSelection = resolveProjectThreadWorkspaceSelection ( {
850+ isGitRepo,
851+ environmentMode : draft . workspaceSelection ?. mode ?? workspaceMode ,
852+ branch : draft . workspaceSelection ?. branch ?? null ,
853+ worktreePath : draft . workspaceSelection ?. worktreePath ?? null ,
854+ } ) ;
855+ const mode = workspaceSelection . environmentMode ;
831856 // When the selection is the stand-in built from the queued snapshot,
832857 // persist the original (possibly absent) snapshot values — the
833858 // stand-in's placeholder title/workspaceRoot must never be written back
@@ -859,12 +884,12 @@ export function NewTaskFlowProvider(props: React.PropsWithChildren) {
859884 ...( projectTitle !== undefined ? { projectTitle } : { } ) ,
860885 ...( projectCwd !== undefined ? { projectCwd } : { } ) ,
861886 workspaceMode : mode ,
862- branch : workspaceSelection ? .branch ?? null ,
863- worktreePath : mode === "worktree" ? null : ( workspaceSelection ? .worktreePath ?? null ) ,
887+ branch : workspaceSelection . branch ,
888+ worktreePath : mode === "worktree" ? null : workspaceSelection . worktreePath ,
864889 // The draft only carries the flag when the user touched it; fall
865890 // back to the resolved default (server settings) so queued tasks
866891 // drain with the same origin mode the composer displayed.
867- ...( ( workspaceSelection ?. startFromOrigin ?? startFromOrigin )
892+ ...( ( draft . workspaceSelection ?. startFromOrigin ?? startFromOrigin )
868893 ? { startFromOrigin : true }
869894 : { } ) ,
870895 } ,
@@ -874,6 +899,7 @@ export function NewTaskFlowProvider(props: React.PropsWithChildren) {
874899 [
875900 editingPendingProject ,
876901 editingPendingTask ,
902+ isGitRepo ,
877903 selectedEnvironmentServerConfig ,
878904 selectedModel ,
879905 selectedProject ,
@@ -981,6 +1007,7 @@ export function NewTaskFlowProvider(props: React.PropsWithChildren) {
9811007 selectedEnvironmentId,
9821008 selectedProjectKey,
9831009 selectedModelKey,
1010+ isGitRepo,
9841011 workspaceMode,
9851012 selectedBranchName,
9861013 selectedWorktreePath,
@@ -1049,6 +1076,7 @@ export function NewTaskFlowProvider(props: React.PropsWithChildren) {
10491076 filteredBranches ,
10501077 finishEditingPendingTask ,
10511078 interactionMode ,
1079+ isGitRepo ,
10521080 planModeEnabled ,
10531081 loadBranches ,
10541082 loadMoreBranches ,
0 commit comments