authorgravatar for saiansh2525@gmail.comYash Singh <saiansh2525@gmail.com> 2026-09-06 20:08:43-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-09-06 20:08:43-05:00
log1e740e48a5f91b3edd35c5446d33b0d36fb5a6ac
treeae4bf79ad0449afbf337604937758b6a2a577c8b
parentefeac144289d0f64bcfe3b9274c616499893be91
signature Signed by PGP key B5690EEEBB952194

fix(server): follow placeholder branches after checkout updates (#10441)


2 files changed, 40 insertions(+), 10 deletions(-)

apps/server/src/orchestration/Layers/CheckpointReactor.test.ts+39-8
......@@ -1002,23 +1002,22 @@ describe("CheckpointReactor", () => {
10021002 expect(thread?.branch).toBe("t3code/renamed-by-agent");
10031003 });
10041004
1005 it("does not adopt a drifted checkout when the worktree is shared by another thread", async () => {
1005 it("follows a checkout from a saved placeholder branch and refreshes its pull request", async () => {
10061006 const pullRequestRefreshCalls: string[] = [];
10071007 const harness = await createHarness({
10081008 seedFilesystemCheckpoints: false,
1009 threadBranch: "t3code/original-branch",
1010 localStatusRefName: "t3code/renamed-by-agent",
1011 secondThreadSharingWorktree: true,
1009 threadBranch: "t3code/fd9cbe0e",
1010 localStatusRefName: "fix/mobile-tool-detail-expansion",
10121011 pullRequestRefreshCalls,
10131012 });
10141013
10151014 harness.provider.emit({
10161015 type: "turn.completed",
1017 eventId: EventId.make("evt-turn-completed-branch-drift-shared"),
1016 eventId: EventId.make("evt-turn-completed-placeholder-drift"),
10181017 provider: ProviderDriverKind.make("codex"),
10191018 createdAt: "2026-01-01T00:00:00.000Z",
10201019 threadId: ThreadId.make("thread-1"),
1021 turnId: asTurnId("turn-branch-drift-shared"),
1020 turnId: asTurnId("turn-placeholder-drift"),
10221021 payload: { state: "completed" },
10231022 });
10241023
......@@ -1026,10 +1025,42 @@ describe("CheckpointReactor", () => {
10261025
10271026 const snapshot = await harness.readModel();
10281027 const thread = snapshot.threads.find((entry) => entry.id === ThreadId.make("thread-1"));
1029 expect(thread?.branch).toBe("t3code/original-branch");
1030 expect(pullRequestRefreshCalls).toEqual([]);
1028 expect(thread?.branch).toBe("fix/mobile-tool-detail-expansion");
1029 expect(thread?.worktreePath).toBe(harness.cwd);
1030 expect(pullRequestRefreshCalls).toEqual([harness.cwd]);
10311031 });
10321032
1033 it.each(["t3code/original-branch", "t3code/fd9cbe0e"])(
1034 "does not adopt a drifted checkout from %s when the worktree is shared by another thread",
1035 async (threadBranch) => {
1036 const pullRequestRefreshCalls: string[] = [];
1037 const harness = await createHarness({
1038 seedFilesystemCheckpoints: false,
1039 threadBranch,
1040 localStatusRefName: "t3code/renamed-by-agent",
1041 secondThreadSharingWorktree: true,
1042 pullRequestRefreshCalls,
1043 });
1044
1045 harness.provider.emit({
1046 type: "turn.completed",
1047 eventId: EventId.make("evt-turn-completed-branch-drift-shared"),
1048 provider: ProviderDriverKind.make("codex"),
1049 createdAt: "2026-01-01T00:00:00.000Z",
1050 threadId: ThreadId.make("thread-1"),
1051 turnId: asTurnId("turn-branch-drift-shared"),
1052 payload: { state: "completed" },
1053 });
1054
1055 await harness.drain();
1056
1057 const snapshot = await harness.readModel();
1058 const thread = snapshot.threads.find((entry) => entry.id === ThreadId.make("thread-1"));
1059 expect(thread?.branch).toBe(threadBranch);
1060 expect(pullRequestRefreshCalls).toEqual([]);
1061 },
1062 );
1063
10331064 it("does not adopt a temporary placeholder checkout as the thread branch", async () => {
10341065 const harness = await createHarness({
10351066 seedFilesystemCheckpoints: false,
apps/server/src/orchestration/Layers/CheckpointReactor.ts+1-2
......@@ -563,8 +563,7 @@ const make = Effect.gen(function* () {
563563 thread.branch === null ||
564564 thread.branch === checkedOutBranch ||
565565 thread.worktreePath === null ||
566 thread.worktreePath !== input.cwd ||
567 isTemporaryWorktreeBranch(thread.branch)
566 thread.worktreePath !== input.cwd
568567 ) {
569568 return;
570569 }