From 6f40d1d7209cfefed07f7bfd42aa35c60c34eb82 Mon Sep 17 00:00:00 2001 From: Ammar Date: Mon, 22 Dec 2025 11:22:40 -0600 Subject: [PATCH] =?UTF-8?q?=F0=9F=A4=96=20fix:=20validate=20trunkBranch=20?= =?UTF-8?q?exists=20before=20sub-agent=20workspace=20creation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When forkWorkspace() fails during task creation, the fallback logic used parentMeta.name directly as the trunkBranch for git worktree creation. This fails when the parent's branch doesn't exist locally (e.g., SSH workspaces, or branches that were never fetched). The fix validates that trunkBranch exists as a local branch before using it, falling back to the repository's default trunk branch (main/master/etc) if not found. For non-git projects (LocalRuntime), git commands are wrapped in try-catch to fall back to "main". Fixes the cosmetic error: fatal: 'git-debounce-5w4e' is not a commit and a branch 'agent_explore_7eeffc7df6' cannot be created from it --- src/node/services/taskService.ts | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/node/services/taskService.ts b/src/node/services/taskService.ts index 58082a0e13..6a7ab4e061 100644 --- a/src/node/services/taskService.ts +++ b/src/node/services/taskService.ts @@ -9,6 +9,7 @@ import type { HistoryService } from "@/node/services/historyService"; import type { PartialService } from "@/node/services/partialService"; import type { InitStateManager } from "@/node/services/initStateManager"; import { log } from "@/node/services/log"; +import { detectDefaultTrunkBranch, listLocalBranches } from "@/node/git"; import { createRuntime } from "@/node/runtime/runtimeFactory"; import type { InitLogger, WorkspaceCreationResult } from "@/node/runtime/Runtime"; import { validateWorkspaceName } from "@/common/utils/validation/workspaceValidation"; @@ -483,9 +484,23 @@ export class TaskService { initLogger, }); - const trunkBranch = forkResult.success - ? (forkResult.sourceBranch ?? parentMeta.name) - : parentMeta.name; + let trunkBranch: string; + if (forkResult.success && forkResult.sourceBranch) { + trunkBranch = forkResult.sourceBranch; + } else { + // Fork failed - validate parentMeta.name is a valid local branch. + // For non-git projects (LocalRuntime), git commands fail - fall back to "main". + try { + const localBranches = await listLocalBranches(parentMeta.projectPath); + if (localBranches.includes(parentMeta.name)) { + trunkBranch = parentMeta.name; + } else { + trunkBranch = await detectDefaultTrunkBranch(parentMeta.projectPath, localBranches); + } + } catch { + trunkBranch = "main"; + } + } const createResult: WorkspaceCreationResult = forkResult.success ? { success: true as const, workspacePath: forkResult.workspacePath } : await runtime.createWorkspace({