Distinguish failed Git inspection from missing worktree registration (#15525)

Apply the reviewed change for Distinguish failed Git inspection from missing worktree registration.

Validation: required local typecheck and tests, passing CI, Greptile 5/5, and independent review of the exact source head.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
Devin FoleyandPaperclip authored and GitHub committed 2026-10-07 19:05:04 -07:00
1 parent ed0c6958f8
commit 1d19f9b562
6 files changed
+235 -13

No files matched your search

+44 -13
View File
@@ -67,6 +67,11 @@ import { isRuntimeOwnedGitBranch } from "./execution-workspace-branch-ownership.
import { logActivity } from "./activity-log.js";
import { readProjectWorkspaceRuntimeConfig } from "./project-workspace-runtime-config.js";
import { workspaceGitOperationScheduler } from "./workspace-git-operation-scheduler.js";
import {
MANAGED_GIT_WORKTREE_REASON_CODES,
readManagedGitInspectionDiagnostic,
type ManagedGitInspectionDiagnostic,
} from "./workspace-validation-diagnostics.js";
import {
cleanupWorktreeInstanceArtifacts,
deriveWorktreeInstanceId,
@@ -2606,13 +2611,8 @@ type GitWorktreeListEntry = {
export type ManagedGitWorktreeBranchInspection = {
valid: boolean;
reason: string | null;
reasonCode:
| "missing_worktree"
| "not_a_git_checkout"
| "not_registered"
| "wrong_repository_root"
| "branch_mismatch"
| null;
reasonCode: typeof MANAGED_GIT_WORKTREE_REASON_CODES[number] | null;
inspectionDiagnostic?: ManagedGitInspectionDiagnostic;
repoRoot: string | null;
worktreePath: string;
expectedBranchName: string | null;
@@ -2735,16 +2735,33 @@ async function resolvePathForWorktreeComparison(value: string): Promise<string>
return fs.realpath(resolved).then((realPath) => path.resolve(realPath)).catch(() => resolved);
}
async function listLinkedGitWorktreePaths(repoRoot: string): Promise<Set<string>> {
const output = await runGit(["worktree", "list", "--porcelain"], repoRoot);
async function listLinkedGitWorktreePaths(repoRoot: string): Promise<
{ paths: Set<string>; diagnostic?: never } | { paths?: never; diagnostic: ManagedGitInspectionDiagnostic }
> {
let proc: Awaited<ReturnType<typeof executeProcess>>;
try {
proc = await executeProcess({ command: "git", args: ["worktree", "list", "--porcelain"], cwd: repoRoot });
} catch (error) {
return { diagnostic: readManagedGitInspectionDiagnostic({
command: "worktree_list", failure: "spawn_failed", errorCode: (error as NodeJS.ErrnoException)?.code,
})! };
}
if (proc.code !== 0) {
return { diagnostic: readManagedGitInspectionDiagnostic({
command: "worktree_list", failure: "nonzero_exit", exitCode: proc.code,
})! };
}
if (proc.stdoutTruncated) {
return { diagnostic: { command: "worktree_list", failure: "output_truncated" } };
}
const paths = new Set<string>();
for (const line of output.split("\n")) {
for (const line of proc.stdout.split("\n")) {
if (!line.startsWith("worktree ")) continue;
const worktree = line.slice("worktree ".length).trim();
if (!worktree) continue;
paths.add(await resolvePathForWorktreeComparison(worktree));
}
return paths;
return { paths };
}
export async function inspectManagedGitWorktreeBranch(input: {
@@ -2783,8 +2800,18 @@ export async function inspectManagedGitWorktreeBranch(input: {
};
}
const listedWorktrees = await listLinkedGitWorktreePaths(repoRoot).catch(() => null);
if (!listedWorktrees?.has(worktreePath)) {
const listedWorktrees = await listLinkedGitWorktreePaths(repoRoot);
if (listedWorktrees.diagnostic) {
return {
...base,
valid: false,
reason: "could not inspect the complete git worktree registration list",
reasonCode: "git_inspection_failed",
repoRoot,
inspectionDiagnostic: listedWorktrees.diagnostic,
};
}
if (!listedWorktrees.paths.has(worktreePath)) {
return {
...base,
valid: false,
@@ -2841,6 +2868,7 @@ async function validateLinkedGitWorktree(input: {
reason: string;
reasonCode: Exclude<ManagedGitWorktreeBranchInspection["reasonCode"], null>;
actualBranchName?: string | null;
inspectionDiagnostic?: ManagedGitInspectionDiagnostic;
}
> {
const inspection = await inspectManagedGitWorktreeBranch({
@@ -2855,6 +2883,7 @@ async function validateLinkedGitWorktree(input: {
reason: inspection.reason ?? "unknown git worktree mismatch",
reasonCode: inspection.reasonCode ?? "not_a_git_checkout",
actualBranchName: inspection.actualBranchName,
...(inspection.inspectionDiagnostic ? { inspectionDiagnostic: inspection.inspectionDiagnostic } : {}),
};
}
@@ -2867,6 +2896,7 @@ export function formatManagedGitWorktreeBranchInspection(input: ManagedGitWorktr
worktreePath: input.worktreePath,
expectedBranchName: input.expectedBranchName,
actualBranchName: input.actualBranchName,
...(input.inspectionDiagnostic ? { inspectionDiagnostic: input.inspectionDiagnostic } : {}),
};
}
@@ -3756,6 +3786,7 @@ export async function ensurePersistedExecutionWorkspaceAvailable(input: {
reasonCode: validation.reasonCode,
worktreePath: reuseWorktreePath,
executionWorkspaceId: input.workspace.id ?? null,
...(validation.inspectionDiagnostic ? { inspectionDiagnostic: validation.inspectionDiagnostic } : {}),
},
},
);