fix: Ensure phase branches exist before task dispatch
Task dispatch computed baseBranch as the phase branch name but never ensured it existed in the git clone. When phases weren't dispatched through the PhaseDispatchManager (which creates branches), the git worktree add failed with "fatal: invalid reference". Now DefaultDispatchManager calls ensureBranch for both the initiative and phase branches before spawning, matching what PhaseDispatchManager already does.
This commit is contained in:
@@ -212,6 +212,9 @@ export async function createContainer(options?: ContainerOptions): Promise<Conta
|
||||
repos.phaseRepository,
|
||||
repos.agentRepository,
|
||||
repos.pageRepository,
|
||||
repos.projectRepository,
|
||||
branchManager,
|
||||
workspaceRoot,
|
||||
);
|
||||
const phaseDispatchManager = new DefaultPhaseDispatchManager(
|
||||
repos.phaseRepository,
|
||||
|
||||
@@ -21,10 +21,13 @@ import type { AgentRepository } from '../db/repositories/agent-repository.js';
|
||||
import type { InitiativeRepository } from '../db/repositories/initiative-repository.js';
|
||||
import type { PhaseRepository } from '../db/repositories/phase-repository.js';
|
||||
import type { PageRepository } from '../db/repositories/page-repository.js';
|
||||
import type { ProjectRepository } from '../db/repositories/project-repository.js';
|
||||
import type { Task, Phase } from '../db/schema.js';
|
||||
import type { PageForSerialization } from '../agent/content-serializer.js';
|
||||
import type { BranchManager } from '../git/branch-manager.js';
|
||||
import type { DispatchManager, QueuedTask, DispatchResult } from './types.js';
|
||||
import { phaseBranchName, taskBranchName, isPlanningCategory, generateInitiativeBranch } from '../git/branch-naming.js';
|
||||
import { ensureProjectClone } from '../git/project-clones.js';
|
||||
import { buildExecutePrompt } from '../agent/prompts/index.js';
|
||||
import { createModuleLogger } from '../logger/index.js';
|
||||
|
||||
@@ -68,6 +71,9 @@ export class DefaultDispatchManager implements DispatchManager {
|
||||
private phaseRepository?: PhaseRepository,
|
||||
private agentRepository?: AgentRepository,
|
||||
private pageRepository?: PageRepository,
|
||||
private projectRepository?: ProjectRepository,
|
||||
private branchManager?: BranchManager,
|
||||
private workspaceRoot?: string,
|
||||
) {}
|
||||
|
||||
/**
|
||||
@@ -332,6 +338,29 @@ export class DefaultDispatchManager implements DispatchManager {
|
||||
} catch {
|
||||
// Non-fatal: fall back to default branching
|
||||
}
|
||||
|
||||
// Ensure branches exist in project clones before spawning worktrees
|
||||
if (baseBranch && this.projectRepository && this.branchManager && this.workspaceRoot) {
|
||||
try {
|
||||
const initiative = await this.initiativeRepository.findById(task.initiativeId);
|
||||
const initBranch = initiative?.branch;
|
||||
if (initBranch) {
|
||||
const projects = await this.projectRepository.findProjectsByInitiativeId(task.initiativeId);
|
||||
for (const project of projects) {
|
||||
const clonePath = await ensureProjectClone(project, this.workspaceRoot);
|
||||
// Ensure initiative branch exists (from project defaultBranch)
|
||||
await this.branchManager.ensureBranch(clonePath, initBranch, project.defaultBranch);
|
||||
// Ensure phase branch exists (from initiative branch)
|
||||
const phBranch = phaseBranchName(initBranch, (await this.phaseRepository?.findById(task.phaseId!))?.name ?? '');
|
||||
if (phBranch) {
|
||||
await this.branchManager.ensureBranch(clonePath, phBranch, initBranch);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
log.warn({ taskId: task.id, err }, 'failed to ensure branches for task dispatch');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Gather initiative context for the agent's input files
|
||||
|
||||
Reference in New Issue
Block a user