fix(workspace): skip git init for workspace-mode project roots

ensureGitRepositoryForProjectPath unconditionally ran `git init` on
non-git paths, including workspace roots. This created a stray empty
repo with unborn HEAD at the workspace root, poisoning every downstream
git command (executor session cwd: `fatal: ambiguous argument 'HEAD'`).

Add an early-return guard that checks loadWorkspaceConfig before any git
operation, keeping the workspace root non-git as intended by the
workspace execution contract.
This commit is contained in:
gsxdsm
2026-06-23 23:14:05 -07:00
parent 905a877954
commit a9ea1f6fe3
2 changed files with 28 additions and 1 deletions

View File

@@ -1,6 +1,6 @@
import { afterEach, describe, expect, it } from "vitest";
import { execFile } from "node:child_process";
import { existsSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
import { existsSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { promisify } from "node:util";
@@ -107,4 +107,17 @@ describe("ensureGitRepositoryForProjectPath", () => {
ensureGitRepositoryForProjectPath(projectPath, { runner }),
).rejects.toBeInstanceOf(GitRepositoryInitializationError);
});
it("skips git init for a workspace-mode project root (.fusion/workspace.json present)", async () => {
const projectPath = tempDir("fusion-git-workspace-");
// Simulate workspace init: .fusion/workspace.json exists, root is non-git
mkdirSync(join(projectPath, ".fusion"), { recursive: true });
writeFileSync(join(projectPath, ".fusion", "workspace.json"), JSON.stringify({ repos: ["repo-a"] }));
const outcome = await ensureGitRepositoryForProjectPath(projectPath);
expect(outcome).toBe("existing");
// No .git should be created at the workspace root
expect(existsSync(join(projectPath, ".git"))).toBe(false);
});
});

View File

@@ -41,6 +41,20 @@ export async function ensureGitRepositoryForProjectPath(
const runner = options.runner ?? runGitCommand;
const timeout = options.timeoutMs ?? DEFAULT_GIT_TIMEOUT_MS;
/*
FNXC:Workspace 2026-06-24-10:00:
A workspace-mode project root is intentionally NOT a git repository — it is a parent
directory containing multiple git sub-repos (detected at init time and recorded in
.fusion/workspace.json). Running `git init` here would create a stray empty repo at the
workspace root, poisoning every downstream git command: the executor sets the session cwd
to this root (browse-only), and `git rev-parse --abbrev-ref HEAD` fails on the unborn HEAD
with "ambiguous argument 'HEAD'". Detect workspace mode via the config file and skip the
git-init so the root stays non-git, matching the workspace execution contract (KTD1).
*/
if (await loadWorkspaceConfig(projectPath)) {
return "existing";
}
if (await isInsideGitWorkTree(projectPath, runner, timeout)) {
return "existing";
}