Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 119 additions & 0 deletions apps/server/src/server.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8675,6 +8675,125 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
}).pipe(Effect.provide(NodeHttpServer.layerTest)),
);

it.effect.each([
{
caseName: "a non-origin remote base",
baseBranch: "upstream/main",
fetchRemoteName: "upstream",
lookupRefName: "main",
remoteRefName: "upstream/main",
},
{
caseName: "an origin-prefixed base",
baseBranch: "origin/main",
fetchRemoteName: "origin",
lookupRefName: "main",
remoteRefName: "origin/main",
},
])(
"fetches the base branch's own remote for $caseName",
({ baseBranch, fetchRemoteName, lookupRefName, remoteRefName }) =>
Effect.gen(function* () {
const fetchedCommit = "abcdef0123456789abcdef0123456789abcdef01";
const remoteExists = vi.fn(
(_: Parameters<GitVcsDriver.GitVcsDriver["Service"]["remoteExists"]>[0]) =>
Effect.succeed(true),
);
const fetchRemote = vi.fn(
(_: Parameters<GitVcsDriver.GitVcsDriver["Service"]["fetchRemote"]>[0]) => Effect.void,
);
const remoteBranchExists = vi.fn(
(_: Parameters<GitVcsDriver.GitVcsDriver["Service"]["remoteBranchExists"]>[0]) =>
Effect.succeed(true),
);
const resolveRemoteTrackingCommit = vi.fn(
(_: Parameters<GitVcsDriver.GitVcsDriver["Service"]["resolveRemoteTrackingCommit"]>[0]) =>
Effect.succeed({
commitSha: fetchedCommit,
remoteRefName,
}),
);
const createWorktree = vi.fn(
(_: Parameters<GitVcsDriver.GitVcsDriver["Service"]["createWorktree"]>[0]) =>
Effect.succeed({
worktree: {
refName: "t3code/bootstrap-refName",
path: "/tmp/bootstrap-worktree",
},
}),
);

yield* buildAppUnderTest({
layers: {
gitVcsDriver: {
remoteExists,
fetchRemote,
remoteBranchExists,
resolveRemoteTrackingCommit,
createWorktree,
},
orchestrationEngine: {
dispatch: (command: OrchestrationCommand) =>
Effect.sync(() => ({ sequence: 1 })),
readEvents: () => Stream.empty,
},
},
});

const createdAt = "2026-01-01T00:00:00.000Z";
const wsUrl = yield* getWsServerUrl("/ws");
yield* Effect.scoped(
withWsRpcClient(wsUrl, (client) =>
client[ORCHESTRATION_WS_METHODS.dispatchCommand]({
type: "thread.turn.start",
commandId: CommandId.make("cmd-bootstrap-turn-start-remote-base"),
threadId: ThreadId.make("thread-bootstrap-remote-base"),
message: {
messageId: MessageId.make("msg-bootstrap-remote-base"),
role: "user",
text: "hello",
attachments: [],
},
modelSelection: defaultModelSelection,
runtimeMode: "full-access",
interactionMode: "default",
bootstrap: {
prepareWorktree: {
projectCwd: "/tmp/project",
baseBranch,
branch: "t3code/bootstrap-refName",
startFromOrigin: true,
},
},
createdAt,
}),
),
);

assert.deepEqual(fetchRemote.mock.calls[0]?.[0], {
cwd: "/tmp/project",
remoteName: fetchRemoteName,
});
assert.deepEqual(remoteBranchExists.mock.calls[0]?.[0], {
cwd: "/tmp/project",
remoteName: fetchRemoteName,
refName: lookupRefName,
});
assert.deepEqual(resolveRemoteTrackingCommit.mock.calls[0]?.[0], {
cwd: "/tmp/project",
refName: baseBranch,
fallbackRemoteName: fetchRemoteName,
});
assert.deepEqual(createWorktree.mock.calls[0]?.[0], {
cwd: "/tmp/project",
refName: fetchedCommit,
newRefName: "t3code/bootstrap-refName",
baseRefName: baseBranch,
path: null,
});
}).pipe(Effect.provide(NodeHttpServer.layerTest)),
);

it.effect("records setup-script failures without aborting bootstrap turn start", () =>
Effect.gen(function* () {
const dispatchedCommands: Array<OrchestrationCommand> = [];
Expand Down
53 changes: 40 additions & 13 deletions apps/server/src/ws.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1091,30 +1091,57 @@ const makeWsRpcLayer = (
}

if (bootstrap?.prepareWorktree) {
let worktreeBaseRef = bootstrap.prepareWorktree.baseBranch;
const baseBranch = bootstrap.prepareWorktree.baseBranch;
let worktreeBaseRef = baseBranch;
// "Start from origin" is a stored default; repos without the
// requested remote branch fall back to the local base branch.
const startFromOrigin =
bootstrap.prepareWorktree.startFromOrigin === true &&
(yield* gitWorkflow.remoteExists({
cwd: bootstrap.prepareWorktree.projectCwd,
remoteName: "origin",
}));
if (startFromOrigin) {
// The base may track a remote other than `origin` (e.g. `upstream/main`),
// so resolve the fetch target from the base ref instead of assuming `origin`.
// Otherwise we pay for a useless `fetch origin` and base the worktree
// on a stale ref while the real remote is never fetched.
const remotePrefix = baseBranch.includes("/")
? baseBranch.slice(0, baseBranch.indexOf("/"))
: null;
let fetchRemoteName: string | null = null;
if (bootstrap.prepareWorktree.startFromOrigin === true) {
if (
remotePrefix !== null &&
(yield* gitWorkflow.remoteExists({
cwd: bootstrap.prepareWorktree.projectCwd,
remoteName: remotePrefix,
}))
) {
fetchRemoteName = remotePrefix;
} else if (
yield* gitWorkflow.remoteExists({
cwd: bootstrap.prepareWorktree.projectCwd,
remoteName: "origin",
})
) {
fetchRemoteName = "origin";
}
}
if (fetchRemoteName !== null) {
yield* gitWorkflow.fetchRemote({
cwd: bootstrap.prepareWorktree.projectCwd,
remoteName: "origin",
remoteName: fetchRemoteName,
});
// remoteBranchExists concatenates refs/remotes/<remote>/<refName>,
// so strip the remote prefix when the base already carries it
// (`upstream/main` on `upstream` must look up `main`, not `upstream/main`).
const remoteRefName = baseBranch.startsWith(`${fetchRemoteName}/`)
? baseBranch.slice(fetchRemoteName.length + 1)
: baseBranch;
const remoteBaseExists = yield* gitWorkflow.remoteBranchExists({
cwd: bootstrap.prepareWorktree.projectCwd,
refName: bootstrap.prepareWorktree.baseBranch,
remoteName: "origin",
refName: remoteRefName,
remoteName: fetchRemoteName,
});
if (remoteBaseExists) {
const resolvedRemoteBase = yield* gitWorkflow.resolveRemoteTrackingCommit({
cwd: bootstrap.prepareWorktree.projectCwd,
refName: bootstrap.prepareWorktree.baseBranch,
fallbackRemoteName: "origin",
refName: baseBranch,
fallbackRemoteName: fetchRemoteName,
});
worktreeBaseRef = resolvedRemoteBase.commitSha;
}
Expand Down
Loading