From ee00a4f0a435fa1bacb80f8eeb96be48ab7bd858 Mon Sep 17 00:00:00 2001 From: marius-kilocode Date: Tue, 18 Aug 2026 11:06:34 +0200 Subject: [PATCH] fix(agent-manager): avoid tracking deleted PR branches --- .../src/agent-manager/WorktreeManager.ts | 10 +++--- .../tests/unit/worktree-manager.test.ts | 34 +++++++++++++++++++ 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/packages/kilo-vscode/src/agent-manager/WorktreeManager.ts b/packages/kilo-vscode/src/agent-manager/WorktreeManager.ts index a67bacaa74..7973adc05d 100644 --- a/packages/kilo-vscode/src/agent-manager/WorktreeManager.ts +++ b/packages/kilo-vscode/src/agent-manager/WorktreeManager.ts @@ -1128,10 +1128,12 @@ export class WorktreeManager { ]) } if (!(await this.gitTry(["show-ref", "--verify", "--quiet", `refs/heads/${info.headRefName}`]))) { - const ref = `refs/remotes/origin/${info.headRefName}` - await this.gitExec(["branch", info.headRefName, ref]) - await this.gitExec(["config", `branch.${info.headRefName}.remote`, "origin"]) - await this.gitExec(["config", `branch.${info.headRefName}.merge`, `refs/heads/${info.headRefName}`]) + const start = `refs/remotes/origin/${info.headRefName}` + await this.gitExec(["branch", info.headRefName, start]) + if (ok) { + await this.gitExec(["config", `branch.${info.headRefName}.remote`, "origin"]) + await this.gitExec(["config", `branch.${info.headRefName}.merge`, `refs/heads/${info.headRefName}`]) + } } } } diff --git a/packages/kilo-vscode/tests/unit/worktree-manager.test.ts b/packages/kilo-vscode/tests/unit/worktree-manager.test.ts index 60b65bbd6f..69ff01da58 100644 --- a/packages/kilo-vscode/tests/unit/worktree-manager.test.ts +++ b/packages/kilo-vscode/tests/unit/worktree-manager.test.ts @@ -1191,6 +1191,40 @@ describe("WorktreeManager.createWorktree advanced", () => { expect(worktreeHead).toBe(remoteHead) expect(result.parentBranch).toBe("topic") }) + + it("does not track a deleted PR source branch when using the pull ref fallback", async () => { + const { bare, clone } = await createTempRepoWithOrigin() + const git = simpleGit(clone) + await git.checkoutLocalBranch("topic") + await fs.writeFile(path.join(clone, "topic.txt"), "topic") + await git.add(".") + await git.commit("topic commit") + await git.push("origin", "topic") + const head = (await git.revparse(["topic"])).trim() + await git.checkout("main") + await git.raw(["config", "remote.origin.fetch", "+refs/heads/main:refs/remotes/origin/main"]) + await git.raw(["update-ref", "-d", "refs/remotes/origin/topic"]) + gitExec(["git", "--git-dir", bare, "update-ref", "refs/pull/1/head", head]) + gitExec(["git", "--git-dir", bare, "update-ref", "-d", "refs/heads/topic"]) + await git.branch(["-D", "topic"]) + + const manager = createManager(clone) + const internal = manager as unknown as { + fetchPRInfo: (parsed: { owner: string; repo: string; number: number }) => Promise + } + internal.fetchPRInfo = async () => ({ + headRefName: "topic", + isCrossRepository: false, + title: "Topic PR", + }) + + const result = await manager.createFromPR("https://github.com/org/repo/pull/1") + const upstream = await git.raw(["config", "--get", "branch.topic.remote"]).catch(() => "") + const worktreeHead = (await simpleGit(result.path).revparse(["HEAD"])).trim() + + expect(worktreeHead).toBe(head) + expect(upstream.trim()).toBe("") + }) }) // ---------------------------------------------------------------------------