fix non-node worktree agent startup

This commit is contained in:
gsxdsm
2026-04-12 22:34:46 -07:00
parent 6ab4a899e6
commit f88d04ae03
3 changed files with 34 additions and 11 deletions

View File

@@ -0,0 +1,5 @@
---
"@gsxdsm/fusion": patch
---
Allow coding agents to start in registered non-Node project worktrees without a root package.json.

View File

@@ -346,10 +346,14 @@ describe("createKbAgent", () => {
existsSyncMock.mockImplementation((path) => {
const value = String(path);
return value === "/project/.worktrees/fn-001" ||
value === "/project/.worktrees/fn-001/.git" ||
value === "/project/.worktrees/fn-001/package.json";
value === "/project/.worktrees/fn-001/.git";
});
execSyncMock.mockImplementation((cmd) => {
if (cmd === "git rev-parse --show-toplevel") {
return "/project/.worktrees/fn-001\n";
}
return "worktree /project\nHEAD abc123\nbranch refs/heads/main\n";
});
execSyncMock.mockReturnValue("worktree /project\nHEAD abc123\nbranch refs/heads/main\n");
const { createKbAgent } = await import("./pi.js");
@@ -364,17 +368,19 @@ describe("createKbAgent", () => {
expect(createAgentSessionMock).not.toHaveBeenCalled();
});
it("allows a coding agent in a registered complete worktree", async () => {
it("allows a coding agent in a registered complete worktree without a root package.json", async () => {
existsSyncMock.mockImplementation((path) => {
const value = String(path);
return value === "/project/.worktrees/fn-001" ||
value === "/project/.worktrees/fn-001/.git" ||
value === "/project/.worktrees/fn-001/package.json";
value === "/project/.worktrees/fn-001/.git";
});
execSyncMock.mockImplementation((cmd) => {
if (cmd === "git rev-parse --show-toplevel") {
return "/project/.worktrees/fn-001\n";
}
return "worktree /project\nHEAD abc123\nbranch refs/heads/main\n\n" +
"worktree /project/.worktrees/fn-001\nHEAD def456\nbranch refs/heads/fusion/fn-001\n";
});
execSyncMock.mockReturnValue(
"worktree /project\nHEAD abc123\nbranch refs/heads/main\n\n" +
"worktree /project/.worktrees/fn-001\nHEAD def456\nbranch refs/heads/fusion/fn-001\n",
);
const { createKbAgent } = await import("./pi.js");

View File

@@ -292,11 +292,23 @@ async function isRegisteredGitWorktree(projectRoot: string, worktreePath: string
}
}
async function isCompleteGitWorktree(worktreePath: string): Promise<boolean> {
try {
const { stdout } = await execAsync("git rev-parse --show-toplevel", {
cwd: worktreePath,
encoding: "utf-8",
});
return resolve(stdout.trim()) === resolve(worktreePath);
} catch {
return false;
}
}
async function assertValidWorktreeSession(cwd: string, projectRoot: string): Promise<void> {
if (!existsSync(cwd)) {
throw new Error(`Refusing to start coding agent in missing worktree: ${cwd}`);
}
if (!existsSync(join(cwd, ".git")) || !existsSync(join(cwd, "package.json"))) {
if (!existsSync(join(cwd, ".git")) || !await isCompleteGitWorktree(cwd)) {
throw new Error(`Refusing to start coding agent in incomplete worktree: ${cwd}`);
}
if (!await isRegisteredGitWorktree(projectRoot, cwd)) {