Skip to content

Commit fc8a009

Browse files
committed
Add PR switch cwd regression test
1 parent 0e8215f commit fc8a009

2 files changed

Lines changed: 75 additions & 4 deletions

File tree

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { describe, expect, test } from "bun:test";
2+
import { resolveReviewScopedAgentCwd } from "./review";
3+
4+
describe("resolveReviewScopedAgentCwd", () => {
5+
test("uses the current PR pool checkout in PR mode", () => {
6+
const worktreePool = {
7+
resolve: (url: string) => url === "https://example.com/pr/2" ? "/tmp/pr-2" : undefined,
8+
};
9+
10+
expect(resolveReviewScopedAgentCwd({
11+
isPRMode: true,
12+
prUrl: "https://example.com/pr/2",
13+
worktreePool,
14+
agentCwd: "/tmp/original-pr",
15+
currentDiffType: "uncommitted",
16+
gitContextCwd: "/repo",
17+
})).toBe("/tmp/pr-2");
18+
});
19+
20+
test("does not reuse the previous PR checkout when a switched PR has no pool entry", () => {
21+
const worktreePool = {
22+
resolve: () => undefined,
23+
};
24+
25+
expect(resolveReviewScopedAgentCwd({
26+
isPRMode: true,
27+
prUrl: "https://example.com/pr/other-repo",
28+
worktreePool,
29+
agentCwd: "/tmp/original-pr",
30+
currentDiffType: "uncommitted",
31+
gitContextCwd: "/repo",
32+
})).toBeUndefined();
33+
});
34+
35+
test("keeps non-PR local review fallback behavior", () => {
36+
expect(resolveReviewScopedAgentCwd({
37+
isPRMode: false,
38+
agentCwd: "/tmp/local-review",
39+
currentDiffType: "uncommitted",
40+
gitContextCwd: "/repo",
41+
})).toBe("/tmp/local-review");
42+
43+
expect(resolveReviewScopedAgentCwd({
44+
isPRMode: false,
45+
currentDiffType: "uncommitted",
46+
gitContextCwd: "/repo",
47+
})).toBe("/repo");
48+
});
49+
});

packages/server/review.ts

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,24 @@ export interface ReviewSession {
130130
dispose: () => void;
131131
}
132132

133+
export interface ResolveReviewScopedAgentCwdOptions {
134+
isPRMode: boolean;
135+
prUrl?: string;
136+
worktreePool?: Pick<import("@plannotator/shared/worktree-pool").WorktreePool, "resolve">;
137+
agentCwd?: string;
138+
currentDiffType: DiffType;
139+
gitContextCwd?: string;
140+
}
141+
142+
export function resolveReviewScopedAgentCwd(
143+
options: ResolveReviewScopedAgentCwdOptions,
144+
): string | undefined {
145+
if (options.isPRMode && options.prUrl && options.worktreePool) {
146+
return options.worktreePool.resolve(options.prUrl);
147+
}
148+
return options.agentCwd ?? resolveVcsCwd(options.currentDiffType, options.gitContextCwd);
149+
}
150+
133151
// --- Server Implementation ---
134152

135153
const MAX_RETRIES = 5;
@@ -190,10 +208,14 @@ export async function createReviewSession(
190208
// Agent jobs — background process manager (late-binds serverUrl via getter)
191209
let serverUrl = "";
192210
const resolveScopedAgentCwd = (): string | undefined => {
193-
if (isPRMode && prMetadata && options.worktreePool) {
194-
return options.worktreePool.resolve(prMetadata.url);
195-
}
196-
return options.agentCwd ?? resolveVcsCwd(currentDiffType, gitContext?.cwd);
211+
return resolveReviewScopedAgentCwd({
212+
isPRMode,
213+
prUrl: prMetadata?.url,
214+
worktreePool: options.worktreePool,
215+
agentCwd: options.agentCwd,
216+
currentDiffType,
217+
gitContextCwd: gitContext?.cwd,
218+
});
197219
};
198220
const resolveAgentCwd = (): string => {
199221
return resolveScopedAgentCwd() ?? cwd;

0 commit comments

Comments
 (0)