diff --git a/scripts/lib/tmux-worktree-orchestrator.js b/scripts/lib/tmux-worktree-orchestrator.js index 8eb947c8..4c9cfa92 100644 --- a/scripts/lib/tmux-worktree-orchestrator.js +++ b/scripts/lib/tmux-worktree-orchestrator.js @@ -190,6 +190,7 @@ function buildOrchestrationPlan(config = {}) { throw new Error('buildOrchestrationPlan requires at least one worker'); } + const seenSlugs = new Set(); const workerPlans = workers.map((worker, index) => { if (!worker || typeof worker.task !== 'string' || worker.task.trim().length === 0) { throw new Error(`Worker ${index + 1} is missing a task`); @@ -197,6 +198,12 @@ function buildOrchestrationPlan(config = {}) { const workerName = worker.name || `worker-${index + 1}`; const workerSlug = slugify(workerName, `worker-${index + 1}`); + + if (seenSlugs.has(workerSlug)) { + throw new Error(`Workers must have unique slugs — duplicate: ${workerSlug}`); + } + seenSlugs.add(workerSlug); + const branchName = `orchestrator-${sessionName}-${workerSlug}`; const worktreePath = path.join(worktreeRoot, `${repoName}-${sessionName}-${workerSlug}`); const workerCoordinationDir = path.join(coordinationDir, workerSlug); @@ -206,7 +213,7 @@ function buildOrchestrationPlan(config = {}) { const launcherCommand = worker.launcherCommand || defaultLauncher; const workerSeedPaths = normalizeSeedPaths(worker.seedPaths, repoRoot); const seedPaths = normalizeSeedPaths([...globalSeedPaths, ...workerSeedPaths], repoRoot); - const templateVariables = { + const templateVariables = buildTemplateVariables({ branch_name: branchName, handoff_file: handoffFilePath, repo_root: repoRoot, @@ -216,7 +223,7 @@ function buildOrchestrationPlan(config = {}) { worker_name: workerName, worker_slug: workerSlug, worktree_path: worktreePath - }; + }); if (!launcherCommand) { throw new Error(`Worker ${workerName} is missing a launcherCommand`);