fix: Fail fast when agent worktree creation or branch setup fails

Previously, branch computation errors and ensureBranch failures were
silently swallowed for all tasks, allowing execution agents to spawn
without proper git isolation. This caused alert-pony to commit directly
to main instead of its task branch.

- manager.ts: Verify each project worktree subdirectory exists after
  createProjectWorktrees; throw if any are missing. Convert passive
  cwdVerified log to a hard guard.
- dispatch/manager.ts: Make branch computation and ensureBranch errors
  fatal for execution tasks (execute, verify, merge, review) while
  keeping them non-fatal for planning tasks.
This commit is contained in:
Lukas May
2026-03-06 14:08:59 +01:00
parent b419981924
commit 0f1c578269
4 changed files with 27 additions and 7 deletions

View File

@@ -239,8 +239,18 @@ export class MultiProviderAgentManager implements AgentManager {
log.debug({ alias, initiativeId, baseBranch, branchName }, 'creating initiative-based worktrees');
agentCwd = await this.processManager.createProjectWorktrees(alias, initiativeId, baseBranch, branchName);
// Log projects linked to the initiative
// Verify each project worktree subdirectory actually exists
const projects = await this.projectRepository.findProjectsByInitiativeId(initiativeId);
for (const project of projects) {
const projectWorktreePath = join(agentCwd, project.name);
if (!existsSync(projectWorktreePath)) {
throw new Error(
`Worktree subdirectory missing after createProjectWorktrees: ${projectWorktreePath}. ` +
`Agent ${alias} cannot run without an isolated worktree.`
);
}
}
log.info({
alias,
initiativeId,
@@ -255,11 +265,12 @@ export class MultiProviderAgentManager implements AgentManager {
}
// Verify the final agentCwd exists
const cwdVerified = existsSync(agentCwd);
if (!existsSync(agentCwd)) {
throw new Error(`Agent workdir does not exist after creation: ${agentCwd}`);
}
log.info({
alias,
agentCwd,
cwdVerified,
initiativeBasedAgent: !!initiativeId
}, 'agent workdir setup completed');

View File

@@ -327,8 +327,13 @@ export class DefaultDispatchManager implements DispatchManager {
}
}
}
} catch {
// Non-fatal: fall back to default branching
} catch (err) {
if (!isPlanningCategory(task.category)) {
// Execution tasks MUST have correct branches — fail loudly
throw new Error(`Failed to compute branches for execution task ${task.id}: ${err}`);
}
// Planning tasks: non-fatal, fall back to default branching
log.debug({ taskId: task.id, err }, 'branch computation skipped for planning task');
}
// Ensure branches exist in project clones before spawning worktrees
@@ -350,7 +355,10 @@ export class DefaultDispatchManager implements DispatchManager {
}
}
} catch (err) {
log.warn({ taskId: task.id, err }, 'failed to ensure branches for task dispatch');
if (!isPlanningCategory(task.category)) {
throw new Error(`Failed to ensure branches for execution task ${task.id}: ${err}`);
}
log.warn({ taskId: task.id, err }, 'failed to ensure branches for planning task dispatch');
}
}
}