authorgravatar for 153842990+yashranaway@users.noreply.github.comAditya Garud <153842990+yashranaway@users.noreply.github.com> 2026-09-02 13:14:14+05:30
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-09-02 00:44:14-07:00
loga81a52afbb4e03ba82b2743801772151ed8c7d70
treea8592f61ceedce664445b6f5c7a3b74a40e9bdd7
parenta56b0cd7178dfef299aa49b26773a80a34abe205
signature Signed by PGP key B5690EEEBB952194

fix(server): allow local-only worktree bases (#8751)


6 files changed, 179 insertions(+), 109 deletions(-)

apps/server/src/git/GitWorkflowService.ts+9
...@@ -73,6 +73,11 @@ export class GitWorkflowService extends Context.Service<...@@ -73,6 +73,11 @@ export class GitWorkflowService extends Context.Service<
73 readonly cwd: string;73 readonly cwd: string;
74 readonly remoteName: string;74 readonly remoteName: string;
75 }) => Effect.Effect<boolean, GitCommandError>;75 }) => Effect.Effect<boolean, GitCommandError>;
76 readonly remoteBranchExists: (input: {
77 readonly cwd: string;
78 readonly remoteName: string;
79 readonly refName: string;
80 }) => Effect.Effect<boolean, GitCommandError>;
76 readonly resolveRemoteTrackingCommit: (input: {81 readonly resolveRemoteTrackingCommit: (input: {
77 readonly cwd: string;82 readonly cwd: string;
78 readonly refName: string;83 readonly refName: string;
...@@ -314,6 +319,10 @@ export const make = Effect.gen(function* () {...@@ -314,6 +319,10 @@ export const make = Effect.gen(function* () {
314 ensureGitCommand("GitWorkflowService.remoteExists", input.cwd).pipe(319 ensureGitCommand("GitWorkflowService.remoteExists", input.cwd).pipe(
315 Effect.andThen(git.remoteExists(input)),320 Effect.andThen(git.remoteExists(input)),
316 ),321 ),
322 remoteBranchExists: (input) =>
323 ensureGitCommand("GitWorkflowService.remoteBranchExists", input.cwd).pipe(
324 Effect.andThen(git.remoteBranchExists(input)),
325 ),
317 resolveRemoteTrackingCommit: (input) =>326 resolveRemoteTrackingCommit: (input) =>
318 ensureGitCommand("GitWorkflowService.resolveRemoteTrackingCommit", input.cwd).pipe(327 ensureGitCommand("GitWorkflowService.resolveRemoteTrackingCommit", input.cwd).pipe(
319 Effect.andThen(git.resolveRemoteTrackingCommit(input)),328 Effect.andThen(git.resolveRemoteTrackingCommit(input)),
apps/server/src/server.test.ts+120-92
...@@ -8378,6 +8378,13 @@ it.layer(NodeServices.layer)("server router seam", (it) => {...@@ -8378,6 +8378,13 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
8378 bootstrapGitOperations.push("fetch");8378 bootstrapGitOperations.push("fetch");
8379 }),8379 }),
8380 );8380 );
8381 const remoteBranchExists = vi.fn(
8382 (_: Parameters<GitVcsDriver.GitVcsDriver["Service"]["remoteBranchExists"]>[0]) =>
8383 Effect.sync(() => {
8384 bootstrapGitOperations.push("remote-branch-exists");
8385 return true;
8386 }),
8387 );
8381 const fetchedOriginCommit = "0123456789abcdef0123456789abcdef01234567";8388 const fetchedOriginCommit = "0123456789abcdef0123456789abcdef01234567";
8382 const resolveRemoteTrackingCommit = vi.fn(8389 const resolveRemoteTrackingCommit = vi.fn(
8383 (_: Parameters<GitVcsDriver.GitVcsDriver["Service"]["resolveRemoteTrackingCommit"]>[0]) =>8390 (_: Parameters<GitVcsDriver.GitVcsDriver["Service"]["resolveRemoteTrackingCommit"]>[0]) =>
...@@ -8421,6 +8428,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => {...@@ -8421,6 +8428,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
8421 gitVcsDriver: {8428 gitVcsDriver: {
8422 remoteExists,8429 remoteExists,
8423 fetchRemote,8430 fetchRemote,
8431 remoteBranchExists,
8424 resolveRemoteTrackingCommit,8432 resolveRemoteTrackingCommit,
8425 createWorktree,8433 createWorktree,
8426 },8434 },
...@@ -8504,6 +8512,11 @@ it.layer(NodeServices.layer)("server router seam", (it) => {...@@ -8504,6 +8512,11 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
8504 cwd: "/tmp/project",8512 cwd: "/tmp/project",
8505 remoteName: "origin",8513 remoteName: "origin",
8506 });8514 });
8515 assert.deepEqual(remoteBranchExists.mock.calls[0]?.[0], {
8516 cwd: "/tmp/project",
8517 remoteName: "origin",
8518 refName: "main",
8519 });
8507 assert.deepEqual(resolveRemoteTrackingCommit.mock.calls[0]?.[0], {8520 assert.deepEqual(resolveRemoteTrackingCommit.mock.calls[0]?.[0], {
8508 cwd: "/tmp/project",8521 cwd: "/tmp/project",
8509 refName: "main",8522 refName: "main",
...@@ -8512,6 +8525,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => {...@@ -8512,6 +8525,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
8512 assert.deepEqual(bootstrapGitOperations, [8525 assert.deepEqual(bootstrapGitOperations, [
8513 "remote-exists",8526 "remote-exists",
8514 "fetch",8527 "fetch",
8528 "remote-branch-exists",
8515 "resolve-remote-commit",8529 "resolve-remote-commit",
8516 "create-worktree",8530 "create-worktree",
8517 ]);8531 ]);
...@@ -8539,108 +8553,122 @@ it.layer(NodeServices.layer)("server router seam", (it) => {...@@ -8539,108 +8553,122 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
8539 }).pipe(Effect.provide(NodeHttpServer.layerTest)),8553 }).pipe(Effect.provide(NodeHttpServer.layerTest)),
8540 );8554 );
85418555
8542 it.effect(8556 it.effect.each([
8543 "falls back to the local base branch when startFromOrigin is set but no origin remote exists",8557 { caseName: "the origin remote is missing", hasOrigin: false },
8544 () =>8558 { caseName: "the base branch exists only locally", hasOrigin: true },
8545 Effect.gen(function* () {8559 ])("falls back to the local base branch when $caseName", ({ hasOrigin }) =>
8546 const dispatchedCommands: Array<OrchestrationCommand> = [];8560 Effect.gen(function* () {
8547 const remoteExists = vi.fn(8561 const dispatchedCommands: Array<OrchestrationCommand> = [];
8548 (_: Parameters<GitVcsDriver.GitVcsDriver["Service"]["remoteExists"]>[0]) =>8562 const remoteExists = vi.fn(
8549 Effect.succeed(false),8563 (_: Parameters<GitVcsDriver.GitVcsDriver["Service"]["remoteExists"]>[0]) =>
8550 );8564 Effect.succeed(hasOrigin),
8551 const fetchRemote = vi.fn(8565 );
8552 (_: Parameters<GitVcsDriver.GitVcsDriver["Service"]["fetchRemote"]>[0]) => Effect.void,8566 const fetchRemote = vi.fn(
8553 );8567 (_: Parameters<GitVcsDriver.GitVcsDriver["Service"]["fetchRemote"]>[0]) => Effect.void,
8554 const resolveRemoteTrackingCommit = vi.fn(8568 );
8555 (_: Parameters<GitVcsDriver.GitVcsDriver["Service"]["resolveRemoteTrackingCommit"]>[0]) =>8569 const resolveRemoteTrackingCommit = vi.fn(
8556 Effect.succeed({8570 (_: Parameters<GitVcsDriver.GitVcsDriver["Service"]["resolveRemoteTrackingCommit"]>[0]) =>
8557 commitSha: "0123456789abcdef0123456789abcdef01234567",8571 Effect.succeed({
8558 remoteRefName: "origin/main",8572 commitSha: "0123456789abcdef0123456789abcdef01234567",
8559 }),8573 remoteRefName: "origin/main",
8560 );8574 }),
8561 const createWorktree = vi.fn(8575 );
8562 (_: Parameters<GitVcsDriver.GitVcsDriver["Service"]["createWorktree"]>[0]) =>8576 const remoteBranchExists = vi.fn(
8563 Effect.succeed({8577 (_: Parameters<GitVcsDriver.GitVcsDriver["Service"]["remoteBranchExists"]>[0]) =>
8564 worktree: {8578 Effect.succeed(false),
8565 refName: "t3code/bootstrap-refName",8579 );
8566 path: "/tmp/bootstrap-worktree",8580 const createWorktree = vi.fn(
8567 },8581 (_: Parameters<GitVcsDriver.GitVcsDriver["Service"]["createWorktree"]>[0]) =>
8568 }),8582 Effect.succeed({
8569 );8583 worktree: {
85708584 refName: "t3code/bootstrap-refName",
8571 yield* buildAppUnderTest({8585 path: "/tmp/bootstrap-worktree",
8572 layers: {
8573 gitVcsDriver: {
8574 remoteExists,
8575 fetchRemote,
8576 resolveRemoteTrackingCommit,
8577 createWorktree,
8578 },
8579 orchestrationEngine: {
8580 dispatch: (command) =>
8581 Effect.sync(() => {
8582 dispatchedCommands.push(command);
8583 return { sequence: dispatchedCommands.length };
8584 }),
8585 readEvents: () => Stream.empty,
8586 },8586 },
8587 }),
8588 );
8589
8590 yield* buildAppUnderTest({
8591 layers: {
8592 gitVcsDriver: {
8593 remoteExists,
8594 fetchRemote,
8595 remoteBranchExists,
8596 resolveRemoteTrackingCommit,
8597 createWorktree,
8587 },8598 },
8588 });8599 orchestrationEngine: {
8600 dispatch: (command) =>
8601 Effect.sync(() => {
8602 dispatchedCommands.push(command);
8603 return { sequence: dispatchedCommands.length };
8604 }),
8605 readEvents: () => Stream.empty,
8606 },
8607 },
8608 });
85898609
8590 const createdAt = "2026-01-01T00:00:00.000Z";8610 const createdAt = "2026-01-01T00:00:00.000Z";
8591 const wsUrl = yield* getWsServerUrl("/ws");8611 const wsUrl = yield* getWsServerUrl("/ws");
8592 yield* Effect.scoped(8612 yield* Effect.scoped(
8593 withWsRpcClient(wsUrl, (client) =>8613 withWsRpcClient(wsUrl, (client) =>
8594 client[ORCHESTRATION_WS_METHODS.dispatchCommand]({8614 client[ORCHESTRATION_WS_METHODS.dispatchCommand]({
8595 type: "thread.turn.start",8615 type: "thread.turn.start",
8596 commandId: CommandId.make("cmd-bootstrap-turn-start-no-origin"),8616 commandId: CommandId.make("cmd-bootstrap-turn-start-no-origin"),
8597 threadId: ThreadId.make("thread-bootstrap-no-origin"),8617 threadId: ThreadId.make("thread-bootstrap-no-origin"),
8598 message: {8618 message: {
8599 messageId: MessageId.make("msg-bootstrap-no-origin"),8619 messageId: MessageId.make("msg-bootstrap-no-origin"),
8600 role: "user",8620 role: "user",
8601 text: "hello",8621 text: "hello",
8602 attachments: [],8622 attachments: [],
8623 },
8624 modelSelection: defaultModelSelection,
8625 runtimeMode: "full-access",
8626 interactionMode: "default",
8627 bootstrap: {
8628 createThread: {
8629 projectId: defaultProjectId,
8630 title: "Bootstrap Thread",
8631 modelSelection: defaultModelSelection,
8632 runtimeMode: "full-access",
8633 interactionMode: "default",
8634 branch: "main",
8635 worktreePath: null,
8636 createdAt,
8603 },8637 },
8604 modelSelection: defaultModelSelection,8638 prepareWorktree: {
8605 runtimeMode: "full-access",8639 projectCwd: "/tmp/project",
8606 interactionMode: "default",8640 baseBranch: "main",
8607 bootstrap: {8641 branch: "t3code/bootstrap-refName",
8608 createThread: {8642 startFromOrigin: true,
8609 projectId: defaultProjectId,
8610 title: "Bootstrap Thread",
8611 modelSelection: defaultModelSelection,
8612 runtimeMode: "full-access",
8613 interactionMode: "default",
8614 branch: "main",
8615 worktreePath: null,
8616 createdAt,
8617 },
8618 prepareWorktree: {
8619 projectCwd: "/tmp/project",
8620 baseBranch: "main",
8621 branch: "t3code/bootstrap-refName",
8622 startFromOrigin: true,
8623 },
8624 },8643 },
8625 createdAt,8644 },
8626 }),8645 createdAt,
8627 ),8646 }),
8628 );8647 ),
8648 );
86298649
8630 assert.deepEqual(remoteExists.mock.calls[0]?.[0], {8650 assert.deepEqual(remoteExists.mock.calls[0]?.[0], {
8651 cwd: "/tmp/project",
8652 remoteName: "origin",
8653 });
8654 assert.equal(fetchRemote.mock.calls.length, hasOrigin ? 1 : 0);
8655 assert.equal(remoteBranchExists.mock.calls.length, hasOrigin ? 1 : 0);
8656 if (hasOrigin) {
8657 assert.deepEqual(remoteBranchExists.mock.calls[0]?.[0], {
8631 cwd: "/tmp/project",8658 cwd: "/tmp/project",
8632 remoteName: "origin",8659 remoteName: "origin",
8633 });
8634 assert.equal(fetchRemote.mock.calls.length, 0);
8635 assert.equal(resolveRemoteTrackingCommit.mock.calls.length, 0);
8636 assert.deepEqual(createWorktree.mock.calls[0]?.[0], {
8637 cwd: "/tmp/project",
8638 refName: "main",8660 refName: "main",
8639 newRefName: "t3code/bootstrap-refName",
8640 baseRefName: "main",
8641 path: null,
8642 });8661 });
8643 }).pipe(Effect.provide(NodeHttpServer.layerTest)),8662 }
8663 assert.equal(resolveRemoteTrackingCommit.mock.calls.length, 0);
8664 assert.deepEqual(createWorktree.mock.calls[0]?.[0], {
8665 cwd: "/tmp/project",
8666 refName: "main",
8667 newRefName: "t3code/bootstrap-refName",
8668 baseRefName: "main",
8669 path: null,
8670 });
8671 }).pipe(Effect.provide(NodeHttpServer.layerTest)),
8644 );8672 );
86458673
8646 it.effect("records setup-script failures without aborting bootstrap turn start", () =>8674 it.effect("records setup-script failures without aborting bootstrap turn start", () =>
apps/server/src/vcs/GitVcsDriver.ts+7
...@@ -204,6 +204,10 @@ export interface GitRemoteExistsInput {...@@ -204,6 +204,10 @@ export interface GitRemoteExistsInput {
204 remoteName: string;204 remoteName: string;
205}205}
206206
207export interface GitRemoteBranchExistsInput extends GitRemoteExistsInput {
208 refName: string;
209}
210
207export interface GitResolveRemoteTrackingCommitInput {211export interface GitResolveRemoteTrackingCommitInput {
208 cwd: string;212 cwd: string;
209 refName: string;213 refName: string;
...@@ -295,6 +299,9 @@ export class GitVcsDriver extends Context.Service<...@@ -295,6 +299,9 @@ export class GitVcsDriver extends Context.Service<
295 ) => Effect.Effect<string | null, GitCommandError>;299 ) => Effect.Effect<string | null, GitCommandError>;
296 readonly fetchRemote: (input: GitFetchRemoteInput) => Effect.Effect<void, GitCommandError>;300 readonly fetchRemote: (input: GitFetchRemoteInput) => Effect.Effect<void, GitCommandError>;
297 readonly remoteExists: (input: GitRemoteExistsInput) => Effect.Effect<boolean, GitCommandError>;301 readonly remoteExists: (input: GitRemoteExistsInput) => Effect.Effect<boolean, GitCommandError>;
302 readonly remoteBranchExists: (
303 input: GitRemoteBranchExistsInput,
304 ) => Effect.Effect<boolean, GitCommandError>;
298 readonly resolveRemoteTrackingCommit: (305 readonly resolveRemoteTrackingCommit: (
299 input: GitResolveRemoteTrackingCommitInput,306 input: GitResolveRemoteTrackingCommitInput,
300 ) => Effect.Effect<GitResolveRemoteTrackingCommitResult, GitCommandError>;307 ) => Effect.Effect<GitResolveRemoteTrackingCommitResult, GitCommandError>;
apps/server/src/vcs/GitVcsDriverCore.test.ts+17
...@@ -1665,6 +1665,23 @@ it.layer(TestLayer)("GitVcsDriver core integration", (it) => {...@@ -1665,6 +1665,23 @@ it.layer(TestLayer)("GitVcsDriver core integration", (it) => {
1665 const driver = yield* GitVcsDriver.GitVcsDriver;1665 const driver = yield* GitVcsDriver.GitVcsDriver;
1666 yield* driver.fetchRemote({ cwd, remoteName: "origin" });1666 yield* driver.fetchRemote({ cwd, remoteName: "origin" });
16671667
1668 assert.equal(
1669 yield* driver.remoteBranchExists({
1670 cwd,
1671 remoteName: "origin",
1672 refName: initialBranch,
1673 }),
1674 true,
1675 );
1676 assert.equal(
1677 yield* driver.remoteBranchExists({
1678 cwd,
1679 remoteName: "origin",
1680 refName: "local-only",
1681 }),
1682 false,
1683 );
1684
1668 const resolvedBase = yield* driver.resolveRemoteTrackingCommit({1685 const resolvedBase = yield* driver.resolveRemoteTrackingCommit({
1669 cwd,1686 cwd,
1670 refName: initialBranch,1687 refName: initialBranch,
apps/server/src/vcs/GitVcsDriverCore.ts+14-11
...@@ -1292,15 +1292,11 @@ export const makeGitVcsDriverCore = Effect.fn("makeGitVcsDriverCore")(function*...@@ -1292,15 +1292,11 @@ export const makeGitVcsDriverCore = Effect.fn("makeGitVcsDriverCore")(function*
1292 }),1292 }),
1293 );1293 );
12941294
1295 const remoteBranchExists = (1295 const remoteBranchExists: GitVcsDriver.GitVcsDriver["Service"]["remoteBranchExists"] = (input) =>
1296 cwd: string,
1297 remoteName: string,
1298 refName: string,
1299 ): Effect.Effect<boolean, GitCommandError> =>
1300 executeGit(1296 executeGit(
1301 "GitVcsDriver.remoteBranchExists",1297 "GitVcsDriver.remoteBranchExists",
1302 cwd,1298 input.cwd,
1303 ["show-ref", "--verify", "--quiet", `refs/remotes/${remoteName}/${refName}`],1299 ["show-ref", "--verify", "--quiet", `refs/remotes/${input.remoteName}/${input.refName}`],
1304 {1300 {
1305 allowNonZeroExit: true,1301 allowNonZeroExit: true,
1306 },1302 },
...@@ -1447,7 +1443,11 @@ export const makeGitVcsDriverCore = Effect.fn("makeGitVcsDriverCore")(function*...@@ -1447,7 +1443,11 @@ export const makeGitVcsDriverCore = Effect.fn("makeGitVcsDriverCore")(function*
14471443
1448 if (1444 if (
1449 primaryRemoteName &&1445 primaryRemoteName &&
1450 (yield* remoteBranchExists(cwd, primaryRemoteName, normalizedCandidate))1446 (yield* remoteBranchExists({
1447 cwd,
1448 remoteName: primaryRemoteName,
1449 refName: normalizedCandidate,
1450 }))
1451 ) {1451 ) {
1452 return `${primaryRemoteName}/${normalizedCandidate}`;1452 return `${primaryRemoteName}/${normalizedCandidate}`;
1453 }1453 }
...@@ -1965,9 +1965,11 @@ export const makeGitVcsDriverCore = Effect.fn("makeGitVcsDriverCore")(function*...@@ -1965,9 +1965,11 @@ export const makeGitVcsDriverCore = Effect.fn("makeGitVcsDriverCore")(function*
1965 };1965 };
1966 }1966 }
19671967
1968 const hasRemoteBranch = yield* remoteBranchExists(cwd, publishRemoteName, branch).pipe(1968 const hasRemoteBranch = yield* remoteBranchExists({
1969 Effect.orElseSucceed(() => false),1969 cwd,
1970 );1970 remoteName: publishRemoteName,
1971 refName: branch,
1972 }).pipe(Effect.orElseSucceed(() => false));
1971 if (hasRemoteBranch) {1973 if (hasRemoteBranch) {
1972 return {1974 return {
1973 status: "skipped_up_to_date" as const,1975 status: "skipped_up_to_date" as const,
...@@ -3315,6 +3317,7 @@ export const makeGitVcsDriverCore = Effect.fn("makeGitVcsDriverCore")(function*...@@ -3315,6 +3317,7 @@ export const makeGitVcsDriverCore = Effect.fn("makeGitVcsDriverCore")(function*
3315 resolveDefaultBranchName,3317 resolveDefaultBranchName,
3316 fetchRemote: (input) => withListRefsInvalidation(input.cwd, fetchRemote(input)),3318 fetchRemote: (input) => withListRefsInvalidation(input.cwd, fetchRemote(input)),
3317 remoteExists,3319 remoteExists,
3320 remoteBranchExists,
3318 resolveRemoteTrackingCommit,3321 resolveRemoteTrackingCommit,
3319 fetchRemoteBranch: (input) => withListRefsInvalidation(input.cwd, fetchRemoteBranch(input)),3322 fetchRemoteBranch: (input) => withListRefsInvalidation(input.cwd, fetchRemoteBranch(input)),
3320 fetchRemoteTrackingBranch: (input) =>3323 fetchRemoteTrackingBranch: (input) =>
apps/server/src/ws.ts+12-6
...@@ -1094,9 +1094,8 @@ const makeWsRpcLayer = (...@@ -1094,9 +1094,8 @@ const makeWsRpcLayer = (
10941094
1095 if (bootstrap?.prepareWorktree) {1095 if (bootstrap?.prepareWorktree) {
1096 let worktreeBaseRef = bootstrap.prepareWorktree.baseBranch;1096 let worktreeBaseRef = bootstrap.prepareWorktree.baseBranch;
1097 // "Start from origin" is a stored default; repos without an1097 // "Start from origin" is a stored default; repos without the
1098 // origin remote fall back to the local base branch instead of1098 // requested remote branch fall back to the local base branch.
1099 // failing the whole bootstrap on `git fetch origin`.
1100 const startFromOrigin =1099 const startFromOrigin =
1101 bootstrap.prepareWorktree.startFromOrigin === true &&1100 bootstrap.prepareWorktree.startFromOrigin === true &&
1102 (yield* gitWorkflow.remoteExists({1101 (yield* gitWorkflow.remoteExists({
...@@ -1108,12 +1107,19 @@ const makeWsRpcLayer = (...@@ -1108,12 +1107,19 @@ const makeWsRpcLayer = (
1108 cwd: bootstrap.prepareWorktree.projectCwd,1107 cwd: bootstrap.prepareWorktree.projectCwd,
1109 remoteName: "origin",1108 remoteName: "origin",
1110 });1109 });
1111 const resolvedRemoteBase = yield* gitWorkflow.resolveRemoteTrackingCommit({1110 const remoteBaseExists = yield* gitWorkflow.remoteBranchExists({
1112 cwd: bootstrap.prepareWorktree.projectCwd,1111 cwd: bootstrap.prepareWorktree.projectCwd,
1113 refName: bootstrap.prepareWorktree.baseBranch,1112 refName: bootstrap.prepareWorktree.baseBranch,
1114 fallbackRemoteName: "origin",1113 remoteName: "origin",
1115 });1114 });
1116 worktreeBaseRef = resolvedRemoteBase.commitSha;1115 if (remoteBaseExists) {
1116 const resolvedRemoteBase = yield* gitWorkflow.resolveRemoteTrackingCommit({
1117 cwd: bootstrap.prepareWorktree.projectCwd,
1118 refName: bootstrap.prepareWorktree.baseBranch,
1119 fallbackRemoteName: "origin",
1120 });
1121 worktreeBaseRef = resolvedRemoteBase.commitSha;
1122 }
1117 }1123 }
1118 const worktree = yield* gitWorkflow.createWorktree({1124 const worktree = yield* gitWorkflow.createWorktree({
1119 cwd: bootstrap.prepareWorktree.projectCwd,1125 cwd: bootstrap.prepareWorktree.projectCwd,