@maestroai/core 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/task/parser.ts","../src/task/writer.ts","../src/utils/id.ts","../src/task/lock.ts","../src/task/manager.ts","../src/utils/logger.ts","../src/agent/lifecycle.ts","../src/agent/pool.ts","../src/agent/roles.ts","../src/agent/config.ts","../src/types/orchestrator-activity.ts","../src/index.ts","../src/messaging/broker.ts","../src/messaging/inbox.ts","../src/orchestrator/orchestrator.ts","../src/feedback/feedback-loop.ts","../src/feedback/progress-tracker.ts","../src/orchestrator/planner.ts","../src/orchestrator/scheduler.ts","../src/orchestrator/pipeline.ts","../src/orchestrator/pm-scanner.ts","../src/project/config.ts","../src/project/workspace.ts"],"sourcesContent":["import type { Task, TaskPriority, TaskStatus } from '../types/task.js';\n\nconst TASK_LINE_REGEX =\n /^- \\[(x| )\\]\\s+(\\S+)\\s+\\|\\s+(.+?)\\s+\\|\\s+(@\\S+|unassigned)\\s+\\|\\s+deps:\\s*(.+?)\\s+\\|\\s+(.+)$/;\n\nconst PRIORITY_HEADER_REGEX = /^##\\s+(Critical|High|Medium|Low)\\s*$/i;\nconst PROJECT_HEADER_REGEX = /^#\\s+Project:\\s+(.+)$/;\nconst NOTE_REGEX = /^\\s+>\\s?(.*)$/;\n\nconst VALID_STATUSES: TaskStatus[] = ['pending', 'in-progress', 'done', 'blocked', 'cancelled'];\n\nfunction normalizePriority(raw: string): TaskPriority {\n return raw.toLowerCase() as TaskPriority;\n}\n\nfunction normalizeStatus(raw: string): { status: TaskStatus; completedAt: string | null } {\n const trimmed = raw.trim();\n\n // Check for done:<timestamp> pattern\n const doneMatch = trimmed.match(/^done:(\\S+)$/);\n if (doneMatch) {\n return { status: 'done', completedAt: doneMatch[1] };\n }\n\n const statusCandidate = trimmed.toLowerCase() as TaskStatus;\n if (VALID_STATUSES.includes(statusCandidate)) {\n return {\n status: statusCandidate,\n completedAt: statusCandidate === 'done' ? new Date().toISOString() : null,\n };\n }\n\n return { status: 'pending', completedAt: null };\n}\n\nexport class TaskParser {\n parse(content: string): { projectName: string; tasks: Task[] } {\n const lines = content.split('\\n');\n let projectName = '';\n let currentPriority: TaskPriority = 'medium';\n const tasks: Task[] = [];\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n\n // Check for project header\n const projectMatch = line.match(PROJECT_HEADER_REGEX);\n if (projectMatch) {\n projectName = projectMatch[1].trim();\n continue;\n }\n\n // Check for priority header\n const priorityMatch = line.match(PRIORITY_HEADER_REGEX);\n if (priorityMatch) {\n currentPriority = normalizePriority(priorityMatch[1]);\n continue;\n }\n\n // Try to parse as a task line\n const task = this.parseLine(line, currentPriority);\n if (task) {\n // Collect trailing note lines\n while (i + 1 < lines.length) {\n const noteMatch = lines[i + 1].match(NOTE_REGEX);\n if (noteMatch) {\n task.notes.push(noteMatch[1]);\n i++;\n } else {\n break;\n }\n }\n tasks.push(task);\n }\n }\n\n return { projectName, tasks };\n }\n\n parseLine(line: string, currentPriority: TaskPriority): Task | null {\n const match = line.match(TASK_LINE_REGEX);\n if (!match) {\n return null;\n }\n\n const [, checkbox, id, title, assigneeRaw, depsRaw, statusRaw] = match;\n const now = new Date().toISOString();\n\n const assignee = assigneeRaw === 'unassigned' ? null : assigneeRaw.slice(1); // strip @\n\n const deps = depsRaw.trim().toLowerCase() === 'none'\n ? []\n : depsRaw.split(',').map((d) => d.trim()).filter(Boolean);\n\n // Determine status: [x] always means done, otherwise read from status field\n let status: TaskStatus;\n let completedAt: string | null = null;\n\n if (checkbox === 'x') {\n status = 'done';\n // Check for done:<timestamp> in status field\n const doneTimestamp = statusRaw.trim().match(/^done:(\\S+)$/);\n completedAt = doneTimestamp ? doneTimestamp[1] : now;\n } else {\n const parsed = normalizeStatus(statusRaw);\n status = parsed.status;\n completedAt = parsed.completedAt;\n }\n\n return {\n id,\n title: title.trim(),\n description: title.trim(),\n status,\n priority: currentPriority,\n assignee,\n dependencies: deps,\n tags: [],\n createdAt: now,\n updatedAt: now,\n completedAt,\n notes: [],\n };\n }\n}\n","import type { Task, TaskPriority } from '../types/task.js';\n\nconst PRIORITY_ORDER: TaskPriority[] = ['critical', 'high', 'medium', 'low'];\n\nconst PRIORITY_LABELS: Record<TaskPriority, string> = {\n critical: 'Critical',\n high: 'High',\n medium: 'Medium',\n low: 'Low',\n};\n\nexport class TaskWriter {\n write(projectName: string, tasks: Task[]): string {\n const lines: string[] = [];\n\n lines.push(`# Project: ${projectName}`);\n lines.push(`# Generated by Maestro | Last updated: ${new Date().toISOString()}`);\n lines.push('');\n\n for (const priority of PRIORITY_ORDER) {\n const group = tasks.filter((t) => t.priority === priority);\n if (group.length === 0) {\n continue;\n }\n\n lines.push(`## ${PRIORITY_LABELS[priority]}`);\n\n for (const task of group) {\n lines.push(this.formatTask(task));\n }\n\n lines.push('');\n }\n\n return lines.join('\\n');\n }\n\n formatTask(task: Task): string {\n const checkbox = task.status === 'done' ? '[x]' : '[ ]';\n const assignee = task.assignee ? `@${task.assignee}` : 'unassigned';\n const deps = task.dependencies.length > 0 ? task.dependencies.join(',') : 'none';\n\n let statusField: string;\n if (task.status === 'done' && task.completedAt) {\n statusField = `done:${task.completedAt}`;\n } else {\n statusField = task.status;\n }\n\n const line = `- ${checkbox} ${task.id} | ${task.title} | ${assignee} | deps: ${deps} | ${statusField}`;\n\n const noteLines = task.notes.map((note) => ` > ${note}`);\n\n return [line, ...noteLines].join('\\n');\n }\n}\n","import { nanoid } from 'nanoid';\n\nlet taskCounter = 0;\n\nexport function generateId(): string {\n return nanoid(12);\n}\n\nexport function generateTaskId(): string {\n taskCounter++;\n return `T-${String(taskCounter).padStart(3, '0')}`;\n}\n\nexport function resetTaskCounter(startFrom = 0): void {\n taskCounter = startFrom;\n}\n\nexport function setTaskCounter(value: number): void {\n taskCounter = value;\n}\n","import lockfile from 'proper-lockfile';\nimport { access, writeFile } from 'node:fs/promises';\n\nasync function ensureFileExists(filePath: string): Promise<void> {\n try {\n await access(filePath);\n } catch {\n await writeFile(filePath, '', 'utf-8');\n }\n}\n\nexport async function acquireLock(filePath: string): Promise<() => Promise<void>> {\n await ensureFileExists(filePath);\n\n const release = await lockfile.lock(filePath, {\n stale: 10_000,\n retries: {\n retries: 5,\n minTimeout: 100,\n maxTimeout: 1000,\n },\n });\n\n return release;\n}\n\nexport async function withLock<T>(filePath: string, fn: () => Promise<T>): Promise<T> {\n const release = await acquireLock(filePath);\n try {\n return await fn();\n } finally {\n await release();\n }\n}\n","import { readFile, writeFile, access } from 'node:fs/promises';\nimport EventEmitter from 'eventemitter3';\nimport type { Task, TaskFilter, TaskPriority, TaskStatus, TaskUpdate } from '../types/task.js';\nimport { generateTaskId, setTaskCounter } from '../utils/id.js';\nimport { TaskParser } from './parser.js';\nimport { TaskWriter } from './writer.js';\nimport { withLock } from './lock.js';\n\ninterface TaskManagerOptions {\n filePath: string;\n projectName: string;\n}\n\nexport class TaskManager extends EventEmitter {\n private readonly filePath: string;\n private readonly projectName: string;\n private readonly parser: TaskParser;\n private readonly writer: TaskWriter;\n\n constructor(options: TaskManagerOptions) {\n super();\n this.filePath = options.filePath;\n this.projectName = options.projectName;\n this.parser = new TaskParser();\n this.writer = new TaskWriter();\n }\n\n private async ensureFile(): Promise<void> {\n try {\n await access(this.filePath);\n } catch {\n await writeFile(this.filePath, '', 'utf-8');\n }\n }\n\n async load(): Promise<Task[]> {\n await this.ensureFile();\n const content = await readFile(this.filePath, 'utf-8');\n const { tasks } = this.parser.parse(content);\n return tasks;\n }\n\n async save(tasks: Task[]): Promise<void> {\n await withLock(this.filePath, async () => {\n const content = this.writer.write(this.projectName, tasks);\n await writeFile(this.filePath, content, 'utf-8');\n });\n }\n\n async getTask(id: string): Promise<Task | undefined> {\n const tasks = await this.load();\n return tasks.find((t) => t.id === id);\n }\n\n async getTasks(filter?: TaskFilter): Promise<Task[]> {\n const tasks = await this.load();\n\n if (!filter) {\n return tasks;\n }\n\n return tasks.filter((task) => {\n if (filter.status && filter.status.length > 0) {\n if (!filter.status.includes(task.status)) {\n return false;\n }\n }\n\n if (filter.assignee !== undefined) {\n if (task.assignee !== filter.assignee) {\n return false;\n }\n }\n\n if (filter.priority && filter.priority.length > 0) {\n if (!filter.priority.includes(task.priority)) {\n return false;\n }\n }\n\n if (filter.tags && filter.tags.length > 0) {\n if (!filter.tags.some((tag) => task.tags.includes(tag))) {\n return false;\n }\n }\n\n return true;\n });\n }\n\n async createTask(data: {\n title: string;\n priority: TaskPriority;\n description?: string;\n dependencies?: string[];\n tags?: string[];\n }): Promise<Task> {\n const tasks = await this.load();\n\n // Set task counter based on existing max ID\n const maxId = this.extractMaxTaskNumber(tasks);\n setTaskCounter(maxId);\n\n const now = new Date().toISOString();\n const task: Task = {\n id: generateTaskId(),\n title: data.title,\n description: data.description ?? data.title,\n status: 'pending',\n priority: data.priority,\n assignee: null,\n dependencies: data.dependencies ?? [],\n tags: data.tags ?? [],\n createdAt: now,\n updatedAt: now,\n completedAt: null,\n notes: [],\n };\n\n tasks.push(task);\n await this.save(tasks);\n this.emit('task:created', task);\n\n return task;\n }\n\n async updateTask(id: string, update: TaskUpdate): Promise<Task> {\n const tasks = await this.load();\n const index = tasks.findIndex((t) => t.id === id);\n\n if (index === -1) {\n throw new Error(`Task not found: ${id}`);\n }\n\n const task = tasks[index];\n const now = new Date().toISOString();\n\n if (update.status !== undefined) {\n task.status = update.status;\n if (update.status === 'done') {\n task.completedAt = now;\n }\n }\n\n if (update.assignee !== undefined) {\n task.assignee = update.assignee;\n }\n\n if (update.priority !== undefined) {\n task.priority = update.priority;\n }\n\n if (update.notes !== undefined) {\n task.notes = update.notes;\n }\n\n task.updatedAt = now;\n tasks[index] = task;\n\n await this.save(tasks);\n this.emit('task:updated', task);\n\n return task;\n }\n\n async assignTask(id: string, agentId: string): Promise<Task> {\n const tasks = await this.load();\n const index = tasks.findIndex((t) => t.id === id);\n\n if (index === -1) {\n throw new Error(`Task not found: ${id}`);\n }\n\n const task = tasks[index];\n task.assignee = agentId;\n task.updatedAt = new Date().toISOString();\n tasks[index] = task;\n\n await this.save(tasks);\n this.emit('task:assigned', task);\n\n return task;\n }\n\n async completeTask(id: string): Promise<Task> {\n const tasks = await this.load();\n const index = tasks.findIndex((t) => t.id === id);\n\n if (index === -1) {\n throw new Error(`Task not found: ${id}`);\n }\n\n const task = tasks[index];\n const now = new Date().toISOString();\n task.status = 'done';\n task.completedAt = now;\n task.updatedAt = now;\n tasks[index] = task;\n\n await this.save(tasks);\n this.emit('task:completed', task);\n\n return task;\n }\n\n private extractMaxTaskNumber(tasks: Task[]): number {\n let max = 0;\n for (const task of tasks) {\n const match = task.id.match(/^T-(\\d+)$/);\n if (match) {\n const num = parseInt(match[1], 10);\n if (num > max) {\n max = num;\n }\n }\n }\n return max;\n }\n}\n","import pino from 'pino';\nimport { openSync, closeSync, writeSync, mkdirSync } from 'node:fs';\nimport { dirname } from 'node:path';\n\n// Simple synchronous file stream for pino that works in bundled Electron\nclass SyncFileStream {\n private fd: number | null = null;\n\n constructor(private destination: string) {\n try {\n mkdirSync(dirname(destination), { recursive: true });\n this.fd = openSync(destination, 'a');\n } catch {\n // If we can't open the file, we'll silently drop logs\n }\n }\n\n write(chunk: string): void {\n if (this.fd !== null) {\n try {\n writeSync(this.fd, chunk);\n } catch {\n // Ignore write errors\n }\n }\n }\n\n end(): void {\n if (this.fd !== null) {\n closeSync(this.fd);\n this.fd = null;\n }\n }\n}\n\n/**\n * Create a pino logger that writes only to a log file (if provided).\n * Console output is intentionally disabled — all user-facing info is\n * surfaced through orchestrator:activity events and the TUI/CLI handlers.\n * This avoids pino output bleeding into the terminal and corrupting the TUI.\n *\n * Uses synchronous file writes to avoid transport/worker thread issues in Electron.\n */\nexport function createLogger(name: string, logFile?: string): pino.Logger {\n const stream = logFile ? new SyncFileStream(logFile) : null;\n\n return pino(\n {\n name,\n level: 'trace',\n },\n stream ?? { write: () => {} } // No-op stream if no log file\n );\n}\n","import { execa, type ResultPromise } from 'execa';\nimport treeKill from 'tree-kill';\nimport { EventEmitter } from 'eventemitter3';\nimport { homedir } from 'node:os';\nimport type { AgentConfig, AgentState, AgentStreamEvent, AgentStatus } from '../types/agent.js';\nimport { createLogger } from '../utils/logger.js';\n\nconst logger = createLogger('agent-process');\n\ninterface AgentProcessEvents {\n 'output': (event: AgentStreamEvent) => void;\n 'status-changed': (oldStatus: AgentStatus, newStatus: AgentStatus) => void;\n 'error': (error: Error) => void;\n 'stopped': (exitCode: number | null) => void;\n}\n\nfunction killProcessTree(pid: number, signal?: string): Promise<void> {\n return new Promise((resolve, reject) => {\n treeKill(pid, signal, (err) => {\n if (err) {\n reject(err);\n } else {\n resolve();\n }\n });\n });\n}\n\nexport class AgentProcess extends EventEmitter<AgentProcessEvents> {\n private subprocess: ResultPromise | null = null;\n private state: AgentState;\n private streamBuffer: string = '';\n\n constructor(private readonly config: AgentConfig) {\n super();\n this.state = {\n config,\n status: 'idle',\n pid: null,\n sessionId: null,\n currentTask: null,\n startedAt: null,\n lastActivityAt: null,\n totalCostUsd: 0,\n turnCount: 0,\n totalInputTokens: 0,\n totalOutputTokens: 0,\n totalCacheReadTokens: 0,\n totalCacheCreationTokens: 0,\n error: null,\n resultError: null,\n rateLimited: false,\n rateLimitResetAt: null,\n };\n }\n\n get id(): string {\n return this.config.id;\n }\n\n get currentState(): AgentState {\n return { ...this.state };\n }\n\n /**\n * Set the current task this agent is working on (task ID + title).\n */\n setCurrentTask(taskInfo: string | null): void {\n this.state.currentTask = taskInfo;\n }\n\n /**\n * Spawn a claude CLI process with the given prompt.\n */\n async spawn(prompt: string): Promise<void> {\n if (this.subprocess) {\n throw new Error(`Agent ${this.id} already has a running process`);\n }\n\n const args = this.buildArgs();\n\n this.setStatus('starting');\n\n const cmd = this.config.claudeCommand ?? 'claude';\n\n logger.info(\n { agentId: this.id, cmd, argCount: args.length, promptLength: prompt.length },\n 'Spawning agent process',\n );\n\n this.subprocess = execa(cmd, args, {\n input: prompt,\n cwd: this.config.workingDirectory,\n env: this.config.claudeEnv ? { ...process.env, ...this.config.claudeEnv } : undefined,\n stdout: 'pipe',\n stderr: 'pipe',\n reject: false,\n });\n\n this.state.pid = this.subprocess.pid ?? null;\n this.state.startedAt = new Date().toISOString();\n this.state.error = null;\n this.state.resultError = null;\n this.state.rateLimited = false;\n this.state.rateLimitResetAt = null;\n\n logger.info({ agentId: this.id, pid: this.state.pid }, 'Agent process started');\n\n this.setStatus('running');\n\n // Emit a synthetic output event with PID info\n this.emitOutput('system', { message: `Process started (PID: ${this.state.pid ?? 'unknown'})`, cmd, argCount: args.length });\n\n // Process stdout and stderr in parallel\n this.processStream().catch((err) => {\n this.state.error = err instanceof Error ? err.message : String(err);\n this.emit('error', err instanceof Error ? err : new Error(String(err)));\n });\n this.processStderr().catch(() => {});\n }\n\n /**\n * Resume a previous session with a new prompt.\n */\n async resume(prompt: string): Promise<void> {\n if (!this.state.sessionId) {\n throw new Error(`Agent ${this.id} has no session to resume`);\n }\n if (this.subprocess) {\n throw new Error(`Agent ${this.id} already has a running process`);\n }\n\n const args = this.buildArgs();\n args.push('--resume', this.state.sessionId);\n\n this.setStatus('starting');\n\n const cmd = this.config.claudeCommand ?? 'claude';\n\n logger.info({ agentId: this.id, cmd, sessionId: this.state.sessionId }, 'Resuming agent process');\n\n this.subprocess = execa(cmd, args, {\n input: prompt,\n cwd: this.config.workingDirectory,\n env: this.config.claudeEnv ? { ...process.env, ...this.config.claudeEnv } : undefined,\n stdout: 'pipe',\n stderr: 'pipe',\n reject: false,\n });\n\n this.state.pid = this.subprocess.pid ?? null;\n this.state.startedAt = new Date().toISOString();\n this.state.error = null;\n this.state.resultError = null;\n this.state.rateLimited = false;\n this.state.rateLimitResetAt = null;\n\n logger.info({ agentId: this.id, pid: this.state.pid }, 'Agent process resumed');\n\n this.setStatus('running');\n\n this.emitOutput('system', { message: `Process resumed (PID: ${this.state.pid ?? 'unknown'})` });\n\n this.processStream().catch((err) => {\n this.state.error = err instanceof Error ? err.message : String(err);\n this.emit('error', err instanceof Error ? err : new Error(String(err)));\n });\n this.processStderr().catch(() => {});\n }\n\n /**\n * Graceful stop: SIGTERM, wait, then force kill.\n */\n async stop(timeoutMs = 10000): Promise<void> {\n if (!this.subprocess || !this.state.pid) {\n return;\n }\n\n this.setStatus('stopping');\n\n try {\n // Send SIGTERM to the process\n this.subprocess.kill('SIGTERM');\n\n // Wait for the process to exit or timeout\n const timeoutPromise = new Promise<'timeout'>((resolve) =>\n setTimeout(() => resolve('timeout'), timeoutMs),\n );\n\n const exitPromise = this.subprocess.then(() => 'exited' as const);\n\n const result = await Promise.race([exitPromise, timeoutPromise]);\n\n if (result === 'timeout' && this.state.pid) {\n // Force kill the entire process tree\n await killProcessTree(this.state.pid, 'SIGKILL');\n }\n } catch {\n // If anything fails, attempt a hard kill\n if (this.state.pid) {\n try {\n await killProcessTree(this.state.pid, 'SIGKILL');\n } catch {\n // Process may already be dead\n }\n }\n } finally {\n this.subprocess = null;\n this.setStatus('stopped');\n }\n }\n\n /**\n * Force kill immediately.\n */\n async kill(): Promise<void> {\n if (!this.subprocess || !this.state.pid) {\n return;\n }\n\n try {\n await killProcessTree(this.state.pid, 'SIGKILL');\n } catch {\n // Process may already be dead\n } finally {\n this.subprocess = null;\n this.setStatus('stopped');\n }\n }\n\n /**\n * Build CLI arguments for the claude command.\n * The prompt is piped via stdin, not passed as a positional argument.\n */\n private buildArgs(): string[] {\n const args: string[] = [\n '--print',\n '--output-format', 'stream-json',\n '--verbose',\n '--model', this.config.model ?? 'sonnet',\n ];\n\n // Pass permission mode (acceptEdits, bypassPermissions, default, etc.)\n if (this.config.permissionMode && this.config.permissionMode !== 'default') {\n args.push('--permission-mode', this.config.permissionMode);\n }\n\n if (this.config.systemPrompt) {\n args.push('--system-prompt', this.config.systemPrompt);\n }\n\n if (this.config.allowedTools && this.config.allowedTools.length > 0) {\n args.push('--allowedTools', this.config.allowedTools.join(','));\n }\n\n if (this.config.maxBudgetUsd !== undefined) {\n args.push('--max-budget-usd', String(this.config.maxBudgetUsd));\n }\n\n // Append custom CLI args from config (settings-level + per-agent merged)\n if (this.config.claudeArgs && this.config.claudeArgs.length > 0) {\n args.push(...this.config.claudeArgs);\n }\n\n return args;\n }\n\n /**\n * Parse NDJSON stream from claude stdout.\n * Reads stdout line by line and emits typed events.\n */\n private async processStream(): Promise<void> {\n if (!this.subprocess || !this.subprocess.stdout) {\n return;\n }\n\n const stdout = this.subprocess.stdout;\n\n for await (const chunk of stdout) {\n const text = typeof chunk === 'string' ? chunk : chunk.toString('utf-8');\n this.streamBuffer += text;\n\n // Process complete lines from the buffer\n let newlineIndex: number;\n while ((newlineIndex = this.streamBuffer.indexOf('\\n')) !== -1) {\n const line = this.streamBuffer.slice(0, newlineIndex).trim();\n this.streamBuffer = this.streamBuffer.slice(newlineIndex + 1);\n\n if (!line) {\n continue;\n }\n\n try {\n const parsed = JSON.parse(line) as Record<string, unknown>;\n const eventType = (parsed.type as string) ?? 'unknown';\n const now = new Date().toISOString();\n\n const streamEvent: AgentStreamEvent = {\n type: eventType as AgentStreamEvent['type'],\n agentId: this.id,\n timestamp: now,\n data: parsed,\n };\n\n // Capture session_id from system events\n if (eventType === 'system' && typeof parsed.session_id === 'string') {\n this.state.sessionId = parsed.session_id;\n }\n\n // Capture cost, turn count, and token usage from result events\n if (eventType === 'result') {\n if (typeof parsed.cost_usd === 'number') {\n this.state.totalCostUsd = parsed.cost_usd;\n }\n if (typeof parsed.num_turns === 'number') {\n this.state.turnCount = parsed.num_turns;\n }\n\n // Capture token usage\n const usage = parsed.usage as Record<string, unknown> | undefined;\n if (usage && typeof usage === 'object') {\n if (typeof usage.input_tokens === 'number') {\n this.state.totalInputTokens = usage.input_tokens;\n }\n if (typeof usage.output_tokens === 'number') {\n this.state.totalOutputTokens = usage.output_tokens;\n }\n if (typeof usage.cache_read_input_tokens === 'number') {\n this.state.totalCacheReadTokens = usage.cache_read_input_tokens;\n }\n if (typeof usage.cache_creation_input_tokens === 'number') {\n this.state.totalCacheCreationTokens = usage.cache_creation_input_tokens;\n }\n }\n\n // Detect API errors from result events (is_error: true)\n if (parsed.is_error === true) {\n const resultText = typeof parsed.result === 'string' ? parsed.result : '';\n this.state.resultError = resultText || 'Unknown API error';\n\n // Check for rate-limit (429) errors\n if (resultText.includes('429') || resultText.includes('Usage limit reached') || resultText.includes('rate limit')) {\n this.state.rateLimited = true;\n // Extract reset time if present\n const resetMatch = resultText.match(/will reset at ([0-9T :.-]+)/);\n if (resetMatch) {\n this.state.rateLimitResetAt = resetMatch[1].trim();\n }\n logger.warn(\n { agentId: this.id, resetAt: this.state.rateLimitResetAt },\n 'Agent hit API rate limit (429)',\n );\n }\n }\n }\n\n this.state.lastActivityAt = now;\n this.emit('output', streamEvent);\n } catch {\n // Line is not valid JSON — emit it as raw text output so it's visible\n this.emitOutput('system', { message: `[stdout] ${line}` });\n }\n }\n }\n\n // Stream ended - wait for the process to exit\n const result = await this.subprocess;\n const exitCode = result?.exitCode ?? null;\n\n this.subprocess = null;\n\n if (this.state.resultError) {\n // The API returned an error in the result (e.g. rate limit 429).\n // Even though the process exited cleanly, treat it as an error.\n this.state.error = this.state.resultError;\n this.emitOutput('error', {\n error: this.state.resultError,\n rateLimited: this.state.rateLimited,\n rateLimitResetAt: this.state.rateLimitResetAt,\n });\n this.setStatus('error');\n } else if (exitCode === 0 || exitCode === null) {\n this.setStatus('stopped');\n } else {\n this.state.error = `Process exited with code ${exitCode}`;\n this.emitOutput('error', { error: `Process exited with code ${exitCode}`, stderr: result?.stderr?.slice(0, 500) });\n this.setStatus('error');\n }\n\n this.emit('stopped', exitCode);\n }\n\n /**\n * Read stderr and emit lines as error events so they're visible.\n */\n private async processStderr(): Promise<void> {\n if (!this.subprocess || !this.subprocess.stderr) {\n return;\n }\n\n let stderrBuffer = '';\n const stderr = this.subprocess.stderr;\n\n for await (const chunk of stderr) {\n const text = typeof chunk === 'string' ? chunk : chunk.toString('utf-8');\n stderrBuffer += text;\n\n let newlineIndex: number;\n while ((newlineIndex = stderrBuffer.indexOf('\\n')) !== -1) {\n const line = stderrBuffer.slice(0, newlineIndex).trim();\n stderrBuffer = stderrBuffer.slice(newlineIndex + 1);\n\n if (line) {\n logger.warn({ agentId: this.id, stderr: line }, 'Agent stderr output');\n this.emitOutput('error', { error: line, source: 'stderr' });\n }\n }\n }\n\n // Flush any remaining stderr\n const remaining = stderrBuffer.trim();\n if (remaining) {\n logger.warn({ agentId: this.id, stderr: remaining }, 'Agent stderr output');\n this.emitOutput('error', { error: remaining, source: 'stderr' });\n }\n }\n\n /**\n * Emit a synthetic output event.\n */\n private emitOutput(type: AgentStreamEvent['type'], data: Record<string, unknown>): void {\n this.emit('output', {\n type,\n agentId: this.id,\n timestamp: new Date().toISOString(),\n data,\n });\n }\n\n /**\n * Update internal state and emit status change events.\n */\n private setStatus(status: AgentStatus): void {\n const oldStatus = this.state.status;\n if (oldStatus === status) {\n return;\n }\n this.state.status = status;\n this.emit('status-changed', oldStatus, status);\n }\n}\n","import { EventEmitter } from 'eventemitter3';\nimport { AgentProcess } from './lifecycle.js';\nimport type { AgentConfig, AgentRole, AgentStatus, AgentStreamEvent } from '../types/agent.js';\n\ninterface AgentPoolEvents {\n 'agent:spawned': (agentId: string, process: AgentProcess) => void;\n 'agent:output': (event: AgentStreamEvent) => void;\n 'agent:status-changed': (agentId: string, oldStatus: AgentStatus, newStatus: AgentStatus) => void;\n 'agent:error': (agentId: string, error: Error) => void;\n 'agent:stopped': (agentId: string, exitCode: number | null) => void;\n}\n\nexport class AgentPool extends EventEmitter<AgentPoolEvents> {\n private agents: Map<string, AgentProcess> = new Map();\n\n /**\n * Spawn a new agent process with the given config and initial prompt.\n */\n async spawnAgent(config: AgentConfig, prompt: string): Promise<AgentProcess> {\n if (this.agents.has(config.id)) {\n throw new Error(`Agent with id \"${config.id}\" already exists in the pool`);\n }\n\n const agent = new AgentProcess(config);\n this.agents.set(config.id, agent);\n\n // Forward events from the individual agent to the pool\n this.attachListeners(agent);\n\n await agent.spawn(prompt);\n\n this.emit('agent:spawned', agent.id, agent);\n\n return agent;\n }\n\n /**\n * Stop a specific agent by ID with an optional timeout.\n */\n async stopAgent(id: string, timeoutMs?: number): Promise<void> {\n const agent = this.agents.get(id);\n if (!agent) {\n throw new Error(`Agent \"${id}\" not found in pool`);\n }\n await agent.stop(timeoutMs);\n }\n\n /**\n * Stop all agents concurrently. Uses Promise.allSettled for graceful handling.\n */\n async stopAll(timeoutMs?: number): Promise<void> {\n const stopPromises = Array.from(this.agents.values()).map((agent) =>\n agent.stop(timeoutMs),\n );\n await Promise.allSettled(stopPromises);\n }\n\n /**\n * Remove a stopped agent from the pool so it can be re-spawned.\n */\n removeAgent(id: string): void {\n const agent = this.agents.get(id);\n if (!agent) return;\n const status = agent.currentState.status;\n if (status !== 'stopped' && status !== 'error') {\n throw new Error(`Cannot remove agent \"${id}\" with status \"${status}\" — must be stopped or error`);\n }\n this.agents.delete(id);\n }\n\n /**\n * Get an agent process by ID.\n */\n getAgent(id: string): AgentProcess | undefined {\n return this.agents.get(id);\n }\n\n /**\n * Get all agents with a specific role.\n */\n getAgentsByRole(role: AgentRole): AgentProcess[] {\n return Array.from(this.agents.values()).filter(\n (agent) => agent.currentState.config.role === role,\n );\n }\n\n /**\n * Get all agents with a specific status.\n */\n getAgentsByStatus(status: AgentStatus): AgentProcess[] {\n return Array.from(this.agents.values()).filter(\n (agent) => agent.currentState.status === status,\n );\n }\n\n /**\n * Get all agents in the pool.\n */\n getAllAgents(): AgentProcess[] {\n return Array.from(this.agents.values());\n }\n\n /**\n * Get aggregate statistics across all agents.\n */\n getStats(): { total: number; running: number; idle: number; stopped: number; totalCostUsd: number } {\n let running = 0;\n let idle = 0;\n let stopped = 0;\n let totalCostUsd = 0;\n\n for (const agent of this.agents.values()) {\n const state = agent.currentState;\n switch (state.status) {\n case 'running':\n case 'starting':\n running++;\n break;\n case 'idle':\n idle++;\n break;\n case 'stopped':\n case 'stopping':\n case 'error':\n stopped++;\n break;\n }\n totalCostUsd += state.totalCostUsd;\n }\n\n return {\n total: this.agents.size,\n running,\n idle,\n stopped,\n totalCostUsd,\n };\n }\n\n /**\n * Attach event forwarding listeners from an agent process to the pool.\n */\n private attachListeners(agent: AgentProcess): void {\n agent.on('output', (event: AgentStreamEvent) => {\n this.emit('agent:output', event);\n });\n\n agent.on('status-changed', (oldStatus: AgentStatus, newStatus: AgentStatus) => {\n this.emit('agent:status-changed', agent.id, oldStatus, newStatus);\n });\n\n agent.on('error', (error: Error) => {\n this.emit('agent:error', agent.id, error);\n });\n\n agent.on('stopped', (exitCode: number | null) => {\n this.emit('agent:stopped', agent.id, exitCode);\n });\n }\n}\n","import type { AgentRole } from '../types/agent.js';\nimport type { TechStackConfig } from '../types/project.js';\n\nexport const ROLE_DESCRIPTIONS: Record<AgentRole, string> = {\n orchestrator:\n 'The orchestrator is the top-level coordinator. It breaks down high-level goals into tasks, ' +\n 'assigns work to other agents, monitors progress, resolves conflicts, and ensures the overall ' +\n 'project stays on track. It communicates directives and reviews results from all other agents.',\n\n 'project-manager':\n 'The project manager tracks priorities, manages dependencies between tasks, updates timelines, ' +\n 'and ensures work is progressing according to plan. It identifies blockers, re-prioritizes when ' +\n 'needed, and keeps the task board organized and up to date.',\n\n architect:\n 'The architect designs the system architecture, makes key technical decisions, defines API ' +\n 'contracts, reviews design proposals, and ensures the codebase maintains structural integrity. ' +\n 'It provides guidance on patterns, technology choices, and code organization.',\n\n developer:\n 'The developer implements features, writes production code, fixes bugs, writes tests, and ' +\n 'ensures code quality. It follows the architecture guidelines, writes clean and well-tested ' +\n 'code, and reports progress on assigned tasks.',\n\n designer:\n 'The designer handles UI/UX design decisions, creates component structures, defines styling ' +\n 'and theming systems, ensures accessibility standards, and maintains visual consistency ' +\n 'across the application.',\n\n 'qa-engineer':\n 'The QA engineer ensures software quality through comprehensive testing strategies. It writes ' +\n 'and maintains test suites (unit, integration, e2e), identifies edge cases, validates ' +\n 'requirements coverage, and reports bugs with clear reproduction steps.',\n\n devops:\n 'The DevOps engineer handles infrastructure, CI/CD pipelines, deployment configurations, ' +\n 'containerization (Docker), environment setup, monitoring, and build tooling. It ensures ' +\n 'the project can be reliably built, tested, and deployed.',\n\n 'technical-writer':\n 'The technical writer creates and maintains project documentation including README files, ' +\n 'API documentation, architecture decision records, user guides, setup instructions, and ' +\n 'inline code documentation. It ensures docs stay accurate and accessible.',\n\n 'code-reviewer':\n 'The code reviewer examines completed work for correctness, security, performance, and ' +\n 'adherence to project standards. It provides constructive feedback, identifies potential ' +\n 'issues, and verifies that changes align with the architecture.',\n};\n\nconst TODO_FORMAT_INSTRUCTIONS = `\n## Todo File Format\n\nThe shared todo file uses markdown: sections for Pending, In Progress, Done, Blocked.\n\nEach task line: \\`- [ ] T-XXX: Title [priority:high] [assignee:agent-id]\\` with a description on the indented line below. Mark done tasks with \\`[x]\\`. Use \\`[blocked-by:T-XXX]\\` for dependencies.\n`.trim();\n\nconst MESSAGE_FORMAT_INSTRUCTIONS = `\n## Messaging System\n\n**Inbox**: Check your inbox directory for JSON message files. Read all pending messages regularly.\n**Outbox**: To send a message, write a JSON file to your outbox directory.\n\nMessage format: \\`{ \"message\": { \"id\": \"unique-id\", \"type\": \"<type>\", \"from\": \"<your-id>\", \"to\": \"<recipient-id>\", \"subject\": \"...\", \"body\": \"...\", \"priority\": \"normal|urgent\", \"timestamp\": \"ISO date\" }, \"status\": \"pending\" }\\`\n\nTypes: task-assignment, task-update, task-complete, task-blocked, question, answer, review-request, review-result, system, directive\n`.trim();\n\nconst PROCESS_SAFETY_RULES = `\n## Process Safety Rules\n\nYou run in a shared multi-agent environment. Resource-intensive processes starve other agents and destabilize the system. The following are **strictly forbidden**:\n\n**No Docker**: \\`docker build\\`, \\`docker run\\`, \\`docker compose up\\`, \\`docker pull/push/exec\\`, \\`podman build/run\\`. You MAY write Dockerfiles and compose configs.\n\n**No servers**: \\`npm run dev\\`, \\`npm start\\`, \\`next dev\\`, \\`vite\\`, \\`flask run\\`, \\`uvicorn\\`, \\`rails server\\`, \\`nodemon\\`, or any process that listens on a port.\n\n**Instead**: Write code and config files. Run only targeted tests (single file). Use lightweight commands (lint, type-check single files). If you need a build or server, message the user.\n`.trim();\n\nconst ROLE_SPECIFIC_INSTRUCTIONS: Record<AgentRole, string> = {\n orchestrator: `\n## Orchestrator-Specific Instructions\n\nYou are the central coordinator for this project. Your responsibilities:\n\n1. **Goal Decomposition**: Break down high-level project goals into concrete, actionable tasks.\n Write these tasks to the shared todo file with clear descriptions and priorities.\n\n2. **Task Assignment**: Assign tasks to the most appropriate agents based on their roles:\n - Architecture and design decisions -> architect\n - Implementation and coding -> developer\n - UI/UX, styling, components -> designer\n - Testing, QA, test suites -> qa-engineer\n - CI/CD, Docker, deployment, infrastructure -> devops\n - Documentation, README, API docs -> technical-writer\n - Code review, security review -> code-reviewer\n - Scheduling and tracking -> project-manager\n\n3. **Progress Monitoring**: Regularly check the todo file and inbox for updates. Track which\n tasks are in progress, completed, or blocked.\n\n4. **Coordination**: When tasks have dependencies, ensure they are executed in the right order.\n Resolve conflicts between agents. Re-assign work if an agent is overloaded. When QA\n returns a task, ensure the project-manager reassigns it to a developer promptly — blocked\n tasks stall all their dependents and can halt the entire project.\n\n5. **Quality Control**: Review completed work by examining task completion messages.\n Request revisions if needed by sending review-request messages.\n\n6. **Decision Making**: Make final calls on technical disputes, prioritization conflicts,\n and scope questions. Send directives when needed.\n\nDo NOT implement code yourself. Your job is to coordinate, not to code.\n`.trim(),\n\n 'project-manager': `\n## Project Manager-Specific Instructions\n\nYou manage the project timeline, priorities, and dependencies. Your responsibilities:\n\n1. **Priority Management**: Keep tasks properly prioritized. Escalate critical items.\n Re-order work based on changing requirements or blockers.\n\n2. **Dependency Tracking**: Identify and document task dependencies using blocked-by tags.\n Alert the orchestrator when circular dependencies or bottlenecks are detected.\n\n3. **Timeline Updates**: Track progress rates and estimate remaining work. Update task\n descriptions with timeline notes when appropriate.\n\n4. **Blocker Resolution**: When a task is blocked, investigate the cause by checking\n dependent tasks and sending questions to the relevant agents.\n\n5. **Status Reporting**: Periodically summarize project status for the orchestrator,\n including completed tasks, active work, blockers, and risks.\n\n6. **Todo Organization**: Keep the todo file clean and well-organized. Move completed\n tasks to the Done section. Archive old items. Ensure consistent formatting.\n\n7. **Task Reassignment & QA Returns**: You have the authority to reassign tasks between\n agents. This is critical for unblocking the pipeline. When QA reports a blocker on a\n task (missing files, broken implementation, failing tests), you MUST:\n a. Move the task from Blocked back to In Progress in the todo file.\n b. Change the assignee from the qa-engineer to an available developer.\n c. Add a note: \\`> [returned] Returned from QA: <reason>\\`\n d. Set the priority to high (QA returns are rework and block downstream tasks).\n e. Send a task-assignment message to the developer with the QA findings.\n f. Send a task-update message to the orchestrator about the reassignment.\n\n Do NOT leave QA-blocked tasks sitting. Every blocked task potentially stalls all its\n dependents. Act on QA returns immediately — they are your highest-priority pipeline work.\n\nFocus on process and organization. Do NOT make technical decisions or write code.\n`.trim(),\n\n architect: `\n## Architect-Specific Instructions\n\nYou design the system architecture and make technical decisions. Your responsibilities:\n\n1. **System Design**: Create and maintain the technical architecture. Document key\n design decisions, API contracts, data models, and component boundaries.\n\n2. **Technology Choices**: Evaluate and select appropriate technologies, libraries,\n and patterns. Justify decisions with clear reasoning.\n\n3. **Code Organization**: Define the project structure, module boundaries, naming\n conventions, and file organization patterns.\n\n4. **Design Reviews**: When developers send review-request messages, evaluate the\n approach against the architecture. Provide specific, actionable feedback.\n\n5. **Pattern Guidance**: Establish coding patterns, error handling strategies,\n and best practices. Document these for the development team.\n\n6. **Technical Debt**: Identify areas of technical debt and propose refactoring\n plans when appropriate.\n\n7. **ARCHITECTURE.md Ownership**: You own ARCHITECTURE.md. Keep it current whenever you\n make design decisions. All other agents rely on it as the source of truth — if it is\n outdated or missing, they will make incorrect assumptions.\n\nYou may write architectural documentation, design specs, and configuration files,\nbut delegate implementation work to developers.\n`.trim(),\n\n developer: `\n## Developer-Specific Instructions\n\nYou implement features, write code, and fix bugs. Your responsibilities:\n\n1. **Implementation**: Read ARCHITECTURE.md before writing any code. Follow its structure,\n patterns, and conventions. Implement features assigned to you in the todo file.\n\n2. **Testing**: Write unit tests, integration tests, and any other tests needed to\n verify your work. Aim for good test coverage on critical paths.\n\n3. **Bug Fixes**: When assigned bugs, investigate the root cause, implement a fix,\n and verify with tests.\n\n4. **Code Quality**: Follow established patterns and conventions. Write clear comments\n where logic is complex. Keep functions focused and composable.\n\n5. **Progress Updates**: When you start, complete, or get blocked on a task, update\n the todo file and send appropriate messages to the orchestrator.\n\n6. **Review & QA Response**: When you receive review-result or task-assignment messages\n with QA feedback, treat them as high priority. QA returns mean a task was sent back\n because implementation was missing or broken — read the \\`[BLOCKER]\\` and \\`[returned]\\`\n notes in the todo file, fix the root cause, then mark the task done so QA can re-verify.\n\n7. **Process Boundaries**: Your job is to write code and tests, NOT to build, compile, or\n run the project. Do not start servers or run full test suites. If you need to verify a specific\n piece of logic, run a single targeted test file. Write the code; let the CI pipeline\n and the user handle builds and deployments.\n\nFocus on writing excellent code. Ask the architect (via messages) if you are unsure\nabout design decisions. Report blockers promptly.\n`.trim(),\n\n designer: `\n## Designer-Specific Instructions\n\nYou handle UI/UX design and visual implementation. Your responsibilities:\n\n1. **Component Design**: Design and implement UI components with clear, reusable\n structures. Define component APIs (props, events, slots).\n\n2. **Styling System**: Create and maintain the design system: colors, typography,\n spacing, breakpoints, and theme configuration.\n\n3. **Layout Architecture**: Design page layouts, navigation structures, and\n responsive behavior. Ensure consistency across views.\n\n4. **Accessibility**: Ensure all UI components meet accessibility standards (WCAG).\n Include proper ARIA attributes, keyboard navigation, and screen reader support.\n\n5. **Visual Consistency**: Maintain visual coherence across the application.\n Review UI-related code changes for design consistency.\n\n6. **Design Documentation**: Document design tokens, component usage patterns,\n and visual guidelines for the development team.\n\nYou write UI code (components, styles, layouts). Coordinate with developers on\nintegration and with the architect on component architecture.\n`.trim(),\n\n 'qa-engineer': `\n## QA Engineer-Specific Instructions\n\nYou ensure software quality through testing and validation. Your responsibilities:\n\n1. **Test Strategy**: Design comprehensive testing strategies covering unit tests,\n integration tests, and end-to-end tests. Identify critical paths that need coverage.\n\n2. **Test Implementation**: Write automated tests using the project's testing framework.\n Cover happy paths, edge cases, error conditions, and boundary values.\n\n3. **Bug Reporting & QA Returns**: When you find bugs or missing implementation, you must\n act immediately — do not just mark a task blocked and wait. Document the issue clearly\n (reproduction steps, expected vs actual behavior, missing files), then:\n a. Add a \\`> [BLOCKER]\\` note to the task in the todo file with specifics.\n b. Send a task-blocked message to the **project-manager** (not just the orchestrator)\n so they can reassign the task back to a developer.\n c. Add a \\`> [pipeline] Returned from QA to develop - <reason>\\` note.\n The project manager will handle reassignment. Do not keep working on a task that has\n missing or fundamentally broken implementation — return it.\n\n4. **Requirements Validation**: Verify that implementations match the task descriptions\n and acceptance criteria. Flag gaps between requirements and implementation.\n\n5. **Regression Testing**: Ensure new changes don't break existing functionality.\n Maintain test suites that catch regressions early.\n\n6. **Test Documentation**: Document test coverage, testing patterns, and any manual\n test procedures that cannot be automated.\n\n7. **Process Boundaries**: Write tests, but be cautious about executing them. Run only\n targeted, specific test files — never a full test suite (e.g. \\`npm test\\` or \\`pytest\\`\n with no arguments). A single test file that takes more than 60 seconds likely indicates\n an integration test that depends on external services; skip it and flag it for manual\n execution. Do not start servers, databases, or other services as part of testing.\n\nFocus on finding issues before they reach production. Coordinate with developers on\nbug fixes and with the architect on testability of the design.\n`.trim(),\n\n devops: `\n## DevOps-Specific Instructions\n\nYou handle infrastructure, deployment, and build tooling. Your responsibilities:\n\n1. **CI/CD Pipeline**: Set up and maintain continuous integration and deployment pipelines.\n Configure build, test, lint, and deploy stages.\n\n2. **Containerization**: Create and maintain Dockerfiles, docker-compose configurations,\n and container orchestration setups as needed.\n\n3. **Environment Configuration**: Set up development, staging, and production environment\n configurations. Manage environment variables, secrets handling, and config files.\n\n4. **Build Tooling**: Configure and optimize build tools, bundlers, and compilation\n pipelines. Ensure fast, reliable builds.\n\n5. **Monitoring & Logging**: Set up application monitoring, error tracking, health checks,\n and structured logging where applicable.\n\n6. **Infrastructure as Code**: Define infrastructure using code (Terraform, CloudFormation,\n etc.) when applicable. Document deployment procedures.\n\n7. **Process Boundaries**: You write configuration, you do NOT execute it. Do not run\n \\`docker build\\`, \\`docker run\\`, \\`docker compose up\\`, or any Docker commands. Do not\n run build pipelines, start servers, or execute deployment scripts. Write the Dockerfiles,\n CI configs, and shell scripts — the actual execution happens in CI/CD or by the user.\n\nWrite configuration files, scripts, and infrastructure code. Do NOT execute Docker\ncommands, build pipelines, or deployment scripts in this environment. Coordinate with\ndevelopers on build requirements and with the architect on deployment architecture.\n`.trim(),\n\n 'technical-writer': `\n## Technical Writer-Specific Instructions\n\nYou create and maintain project documentation. Your responsibilities:\n\n1. **README & Setup Guides**: Write clear README files with project overview, setup\n instructions, prerequisites, and quickstart guides.\n\n2. **API Documentation**: Document public APIs, endpoints, request/response formats,\n authentication, and error codes. Keep API docs in sync with implementation.\n\n3. **Architecture Documentation**: Work with the architect to document system design,\n data flow diagrams, component relationships, and design decisions (ADRs).\n\n4. **User Guides**: Write end-user documentation, tutorials, and how-to guides that\n explain features and workflows in accessible language.\n\n5. **Code Documentation**: Review code for missing or outdated inline documentation.\n Add JSDoc/docstrings to public interfaces, complex functions, and non-obvious logic.\n\n6. **Changelog & Release Notes**: Maintain changelogs and write release notes that\n clearly communicate changes, fixes, and breaking changes.\n\nWrite documentation files (markdown, JSDoc, etc.). Coordinate with all team members\nto ensure docs accurately reflect the current state of the project.\n`.trim(),\n\n 'code-reviewer': `\n## Code Reviewer-Specific Instructions\n\nYou review completed work for quality and correctness. Your responsibilities:\n\n1. **Code Review**: Examine implementation code for correctness, readability, and\n adherence to project conventions. Check for logic errors, off-by-one errors,\n and edge case handling.\n\n2. **Security Review**: Identify potential security vulnerabilities: injection attacks,\n authentication/authorization issues, data exposure, and insecure defaults.\n\n3. **Performance Review**: Flag performance anti-patterns: N+1 queries, unnecessary\n re-renders, memory leaks, missing indexes, and inefficient algorithms.\n\n4. **Standards Compliance**: Verify code follows ARCHITECTURE.md, naming conventions,\n file organization patterns, and coding standards. Flag deviations.\n\n5. **Feedback Delivery**: Provide specific, constructive feedback. Distinguish between\n blocking issues and suggestions. Include code examples for recommended changes.\n\n6. **Verification**: After developers address review feedback, verify the changes\n resolve the identified issues without introducing new problems.\n\nDo NOT implement changes yourself. Send review-result messages with specific feedback.\nCoordinate with the architect on design-level concerns and developers on implementation.\n`.trim(),\n};\n\nexport interface SystemPromptParams {\n role: AgentRole;\n agentId: string;\n projectName: string;\n todoFilePath: string;\n inboxPath: string;\n outboxPath: string;\n workingDirectory: string;\n techStack?: TechStackConfig;\n}\n\nfunction buildTechStackSection(ts?: TechStackConfig): string {\n if (!ts) return '';\n const lines: string[] = ['# Tech Stack'];\n if (ts.frontend) lines.push(`- **Frontend**: ${ts.frontend}`);\n if (ts.uiLibrary) lines.push(`- **UI Library**: ${ts.uiLibrary}`);\n if (ts.backend) lines.push(`- **Backend**: ${ts.backend}`);\n if (ts.database) lines.push(`- **Database**: ${ts.database}`);\n if (ts.other) lines.push(`- **Other**: ${ts.other}`);\n if (lines.length === 1) return '';\n lines.push('', 'Use these technologies in your work. Follow their conventions and best practices.');\n return lines.join('\\n');\n}\n\nexport function getDefaultSystemPrompt(params: SystemPromptParams): string {\n const {\n role,\n agentId,\n projectName,\n todoFilePath,\n inboxPath,\n outboxPath,\n workingDirectory,\n techStack,\n } = params;\n\n const techStackSection = buildTechStackSection(techStack);\n\n return `\n# Agent Identity\n\nYou are **${agentId}**, a ${role} agent working on the **${projectName}** project.\n\n${ROLE_DESCRIPTIONS[role]}\n\n# Working Environment\n\n- **Working Directory**: ${workingDirectory}\n- **Todo File**: ${todoFilePath}\n- **Inbox Directory**: ${inboxPath}\n- **Outbox Directory**: ${outboxPath}\n\nYou should regularly check the todo file for task updates and your inbox for new messages.\nWhen you need to communicate with other agents, write message files to your outbox.\n\n${techStackSection ? techStackSection + '\\n\\n' : ''}${TODO_FORMAT_INSTRUCTIONS}\n\n${MESSAGE_FORMAT_INSTRUCTIONS}\n\n${ROLE_SPECIFIC_INSTRUCTIONS[role]}\n\n${PROCESS_SAFETY_RULES}\n\n## Architecture Compliance\n\nIf an \\`ARCHITECTURE.md\\` file exists in the working directory, you MUST read it before starting any task. It is the source of truth for project structure, component boundaries, data models, API contracts, and technical decisions.\n\n- **Follow the architecture.** Do not contradict decisions documented in ARCHITECTURE.md.\n- **Check before creating.** Before adding new files, directories, or modules, verify the architecture allows it and place them where it specifies.\n- **Flag conflicts.** If a task asks you to do something that conflicts with ARCHITECTURE.md, do NOT silently proceed. Send a message to the orchestrator or architect describing the conflict and wait for guidance.\n- **Keep it updated.** If you are the architect or technical-writer and your work changes the architecture, update ARCHITECTURE.md to reflect the new state.\n\n## Asking the User Questions\n\nTo ask the user a question, send a message with \\`to: \"user\"\\` and \\`type: \"question\"\\` to your outbox. Only ask when you genuinely cannot proceed without user input.\n\n# General Guidelines\n\n- Identify yourself as \"${agentId}\" in messages\n- Check your inbox at the start of each task cycle\n- Update the todo file when you start or complete work\n- Send task-blocked messages immediately when you hit a blocker\n- Focus on your role; do not overstep into other agents' responsibilities\n`.trim();\n}\n","import { readFileSync, existsSync } from 'node:fs';\nimport path from 'node:path';\nimport type { AgentConfig, AgentRole } from '../types/agent.js';\nimport type { ProjectConfig } from '../types/project.js';\nimport { getDefaultSystemPrompt } from './roles.js';\n\n/**\n * Load and generate AgentConfig[] from a ProjectConfig.\n *\n * For each role config:\n * - If count > 1, generates multiple configs with IDs like \"developer-1\", \"developer-2\"\n * - If count === 1, uses the role as the ID (e.g., \"orchestrator\")\n * - Loads system prompts from systemPromptFile if specified, otherwise uses getDefaultSystemPrompt\n */\nexport function loadAgentConfigs(projectConfig: ProjectConfig): AgentConfig[] {\n const configs: AgentConfig[] = [];\n const { settings } = projectConfig;\n\n for (const roleConfig of projectConfig.agents) {\n const count = roleConfig.count ?? 1;\n\n for (let i = 1; i <= count; i++) {\n const agentId = count > 1\n ? `${roleConfig.role}-${i}`\n : roleConfig.role;\n\n const systemPrompt = resolveSystemPrompt({\n roleConfig,\n agentId,\n role: roleConfig.role,\n projectConfig,\n });\n\n // Merge CLI args: settings-level defaults + per-agent overrides\n const mergedArgs = [\n ...(settings.claudeArgs ?? []),\n ...(roleConfig.claudeArgs ?? []),\n ];\n // Merge env vars: settings-level defaults, then per-agent overrides\n const mergedEnv = {\n ...(settings.claudeEnv ?? {}),\n ...(roleConfig.claudeEnv ?? {}),\n };\n\n const config: AgentConfig = {\n id: agentId,\n role: roleConfig.role,\n name: formatAgentName(roleConfig.role, count > 1 ? i : undefined),\n model: roleConfig.model ?? settings.defaultModel,\n systemPrompt,\n allowedTools: roleConfig.allowedTools,\n maxBudgetUsd: roleConfig.maxBudgetUsd,\n workingDirectory: settings.workingDirectory,\n permissionMode: roleConfig.permissionMode ?? 'default',\n claudeCommand: settings.claudeCommand,\n claudeArgs: mergedArgs.length > 0 ? mergedArgs : undefined,\n claudeEnv: Object.keys(mergedEnv).length > 0 ? mergedEnv : undefined,\n maxTurns: roleConfig.maxTurns,\n };\n\n configs.push(config);\n }\n }\n\n return configs;\n}\n\n/**\n * Resolve the system prompt for an agent, checking in order:\n * 1. systemPromptOverride (inline string)\n * 2. systemPromptFile (path to a file)\n * 3. getDefaultSystemPrompt (generated from role)\n */\nfunction resolveSystemPrompt(params: {\n roleConfig: ProjectConfig['agents'][number];\n agentId: string;\n role: AgentRole;\n projectConfig: ProjectConfig;\n}): string {\n const { roleConfig, agentId, role, projectConfig } = params;\n const { settings } = projectConfig;\n\n // 1. Inline override takes highest priority\n if (roleConfig.systemPromptOverride) {\n return roleConfig.systemPromptOverride;\n }\n\n // 2. Load from file if specified\n if (roleConfig.systemPromptFile) {\n const promptPath = path.isAbsolute(roleConfig.systemPromptFile)\n ? roleConfig.systemPromptFile\n : path.resolve(settings.workingDirectory, roleConfig.systemPromptFile);\n\n return readFileSync(promptPath, 'utf-8');\n }\n\n // 3. Check for local .agents/ directory prompt files\n const localAgentsDir = path.resolve(settings.workingDirectory, '.agents');\n const localPromptPath = path.join(localAgentsDir, `${role}.md`);\n\n if (existsSync(localPromptPath)) {\n try {\n const content = readFileSync(localPromptPath, 'utf-8').trim();\n if (content) {\n const todoFilePath = path.resolve(settings.workingDirectory, settings.todoFile);\n const messagesDir = path.resolve(settings.workingDirectory, settings.messagesDirectory);\n return content\n .replace(/\\{\\{agentId\\}\\}/g, agentId)\n .replace(/\\{\\{projectName\\}\\}/g, projectConfig.name)\n .replace(/\\{\\{todoFilePath\\}\\}/g, todoFilePath)\n .replace(/\\{\\{inboxPath\\}\\}/g, path.join(messagesDir, agentId, 'inbox'))\n .replace(/\\{\\{outboxPath\\}\\}/g, path.join(messagesDir, agentId, 'outbox'))\n .replace(/\\{\\{workingDirectory\\}\\}/g, settings.workingDirectory);\n }\n } catch {\n // File unreadable, fall through to default\n }\n }\n\n // 4. Generate default system prompt\n const todoFilePath = path.resolve(settings.workingDirectory, settings.todoFile);\n const messagesDir = path.resolve(settings.workingDirectory, settings.messagesDirectory);\n\n return getDefaultSystemPrompt({\n role,\n agentId,\n projectName: projectConfig.name,\n todoFilePath,\n inboxPath: path.join(messagesDir, agentId, 'inbox'),\n outboxPath: path.join(messagesDir, agentId, 'outbox'),\n workingDirectory: settings.workingDirectory,\n techStack: projectConfig.techStack,\n });\n}\n\n/**\n * Format a human-readable agent name from role and optional index.\n */\nfunction formatAgentName(role: AgentRole, index?: number): string {\n const roleName = role\n .split('-')\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join(' ');\n\n return index !== undefined ? `${roleName} ${index}` : roleName;\n}\n","/**\n * Orchestrator activity log types.\n *\n * These represent structured events that the orchestrator emits so that\n * a persistent \"Orchestrator\" panel in the TUI can display what's happening\n * at a high level: task delegations, status updates, phase transitions,\n * agent hand-offs, and pipeline progress.\n */\n\nexport type OrchestratorActivityKind =\n | 'task-delegated'\n | 'task-completed'\n | 'task-blocked'\n | 'task-failed'\n | 'agent-spawned'\n | 'agent-stopped'\n | 'agent-error'\n | 'phase-changed'\n | 'pipeline-handoff'\n | 'plan-created'\n | 'plan-approved'\n | 'plan-rejected'\n | 'budget-warning'\n | 'rate-limit'\n | 'project-completed'\n | 'cycle-summary'\n | 'gap-detected'\n | 'pm-scan'\n | 'info';\n\nexport interface OrchestratorActivity {\n id: string;\n kind: OrchestratorActivityKind;\n timestamp: string;\n message: string;\n details?: {\n taskId?: string;\n taskTitle?: string;\n agentId?: string;\n agentRole?: string;\n fromPhase?: string;\n toPhase?: string;\n pipelineStage?: string;\n cost?: number;\n [key: string]: unknown;\n };\n}\n\n/**\n * Task pipeline stages — each task flows through a defined sequence of\n * stages with role-based handoffs between agents.\n */\nexport type PipelineStage = 'plan' | 'develop' | 'qa' | 'review';\n\nexport const PIPELINE_STAGE_ORDER: PipelineStage[] = ['plan', 'develop', 'qa', 'review'];\n\n/**\n * Maps pipeline stages to the agent roles responsible for executing them.\n */\nexport const PIPELINE_STAGE_ROLES: Record<PipelineStage, string[]> = {\n plan: ['project-manager', 'architect'],\n develop: ['developer'],\n qa: ['qa-engineer'],\n review: ['project-manager'],\n};\n\nexport interface TaskPipelineState {\n taskId: string;\n currentStage: PipelineStage;\n stageHistory: {\n stage: PipelineStage;\n agentId: string;\n startedAt: string;\n completedAt: string | null;\n status: 'in-progress' | 'completed' | 'failed';\n }[];\n createdAt: string;\n}\n","// Types\nexport * from './types/index.js';\n\n// Task management\nexport { TaskParser } from './task/parser.js';\nexport { TaskWriter } from './task/writer.js';\nexport { TaskManager } from './task/manager.js';\n\n// Agent management\nexport { AgentProcess } from './agent/lifecycle.js';\nexport { AgentPool } from './agent/pool.js';\nexport { getDefaultSystemPrompt, ROLE_DESCRIPTIONS } from './agent/roles.js';\nexport { loadAgentConfigs } from './agent/config.js';\n\n// Messaging\nexport { MessageBroker } from './messaging/broker.js';\nexport { InboxWatcher } from './messaging/inbox.js';\n\n// Orchestrator\nexport { Orchestrator } from './orchestrator/orchestrator.js';\nexport { Planner, type PlannedTask } from './orchestrator/planner.js';\nexport { Scheduler } from './orchestrator/scheduler.js';\nexport { TaskPipeline } from './orchestrator/pipeline.js';\nexport { ProjectManagerScanner } from './orchestrator/pm-scanner.js';\n\n// Feedback\nexport { FeedbackLoop } from './feedback/feedback-loop.js';\nexport { ProgressTracker } from './feedback/progress-tracker.js';\n\n// Project\nexport { loadProjectConfig, validateProjectConfig } from './project/config.js';\nexport { WorkspaceManager } from './project/workspace.js';\n\n// Utils\nexport { createLogger } from './utils/logger.js';\nexport { generateId, generateTaskId, resetTaskCounter } from './utils/id.js';\n","import { EventEmitter } from 'eventemitter3';\nimport { mkdir, writeFile, readFile, readdir, rename, unlink } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { Message, MessageEnvelope } from '../types/message.js';\nimport { InboxWatcher } from './inbox.js';\nimport { createLogger } from '../utils/logger.js';\n\nconst logger = createLogger('message-broker');\n\n/**\n * Build a filename for a message file.\n * Format: {taskId}_{messageId}.json (or general_{messageId}.json if no taskId)\n */\nfunction messageFileName(message: Message): string {\n const prefix = message.taskId ?? 'general';\n return `${prefix}_${message.id}.json`;\n}\n\nexport class MessageBroker extends EventEmitter {\n private baseDir: string;\n private watchers: Map<string, InboxWatcher> = new Map();\n private registeredAgents: Set<string> = new Set();\n\n constructor(baseDir: string) {\n super();\n this.baseDir = baseDir;\n }\n\n /**\n * Initialize directory structure for an agent.\n * Creates inbox/, outbox/, and processed/ directories.\n */\n async registerAgent(agentId: string): Promise<void> {\n const agentDir = join(this.baseDir, agentId);\n await mkdir(join(agentDir, 'inbox'), { recursive: true });\n await mkdir(join(agentDir, 'outbox'), { recursive: true });\n await mkdir(join(agentDir, 'processed'), { recursive: true });\n this.registeredAgents.add(agentId);\n logger.debug({ agentId }, 'Registered agent');\n }\n\n /**\n * Initialize directories for all agents and start watching.\n * Watches each agent's outbox directory so that messages agents write\n * there are automatically picked up and routed.\n */\n async start(agentIds: string[]): Promise<void> {\n for (const agentId of agentIds) {\n await this.registerAgent(agentId);\n }\n\n for (const agentId of agentIds) {\n // Watch the agent's outbox for messages it sends\n const outboxDir = join(this.baseDir, agentId, 'outbox');\n const processedDir = join(this.baseDir, agentId, 'processed');\n const watcher = new InboxWatcher(outboxDir, processedDir);\n\n watcher.on('message', (envelope: MessageEnvelope) => {\n logger.info(\n { from: envelope.message.from, to: envelope.message.to, type: envelope.message.type },\n 'Message received from agent outbox',\n );\n this.emit('message:received', envelope.message);\n\n // Route the message to its recipient\n if (envelope.message.to === '*') {\n this.broadcast(envelope.message).catch((err) => {\n logger.error({ err }, 'Failed to broadcast message');\n });\n } else {\n this.sendMessage(envelope.message).catch((err) => {\n logger.error({ err }, 'Failed to route message');\n });\n }\n });\n\n await watcher.start();\n this.watchers.set(agentId, watcher);\n }\n\n logger.info({ agentCount: agentIds.length }, 'Message broker started');\n }\n\n /**\n * Send a message to an agent's inbox.\n * If message.to is \"*\", broadcasts to all registered agents instead.\n */\n async sendMessage(message: Message): Promise<void> {\n if (message.to === '*') {\n await this.broadcast(message);\n return;\n }\n\n // Intercept user-directed messages\n if (message.to === 'user') {\n logger.info({ from: message.from, type: message.type }, 'User-directed message intercepted');\n this.emit('message:user-directed', message);\n return;\n }\n\n if (!this.registeredAgents.has(message.to)) {\n logger.warn({ to: message.to }, 'Attempted to send message to unregistered agent');\n return;\n }\n\n const envelope: MessageEnvelope = {\n message,\n deliveredAt: null,\n readAt: null,\n status: 'pending',\n };\n\n const filePath = join(this.baseDir, message.to, 'inbox', messageFileName(message));\n await writeFile(filePath, JSON.stringify(envelope, null, 2), 'utf-8');\n\n logger.debug(\n { id: message.id, from: message.from, to: message.to, type: message.type },\n 'Message sent',\n );\n this.emit('message:sent', message);\n }\n\n /**\n * Send a message to all registered agents' inboxes.\n */\n async broadcast(message: Message): Promise<void> {\n const promises: Promise<void>[] = [];\n\n for (const agentId of this.registeredAgents) {\n // Don't send broadcast back to the sender\n if (agentId === message.from) {\n continue;\n }\n\n const envelope: MessageEnvelope = {\n message: { ...message, to: agentId },\n deliveredAt: null,\n readAt: null,\n status: 'pending',\n };\n\n const broadcastMsg = { ...message, to: agentId };\n const filePath = join(this.baseDir, agentId, 'inbox', messageFileName(broadcastMsg));\n promises.push(\n writeFile(filePath, JSON.stringify(envelope, null, 2), 'utf-8').then(() => {\n this.emit('message:sent', broadcastMsg);\n }),\n );\n }\n\n await Promise.all(promises);\n logger.debug(\n { id: message.id, from: message.from, agentCount: this.registeredAgents.size },\n 'Broadcast sent',\n );\n }\n\n /**\n * Mark an inbox message as processed and move it to the processed directory.\n * Called when a task completes so the inbox reflects the current state.\n */\n async markInboxProcessed(agentId: string, taskId: string): Promise<void> {\n const inboxDir = join(this.baseDir, agentId, 'inbox');\n const processedDir = join(this.baseDir, agentId, 'processed');\n\n try {\n const files = await readdir(inboxDir);\n for (const file of files) {\n if (!file.endsWith('.json')) continue;\n const filePath = join(inboxDir, file);\n try {\n const content = await readFile(filePath, 'utf-8');\n const envelope: MessageEnvelope = JSON.parse(content);\n if (envelope.message.taskId === taskId) {\n envelope.status = 'processed';\n envelope.readAt = new Date().toISOString();\n // Write updated status then move to processed\n await writeFile(filePath, JSON.stringify(envelope, null, 2), 'utf-8');\n const destPath = join(processedDir, file);\n await rename(filePath, destPath);\n logger.debug({ agentId, taskId, messageId: envelope.message.id }, 'Inbox message marked as processed');\n }\n } catch {\n // Skip files that can't be read or parsed\n }\n }\n } catch {\n // Inbox directory may not exist yet\n }\n }\n\n /**\n * Clean up stale inbox messages for a task (e.g., after restart when\n * in-progress tasks are reset). Moves matching messages to processed/.\n */\n async cleanInboxForTask(agentId: string, taskId: string): Promise<void> {\n await this.markInboxProcessed(agentId, taskId);\n }\n\n /**\n * Read processed messages for a specific task across all agents.\n * Used to display task completion details in the TUI.\n */\n async getProcessedMessagesForTask(taskId: string): Promise<MessageEnvelope[]> {\n const results: MessageEnvelope[] = [];\n\n // Discover all agent directories on disk (not just registered ones)\n // so we find messages from previous sessions too.\n let agentDirs: string[] = [];\n try {\n const entries = await readdir(this.baseDir, { withFileTypes: true });\n agentDirs = entries.filter((e) => e.isDirectory()).map((e) => e.name);\n } catch {\n return results;\n }\n\n for (const agentId of agentDirs) {\n // Scan both inbox and processed directories\n for (const subdir of ['inbox', 'processed']) {\n const dir = join(this.baseDir, agentId, subdir);\n try {\n const entries = await readdir(dir, { withFileTypes: true });\n for (const entry of entries) {\n if (!entry.isFile() || !entry.name.endsWith('.json')) continue;\n try {\n const content = await readFile(join(dir, entry.name), 'utf-8');\n const envelope: MessageEnvelope = JSON.parse(content);\n if (envelope.message?.taskId === taskId) {\n results.push(envelope);\n }\n } catch {\n // Skip unreadable files\n }\n }\n } catch {\n // Directory may not exist\n }\n }\n }\n\n // Deduplicate by message id (same message may exist in inbox and processed)\n const seen = new Set<string>();\n const deduped = results.filter((env) => {\n if (seen.has(env.message.id)) return false;\n seen.add(env.message.id);\n return true;\n });\n\n // Sort by timestamp\n deduped.sort((a, b) => a.message.timestamp.localeCompare(b.message.timestamp));\n return deduped;\n }\n\n /**\n * Move ALL inbox messages to processed/ for every agent directory.\n * Called on startup to ensure a clean slate — agents should not pick up\n * stale task-assignment messages from a previous session.\n */\n async cleanAllInboxes(): Promise<void> {\n let agentDirs: string[] = [];\n try {\n const entries = await readdir(this.baseDir, { withFileTypes: true });\n agentDirs = entries.filter((e) => e.isDirectory()).map((e) => e.name);\n } catch {\n return;\n }\n\n let movedCount = 0;\n for (const agentId of agentDirs) {\n const inboxDir = join(this.baseDir, agentId, 'inbox');\n const processedDir = join(this.baseDir, agentId, 'processed');\n try {\n await mkdir(processedDir, { recursive: true });\n const files = await readdir(inboxDir);\n for (const file of files) {\n if (!file.endsWith('.json')) continue;\n try {\n await rename(join(inboxDir, file), join(processedDir, file));\n movedCount++;\n } catch {\n // File may already be moved\n }\n }\n } catch {\n // Directory may not exist\n }\n }\n\n if (movedCount > 0) {\n logger.info({ movedCount }, 'Cleaned stale inbox messages from previous session');\n }\n }\n\n get messagesBaseDir(): string {\n return this.baseDir;\n }\n\n /**\n * Stop all watchers and clean up.\n */\n async stop(): Promise<void> {\n const stopPromises: Promise<void>[] = [];\n for (const [agentId, watcher] of this.watchers) {\n logger.debug({ agentId }, 'Stopping watcher');\n stopPromises.push(watcher.stop());\n }\n await Promise.all(stopPromises);\n this.watchers.clear();\n logger.info('Message broker stopped');\n }\n}\n","import { watch, type FSWatcher } from 'chokidar';\nimport { EventEmitter } from 'eventemitter3';\nimport { readFile, rename, mkdir } from 'node:fs/promises';\nimport { join, basename } from 'node:path';\nimport type { MessageEnvelope } from '../types/message.js';\nimport { createLogger } from '../utils/logger.js';\n\nconst logger = createLogger('inbox-watcher');\n\nexport class InboxWatcher extends EventEmitter {\n private watcher: FSWatcher | null = null;\n private dir: string;\n private processedDir: string;\n\n constructor(inboxDir: string, processedDir: string) {\n super();\n this.dir = inboxDir;\n this.processedDir = processedDir;\n }\n\n async start(): Promise<void> {\n await mkdir(this.dir, { recursive: true });\n await mkdir(this.processedDir, { recursive: true });\n\n this.watcher = watch(this.dir, {\n ignoreInitial: false,\n awaitWriteFinish: { stabilityThreshold: 200 },\n });\n\n this.watcher.on('add', (filePath: string) => {\n if (filePath.endsWith('.json')) {\n this.processFile(filePath).catch((err) => {\n logger.error({ err, filePath }, 'Failed to process inbox file');\n });\n }\n });\n\n this.watcher.on('error', (err: unknown) => {\n logger.error({ err }, 'Inbox watcher error');\n });\n }\n\n async stop(): Promise<void> {\n if (this.watcher) {\n await this.watcher.close();\n this.watcher = null;\n }\n }\n\n private async processFile(filePath: string): Promise<void> {\n try {\n const content = await readFile(filePath, 'utf-8');\n let envelope: MessageEnvelope;\n\n try {\n envelope = JSON.parse(content) as MessageEnvelope;\n } catch {\n logger.warn({ filePath }, 'Malformed JSON in inbox file, skipping');\n return;\n }\n\n envelope.deliveredAt = new Date().toISOString();\n envelope.status = 'delivered';\n\n this.emit('message', envelope);\n\n const destPath = join(this.processedDir, basename(filePath));\n await rename(filePath, destPath);\n } catch (err) {\n // File may have been already moved or deleted\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n logger.debug({ filePath }, 'Inbox file already removed');\n return;\n }\n throw err;\n }\n }\n}\n","import { EventEmitter } from 'eventemitter3';\nimport { mkdir } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { ProjectConfig } from '../types/project.js';\nimport type { OrchestratorStats, MaestroEvents, ProjectCompletionSummary } from '../types/events.js';\nimport type { AgentStreamEvent, AgentStatus } from '../types/agent.js';\nimport type { Message } from '../types/message.js';\nimport type { Task } from '../types/task.js';\nimport type { FeedbackSettings, InteractionMode, PlanProposal, PlannedTaskSummary, UserQuestion } from '../types/feedback.js';\nimport type { OrchestratorActivity, PipelineStage } from '../types/orchestrator-activity.js';\nimport { PIPELINE_STAGE_ROLES } from '../types/orchestrator-activity.js';\nimport { MessageBroker } from '../messaging/broker.js';\nimport { FeedbackLoop } from '../feedback/feedback-loop.js';\nimport { Planner } from './planner.js';\nimport { Scheduler, type TaskAssignment } from './scheduler.js';\nimport { TaskPipeline } from './pipeline.js';\nimport { ProjectManagerScanner } from './pm-scanner.js';\nimport { generateId, generateTaskId } from '../utils/id.js';\nimport { createLogger } from '../utils/logger.js';\n\nconst logger = createLogger('orchestrator');\n\nexport class Orchestrator extends EventEmitter {\n private config: ProjectConfig;\n private running = false;\n private paused = false;\n private intervalId: ReturnType<typeof setInterval> | null = null;\n private startedAt: number | null = null;\n\n private broker: MessageBroker | null = null;\n private scheduler: Scheduler | null = null;\n private planner: Planner | null = null;\n private pipeline: TaskPipeline;\n private pmScanner: ProjectManagerScanner;\n\n // These will hold references to modules that manage tasks and agents.\n // They are typed loosely here because TaskManager, AgentPool, and\n // WorkspaceManager are sibling modules that may not yet be implemented.\n // The orchestrator interfaces with them via their public APIs.\n private taskManager: any = null;\n private agentPool: any = null;\n private agentConfigs: any[] = [];\n private cachedTasks: Task[] = [];\n private feedbackLoop: FeedbackLoop | null = null;\n private planApprovalPending = false;\n private phase: 'planning' | 'architecture' | 'development' = 'planning';\n private architectureApprovalPending = false;\n\n constructor(config: ProjectConfig) {\n super();\n this.config = config;\n this.pipeline = new TaskPipeline();\n this.pmScanner = new ProjectManagerScanner();\n }\n\n get isActive(): boolean {\n return this.running;\n }\n\n get isPaused(): boolean {\n return this.paused;\n }\n\n /**\n * Emit a structured orchestrator activity event.\n * These feed the persistent \"Orchestrator\" panel in the TUI.\n */\n private emitActivity(\n kind: OrchestratorActivity['kind'],\n message: string,\n details?: OrchestratorActivity['details'],\n ): void {\n const activity: OrchestratorActivity = {\n id: generateId(),\n kind,\n timestamp: new Date().toISOString(),\n message,\n details,\n };\n this.emit('orchestrator:activity', activity);\n }\n\n /**\n * Start the orchestrator:\n * 1. Ensure workspace directories exist\n * 2. Initialize TaskManager, AgentPool, MessageBroker, Scheduler, Planner\n * 3. Load agent configs and register them with the broker\n * 4. If no tasks exist, use Planner to decompose the project description\n * 5. Start the polling loop\n */\n async start(): Promise<void> {\n if (this.running) {\n logger.warn('Orchestrator already running');\n return;\n }\n\n const settings = this.config.settings;\n\n // Step 1: Ensure workspace directories exist\n await mkdir(settings.messagesDirectory, { recursive: true });\n await mkdir(settings.logsDirectory, { recursive: true });\n\n // Step 2: Initialize core components\n // Dynamically import sibling modules to avoid hard circular deps at parse time\n const [{ TaskManager }, { AgentPool }, { loadAgentConfigs }] = await Promise.all([\n import('../task/manager.js'),\n import('../agent/pool.js'),\n import('../agent/config.js'),\n ]);\n\n this.taskManager = new TaskManager({ filePath: settings.todoFile, projectName: this.config.name });\n this.agentPool = new AgentPool();\n this.broker = new MessageBroker(settings.messagesDirectory);\n this.scheduler = new Scheduler();\n this.scheduler.setPipeline(this.pipeline);\n this.planner = new Planner({\n model: settings.defaultModel,\n workingDirectory: settings.workingDirectory,\n claudeCommand: settings.claudeCommand,\n claudeEnv: settings.claudeEnv,\n techStack: this.config.techStack,\n });\n\n this.feedbackLoop = new FeedbackLoop(settings.feedback);\n\n // Forward feedback events\n this.feedbackLoop.on('plan:proposed', (p) => this.emit('plan:proposed', p));\n this.feedbackLoop.on('plan:decided', (...args) => this.emit('plan:decided', ...args));\n this.feedbackLoop.on('question:asked', (q) => this.emit('question:asked', q));\n this.feedbackLoop.on('question:answered', (...args) => this.emit('question:answered', ...args));\n this.feedbackLoop.on('progress:report', (r) => this.emit('progress:report', r));\n this.feedbackLoop.on('milestone:reached', (m) => this.emit('milestone:reached', m));\n this.feedbackLoop.on('milestone:acknowledged', (id) => this.emit('milestone:acknowledged', id));\n this.feedbackLoop.on('interaction-mode:changed', (m) => this.emit('interaction-mode:changed', m));\n\n // Step 3: Load agent configs and register with broker\n const agentConfigs = loadAgentConfigs(this.config);\n const agentIds = agentConfigs.map((c) => c.id);\n\n // Store agent configs for spawning during orchestration cycles\n this.agentConfigs = agentConfigs;\n\n this.emitActivity('info', `Orchestrator starting with ${agentConfigs.length} agent(s) configured`);\n\n // Start broker (registers agents and starts watching outboxes)\n await this.broker.start(agentIds);\n\n // Forward broker events\n this.broker.on('message:received', (message: Message) => {\n this.emit('message:received', message);\n });\n this.broker.on('message:sent', (message: Message) => {\n this.emit('message:sent', message);\n });\n\n // Forward agent pool events with activity logging\n this.agentPool.on('agent:output', (event: AgentStreamEvent) => {\n this.emit('agent:output', event);\n });\n\n this.agentPool.on('agent:status-changed', (agentId: string, oldStatus: AgentStatus, newStatus: AgentStatus) => {\n this.emit('agent:status-changed', agentId, oldStatus, newStatus);\n });\n\n this.agentPool.on('agent:error', (agentId: string, error: Error) => {\n this.emit('agent:error', agentId, error);\n this.emitActivity('agent-error', `Agent ${agentId} encountered an error: ${error.message}`, {\n agentId,\n });\n });\n\n this.agentPool.on('agent:stopped', (agentId: string, exitCode: number | null) => {\n this.emit('agent:stopped', agentId, exitCode);\n this.emitActivity('agent-stopped', `Agent ${agentId} stopped (exit code: ${exitCode})`, {\n agentId,\n });\n });\n\n this.agentPool.on('agent:spawned', (agentId: string) => {\n const agent = this.agentPool.getAgent(agentId);\n if (agent) {\n this.emit('agent:spawned', agent.currentState);\n this.emitActivity('agent-spawned', `Spawned agent ${agent.currentState.config.name} (${agent.currentState.config.role})`, {\n agentId,\n agentRole: agent.currentState.config.role,\n });\n }\n });\n\n // Step 4: Decompose project goal into initial tasks if needed\n const existingTasks: Task[] = await this.taskManager.load();\n if (existingTasks.length === 0) {\n logger.info('No existing tasks found, decomposing project goal');\n this.emitActivity('info', 'No existing tasks found, decomposing project goal...');\n const plannedTasks = await this.planner.decompose(this.config.description);\n\n // Convert to PlannedTaskSummary for plan proposal\n const summaries: PlannedTaskSummary[] = plannedTasks.map((t) => ({\n title: t.title,\n description: t.description,\n priority: t.priority,\n assignedRole: '', // Will be determined by scheduler\n tags: t.tags,\n }));\n\n this.emitActivity('plan-created', `Created plan with ${plannedTasks.length} task(s) from project goal`);\n\n // Don't block start() on plan approval — this allows the TUI/UI\n // to render and display the plan for user approval.\n this.planApprovalPending = true;\n this.feedbackLoop!.proposePlan(summaries, this.config.description).then(async (decision) => {\n this.planApprovalPending = false;\n\n if (decision === 'rejected') {\n logger.info('Plan rejected by user, stopping');\n this.emitActivity('plan-rejected', 'Plan rejected by user, stopping orchestrator');\n await this.stop();\n return;\n }\n\n this.emitActivity('plan-approved', 'Plan approved, creating tasks...');\n\n // Resolve dependency titles to task IDs as tasks are created\n const titleToId = new Map<string, string>();\n for (const planned of plannedTasks) {\n const resolvedDeps = planned.dependencies\n .map((depTitle) => titleToId.get(depTitle))\n .filter((id): id is string => id != null);\n\n const task = await this.taskManager.createTask({\n title: planned.title,\n description: planned.description,\n priority: planned.priority,\n dependencies: resolvedDeps,\n tags: planned.tags,\n });\n titleToId.set(planned.title, task.id);\n this.emit('task:created', task);\n\n // Register task in pipeline\n this.pipeline.initTask(task);\n }\n\n // Notify TUI that all tasks are now available\n const allNewTasks = await this.taskManager.load();\n this.emit('tasks:loaded', allNewTasks);\n\n // Determine initial phase based on whether architecture tasks exist\n const hasArchTasks = plannedTasks.some((t) => t.tags.includes('architecture'));\n this.phase = hasArchTasks ? 'architecture' : 'development';\n this.emit('phase:changed', this.phase);\n this.emitActivity('phase-changed', `Phase set to: ${this.phase}`, { toPhase: this.phase });\n logger.info({ count: plannedTasks.length, phase: this.phase }, 'Initial tasks created from project goal');\n }).catch((err) => {\n this.planApprovalPending = false;\n logger.error({ err }, 'Plan approval flow failed');\n });\n } else {\n // Existing tasks: clean slate on resume.\n // Move ALL inbox messages to processed/ so agents don't pick up stale assignments.\n if (this.broker) {\n await this.broker.cleanAllInboxes();\n }\n\n // Reset stale in-progress tasks from a previous session.\n // After restart, no agents are running, so any in-progress task is stale.\n const staleTasks = existingTasks.filter((t: Task) => t.status === 'in-progress');\n for (const task of staleTasks) {\n await this.taskManager.updateTask(task.id, {\n status: 'pending',\n assignee: null,\n });\n logger.info(\n { taskId: task.id, previousAssignee: task.assignee },\n 'Reset stale in-progress task to pending (previous session ended)',\n );\n }\n\n // Determine phase based on architecture task statuses\n // Reload tasks since we may have updated some above\n const refreshedTasks: Task[] = staleTasks.length > 0\n ? await this.taskManager.load()\n : existingTasks;\n const archTasks = refreshedTasks.filter((t: Task) => t.tags.includes('architecture'));\n const archPending = archTasks.some((t: Task) => t.status !== 'done');\n if (archTasks.length > 0 && archPending) {\n this.phase = 'architecture';\n } else {\n this.phase = 'development';\n }\n this.emit('phase:changed', this.phase);\n this.emitActivity('phase-changed', `Resuming in phase: ${this.phase} (${existingTasks.length} existing tasks)`, {\n toPhase: this.phase,\n });\n\n // Register existing tasks in pipeline\n for (const task of existingTasks) {\n if (!this.pipeline.has(task.id)) {\n this.pipeline.initTask(task);\n }\n }\n\n // Notify TUI that tasks are loaded (use refreshed list if stale tasks were reset)\n this.emit('tasks:loaded', refreshedTasks);\n\n logger.info({\n phase: this.phase,\n existingTaskCount: existingTasks.length,\n staleTasksReset: staleTasks.length,\n }, 'Resuming with existing tasks');\n }\n\n // Step 5: Start the polling loop\n this.running = true;\n this.startedAt = Date.now();\n\n this.intervalId = setInterval(() => {\n this.cycle().catch((err) => {\n logger.error({ err }, 'Orchestrator cycle failed');\n });\n }, settings.pollIntervalMs);\n\n // Run the first cycle immediately\n await this.cycle();\n\n // Step 6: Start the PM scanner loop for continuous project assessment\n this.pmScanner.start(() => {\n this.runPMScan().catch((err) => {\n logger.error({ err }, 'PM scan failed');\n });\n });\n\n this.emitActivity('info', 'Orchestrator started and running (PM scanner active)');\n logger.info('Orchestrator started');\n }\n\n /**\n * Stop the orchestrator gracefully.\n */\n async stop(): Promise<void> {\n if (!this.running) {\n return;\n }\n\n logger.info('Stopping orchestrator');\n this.emitActivity('info', 'Orchestrator shutting down...');\n\n // Clear the polling interval\n if (this.intervalId !== null) {\n clearInterval(this.intervalId);\n this.intervalId = null;\n }\n\n // Stop the PM scanner\n this.pmScanner.stop();\n\n // Stop all agents\n if (this.agentPool) {\n await this.agentPool.stopAll();\n }\n\n // Stop the message broker (closes chokidar file watchers)\n if (this.broker) {\n await this.broker.stop();\n }\n\n // Clean up feedback loop (clears pending timers and resolvers)\n if (this.feedbackLoop) {\n this.feedbackLoop.cleanup();\n }\n\n this.running = false;\n this.paused = false;\n logger.info('Orchestrator stopped');\n }\n\n /**\n * Pause the orchestrator: stop the polling cycle and all running agents.\n * Tasks and state are preserved so work can be resumed later.\n */\n async pause(): Promise<void> {\n if (!this.running || this.paused) return;\n\n this.paused = true;\n logger.info('Pausing orchestrator');\n this.emitActivity('info', 'Orchestrator pausing — stopping agents...');\n\n // Stop the polling cycle\n if (this.intervalId !== null) {\n clearInterval(this.intervalId);\n this.intervalId = null;\n }\n\n // Stop the PM scanner\n this.pmScanner.stop();\n\n // Stop all agents gracefully\n if (this.agentPool) {\n await this.agentPool.stopAll();\n }\n\n // Reset in-progress tasks back to pending so they can be re-assigned on resume\n if (this.taskManager) {\n const tasks: Task[] = await this.taskManager.load();\n for (const task of tasks) {\n if (task.status === 'in-progress') {\n await this.taskManager.updateTask(task.id, {\n status: 'pending',\n assignee: null,\n });\n }\n }\n // Notify TUI of updated tasks\n const refreshed = await this.taskManager.load();\n this.emit('tasks:loaded', refreshed);\n }\n\n this.emitActivity('info', 'Orchestrator paused');\n this.emit('orchestrator:paused');\n logger.info('Orchestrator paused');\n }\n\n /**\n * Resume the orchestrator after a pause. Restarts the polling cycle\n * and PM scanner so agents can be re-assigned to pending tasks.\n */\n async resume(): Promise<void> {\n if (!this.running || !this.paused) return;\n\n this.paused = false;\n logger.info('Resuming orchestrator');\n this.emitActivity('info', 'Orchestrator resuming...');\n\n // Clean stale inbox messages so fresh assignments are sent\n if (this.broker) {\n await this.broker.cleanAllInboxes();\n }\n\n // Restart the polling loop\n const settings = this.config.settings;\n this.intervalId = setInterval(() => {\n this.cycle().catch((err) => {\n logger.error({ err }, 'Orchestrator cycle failed');\n });\n }, settings.pollIntervalMs);\n\n // Run one cycle immediately\n await this.cycle();\n\n // Restart PM scanner\n this.pmScanner.start(() => {\n this.runPMScan().catch((err) => {\n logger.error({ err }, 'PM scan failed');\n });\n });\n\n this.emitActivity('info', 'Orchestrator resumed');\n this.emit('orchestrator:resumed');\n logger.info('Orchestrator resumed');\n }\n\n /**\n * Add new instructions: decompose them into tasks and append to the\n * existing todo.md without deleting any existing tasks.\n */\n async addInstructions(instructions: string): Promise<Task[]> {\n if (!this.planner || !this.taskManager) {\n throw new Error('Orchestrator must be started before adding instructions');\n }\n\n this.emitActivity('info', 'Decomposing new instructions into tasks...');\n this.emit('instructions:decomposing', instructions);\n\n const plannedTasks = await this.planner.decompose(instructions);\n\n // Load existing tasks to preserve them and resolve dependency IDs\n const existingTasks = await this.taskManager.load();\n const titleToId = new Map<string, string>();\n for (const t of existingTasks) {\n titleToId.set(t.title, t.id);\n }\n\n const createdTasks: Task[] = [];\n for (const planned of plannedTasks) {\n const resolvedDeps = planned.dependencies\n .map((depTitle) => titleToId.get(depTitle))\n .filter((id): id is string => id != null);\n\n const task = await this.taskManager.createTask({\n title: planned.title,\n description: planned.description,\n priority: planned.priority,\n dependencies: resolvedDeps,\n tags: planned.tags,\n });\n titleToId.set(planned.title, task.id);\n this.emit('task:created', task);\n\n // Register in pipeline\n this.pipeline.initTask(task);\n createdTasks.push(task);\n }\n\n // Notify TUI that tasks list has changed\n const allTasks = await this.taskManager.load();\n this.emit('tasks:loaded', allTasks);\n\n this.emitActivity('info', `Added ${createdTasks.length} new task(s) from instructions`);\n this.emit('instructions:added', createdTasks);\n\n logger.info({ count: createdTasks.length }, 'New tasks added from instructions');\n return createdTasks;\n }\n\n /**\n * A single orchestration cycle:\n * 1. Load current tasks\n * 2. Run scheduler to determine assignments\n * 3. For each assignment: update task, send message, spawn agent\n * 4. Handle pipeline handoffs for completed tasks\n * 5. Check budget limits\n * 6. Emit cycle stats\n */\n private async cycle(): Promise<void> {\n if (!this.taskManager || !this.scheduler || !this.broker || !this.agentPool) {\n return;\n }\n\n // Skip cycles while paused or waiting for plan approval\n if (this.paused || this.planApprovalPending) {\n return;\n }\n\n // 1. Load current tasks and agent states\n let tasks: Task[] = await this.taskManager.load();\n\n // 1b. Detect completed/errored agents and update their task statuses\n const poolAgents = this.agentPool.getAllAgents().map((a: any) => a.currentState);\n let tasksUpdated = false;\n\n for (const agentState of poolAgents) {\n if (agentState.status === 'stopped' || agentState.status === 'error') {\n // Clear current task label on the agent process\n const agentProcess = this.agentPool.getAgent(agentState.config.id);\n if (agentProcess) {\n agentProcess.setCurrentTask(null);\n }\n\n const assignedTask = tasks.find(\n (t: Task) => t.status === 'in-progress' && t.assignee === agentState.config.id\n );\n if (assignedTask) {\n if (agentState.status === 'stopped') {\n // Check pipeline for handoff\n const handoff = this.pipeline.completeStage(assignedTask.id);\n\n if (handoff && handoff.nextStage) {\n // Pipeline has a next stage — create a handoff task or re-queue\n this.emitActivity('pipeline-handoff', handoff.handoffMessage, {\n taskId: assignedTask.id,\n taskTitle: assignedTask.title,\n agentId: agentState.config.id,\n agentRole: agentState.config.role,\n pipelineStage: handoff.nextStage,\n });\n\n // Reset task to pending so the scheduler can re-assign to the right role\n await this.taskManager.updateTask(assignedTask.id, {\n status: 'pending',\n assignee: null,\n notes: [\n ...assignedTask.notes,\n `[pipeline] Handed off to ${handoff.nextStage} stage`,\n ],\n });\n\n // Send handoff message to broadcast channel\n const handoffMsg: Message = {\n id: generateId(),\n type: 'task-update',\n from: 'orchestrator',\n to: '*',\n subject: `Pipeline Handoff: ${assignedTask.title}`,\n body: `${handoff.handoffMessage}\\n\\nTask \"${assignedTask.title}\" (${assignedTask.id}) is now in the ${handoff.nextStage} stage. Required roles: ${handoff.requiredRoles.join(', ')}`,\n taskId: assignedTask.id,\n priority: assignedTask.priority === 'critical' ? 'urgent' : 'normal',\n timestamp: new Date().toISOString(),\n metadata: {\n pipelineStage: handoff.nextStage,\n previousAgent: agentState.config.id,\n },\n };\n await this.broker.sendMessage(handoffMsg);\n } else {\n // Pipeline complete or no pipeline — mark as done\n await this.taskManager.updateTask(assignedTask.id, { status: 'done' });\n this.emit('task:completed', assignedTask);\n this.emitActivity('task-completed', `Task completed: ${assignedTask.title}`, {\n taskId: assignedTask.id,\n taskTitle: assignedTask.title,\n agentId: agentState.config.id,\n agentRole: agentState.config.role,\n });\n }\n\n logger.info(\n { taskId: assignedTask.id, agentId: agentState.config.id },\n 'Task stage completed (agent process stopped)',\n );\n } else if (agentState.rateLimited) {\n // Agent hit an API rate limit (429) — alert and pause\n this.pipeline.failStage(assignedTask.id);\n await this.taskManager.updateTask(assignedTask.id, {\n status: 'pending',\n assignee: null,\n });\n\n const stats = this.getStats();\n const totalTokens = stats.totalInputTokens + stats.totalOutputTokens + stats.totalCacheReadTokens + stats.totalCacheCreationTokens;\n const resetInfo = agentState.rateLimitResetAt ? ` Resets at ${agentState.rateLimitResetAt}.` : '';\n this.emitActivity('rate-limit',\n `RATE LIMIT: Agent ${agentState.config.name} (${agentState.config.role}) hit API usage limit.${resetInfo} Total tokens used: ${this.formatTokenCount(totalTokens)} (in:${this.formatTokenCount(stats.totalInputTokens)} out:${this.formatTokenCount(stats.totalOutputTokens)} cache-r:${this.formatTokenCount(stats.totalCacheReadTokens)} cache-w:${this.formatTokenCount(stats.totalCacheCreationTokens)}) | $${stats.totalCostUsd.toFixed(4)}`, {\n taskId: assignedTask.id,\n taskTitle: assignedTask.title,\n agentId: agentState.config.id,\n agentRole: agentState.config.role,\n rateLimitResetAt: agentState.rateLimitResetAt,\n totalTokens,\n cost: stats.totalCostUsd,\n });\n this.emit('rate-limit', agentState.config.id, agentState.rateLimitResetAt);\n\n // Clean up the stale inbox message so a new one is sent on reassignment\n await this.broker.cleanInboxForTask(agentState.config.id, assignedTask.id);\n logger.warn(\n { taskId: assignedTask.id, agentId: agentState.config.id, resetAt: agentState.rateLimitResetAt },\n 'Agent hit rate limit — task reset to pending',\n );\n } else {\n // Agent errored — mark pipeline stage as failed and reset task\n this.pipeline.failStage(assignedTask.id);\n await this.taskManager.updateTask(assignedTask.id, {\n status: 'pending',\n assignee: null,\n });\n this.emitActivity('task-failed', `Task failed and reset: ${assignedTask.title} (agent ${agentState.config.id} errored)`, {\n taskId: assignedTask.id,\n taskTitle: assignedTask.title,\n agentId: agentState.config.id,\n });\n // Clean up the stale inbox message so a new one is sent on reassignment\n await this.broker.cleanInboxForTask(agentState.config.id, assignedTask.id);\n logger.warn(\n { taskId: assignedTask.id, agentId: agentState.config.id },\n 'Task reset to pending (agent process errored)',\n );\n }\n tasksUpdated = true;\n }\n }\n }\n\n // 1b2. Detect orphaned in-progress tasks — the assignee is not actively\n // running in the pool (not spawned, or already idle/stopped/errored).\n // This catches tasks that got stuck from a previous session, a missed\n // state transition, or an agent that exited without the task being updated.\n const activeAgentIds = new Set(\n poolAgents\n .filter((a: any) => a.status === 'running' || a.status === 'starting')\n .map((a: any) => a.config.id),\n );\n\n for (const task of tasks) {\n if (task.status !== 'in-progress') continue;\n if (!task.assignee) {\n // In-progress with no assignee — reset\n await this.taskManager.updateTask(task.id, { status: 'pending', assignee: null });\n this.emitActivity('info', `Reset orphaned task \"${task.title}\" (no assignee)`, { taskId: task.id });\n tasksUpdated = true;\n continue;\n }\n // If the assignee isn't actively running, the task is orphaned\n if (!activeAgentIds.has(task.assignee)) {\n const inPool = poolAgents.find((a: any) => a.config.id === task.assignee);\n // Reset if the agent is not in pool, idle, stopped, or errored.\n // All of these mean the agent is no longer working on the task.\n if (!inPool || inPool.status === 'idle' || inPool.status === 'stopped' || inPool.status === 'error') {\n await this.taskManager.updateTask(task.id, { status: 'pending', assignee: null });\n this.emitActivity('info', `Reset orphaned task \"${task.title}\" (agent ${task.assignee} ${inPool ? inPool.status : 'not in pool'})`, {\n taskId: task.id,\n agentId: task.assignee,\n });\n logger.info({ taskId: task.id, assignee: task.assignee, agentStatus: inPool?.status }, 'Reset orphaned in-progress task');\n tasksUpdated = true;\n }\n }\n }\n\n // 1b3. Detect blocked tasks whose dependencies are all resolved.\n // If a task is blocked but all its dependencies are done/cancelled,\n // unblock it so it can be scheduled.\n for (const task of tasks) {\n if (task.status !== 'blocked') continue;\n if (task.dependencies.length === 0) {\n // Blocked with no dependencies — shouldn't happen, reset to pending\n await this.taskManager.updateTask(task.id, { status: 'pending' });\n this.emitActivity('info', `Unblocked task \"${task.title}\" (no dependencies)`, { taskId: task.id });\n tasksUpdated = true;\n continue;\n }\n const allDepsResolved = task.dependencies.every((depId) => {\n const dep = tasks.find((t: Task) => t.id === depId);\n return !dep || dep.status === 'done' || dep.status === 'cancelled';\n });\n if (allDepsResolved) {\n await this.taskManager.updateTask(task.id, { status: 'pending' });\n this.emitActivity('info', `Unblocked task \"${task.title}\" (all dependencies resolved)`, { taskId: task.id });\n tasksUpdated = true;\n }\n }\n\n // 1c. Reload tasks if any statuses changed\n if (tasksUpdated) {\n tasks = await this.taskManager.load();\n }\n this.cachedTasks = tasks;\n\n // Check progress and emit reports/milestones\n if (this.feedbackLoop) {\n this.feedbackLoop.checkProgress(tasks, this.getStats());\n }\n\n // 1d. Check if all tasks are completed\n if (tasks.length > 0) {\n const allDone = tasks.every((t: Task) => t.status === 'done' || t.status === 'cancelled');\n if (allDone) {\n const summary = this.buildCompletionSummary(tasks);\n this.emit('project:completed', summary);\n this.emitActivity('project-completed', `All ${summary.totalTasks} tasks completed! Total cost: $${summary.totalCostUsd.toFixed(4)}`);\n logger.info({ totalTasks: summary.totalTasks, totalCost: summary.totalCostUsd }, 'All tasks completed');\n await this.stop();\n return;\n }\n }\n\n // 1e. Architecture phase gating\n if (this.phase === 'architecture') {\n if (this.architectureApprovalPending) {\n return; // Waiting for user to approve architecture\n }\n\n const archTasks = tasks.filter((t: Task) => t.tags.includes('architecture'));\n const allArchDone = archTasks.length > 0 && archTasks.every((t: Task) => t.status === 'done');\n\n if (allArchDone) {\n // Architecture phase complete — check interaction mode\n const mode = this.feedbackLoop?.interactionMode ?? 'unattended';\n if (mode === 'supervised' || mode === 'interactive') {\n this.architectureApprovalPending = true;\n this.emit('architecture:ready', archTasks);\n this.emitActivity('phase-changed', 'Architecture phase complete, waiting for user review', {\n fromPhase: 'architecture',\n });\n logger.info('Architecture phase complete, waiting for user review');\n return;\n } else {\n this.phase = 'development';\n this.emit('phase:changed', 'development');\n this.emitActivity('phase-changed', 'Architecture complete, advancing to development', {\n fromPhase: 'architecture',\n toPhase: 'development',\n });\n logger.info('Architecture phase complete, advancing to development');\n }\n }\n }\n\n // Build virtual agent states: agents in the pool plus unspawned configs.\n // The scheduler needs to see available agents to make assignments, but\n // the pool starts empty — agents only enter when spawned. So we present\n // unspawned configs as 'idle' and stopped agents as 'idle' (available for new tasks).\n const poolAgentIds = new Set(poolAgents.map((a: any) => a.config.id));\n\n const virtualAgentStates: any[] = poolAgents.map((a: any) => {\n // Treat stopped/error agents as idle so the scheduler can reassign them\n if (a.status === 'stopped' || a.status === 'error') {\n return { ...a, status: 'idle' };\n }\n return a;\n });\n\n // Add unspawned agent configs as idle virtual agents\n for (const config of this.agentConfigs) {\n if (!poolAgentIds.has(config.id)) {\n virtualAgentStates.push({\n config,\n status: 'idle',\n pid: null,\n sessionId: null,\n currentTask: null,\n startedAt: null,\n lastActivityAt: null,\n totalCostUsd: 0,\n turnCount: 0,\n totalInputTokens: 0,\n totalOutputTokens: 0,\n totalCacheReadTokens: 0,\n totalCacheCreationTokens: 0,\n error: null,\n resultError: null,\n rateLimited: false,\n rateLimitResetAt: null,\n });\n }\n }\n\n // 2. Run scheduler (filter inputs during architecture phase)\n let schedulerTasks = tasks;\n let schedulerAgents = virtualAgentStates;\n if (this.phase === 'architecture') {\n schedulerTasks = tasks.filter((t: Task) => t.tags.includes('architecture'));\n schedulerAgents = virtualAgentStates.filter((a: any) => a.config.role === 'architect');\n }\n const assignments: TaskAssignment[] = this.scheduler.schedule(schedulerTasks, schedulerAgents);\n\n // 3. Process each assignment\n for (const assignment of assignments) {\n const task = tasks.find((t) => t.id === assignment.taskId);\n if (!task) continue;\n\n // Ensure task is registered in pipeline\n if (!this.pipeline.has(task.id)) {\n this.pipeline.initTask(task);\n }\n\n // Record pipeline stage start\n this.pipeline.startStage(task.id, assignment.agentId);\n const pipelineState = this.pipeline.getState(task.id);\n const currentStage = pipelineState?.currentStage ?? 'develop';\n\n // Update task status and assignee\n await this.taskManager.updateTask(assignment.taskId, {\n status: 'in-progress',\n assignee: assignment.agentId,\n });\n\n this.emit('task:assigned', task, assignment.agentId);\n\n // Find the agent config to get the role name\n const agentConfig = this.agentConfigs.find((c: any) => c.id === assignment.agentId);\n const agentRole = agentConfig?.role ?? 'unknown';\n\n this.emitActivity('task-delegated', `Delegated \"${task.title}\" to ${agentConfig?.name ?? assignment.agentId} (${agentRole}) [stage: ${currentStage}]`, {\n taskId: task.id,\n taskTitle: task.title,\n agentId: assignment.agentId,\n agentRole,\n pipelineStage: currentStage,\n });\n\n // Send task-assignment message to the agent, including pipeline context\n const pipelineContext = pipelineState\n ? `\\n\\n**Pipeline Stage:** ${currentStage}\\n**Pipeline History:** ${pipelineState.stageHistory.map((h) => `${h.stage}(${h.status})`).join(' -> ') || 'none'}`\n : '';\n\n const message: Message = {\n id: generateId(),\n type: 'task-assignment',\n from: 'orchestrator',\n to: assignment.agentId,\n subject: `Task Assignment: ${task.title}`,\n body: this.buildTaskPrompt(task) + pipelineContext,\n taskId: task.id,\n priority: task.priority === 'critical' ? 'urgent' : 'normal',\n timestamp: new Date().toISOString(),\n metadata: {\n pipelineStage: currentStage,\n },\n };\n\n await this.broker.sendMessage(message);\n\n // Spawn or resume the agent with the task\n const taskLabel = `${task.id}: ${task.title}`;\n try {\n const existingAgent = this.agentPool.getAgent(assignment.agentId);\n if (existingAgent) {\n existingAgent.setCurrentTask(taskLabel);\n const agentStatus = existingAgent.currentState.status;\n if (agentStatus === 'stopped' || agentStatus === 'error') {\n // Agent finished previous task — resume session or re-spawn\n if (existingAgent.currentState.sessionId && agentStatus === 'stopped') {\n await existingAgent.resume(message.body);\n } else {\n // No session to resume — remove and spawn fresh\n this.agentPool.removeAgent(assignment.agentId);\n if (agentConfig) {\n const newAgent = await this.agentPool.spawnAgent(agentConfig, message.body);\n newAgent.setCurrentTask(taskLabel);\n }\n }\n }\n // If running/starting, skip — agent is already busy\n } else {\n // Agent not in pool yet — spawn it\n if (agentConfig) {\n const newAgent = await this.agentPool.spawnAgent(agentConfig, message.body);\n newAgent.setCurrentTask(taskLabel);\n }\n }\n } catch (err) {\n logger.error(\n { err, agentId: assignment.agentId, taskId: assignment.taskId },\n 'Failed to spawn agent for task',\n );\n this.emitActivity('agent-error', `Failed to spawn agent ${assignment.agentId} for task ${task.title}`, {\n agentId: assignment.agentId,\n taskId: task.id,\n taskTitle: task.title,\n });\n }\n }\n\n // 4. Check budget limits\n this.checkBudget();\n\n // 5. Emit cycle stats\n const stats = this.getStats();\n this.emit('orchestrator:cycle', stats);\n\n // 6. Emit cycle summary activity for visibility\n const pendingCount = tasks.filter((t: Task) => t.status === 'pending').length;\n const inProgressCount = tasks.filter((t: Task) => t.status === 'in-progress').length;\n const doneCount = tasks.filter((t: Task) => t.status === 'done').length;\n const activeCount = stats.activeAgents;\n\n if (tasks.length > 0) {\n const totalTokens = stats.totalInputTokens + stats.totalOutputTokens + stats.totalCacheReadTokens + stats.totalCacheCreationTokens;\n const tokenStr = totalTokens > 0 ? ` | ${this.formatTokenCount(totalTokens)} tokens (in:${this.formatTokenCount(stats.totalInputTokens)} out:${this.formatTokenCount(stats.totalOutputTokens)} cache-r:${this.formatTokenCount(stats.totalCacheReadTokens)} cache-w:${this.formatTokenCount(stats.totalCacheCreationTokens)})` : '';\n this.emitActivity('cycle-summary',\n `Cycle: ${doneCount}/${tasks.length} done | ${inProgressCount} in-progress | ${pendingCount} pending | ${activeCount} agent(s) active | $${stats.totalCostUsd.toFixed(4)}${tokenStr}`,\n );\n }\n }\n\n /**\n * Run a single PM scan pass — assess project health, identify gaps and\n * blockers, and surface findings in the orchestrator activity log.\n */\n private async runPMScan(): Promise<void> {\n if (!this.running || !this.taskManager || !this.agentPool) return;\n\n const tasks: Task[] = await this.taskManager.load();\n if (tasks.length === 0) return;\n\n // Build current agent states (same logic as cycle())\n const poolAgents = this.agentPool.getAllAgents().map((a: any) => a.currentState);\n const poolAgentIds = new Set(poolAgents.map((a: any) => a.config.id));\n\n const allAgentStates: any[] = [...poolAgents];\n for (const config of this.agentConfigs) {\n if (!poolAgentIds.has(config.id)) {\n allAgentStates.push({\n config,\n status: 'idle',\n pid: null,\n sessionId: null,\n currentTask: null,\n startedAt: null,\n lastActivityAt: null,\n totalCostUsd: 0,\n turnCount: 0,\n totalInputTokens: 0,\n totalOutputTokens: 0,\n totalCacheReadTokens: 0,\n totalCacheCreationTokens: 0,\n error: null,\n resultError: null,\n rateLimited: false,\n rateLimitResetAt: null,\n });\n }\n }\n\n const result = this.pmScanner.scan(tasks, allAgentStates, this.phase);\n\n // Emit findings to the orchestrator activity log\n for (const finding of result.findings) {\n if (finding.kind === 'all-clear') {\n // Don't spam the log with \"all clear\" every scan\n continue;\n }\n\n const activityKind = finding.severity === 'critical' ? 'gap-detected' as const : 'info' as const;\n this.emitActivity(activityKind, `[PM] ${finding.message}`, {\n taskId: finding.taskId,\n agentId: finding.agentId,\n });\n }\n\n // Emit the summary line\n this.emitActivity('pm-scan', result.summary);\n\n // Send any actionable messages (e.g., nudge stale agents, escalate bottlenecks)\n if (this.broker) {\n const messages = this.pmScanner.buildMessages(result);\n for (const msg of messages) {\n try {\n await this.broker.sendMessage(msg);\n } catch (err) {\n logger.error({ err, msgId: msg.id }, 'Failed to send PM scan message');\n }\n }\n }\n\n logger.debug({ findingCount: result.findings.length }, 'PM scan complete');\n }\n\n /**\n * Build a task prompt for an agent.\n */\n private buildTaskPrompt(task: Task): string {\n const parts = [\n `# Task: ${task.title}`,\n `**ID:** ${task.id}`,\n `**Priority:** ${task.priority}`,\n '',\n task.description,\n ];\n\n if (task.tags.length > 0) {\n parts.push('', `**Tags:** ${task.tags.join(', ')}`);\n }\n\n if (task.notes.length > 0) {\n parts.push('', '**Notes:**');\n for (const note of task.notes) {\n parts.push(`- ${note}`);\n }\n }\n\n return parts.join('\\n');\n }\n\n /**\n * Check whether the total cost across all agents exceeds the budget.\n */\n private checkBudget(): void {\n const maxBudget = this.config.settings.maxTotalBudgetUsd;\n if (maxBudget == null) return;\n\n const agentStates = this.agentPool.getAllAgents().map((a: any) => a.currentState);\n const totalCost = agentStates.reduce(\n (sum: number, a: { totalCostUsd: number }) => sum + a.totalCostUsd,\n 0,\n );\n\n const warningThreshold = maxBudget * 0.8;\n\n if (totalCost >= maxBudget) {\n this.emit('budget:exceeded', totalCost, maxBudget);\n this.emitActivity('budget-warning', `Budget exceeded: $${totalCost.toFixed(4)} / $${maxBudget.toFixed(2)}`, {\n cost: totalCost,\n });\n logger.warn({ totalCost, maxBudget }, 'Budget exceeded, stopping orchestrator');\n this.stop().catch((err) => {\n logger.error({ err }, 'Failed to stop orchestrator after budget exceeded');\n });\n } else if (totalCost >= warningThreshold) {\n this.emit('budget:warning', totalCost, maxBudget);\n this.emitActivity('budget-warning', `Approaching budget limit: $${totalCost.toFixed(4)} / $${maxBudget.toFixed(2)} (${((totalCost / maxBudget) * 100).toFixed(0)}%)`, {\n cost: totalCost,\n });\n logger.warn({ totalCost, maxBudget }, 'Approaching budget limit');\n }\n }\n\n /**\n * Get all current tasks.\n */\n async getTasks(): Promise<Task[]> {\n if (!this.taskManager) return [];\n return this.taskManager.load();\n }\n\n /**\n * Get all agent states.\n */\n getAgentStates(): any[] {\n if (!this.agentPool) return [];\n return this.agentPool.getAllAgents().map((a: any) => a.currentState);\n }\n\n /**\n * Get the pipeline state for a specific task.\n */\n getTaskPipelineState(taskId: string) {\n return this.pipeline.getState(taskId);\n }\n\n /**\n * Get current orchestrator statistics.\n */\n getStats(): OrchestratorStats {\n const tasks = this.cachedTasks;\n const agentStates = this.agentPool ? this.agentPool.getAllAgents().map((a: any) => a.currentState) : [];\n const spawnedIds = new Set(agentStates.map((a: any) => a.config.id));\n\n const completedTasks = tasks.filter((t: Task) => t.status === 'done').length;\n const activeAgents = agentStates.filter(\n (a: { status: string }) => a.status === 'running' || a.status === 'starting',\n ).length;\n const totalCostUsd = agentStates.reduce(\n (sum: number, a: { totalCostUsd: number }) => sum + a.totalCostUsd,\n 0,\n );\n const totalInputTokens = agentStates.reduce(\n (sum: number, a: { totalInputTokens: number }) => sum + a.totalInputTokens,\n 0,\n );\n const totalOutputTokens = agentStates.reduce(\n (sum: number, a: { totalOutputTokens: number }) => sum + a.totalOutputTokens,\n 0,\n );\n const totalCacheReadTokens = agentStates.reduce(\n (sum: number, a: { totalCacheReadTokens: number }) => sum + a.totalCacheReadTokens,\n 0,\n );\n const totalCacheCreationTokens = agentStates.reduce(\n (sum: number, a: { totalCacheCreationTokens: number }) => sum + a.totalCacheCreationTokens,\n 0,\n );\n const uptimeMs = this.startedAt ? Date.now() - this.startedAt : 0;\n\n // Build full agent roster: spawned agents + unspawned configs\n const agents: OrchestratorStats['agents'] = agentStates.map((a: any) => ({\n id: a.config.id,\n name: a.config.name,\n role: a.config.role,\n status: a.status,\n spawned: true,\n currentTask: a.currentTask,\n }));\n for (const config of this.agentConfigs) {\n if (!spawnedIds.has(config.id)) {\n agents.push({\n id: config.id,\n name: config.name,\n role: config.role,\n status: 'idle',\n spawned: false,\n currentTask: null,\n });\n }\n }\n\n return {\n totalTasks: tasks.length,\n completedTasks,\n activeAgents,\n totalCostUsd,\n totalInputTokens,\n totalOutputTokens,\n totalCacheReadTokens,\n totalCacheCreationTokens,\n uptimeMs,\n agents,\n };\n }\n\n /**\n * Format a token count for display (e.g. 1234567 → \"1.23M\", 45678 → \"45.7k\").\n */\n private formatTokenCount(tokens: number): string {\n if (tokens >= 1_000_000) {\n return `${(tokens / 1_000_000).toFixed(2)}M`;\n }\n if (tokens >= 1_000) {\n return `${(tokens / 1_000).toFixed(1)}k`;\n }\n return String(tokens);\n }\n\n /**\n * Build a summary of the completed project for reporting.\n */\n private buildCompletionSummary(tasks: Task[]): ProjectCompletionSummary {\n const agentStates = this.agentPool\n ? this.agentPool.getAllAgents().map((a: any) => a.currentState)\n : [];\n\n const agentTaskCounts = new Map<string, number>();\n for (const task of tasks) {\n if (task.assignee && task.status === 'done') {\n agentTaskCounts.set(task.assignee, (agentTaskCounts.get(task.assignee) ?? 0) + 1);\n }\n }\n\n const agentSummaries = agentStates.map((a: any) => ({\n agentId: a.config.id,\n name: a.config.name,\n role: a.config.role,\n tasksCompleted: agentTaskCounts.get(a.config.id) ?? 0,\n costUsd: a.totalCostUsd,\n inputTokens: a.totalInputTokens ?? 0,\n outputTokens: a.totalOutputTokens ?? 0,\n }));\n\n const doneTasks = tasks.filter((t: Task) => t.status === 'done').length;\n const cancelledTasks = tasks.filter((t: Task) => t.status === 'cancelled').length;\n\n return {\n totalTasks: tasks.length,\n doneTasks,\n cancelledTasks,\n totalCostUsd: agentStates.reduce((sum: number, a: any) => sum + a.totalCostUsd, 0),\n totalInputTokens: agentStates.reduce((sum: number, a: any) => sum + (a.totalInputTokens ?? 0), 0),\n totalOutputTokens: agentStates.reduce((sum: number, a: any) => sum + (a.totalOutputTokens ?? 0), 0),\n totalCacheReadTokens: agentStates.reduce((sum: number, a: any) => sum + (a.totalCacheReadTokens ?? 0), 0),\n totalCacheCreationTokens: agentStates.reduce((sum: number, a: any) => sum + (a.totalCacheCreationTokens ?? 0), 0),\n uptimeMs: this.startedAt ? Date.now() - this.startedAt : 0,\n agentSummaries,\n completedAt: new Date().toISOString(),\n };\n }\n\n /**\n * Approve the architecture and advance to development phase.\n */\n approveArchitecture(): void {\n if (this.architectureApprovalPending) {\n this.architectureApprovalPending = false;\n this.phase = 'development';\n this.emit('phase:changed', 'development');\n this.emitActivity('phase-changed', 'Architecture approved, advancing to development phase', {\n fromPhase: 'architecture',\n toPhase: 'development',\n });\n logger.info('Architecture approved, advancing to development phase');\n }\n }\n\n /**\n * Get the current orchestration phase.\n */\n getPhase(): string {\n return this.phase;\n }\n\n decidePlan(proposalId: string, decision: 'approved' | 'rejected', modifications?: string): void {\n this.feedbackLoop?.decidePlan(proposalId, decision, modifications);\n }\n\n answerQuestion(questionId: string, answer: string): void {\n this.feedbackLoop?.answerQuestion(questionId, answer);\n }\n\n acknowledgeMilestone(milestoneId: string): void {\n this.feedbackLoop?.acknowledgeMilestone(milestoneId);\n }\n\n setInteractionMode(mode: InteractionMode): void {\n this.feedbackLoop?.setMode(mode);\n }\n\n getInteractionMode(): InteractionMode {\n return this.feedbackLoop?.interactionMode ?? 'supervised';\n }\n\n getPendingPlan(): PlanProposal | null {\n return this.feedbackLoop?.getPendingPlan() ?? null;\n }\n\n getPendingQuestions(): UserQuestion[] {\n return this.feedbackLoop?.getPendingQuestions() ?? [];\n }\n\n /**\n * Get processed messages for a specific task (for task detail view).\n */\n async getTaskMessages(taskId: string): Promise<import('../types/message.js').MessageEnvelope[]> {\n if (!this.broker) return [];\n return this.broker.getProcessedMessagesForTask(taskId);\n }\n}\n","import { EventEmitter } from 'eventemitter3';\nimport type { FeedbackSettings, InteractionMode, PlanProposal, PlannedTaskSummary, UserQuestion, MilestoneEvent, ProgressReport } from '../types/feedback.js';\nimport type { Task } from '../types/task.js';\nimport type { OrchestratorStats } from '../types/events.js';\nimport { ProgressTracker } from './progress-tracker.js';\nimport { generateId } from '../utils/id.js';\nimport { createLogger } from '../utils/logger.js';\n\nconst logger = createLogger('feedback-loop');\n\nconst DEFAULT_SETTINGS: FeedbackSettings = {\n interactionMode: 'supervised',\n progressReportIntervalMs: 60000,\n milestonePercentages: [25, 50, 75, 100],\n questionTimeoutMs: 300000,\n requirePlanApproval: true,\n};\n\nexport class FeedbackLoop extends EventEmitter {\n private mode: InteractionMode;\n private settings: FeedbackSettings;\n private pendingPlan: PlanProposal | null = null;\n private planResolver: ((decision: 'approved' | 'rejected') => void) | null = null;\n private pendingQuestions: Map<string, { question: UserQuestion; resolve: (answer: string | null) => void; timer: ReturnType<typeof setTimeout> | null }> = new Map();\n private lastProgressReport: number = 0;\n private progressTracker: ProgressTracker;\n private reachedMilestones: Set<number> = new Set();\n private pendingMilestone: { milestone: MilestoneEvent; resolve: () => void } | null = null;\n\n constructor(settings?: Partial<FeedbackSettings>) {\n super();\n this.settings = { ...DEFAULT_SETTINGS, ...settings };\n this.mode = this.settings.interactionMode;\n this.progressTracker = new ProgressTracker();\n }\n\n get interactionMode(): InteractionMode { return this.mode; }\n\n setMode(mode: InteractionMode): void {\n this.mode = mode;\n this.emit('interaction-mode:changed', mode);\n }\n\n /**\n * Propose a plan for approval.\n * In unattended mode: auto-approves immediately.\n * In supervised/interactive: emits plan:proposed and waits for decidePlan() call.\n */\n async proposePlan(tasks: PlannedTaskSummary[], projectGoal: string): Promise<'approved' | 'rejected'> {\n if (this.mode === 'unattended' && !this.settings.requirePlanApproval) {\n return 'approved';\n }\n // Even in unattended mode, if requirePlanApproval is true, we need approval\n // But in pure unattended, auto-approve\n if (this.mode === 'unattended') {\n return 'approved';\n }\n\n const proposal: PlanProposal = {\n id: generateId(),\n tasks,\n totalEstimatedTasks: tasks.length,\n projectGoal,\n createdAt: new Date().toISOString(),\n status: 'pending',\n };\n\n this.pendingPlan = proposal;\n\n return new Promise((resolve) => {\n this.planResolver = resolve;\n // Emit AFTER setting the resolver so synchronous handlers\n // that call decidePlan() can resolve the promise immediately\n this.emit('plan:proposed', proposal);\n });\n }\n\n decidePlan(proposalId: string, decision: 'approved' | 'rejected', modifications?: string): void {\n if (!this.pendingPlan || this.pendingPlan.id !== proposalId) {\n logger.warn({ proposalId }, 'No pending plan with this ID');\n return;\n }\n this.pendingPlan.status = decision === 'approved' ? 'approved' : 'rejected';\n this.emit('plan:decided', proposalId, decision, modifications);\n if (this.planResolver) {\n this.planResolver(decision);\n this.planResolver = null;\n }\n this.pendingPlan = null;\n }\n\n /**\n * Route a question from an agent to the user.\n * In unattended mode: returns null immediately (agent should handle itself).\n * In interactive: emits question:asked and waits for answerQuestion() call with timeout.\n * In supervised: same as interactive but question is lower priority.\n */\n async routeQuestion(fromAgent: string, question: string, opts?: { taskId?: string; context?: string; options?: string[] }): Promise<string | null> {\n if (this.mode === 'unattended') {\n return null;\n }\n\n const userQuestion: UserQuestion = {\n id: generateId(),\n fromAgent,\n taskId: opts?.taskId,\n question,\n context: opts?.context,\n options: opts?.options,\n createdAt: new Date().toISOString(),\n status: 'pending',\n };\n\n this.emit('question:asked', userQuestion);\n\n return new Promise((resolve) => {\n const timer = setTimeout(() => {\n userQuestion.status = 'timed-out';\n this.pendingQuestions.delete(userQuestion.id);\n resolve(null);\n }, this.settings.questionTimeoutMs);\n\n this.pendingQuestions.set(userQuestion.id, { question: userQuestion, resolve, timer });\n });\n }\n\n answerQuestion(questionId: string, answer: string): void {\n const entry = this.pendingQuestions.get(questionId);\n if (!entry) {\n logger.warn({ questionId }, 'No pending question with this ID');\n return;\n }\n entry.question.status = 'answered';\n entry.question.answer = answer;\n if (entry.timer) clearTimeout(entry.timer);\n this.pendingQuestions.delete(questionId);\n this.emit('question:answered', questionId, answer);\n entry.resolve(answer);\n }\n\n /**\n * Called each orchestrator cycle to check progress and emit reports/milestones.\n */\n checkProgress(tasks: Task[], stats: OrchestratorStats): void {\n const now = Date.now();\n\n // Periodic progress reports\n if (now - this.lastProgressReport >= this.settings.progressReportIntervalMs) {\n const report = this.progressTracker.generateReport(tasks, stats);\n this.emit('progress:report', report);\n this.lastProgressReport = now;\n }\n\n // Milestone detection\n const percent = this.progressTracker.getCompletionPercentage(tasks);\n for (const threshold of this.settings.milestonePercentages) {\n if (percent >= threshold && !this.reachedMilestones.has(threshold)) {\n this.reachedMilestones.add(threshold);\n const milestone: MilestoneEvent = {\n id: generateId(),\n name: `${threshold}% Complete`,\n percentComplete: threshold,\n message: `Project has reached ${threshold}% completion (${stats.completedTasks}/${stats.totalTasks} tasks done)`,\n requiresAck: this.mode === 'supervised' || this.mode === 'interactive',\n createdAt: new Date().toISOString(),\n };\n this.emit('milestone:reached', milestone);\n }\n }\n }\n\n acknowledgeMilestone(milestoneId: string): void {\n this.emit('milestone:acknowledged', milestoneId);\n }\n\n /**\n * Clean up all pending timers and resolvers.\n * Call this during shutdown to prevent leaked timers from blocking process exit.\n */\n cleanup(): void {\n // Clear pending question timers\n for (const [id, entry] of this.pendingQuestions) {\n if (entry.timer) clearTimeout(entry.timer);\n entry.resolve(null);\n }\n this.pendingQuestions.clear();\n\n // Resolve any pending plan\n if (this.planResolver) {\n this.planResolver('rejected');\n this.planResolver = null;\n }\n this.pendingPlan = null;\n\n this.removeAllListeners();\n logger.debug('FeedbackLoop cleaned up');\n }\n\n getPendingPlan(): PlanProposal | null { return this.pendingPlan; }\n getPendingQuestions(): UserQuestion[] { return Array.from(this.pendingQuestions.values()).map(e => e.question); }\n}\n","import type { Task } from '../types/task.js';\nimport type { ProgressReport } from '../types/feedback.js';\nimport type { OrchestratorStats } from '../types/events.js';\nimport { generateId } from '../utils/id.js';\n\nconst PHASE_ORDER = ['planning', 'architecture', 'design', 'implementation', 'testing', 'documentation'];\n\nexport class ProgressTracker {\n generateReport(tasks: Task[], stats: OrchestratorStats): ProgressReport {\n const completedTasks = tasks.filter((t) => t.status === 'done');\n const pendingTasks = tasks.filter((t) => t.status === 'pending');\n const blockedTasks = tasks.filter((t) => t.status === 'blocked');\n\n return {\n id: generateId(),\n phase: this.detectPhase(tasks),\n completedTasks: completedTasks.length,\n totalTasks: tasks.length,\n percentComplete: this.getCompletionPercentage(tasks),\n recentCompletions: completedTasks.map((t) => t.title),\n upcomingWork: pendingTasks.map((t) => t.title),\n blockers: blockedTasks.map((t) => t.title),\n totalCostUsd: stats.totalCostUsd,\n createdAt: new Date().toISOString(),\n };\n }\n\n getCompletionPercentage(tasks: Task[]): number {\n if (tasks.length === 0) return 0;\n const doneCount = tasks.filter((t) => t.status === 'done').length;\n return Math.round((doneCount / tasks.length) * 100);\n }\n\n detectPhase(tasks: Task[]): string {\n const inProgressTasks = tasks.filter((t) => t.status === 'in-progress');\n\n if (inProgressTasks.length === 0) {\n return 'implementation';\n }\n\n // Count tag occurrences among in-progress tasks\n const tagCounts = new Map<string, number>();\n for (const task of inProgressTasks) {\n for (const tag of task.tags) {\n const normalizedTag = tag.toLowerCase();\n if (PHASE_ORDER.includes(normalizedTag)) {\n tagCounts.set(normalizedTag, (tagCounts.get(normalizedTag) ?? 0) + 1);\n }\n }\n }\n\n if (tagCounts.size === 0) {\n return 'implementation';\n }\n\n // Find the most common phase tag\n let maxCount = 0;\n let mostCommonPhase = 'implementation';\n for (const [tag, count] of tagCounts) {\n if (count > maxCount) {\n maxCount = count;\n mostCommonPhase = tag;\n }\n }\n\n return mostCommonPhase;\n }\n}\n","import { execa } from 'execa';\nimport { readdirSync, statSync } from 'node:fs';\nimport { join, relative } from 'node:path';\nimport type { TaskPriority } from '../types/task.js';\nimport type { TechStackConfig } from '../types/project.js';\nimport { createLogger } from '../utils/logger.js';\n\nconst logger = createLogger('planner');\n\nexport interface PlannedTask {\n title: string;\n priority: TaskPriority;\n description: string;\n dependencies: string[];\n tags: string[];\n}\n\nconst IGNORE_DIRS = new Set([\n '.git', 'node_modules', '.maestro', 'dist', 'build', 'out',\n '.next', '.nuxt', '.output', '.cache', '.turbo', 'coverage',\n '__pycache__', '.venv', 'venv', '.tox', 'target',\n]);\n\nconst IGNORE_FILES = new Set([\n '.DS_Store', 'Thumbs.db', '.env', '.env.local',\n]);\n\nconst DECOMPOSE_PROMPT = `You are a project planning assistant. Break down the following project goal into a set of discrete, actionable tasks.\n\nReturn ONLY a JSON array (no markdown, no explanation) where each element has:\n- \"title\": short task title\n- \"priority\": one of \"critical\", \"high\", \"medium\", \"low\"\n- \"description\": detailed description of what needs to be done\n- \"dependencies\": array of titles of tasks this depends on (empty array if none)\n- \"tags\": array of relevant tags from: \"architecture\", \"design-system\", \"ui\", \"ux\", \"design\", \"planning\", \"priority\", \"frontend\", \"backend\", \"testing\", \"qa\", \"e2e\", \"documentation\", \"docs\", \"api-docs\", \"devops\", \"ci-cd\", \"deployment\", \"docker\", \"infrastructure\", \"security\", \"review\", \"code-review\"\n\nOrder tasks so that dependencies come before the tasks that depend on them.\n\nIMPORTANT — You MUST include tasks for ALL of the following categories. A complete project requires work from every team role:\n\n1. **Architecture** (tag: \"architecture\"): At least one task for creating ARCHITECTURE.md with system design, component structure, data models, and key technical decisions. This should have no dependencies and be listed as a dependency for implementation tasks.\n\n2. **Design** (tags: \"design\", \"ui\", \"ux\", \"design-system\"): Tasks for UI/UX design, component design, design system setup, styling, and visual layouts.\n\n3. **Frontend/Backend development** (tags: \"frontend\", \"backend\"): Core implementation tasks for building features.\n\n4. **Testing & QA** (tags: \"testing\", \"qa\", \"e2e\"): Tasks for writing unit tests, integration tests, and end-to-end tests. These should depend on the implementation tasks they test. Include at least one task for setting up the test framework and one for writing tests for each major feature.\n\n5. **Documentation** (tags: \"documentation\", \"docs\", \"api-docs\"): Tasks for writing README, API documentation, user guides, and inline documentation. These should depend on the features being documented.\n\n6. **DevOps & CI/CD** (tags: \"devops\", \"ci-cd\", \"deployment\", \"docker\", \"infrastructure\"): Tasks for setting up CI/CD pipelines, Docker configuration, deployment scripts, and infrastructure. Include at least one devops task.\n\n7. **Code Review** (tags: \"code-review\", \"review\", \"security\"): Tasks for reviewing code quality, security audit, and ensuring best practices. These should depend on implementation tasks and run toward the end.\n\nEach category must have at least one task. This ensures all team members (architect, designer, developers, QA engineer, technical writer, DevOps engineer, code reviewer) have meaningful work assigned to them.\n`;\n\nexport class Planner {\n private model: string;\n private workingDirectory: string;\n private claudeCommand: string;\n private claudeEnv?: Record<string, string>;\n private techStack?: TechStackConfig;\n\n constructor(opts: { model?: string; workingDirectory: string; claudeCommand?: string; claudeEnv?: Record<string, string>; techStack?: TechStackConfig }) {\n this.model = opts.model ?? 'sonnet';\n this.workingDirectory = opts.workingDirectory;\n this.claudeCommand = opts.claudeCommand ?? 'claude';\n this.claudeEnv = opts.claudeEnv;\n this.techStack = opts.techStack;\n }\n\n /**\n * Use Claude CLI to decompose a goal into a list of planned tasks.\n */\n async decompose(goal: string): Promise<PlannedTask[]> {\n const tree = this.scanDirectory(this.workingDirectory, 4);\n const hasFiles = tree.length > 0;\n\n let prompt = DECOMPOSE_PROMPT;\n if (hasFiles) {\n prompt += `\\nProject working directory: ${this.workingDirectory}\\n`;\n prompt += `\\nExisting project structure:\\n\\`\\`\\`\\n${tree.join('\\n')}\\n\\`\\`\\`\\n`;\n prompt += `\\nConsider the existing files and structure when planning tasks. `;\n prompt += `Build on what already exists rather than recreating from scratch.\\n`;\n }\n\n if (this.techStack) {\n const parts: string[] = [];\n if (this.techStack.frontend) parts.push(`- Frontend: ${this.techStack.frontend}`);\n if (this.techStack.uiLibrary) parts.push(`- UI Library: ${this.techStack.uiLibrary}`);\n if (this.techStack.backend) parts.push(`- Backend: ${this.techStack.backend}`);\n if (this.techStack.database) parts.push(`- Database: ${this.techStack.database}`);\n if (this.techStack.other) parts.push(`- Other: ${this.techStack.other}`);\n if (parts.length > 0) {\n prompt += `\\nTech Stack:\\n${parts.join('\\n')}\\n`;\n prompt += `\\nUse the specified technologies in your task planning. `;\n prompt += `Include setup and configuration tasks for these technologies as needed.\\n`;\n }\n }\n\n prompt += `\\nGoal:\\n${goal}`;\n\n logger.info({ model: this.model, cwd: this.workingDirectory, fileCount: tree.length }, 'Decomposing goal into tasks');\n\n try {\n const result = await execa(this.claudeCommand, [\n '--print',\n '--output-format', 'json',\n '--model', this.model,\n ], {\n input: prompt,\n cwd: this.workingDirectory,\n env: this.claudeEnv ? { ...process.env, ...this.claudeEnv } : undefined,\n timeout: 120_000,\n });\n\n const output = result.stdout.trim();\n return this.parseResponse(output);\n } catch (err) {\n logger.error({ err }, 'Failed to decompose goal via Claude CLI');\n // Fall back to a single task containing the entire goal\n return [{\n title: 'Implement project goal',\n priority: 'high',\n description: goal,\n dependencies: [],\n tags: [],\n }];\n }\n }\n\n /**\n * Scan a directory recursively and return an indented tree listing.\n */\n private scanDirectory(dir: string, maxDepth: number, depth = 0, prefix = ''): string[] {\n if (depth >= maxDepth) return [];\n\n const lines: string[] = [];\n let entries: string[];\n\n try {\n entries = readdirSync(dir).sort();\n } catch {\n return lines;\n }\n\n const dirs: string[] = [];\n const files: string[] = [];\n\n for (const entry of entries) {\n if (IGNORE_DIRS.has(entry) || IGNORE_FILES.has(entry) || entry.startsWith('.')) continue;\n const fullPath = join(dir, entry);\n try {\n const stat = statSync(fullPath);\n if (stat.isDirectory()) {\n dirs.push(entry);\n } else {\n files.push(entry);\n }\n } catch {\n // Skip inaccessible entries\n }\n }\n\n for (const file of files) {\n lines.push(`${prefix}${file}`);\n }\n\n for (const d of dirs) {\n lines.push(`${prefix}${d}/`);\n const subLines = this.scanDirectory(join(dir, d), maxDepth, depth + 1, prefix + ' ');\n lines.push(...subLines);\n }\n\n return lines;\n }\n\n private parseResponse(output: string): PlannedTask[] {\n try {\n // Claude --output-format json wraps the response in a JSON object\n // with a \"result\" field containing the text response\n let text = output;\n\n try {\n const parsed = JSON.parse(output);\n if (parsed && typeof parsed === 'object' && 'result' in parsed) {\n text = parsed.result;\n }\n } catch {\n // Output may already be the raw text, continue\n }\n\n // Extract JSON array from the text (may be wrapped in markdown code fences)\n const jsonMatch = text.match(/\\[[\\s\\S]*\\]/);\n if (!jsonMatch) {\n throw new Error('No JSON array found in response');\n }\n\n const tasks = JSON.parse(jsonMatch[0]) as PlannedTask[];\n\n if (!Array.isArray(tasks) || tasks.length === 0) {\n throw new Error('Parsed result is not a non-empty array');\n }\n\n // Validate each task has required fields\n for (const task of tasks) {\n if (!task.title || !task.description) {\n throw new Error(`Task missing required fields: ${JSON.stringify(task)}`);\n }\n task.priority = task.priority ?? 'medium';\n task.dependencies = task.dependencies ?? [];\n task.tags = task.tags ?? [];\n }\n\n logger.info({ taskCount: tasks.length }, 'Goal decomposed into tasks');\n return tasks;\n } catch (err) {\n logger.warn({ err }, 'Failed to parse planner response, returning single task');\n return [{\n title: 'Implement project goal',\n priority: 'high',\n description: output,\n dependencies: [],\n tags: [],\n }];\n }\n }\n}\n","import type { Task, TaskPriority } from '../types/task.js';\nimport type { AgentState, AgentRole } from '../types/agent.js';\nimport type { PipelineStage } from '../types/orchestrator-activity.js';\nimport { PIPELINE_STAGE_ROLES } from '../types/orchestrator-activity.js';\nimport type { TaskPipeline } from './pipeline.js';\nimport { createLogger } from '../utils/logger.js';\n\nconst logger = createLogger('scheduler');\n\nexport interface TaskAssignment {\n taskId: string;\n agentId: string;\n}\n\n/**\n * Maps task tags to the agent role best suited to handle them.\n * A task may have multiple tags; the first matching role wins.\n */\nconst TAG_ROLE_MAP: Record<string, AgentRole> = {\n 'architecture': 'architect',\n 'design-system': 'architect',\n 'ui': 'designer',\n 'ux': 'designer',\n 'design': 'designer',\n 'planning': 'project-manager',\n 'priority': 'project-manager',\n 'testing': 'qa-engineer',\n 'qa': 'qa-engineer',\n 'e2e': 'qa-engineer',\n 'devops': 'devops',\n 'ci-cd': 'devops',\n 'deployment': 'devops',\n 'infrastructure': 'devops',\n 'docker': 'devops',\n 'documentation': 'technical-writer',\n 'docs': 'technical-writer',\n 'api-docs': 'technical-writer',\n 'review': 'code-reviewer',\n 'code-review': 'code-reviewer',\n 'security': 'code-reviewer',\n};\n\n/**\n * Fallback roles: when the preferred role has no idle agents,\n * try these roles in order before giving up.\n */\nconst ROLE_FALLBACK: Partial<Record<AgentRole, AgentRole[]>> = {\n 'designer': ['developer'],\n 'architect': ['developer'],\n 'project-manager': [],\n 'qa-engineer': ['developer'],\n 'devops': ['developer'],\n 'technical-writer': ['developer'],\n 'code-reviewer': ['architect', 'developer'],\n};\n\n/** Ordering for task priority: lower index = higher urgency. */\nconst PRIORITY_ORDER: Record<TaskPriority, number> = {\n critical: 0,\n high: 1,\n medium: 2,\n low: 3,\n};\n\nexport class Scheduler {\n /** Optional pipeline reference for pipeline-aware scheduling. */\n private pipeline: TaskPipeline | null = null;\n\n /**\n * Set a pipeline reference so the scheduler can use pipeline stage\n * information when determining which role should handle a task.\n */\n setPipeline(pipeline: TaskPipeline): void {\n this.pipeline = pipeline;\n }\n\n /**\n * Determine which pending tasks should be assigned to which idle agents.\n *\n * Rules:\n * 1. Only consider tasks whose status is 'pending' and whose dependencies are all 'done'.\n * 2. Only consider agents whose status is 'idle'.\n * 3. Match tasks to agents by role:\n * - If a task has a pipeline state, use the pipeline stage to determine role\n * - Otherwise, fall back to tag-based role determination\n * 4. Assign higher-priority tasks first.\n * 5. Each agent receives at most one assignment per scheduling cycle.\n */\n schedule(tasks: Task[], agents: AgentState[]): TaskAssignment[] {\n const taskStatusMap = new Map<string, Task>();\n for (const task of tasks) {\n taskStatusMap.set(task.id, task);\n }\n\n // Find tasks that are ready to be assigned\n const readyTasks = tasks.filter((task) => {\n if (task.status !== 'pending') return false;\n\n // All dependencies must be 'done' (or missing — a missing dep means\n // the task was deleted or never created, so treat it as satisfied).\n return task.dependencies.every((depId) => {\n const dep = taskStatusMap.get(depId);\n return !dep || dep.status === 'done';\n });\n });\n\n // Sort by priority (critical first)\n readyTasks.sort((a, b) => PRIORITY_ORDER[a.priority] - PRIORITY_ORDER[b.priority]);\n\n // Collect idle agents into a map by role for efficient lookup\n const idleAgentsByRole = new Map<AgentRole, AgentState[]>();\n for (const agent of agents) {\n if (agent.status !== 'idle') continue;\n const role = agent.config.role;\n if (!idleAgentsByRole.has(role)) {\n idleAgentsByRole.set(role, []);\n }\n idleAgentsByRole.get(role)!.push(agent);\n }\n\n const assignments: TaskAssignment[] = [];\n const assignedAgentIds = new Set<string>();\n\n for (const task of readyTasks) {\n const neededRole = this.determineRole(task);\n const rolesToTry: AgentRole[] = [neededRole, ...(ROLE_FALLBACK[neededRole] ?? [])];\n let assigned = false;\n\n for (const role of rolesToTry) {\n const candidates = idleAgentsByRole.get(role);\n if (!candidates || candidates.length === 0) {\n continue;\n }\n\n const agent = candidates.find((a) => !assignedAgentIds.has(a.config.id));\n if (!agent) {\n continue;\n }\n\n assignedAgentIds.add(agent.config.id);\n assignments.push({\n taskId: task.id,\n agentId: agent.config.id,\n });\n\n logger.debug(\n { taskId: task.id, agentId: agent.config.id, neededRole, actualRole: role },\n role === neededRole ? 'Task assigned to agent' : 'Task assigned to fallback agent',\n );\n assigned = true;\n break;\n }\n\n if (!assigned) {\n // This is normal — all agents for the needed role are busy.\n // The task will be retried on the next scheduling cycle.\n logger.trace(\n { taskId: task.id, neededRole },\n 'No idle agent available for role, will retry next cycle',\n );\n }\n }\n\n return assignments;\n }\n\n /**\n * Determine the best role for a task.\n *\n * If the task has an active pipeline state, the pipeline stage takes\n * priority over tag-based role determination. This enables the\n * plan -> develop -> qa -> review handoff sequence.\n *\n * Falls back to tag-based determination, then defaults to 'developer'.\n */\n private determineRole(task: Task): AgentRole {\n // Pipeline-aware: check if this task is in a pipeline stage\n if (this.pipeline) {\n const pipelineState = this.pipeline.getState(task.id);\n if (pipelineState) {\n const stageRoles = PIPELINE_STAGE_ROLES[pipelineState.currentStage];\n if (stageRoles && stageRoles.length > 0) {\n // Return the first role for the current pipeline stage\n return stageRoles[0] as AgentRole;\n }\n }\n }\n\n // Fall back to tag-based role determination\n for (const tag of task.tags) {\n const role = TAG_ROLE_MAP[tag];\n if (role) {\n return role;\n }\n }\n return 'developer';\n }\n}\n","import type {\n PipelineStage,\n TaskPipelineState,\n} from '../types/orchestrator-activity.js';\nimport { PIPELINE_STAGE_ORDER, PIPELINE_STAGE_ROLES } from '../types/orchestrator-activity.js';\nimport type { Task } from '../types/task.js';\nimport type { AgentRole } from '../types/agent.js';\nimport { createLogger } from '../utils/logger.js';\n\nconst logger = createLogger('pipeline');\n\n/**\n * TaskPipeline manages the lifecycle of tasks through a multi-stage pipeline:\n * plan -> develop -> qa -> review\n *\n * Each stage maps to one or more agent roles. When a stage completes, the\n * pipeline advances the task to the next stage and returns handoff information\n * so the orchestrator can delegate to the appropriate agent.\n */\nexport class TaskPipeline {\n private pipelines = new Map<string, TaskPipelineState>();\n\n /**\n * Register a task in the pipeline at a given starting stage.\n * Tasks tagged with 'architecture' or 'planning' start at 'plan'.\n * Tasks tagged with 'testing' or 'qa' start at 'qa'.\n * All others start at 'develop' (they'll skip the plan stage\n * if they were already created from the planner).\n */\n initTask(task: Task, startStage?: PipelineStage): TaskPipelineState {\n const stage = startStage ?? this.inferStartStage(task);\n const state: TaskPipelineState = {\n taskId: task.id,\n currentStage: stage,\n stageHistory: [],\n createdAt: new Date().toISOString(),\n };\n this.pipelines.set(task.id, state);\n logger.debug({ taskId: task.id, stage }, 'Task registered in pipeline');\n return state;\n }\n\n /**\n * Get the pipeline state for a task.\n */\n getState(taskId: string): TaskPipelineState | undefined {\n return this.pipelines.get(taskId);\n }\n\n /**\n * Record that an agent has started working on the current stage.\n */\n startStage(taskId: string, agentId: string): void {\n const state = this.pipelines.get(taskId);\n if (!state) return;\n\n state.stageHistory.push({\n stage: state.currentStage,\n agentId,\n startedAt: new Date().toISOString(),\n completedAt: null,\n status: 'in-progress',\n });\n }\n\n /**\n * Complete the current stage and return the next stage (if any).\n * Returns null if the pipeline is finished.\n */\n completeStage(taskId: string): {\n nextStage: PipelineStage | null;\n requiredRoles: string[];\n handoffMessage: string;\n } | null {\n const state = this.pipelines.get(taskId);\n if (!state) return null;\n\n // Mark current stage entry as completed\n const currentEntry = state.stageHistory.find(\n (h) => h.stage === state.currentStage && h.status === 'in-progress',\n );\n if (currentEntry) {\n currentEntry.completedAt = new Date().toISOString();\n currentEntry.status = 'completed';\n }\n\n // Find next stage\n const currentIndex = PIPELINE_STAGE_ORDER.indexOf(state.currentStage);\n if (currentIndex < 0 || currentIndex >= PIPELINE_STAGE_ORDER.length - 1) {\n // Pipeline complete\n logger.info({ taskId }, 'Task pipeline completed');\n return {\n nextStage: null,\n requiredRoles: [],\n handoffMessage: `Pipeline complete for task ${taskId}`,\n };\n }\n\n const nextStage = PIPELINE_STAGE_ORDER[currentIndex + 1];\n state.currentStage = nextStage;\n const requiredRoles = PIPELINE_STAGE_ROLES[nextStage];\n\n const stageLabels: Record<PipelineStage, string> = {\n plan: 'Planning & Architecture',\n develop: 'Development',\n qa: 'QA & Testing',\n review: 'Project Manager Review',\n };\n\n logger.info({ taskId, from: PIPELINE_STAGE_ORDER[currentIndex], to: nextStage }, 'Pipeline handoff');\n\n return {\n nextStage,\n requiredRoles,\n handoffMessage: `Handoff: ${stageLabels[PIPELINE_STAGE_ORDER[currentIndex]]} -> ${stageLabels[nextStage]}`,\n };\n }\n\n /**\n * Mark a stage as failed.\n */\n failStage(taskId: string): void {\n const state = this.pipelines.get(taskId);\n if (!state) return;\n\n const currentEntry = state.stageHistory.find(\n (h) => h.stage === state.currentStage && h.status === 'in-progress',\n );\n if (currentEntry) {\n currentEntry.completedAt = new Date().toISOString();\n currentEntry.status = 'failed';\n }\n }\n\n /**\n * Get the role(s) needed for the current pipeline stage of a task.\n */\n getRequiredRoles(taskId: string): AgentRole[] {\n const state = this.pipelines.get(taskId);\n if (!state) return ['developer'];\n return PIPELINE_STAGE_ROLES[state.currentStage] as AgentRole[];\n }\n\n /**\n * Check if a task has a pipeline registered.\n */\n has(taskId: string): boolean {\n return this.pipelines.has(taskId);\n }\n\n /**\n * Infer the starting pipeline stage from task tags.\n */\n private inferStartStage(task: Task): PipelineStage {\n const tags = task.tags.map((t) => t.toLowerCase());\n\n if (tags.includes('architecture') || tags.includes('planning') || tags.includes('design-system')) {\n return 'plan';\n }\n if (tags.includes('testing') || tags.includes('qa') || tags.includes('e2e')) {\n return 'qa';\n }\n // Most tasks coming from the planner already have a plan, so start at develop\n return 'develop';\n }\n}\n","import type { Task } from '../types/task.js';\nimport type { AgentState, AgentConfig } from '../types/agent.js';\nimport type { OrchestratorActivity } from '../types/orchestrator-activity.js';\nimport type { Message } from '../types/message.js';\nimport { generateId } from '../utils/id.js';\nimport { createLogger } from '../utils/logger.js';\n\nconst logger = createLogger('pm-scanner');\n\n/**\n * Findings from a PM scan cycle — these are deterministic assessments\n * that the orchestrator can act on or surface in the activity log.\n */\nexport interface PMScanResult {\n timestamp: string;\n findings: PMFinding[];\n summary: string;\n}\n\nexport type PMFindingKind =\n | 'blocked-task'\n | 'stale-task'\n | 'unassigned-ready-task'\n | 'agent-idle'\n | 'agent-errored'\n | 'dependency-bottleneck'\n | 'high-priority-waiting'\n | 'progress-stalled'\n | 'all-clear';\n\nexport interface PMFinding {\n kind: PMFindingKind;\n severity: 'info' | 'warning' | 'critical';\n message: string;\n taskId?: string;\n agentId?: string;\n}\n\n/**\n * Default scan interval: 30 seconds.\n * This is separate from the orchestrator poll interval so the PM scans\n * at a slower cadence — it's an assessment, not a scheduling loop.\n */\nconst DEFAULT_SCAN_INTERVAL_MS = 30_000;\n\n/**\n * After this many consecutive cycles with a task in-progress and no\n * completion, flag it as potentially stalled.\n */\nconst STALE_TASK_THRESHOLD_MS = 5 * 60_000; // 5 minutes\n\n/**\n * ProjectManagerScanner runs a periodic assessment loop that inspects the\n * current task board and agent pool, identifies gaps, blockers, stalled\n * progress, and idle resources, then reports findings via the orchestrator's\n * activity log and (optionally) sends messages to the relevant agents.\n *\n * This is NOT an LLM call — it's deterministic analysis. It runs the PM\n * role at the *orchestration layer* rather than spawning a Claude subprocess.\n * For deeper analysis that requires reasoning (e.g., \"is this architecture\n * design good?\"), a real PM agent is spawned via the pipeline's `review` stage.\n */\nexport class ProjectManagerScanner {\n private intervalId: ReturnType<typeof setInterval> | null = null;\n private scanIntervalMs: number;\n private lastScanTasks: Map<string, { status: string; at: number }> = new Map();\n private cycleCount = 0;\n /** Track tasks that have already received a PM message to avoid duplicates. */\n private messagedTasks: Set<string> = new Set();\n\n constructor(scanIntervalMs?: number) {\n this.scanIntervalMs = scanIntervalMs ?? DEFAULT_SCAN_INTERVAL_MS;\n }\n\n /**\n * Start the periodic scan loop.\n * @param scanFn — called each interval; the orchestrator provides context.\n */\n start(scanFn: () => void): void {\n if (this.intervalId) return;\n this.intervalId = setInterval(scanFn, this.scanIntervalMs);\n logger.info({ intervalMs: this.scanIntervalMs }, 'PM scanner started');\n }\n\n stop(): void {\n if (this.intervalId) {\n clearInterval(this.intervalId);\n this.intervalId = null;\n }\n logger.info('PM scanner stopped');\n }\n\n /**\n * Run a single scan pass.\n *\n * @param tasks - Current task list\n * @param agents - Current agent states (from pool + virtual)\n * @param phase - Current orchestrator phase\n */\n scan(\n tasks: Task[],\n agents: AgentState[],\n phase: string,\n ): PMScanResult {\n this.cycleCount++;\n const now = Date.now();\n const findings: PMFinding[] = [];\n\n // --- 1. Blocked tasks ---\n const blockedTasks = tasks.filter((t) => t.status === 'blocked');\n for (const task of blockedTasks) {\n const blockerIds = task.dependencies.filter((depId) => {\n const dep = tasks.find((t) => t.id === depId);\n return dep && dep.status !== 'done';\n });\n findings.push({\n kind: 'blocked-task',\n severity: task.priority === 'critical' ? 'critical' : 'warning',\n message: `Task \"${task.title}\" (${task.id}) is blocked by: ${blockerIds.join(', ')}`,\n taskId: task.id,\n });\n }\n\n // --- 2. High-priority tasks waiting too long ---\n const highPriorityPending = tasks.filter(\n (t) => t.status === 'pending' && (t.priority === 'critical' || t.priority === 'high'),\n );\n for (const task of highPriorityPending) {\n findings.push({\n kind: 'high-priority-waiting',\n severity: task.priority === 'critical' ? 'critical' : 'warning',\n message: `High-priority task \"${task.title}\" (${task.id}) is pending and unassigned`,\n taskId: task.id,\n });\n }\n\n // --- 3. Stale in-progress tasks (no movement for STALE_TASK_THRESHOLD_MS) ---\n const inProgressTasks = tasks.filter((t) => t.status === 'in-progress');\n for (const task of inProgressTasks) {\n const prev = this.lastScanTasks.get(task.id);\n if (prev && prev.status === 'in-progress') {\n const elapsed = now - prev.at;\n if (elapsed > STALE_TASK_THRESHOLD_MS) {\n findings.push({\n kind: 'stale-task',\n severity: 'warning',\n message: `Task \"${task.title}\" (${task.id}) has been in-progress for ${Math.round(elapsed / 60_000)}min without completion`,\n taskId: task.id,\n agentId: task.assignee ?? undefined,\n });\n }\n } else {\n // First time seeing this task in-progress — record the timestamp\n this.lastScanTasks.set(task.id, { status: 'in-progress', at: now });\n }\n }\n\n // Clean up completed tasks from tracking\n for (const task of tasks) {\n if (task.status === 'done' || task.status === 'cancelled') {\n this.lastScanTasks.delete(task.id);\n this.clearTrackedTask(task.id);\n } else if (task.status !== 'in-progress') {\n // Reset tracking if it goes back to pending\n const prev = this.lastScanTasks.get(task.id);\n if (prev && prev.status === 'in-progress') {\n this.lastScanTasks.delete(task.id);\n this.clearTrackedTask(task.id);\n }\n }\n }\n\n // --- 4. Ready tasks with no idle agents to handle them ---\n const taskStatusMap = new Map(tasks.map((t) => [t.id, t]));\n const readyTasks = tasks.filter((t) => {\n if (t.status !== 'pending') return false;\n return t.dependencies.every((depId) => {\n const dep = taskStatusMap.get(depId);\n return dep && dep.status === 'done';\n });\n });\n const idleAgents = agents.filter((a) => a.status === 'idle');\n\n if (readyTasks.length > 0 && idleAgents.length === 0) {\n findings.push({\n kind: 'unassigned-ready-task',\n severity: 'warning',\n message: `${readyTasks.length} task(s) ready but no idle agents available`,\n });\n }\n\n // --- 5. Agents with errors ---\n const erroredAgents = agents.filter((a) => a.status === 'error');\n for (const agent of erroredAgents) {\n findings.push({\n kind: 'agent-errored',\n severity: 'warning',\n message: `Agent ${agent.config.name} (${agent.config.id}) is in error state: ${agent.error ?? 'unknown'}`,\n agentId: agent.config.id,\n });\n }\n\n // --- 6. Idle agents with pending work (possible scheduling gap) ---\n if (idleAgents.length > 0 && readyTasks.length > 0) {\n findings.push({\n kind: 'agent-idle',\n severity: 'info',\n message: `${idleAgents.length} idle agent(s) with ${readyTasks.length} ready task(s) — scheduling may pick these up next cycle`,\n });\n }\n\n // --- 7. Dependency bottleneck detection ---\n // Find tasks that are blocking many other tasks\n const blockingCounts = new Map<string, number>();\n for (const task of tasks) {\n if (task.status === 'done' || task.status === 'cancelled') continue;\n for (const depId of task.dependencies) {\n const dep = taskStatusMap.get(depId);\n if (dep && dep.status !== 'done') {\n blockingCounts.set(depId, (blockingCounts.get(depId) ?? 0) + 1);\n }\n }\n }\n for (const [taskId, count] of blockingCounts) {\n if (count >= 3) {\n const task = taskStatusMap.get(taskId);\n findings.push({\n kind: 'dependency-bottleneck',\n severity: 'critical',\n message: `Task \"${task?.title ?? taskId}\" is blocking ${count} other tasks — should be prioritized`,\n taskId,\n });\n }\n }\n\n // --- 8. Progress stall detection ---\n // If we've run several scans and the done count hasn't changed, flag it\n const doneCount = tasks.filter((t) => t.status === 'done').length;\n const inProgressCount = inProgressTasks.length;\n const pendingCount = tasks.filter((t) => t.status === 'pending').length;\n\n // --- Build summary ---\n if (findings.length === 0) {\n findings.push({\n kind: 'all-clear',\n severity: 'info',\n message: 'All systems nominal — no gaps or blockers detected',\n });\n }\n\n const criticalCount = findings.filter((f) => f.severity === 'critical').length;\n const warningCount = findings.filter((f) => f.severity === 'warning').length;\n\n let summary: string;\n if (criticalCount > 0) {\n summary = `PM Scan: ${criticalCount} critical, ${warningCount} warning(s) | ${doneCount}/${tasks.length} done | ${inProgressCount} active | ${pendingCount} pending`;\n } else if (warningCount > 0) {\n summary = `PM Scan: ${warningCount} warning(s) | ${doneCount}/${tasks.length} done | ${inProgressCount} active | ${pendingCount} pending`;\n } else {\n summary = `PM Scan: All clear | ${doneCount}/${tasks.length} done | ${inProgressCount} active | ${pendingCount} pending`;\n }\n\n return {\n timestamp: new Date().toISOString(),\n findings,\n summary,\n };\n }\n\n /**\n * Build messages from PM findings that should be sent to agents.\n * Only produces messages for actionable findings.\n * Tracks which tasks have already been messaged to avoid flooding inboxes.\n */\n buildMessages(result: PMScanResult): Message[] {\n const messages: Message[] = [];\n\n for (const finding of result.findings) {\n // Escalate critical bottlenecks as urgent messages to orchestrator\n // (only once per task)\n if (finding.kind === 'dependency-bottleneck' && finding.severity === 'critical' && finding.taskId) {\n const key = `bottleneck:${finding.taskId}`;\n if (this.messagedTasks.has(key)) continue;\n this.messagedTasks.add(key);\n\n messages.push({\n id: generateId(),\n type: 'directive',\n from: 'project-manager',\n to: 'orchestrator',\n subject: `Bottleneck: ${finding.message}`,\n body: `The project manager has identified a critical dependency bottleneck.\\n\\n${finding.message}\\n\\nRecommendation: Prioritize this task immediately to unblock downstream work.`,\n taskId: finding.taskId,\n priority: 'urgent',\n timestamp: result.timestamp,\n });\n }\n\n // Notify agents about stale tasks (only once per task)\n if (finding.kind === 'stale-task' && finding.agentId && finding.taskId) {\n const key = `stale:${finding.taskId}`;\n if (this.messagedTasks.has(key)) continue;\n this.messagedTasks.add(key);\n\n messages.push({\n id: generateId(),\n type: 'system',\n from: 'project-manager',\n to: finding.agentId,\n subject: `Status check: ${finding.taskId}`,\n body: `The project manager is checking on progress.\\n\\n${finding.message}\\n\\nPlease provide a status update or flag any blockers you're experiencing.`,\n taskId: finding.taskId,\n priority: 'normal',\n timestamp: result.timestamp,\n });\n }\n }\n\n return messages;\n }\n\n /**\n * Clear tracked messages for a task (e.g., when it moves from in-progress\n * back to pending, allowing a new message if it stalls again later).\n */\n clearTrackedTask(taskId: string): void {\n for (const key of this.messagedTasks) {\n if (key.endsWith(`:${taskId}`)) {\n this.messagedTasks.delete(key);\n }\n }\n }\n}\n","import { z } from 'zod';\nimport { readFile } from 'node:fs/promises';\nimport { parse as parseYaml } from 'yaml';\nimport type { ProjectConfig } from '../types/project.js';\n\nconst permissionModeSchema = z.enum(['default', 'acceptEdits', 'bypassPermissions']);\n\nconst agentRoleConfigSchema = z.object({\n role: z.enum(['orchestrator', 'project-manager', 'architect', 'developer', 'designer', 'qa-engineer', 'devops', 'technical-writer', 'code-reviewer']),\n count: z.number().int().min(1),\n model: z.string().optional(),\n systemPromptFile: z.string().optional(),\n systemPromptOverride: z.string().optional(),\n allowedTools: z.array(z.string()).optional(),\n maxBudgetUsd: z.number().positive().optional(),\n permissionMode: permissionModeSchema.optional(),\n claudeArgs: z.array(z.string()).optional(),\n claudeEnv: z.record(z.string()).optional(),\n maxTurns: z.number().int().positive().optional(),\n});\n\nconst projectSettingsSchema = z.object({\n workingDirectory: z.string().default('.'),\n todoFile: z.string().default('todo.md'),\n messagesDirectory: z.string().default('.maestro/messages'),\n logsDirectory: z.string().default('.maestro/logs'),\n defaultModel: z.string().default('sonnet'),\n maxConcurrentAgents: z.number().int().min(1).default(5),\n pollIntervalMs: z.number().int().min(500).default(5000),\n maxTotalBudgetUsd: z.number().positive().optional(),\n claudeCommand: z.string().optional(),\n claudeArgs: z.array(z.string()).optional(),\n claudeEnv: z.record(z.string()).optional(),\n feedback: z.object({\n interactionMode: z.enum(['unattended', 'supervised', 'interactive']).default('supervised'),\n progressReportIntervalMs: z.number().int().min(1000).default(60000),\n milestonePercentages: z.array(z.number().min(0).max(100)).default([25, 50, 75, 100]),\n questionTimeoutMs: z.number().int().min(1000).default(300000),\n requirePlanApproval: z.boolean().default(true),\n }).optional(),\n});\n\nconst techStackSchema = z.object({\n frontend: z.string().optional(),\n uiLibrary: z.string().optional(),\n backend: z.string().optional(),\n database: z.string().optional(),\n other: z.string().optional(),\n}).optional();\n\nexport const projectConfigSchema = z.object({\n name: z.string().min(1),\n description: z.string(),\n version: z.string(),\n agents: z.array(agentRoleConfigSchema).min(1),\n settings: projectSettingsSchema.default({}),\n techStack: techStackSchema,\n});\n\n/**\n * Load and validate a project configuration from a YAML file.\n *\n * Reads the file at the given path, parses it as YAML, and validates\n * the result against the project config schema.\n */\nexport async function loadProjectConfig(filePath: string): Promise<ProjectConfig> {\n const raw = await readFile(filePath, 'utf-8');\n const parsed = parseYaml(raw);\n return validateProjectConfig(parsed);\n}\n\n/**\n * Validate an unknown value against the project config schema.\n *\n * Returns a fully typed ProjectConfig with defaults applied, or\n * throws a ZodError if validation fails.\n */\nexport function validateProjectConfig(config: unknown): ProjectConfig {\n return projectConfigSchema.parse(config) as ProjectConfig;\n}\n","import { mkdir } from 'node:fs/promises';\nimport path from 'node:path';\nimport type { ProjectConfig } from '../types/project.js';\n\n/**\n * Manages the runtime directory structure for a Maestro project.\n *\n * Ensures all required directories exist and provides absolute path\n * resolution for todo files, message inboxes/outboxes, and log files.\n */\nexport class WorkspaceManager {\n private baseDir: string;\n private config: ProjectConfig | null = null;\n\n constructor(baseDir: string) {\n this.baseDir = path.resolve(baseDir);\n }\n\n /**\n * Create all runtime directories required by the project.\n *\n * This creates the top-level .maestro directory, the messages directory,\n * the logs directory, and per-agent inbox/outbox directories for every\n * agent defined in the project config.\n */\n async initialize(config: ProjectConfig): Promise<void> {\n this.config = config;\n\n const messagesDir = this.getMessagesDir();\n const logsDir = this.getLogsDir();\n\n // Create top-level runtime directories\n await mkdir(messagesDir, { recursive: true });\n await mkdir(logsDir, { recursive: true });\n\n // Create per-agent inbox and outbox directories\n for (const agentRoleConfig of config.agents) {\n for (let i = 0; i < agentRoleConfig.count; i++) {\n const agentId = agentRoleConfig.count === 1\n ? agentRoleConfig.role\n : `${agentRoleConfig.role}-${i + 1}`;\n\n await mkdir(this.getAgentInboxPath(agentId), { recursive: true });\n await mkdir(this.getAgentOutboxPath(agentId), { recursive: true });\n }\n }\n }\n\n /**\n * Get the absolute path to the project's todo file.\n */\n getTodoFilePath(): string {\n const todoFile = this.config?.settings.todoFile ?? 'todo.md';\n return path.resolve(this.baseDir, todoFile);\n }\n\n /**\n * Get the absolute path to the messages directory.\n */\n getMessagesDir(): string {\n const messagesDir = this.config?.settings.messagesDirectory ?? '.maestro/messages';\n return path.resolve(this.baseDir, messagesDir);\n }\n\n /**\n * Get the absolute path to the logs directory.\n */\n getLogsDir(): string {\n const logsDir = this.config?.settings.logsDirectory ?? '.maestro/logs';\n return path.resolve(this.baseDir, logsDir);\n }\n\n /**\n * Get the absolute path to a specific agent's log file.\n */\n getAgentLogPath(agentId: string): string {\n return path.resolve(this.getLogsDir(), `${agentId}.log`);\n }\n\n /**\n * Get the absolute path to a specific agent's inbox directory.\n */\n getAgentInboxPath(agentId: string): string {\n return path.resolve(this.getMessagesDir(), agentId, 'inbox');\n }\n\n /**\n * Get the absolute path to a specific agent's outbox directory.\n */\n getAgentOutboxPath(agentId: string): string {\n return path.resolve(this.getMessagesDir(), agentId, 'outbox');\n }\n}\n"],"mappings":"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","names":["writeFile","access","EventEmitter","EventEmitter","todoFilePath","messagesDir","EventEmitter","mkdir","writeFile","readFile","rename","join","EventEmitter","readFile","logger","logger","EventEmitter","join","mkdir","writeFile","readFile","rename","EventEmitter","mkdir","EventEmitter","logger","EventEmitter","execa","join","logger","logger","PRIORITY_ORDER","logger","logger","logger","EventEmitter","mkdir","TaskManager","AgentPool","loadAgentConfigs","stats","readFile","mkdir","path"]}
1
+ {"version":3,"sources":["../src/task/parser.ts","../src/task/writer.ts","../src/utils/id.ts","../src/task/lock.ts","../src/task/manager.ts","../src/utils/logger.ts","../src/agent/lifecycle.ts","../src/agent/pool.ts","../src/agent/roles.ts","../src/agent/config.ts","../src/types/orchestrator-activity.ts","../src/index.ts","../src/messaging/broker.ts","../src/messaging/inbox.ts","../src/orchestrator/orchestrator.ts","../src/feedback/feedback-loop.ts","../src/feedback/progress-tracker.ts","../src/orchestrator/planner.ts","../src/orchestrator/scheduler.ts","../src/orchestrator/pipeline.ts","../src/orchestrator/pm-scanner.ts","../src/project/config.ts","../src/project/workspace.ts"],"sourcesContent":["import type { Task, TaskPriority, TaskStatus } from '../types/task.js';\n\nconst TASK_LINE_REGEX =\n /^- \\[(x| )\\]\\s+(\\S+)\\s+\\|\\s+(.+?)\\s+\\|\\s+(@\\S+|unassigned)\\s+\\|\\s+deps:\\s*(.+?)\\s+\\|\\s+(.+)$/;\n\nconst PRIORITY_HEADER_REGEX = /^##\\s+(Critical|High|Medium|Low)\\s*$/i;\nconst PROJECT_HEADER_REGEX = /^#\\s+Project:\\s+(.+)$/;\nconst NOTE_REGEX = /^\\s+>\\s?(.*)$/;\n\nconst VALID_STATUSES: TaskStatus[] = ['pending', 'in-progress', 'done', 'blocked', 'cancelled'];\n\nfunction normalizePriority(raw: string): TaskPriority {\n return raw.toLowerCase() as TaskPriority;\n}\n\nfunction normalizeStatus(raw: string): { status: TaskStatus; completedAt: string | null } {\n const trimmed = raw.trim();\n\n // Check for done:<timestamp> pattern\n const doneMatch = trimmed.match(/^done:(\\S+)$/);\n if (doneMatch) {\n return { status: 'done', completedAt: doneMatch[1] };\n }\n\n const statusCandidate = trimmed.toLowerCase() as TaskStatus;\n if (VALID_STATUSES.includes(statusCandidate)) {\n return {\n status: statusCandidate,\n completedAt: statusCandidate === 'done' ? new Date().toISOString() : null,\n };\n }\n\n return { status: 'pending', completedAt: null };\n}\n\nexport class TaskParser {\n parse(content: string): { projectName: string; tasks: Task[] } {\n const lines = content.split('\\n');\n let projectName = '';\n let currentPriority: TaskPriority = 'medium';\n const tasks: Task[] = [];\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n\n // Check for project header\n const projectMatch = line.match(PROJECT_HEADER_REGEX);\n if (projectMatch) {\n projectName = projectMatch[1].trim();\n continue;\n }\n\n // Check for priority header\n const priorityMatch = line.match(PRIORITY_HEADER_REGEX);\n if (priorityMatch) {\n currentPriority = normalizePriority(priorityMatch[1]);\n continue;\n }\n\n // Try to parse as a task line\n const task = this.parseLine(line, currentPriority);\n if (task) {\n // Collect trailing note lines\n while (i + 1 < lines.length) {\n const noteMatch = lines[i + 1].match(NOTE_REGEX);\n if (noteMatch) {\n task.notes.push(noteMatch[1]);\n i++;\n } else {\n break;\n }\n }\n tasks.push(task);\n }\n }\n\n return { projectName, tasks };\n }\n\n parseLine(line: string, currentPriority: TaskPriority): Task | null {\n const match = line.match(TASK_LINE_REGEX);\n if (!match) {\n return null;\n }\n\n const [, checkbox, id, title, assigneeRaw, depsRaw, statusRaw] = match;\n const now = new Date().toISOString();\n\n const assignee = assigneeRaw === 'unassigned' ? null : assigneeRaw.slice(1); // strip @\n\n const deps = depsRaw.trim().toLowerCase() === 'none'\n ? []\n : depsRaw.split(',').map((d) => d.trim()).filter(Boolean);\n\n // Determine status: [x] always means done, otherwise read from status field\n let status: TaskStatus;\n let completedAt: string | null = null;\n\n if (checkbox === 'x') {\n status = 'done';\n // Check for done:<timestamp> in status field\n const doneTimestamp = statusRaw.trim().match(/^done:(\\S+)$/);\n completedAt = doneTimestamp ? doneTimestamp[1] : now;\n } else {\n const parsed = normalizeStatus(statusRaw);\n status = parsed.status;\n completedAt = parsed.completedAt;\n }\n\n return {\n id,\n title: title.trim(),\n description: title.trim(),\n status,\n priority: currentPriority,\n assignee,\n dependencies: deps,\n tags: [],\n createdAt: now,\n updatedAt: now,\n completedAt,\n notes: [],\n };\n }\n}\n","import type { Task, TaskPriority } from '../types/task.js';\n\nconst PRIORITY_ORDER: TaskPriority[] = ['critical', 'high', 'medium', 'low'];\n\nconst PRIORITY_LABELS: Record<TaskPriority, string> = {\n critical: 'Critical',\n high: 'High',\n medium: 'Medium',\n low: 'Low',\n};\n\nexport class TaskWriter {\n write(projectName: string, tasks: Task[]): string {\n const lines: string[] = [];\n\n lines.push(`# Project: ${projectName}`);\n lines.push(`# Generated by Maestro | Last updated: ${new Date().toISOString()}`);\n lines.push('');\n\n for (const priority of PRIORITY_ORDER) {\n const group = tasks.filter((t) => t.priority === priority);\n if (group.length === 0) {\n continue;\n }\n\n lines.push(`## ${PRIORITY_LABELS[priority]}`);\n\n for (const task of group) {\n lines.push(this.formatTask(task));\n }\n\n lines.push('');\n }\n\n return lines.join('\\n');\n }\n\n formatTask(task: Task): string {\n const checkbox = task.status === 'done' ? '[x]' : '[ ]';\n const assignee = task.assignee ? `@${task.assignee}` : 'unassigned';\n const deps = task.dependencies.length > 0 ? task.dependencies.join(',') : 'none';\n\n let statusField: string;\n if (task.status === 'done' && task.completedAt) {\n statusField = `done:${task.completedAt}`;\n } else {\n statusField = task.status;\n }\n\n const line = `- ${checkbox} ${task.id} | ${task.title} | ${assignee} | deps: ${deps} | ${statusField}`;\n\n const noteLines = task.notes.map((note) => ` > ${note}`);\n\n return [line, ...noteLines].join('\\n');\n }\n}\n","import { nanoid } from 'nanoid';\n\nlet taskCounter = 0;\n\nexport function generateId(): string {\n return nanoid(12);\n}\n\nexport function generateTaskId(): string {\n taskCounter++;\n return `T-${String(taskCounter).padStart(3, '0')}`;\n}\n\nexport function resetTaskCounter(startFrom = 0): void {\n taskCounter = startFrom;\n}\n\nexport function setTaskCounter(value: number): void {\n taskCounter = value;\n}\n","import lockfile from 'proper-lockfile';\nimport { access, writeFile } from 'node:fs/promises';\n\nasync function ensureFileExists(filePath: string): Promise<void> {\n try {\n await access(filePath);\n } catch {\n await writeFile(filePath, '', 'utf-8');\n }\n}\n\nexport async function acquireLock(filePath: string): Promise<() => Promise<void>> {\n await ensureFileExists(filePath);\n\n const release = await lockfile.lock(filePath, {\n stale: 10_000,\n retries: {\n retries: 5,\n minTimeout: 100,\n maxTimeout: 1000,\n },\n });\n\n return release;\n}\n\nexport async function withLock<T>(filePath: string, fn: () => Promise<T>): Promise<T> {\n const release = await acquireLock(filePath);\n try {\n return await fn();\n } finally {\n await release();\n }\n}\n","import { readFile, writeFile, access } from 'node:fs/promises';\nimport EventEmitter from 'eventemitter3';\nimport type { Task, TaskFilter, TaskPriority, TaskStatus, TaskUpdate } from '../types/task.js';\nimport { generateTaskId, setTaskCounter } from '../utils/id.js';\nimport { TaskParser } from './parser.js';\nimport { TaskWriter } from './writer.js';\nimport { withLock } from './lock.js';\n\ninterface TaskManagerOptions {\n filePath: string;\n projectName: string;\n}\n\nexport class TaskManager extends EventEmitter {\n private readonly filePath: string;\n private readonly projectName: string;\n private readonly parser: TaskParser;\n private readonly writer: TaskWriter;\n\n constructor(options: TaskManagerOptions) {\n super();\n this.filePath = options.filePath;\n this.projectName = options.projectName;\n this.parser = new TaskParser();\n this.writer = new TaskWriter();\n }\n\n private async ensureFile(): Promise<void> {\n try {\n await access(this.filePath);\n } catch {\n await writeFile(this.filePath, '', 'utf-8');\n }\n }\n\n async load(): Promise<Task[]> {\n await this.ensureFile();\n const content = await readFile(this.filePath, 'utf-8');\n const { tasks } = this.parser.parse(content);\n return tasks;\n }\n\n async save(tasks: Task[]): Promise<void> {\n await withLock(this.filePath, async () => {\n const content = this.writer.write(this.projectName, tasks);\n await writeFile(this.filePath, content, 'utf-8');\n });\n }\n\n async getTask(id: string): Promise<Task | undefined> {\n const tasks = await this.load();\n return tasks.find((t) => t.id === id);\n }\n\n async getTasks(filter?: TaskFilter): Promise<Task[]> {\n const tasks = await this.load();\n\n if (!filter) {\n return tasks;\n }\n\n return tasks.filter((task) => {\n if (filter.status && filter.status.length > 0) {\n if (!filter.status.includes(task.status)) {\n return false;\n }\n }\n\n if (filter.assignee !== undefined) {\n if (task.assignee !== filter.assignee) {\n return false;\n }\n }\n\n if (filter.priority && filter.priority.length > 0) {\n if (!filter.priority.includes(task.priority)) {\n return false;\n }\n }\n\n if (filter.tags && filter.tags.length > 0) {\n if (!filter.tags.some((tag) => task.tags.includes(tag))) {\n return false;\n }\n }\n\n return true;\n });\n }\n\n async createTask(data: {\n title: string;\n priority: TaskPriority;\n description?: string;\n dependencies?: string[];\n tags?: string[];\n }): Promise<Task> {\n const tasks = await this.load();\n\n // Set task counter based on existing max ID\n const maxId = this.extractMaxTaskNumber(tasks);\n setTaskCounter(maxId);\n\n const now = new Date().toISOString();\n const task: Task = {\n id: generateTaskId(),\n title: data.title,\n description: data.description ?? data.title,\n status: 'pending',\n priority: data.priority,\n assignee: null,\n dependencies: data.dependencies ?? [],\n tags: data.tags ?? [],\n createdAt: now,\n updatedAt: now,\n completedAt: null,\n notes: [],\n };\n\n tasks.push(task);\n await this.save(tasks);\n this.emit('task:created', task);\n\n return task;\n }\n\n async updateTask(id: string, update: TaskUpdate): Promise<Task> {\n const tasks = await this.load();\n const index = tasks.findIndex((t) => t.id === id);\n\n if (index === -1) {\n throw new Error(`Task not found: ${id}`);\n }\n\n const task = tasks[index];\n const now = new Date().toISOString();\n\n if (update.status !== undefined) {\n task.status = update.status;\n if (update.status === 'done') {\n task.completedAt = now;\n }\n }\n\n if (update.assignee !== undefined) {\n task.assignee = update.assignee;\n }\n\n if (update.priority !== undefined) {\n task.priority = update.priority;\n }\n\n if (update.notes !== undefined) {\n task.notes = update.notes;\n }\n\n task.updatedAt = now;\n tasks[index] = task;\n\n await this.save(tasks);\n this.emit('task:updated', task);\n\n return task;\n }\n\n async assignTask(id: string, agentId: string): Promise<Task> {\n const tasks = await this.load();\n const index = tasks.findIndex((t) => t.id === id);\n\n if (index === -1) {\n throw new Error(`Task not found: ${id}`);\n }\n\n const task = tasks[index];\n task.assignee = agentId;\n task.updatedAt = new Date().toISOString();\n tasks[index] = task;\n\n await this.save(tasks);\n this.emit('task:assigned', task);\n\n return task;\n }\n\n async completeTask(id: string): Promise<Task> {\n const tasks = await this.load();\n const index = tasks.findIndex((t) => t.id === id);\n\n if (index === -1) {\n throw new Error(`Task not found: ${id}`);\n }\n\n const task = tasks[index];\n const now = new Date().toISOString();\n task.status = 'done';\n task.completedAt = now;\n task.updatedAt = now;\n tasks[index] = task;\n\n await this.save(tasks);\n this.emit('task:completed', task);\n\n return task;\n }\n\n private extractMaxTaskNumber(tasks: Task[]): number {\n let max = 0;\n for (const task of tasks) {\n const match = task.id.match(/^T-(\\d+)$/);\n if (match) {\n const num = parseInt(match[1], 10);\n if (num > max) {\n max = num;\n }\n }\n }\n return max;\n }\n}\n","import pino from 'pino';\nimport { openSync, closeSync, writeSync, mkdirSync } from 'node:fs';\nimport { dirname } from 'node:path';\n\n// Simple synchronous file stream for pino that works in bundled Electron\nclass SyncFileStream {\n private fd: number | null = null;\n\n constructor(private destination: string) {\n try {\n mkdirSync(dirname(destination), { recursive: true });\n this.fd = openSync(destination, 'a');\n } catch {\n // If we can't open the file, we'll silently drop logs\n }\n }\n\n write(chunk: string): void {\n if (this.fd !== null) {\n try {\n writeSync(this.fd, chunk);\n } catch {\n // Ignore write errors\n }\n }\n }\n\n end(): void {\n if (this.fd !== null) {\n closeSync(this.fd);\n this.fd = null;\n }\n }\n}\n\n/**\n * Create a pino logger that writes only to a log file (if provided).\n * Console output is intentionally disabled — all user-facing info is\n * surfaced through orchestrator:activity events and the TUI/CLI handlers.\n * This avoids pino output bleeding into the terminal and corrupting the TUI.\n *\n * Uses synchronous file writes to avoid transport/worker thread issues in Electron.\n */\nexport function createLogger(name: string, logFile?: string): pino.Logger {\n const stream = logFile ? new SyncFileStream(logFile) : null;\n\n return pino(\n {\n name,\n level: 'trace',\n },\n stream ?? { write: () => {} } // No-op stream if no log file\n );\n}\n","import { execa, type ResultPromise } from 'execa';\nimport treeKill from 'tree-kill';\nimport { EventEmitter } from 'eventemitter3';\nimport { homedir } from 'node:os';\nimport type { AgentConfig, AgentState, AgentStreamEvent, AgentStatus } from '../types/agent.js';\nimport { createLogger } from '../utils/logger.js';\n\nconst logger = createLogger('agent-process');\n\ninterface AgentProcessEvents {\n 'output': (event: AgentStreamEvent) => void;\n 'status-changed': (oldStatus: AgentStatus, newStatus: AgentStatus) => void;\n 'error': (error: Error) => void;\n 'stopped': (exitCode: number | null) => void;\n}\n\nfunction killProcessTree(pid: number, signal?: string): Promise<void> {\n return new Promise((resolve, reject) => {\n treeKill(pid, signal, (err) => {\n if (err) {\n reject(err);\n } else {\n resolve();\n }\n });\n });\n}\n\nexport class AgentProcess extends EventEmitter<AgentProcessEvents> {\n private subprocess: ResultPromise | null = null;\n private state: AgentState;\n private streamBuffer: string = '';\n\n constructor(private readonly config: AgentConfig) {\n super();\n this.state = {\n config,\n status: 'idle',\n pid: null,\n sessionId: null,\n currentTask: null,\n startedAt: null,\n lastActivityAt: null,\n totalCostUsd: 0,\n turnCount: 0,\n totalInputTokens: 0,\n totalOutputTokens: 0,\n totalCacheReadTokens: 0,\n totalCacheCreationTokens: 0,\n error: null,\n resultError: null,\n rateLimited: false,\n rateLimitResetAt: null,\n };\n }\n\n get id(): string {\n return this.config.id;\n }\n\n get currentState(): AgentState {\n return { ...this.state };\n }\n\n /**\n * Set the current task this agent is working on (task ID + title).\n */\n setCurrentTask(taskInfo: string | null): void {\n this.state.currentTask = taskInfo;\n }\n\n /**\n * Spawn a claude CLI process with the given prompt.\n */\n async spawn(prompt: string): Promise<void> {\n if (this.subprocess) {\n throw new Error(`Agent ${this.id} already has a running process`);\n }\n\n const args = this.buildArgs();\n\n this.setStatus('starting');\n\n const cmd = this.config.claudeCommand ?? 'claude';\n\n logger.info(\n { agentId: this.id, cmd, argCount: args.length, promptLength: prompt.length },\n 'Spawning agent process',\n );\n\n this.subprocess = execa(cmd, args, {\n input: prompt,\n cwd: this.config.workingDirectory,\n env: this.config.claudeEnv ? { ...process.env, ...this.config.claudeEnv } : undefined,\n stdout: 'pipe',\n stderr: 'pipe',\n reject: false,\n });\n\n this.state.pid = this.subprocess.pid ?? null;\n this.state.startedAt = new Date().toISOString();\n this.state.error = null;\n this.state.resultError = null;\n this.state.rateLimited = false;\n this.state.rateLimitResetAt = null;\n\n logger.info({ agentId: this.id, pid: this.state.pid }, 'Agent process started');\n\n this.setStatus('running');\n\n // Emit a synthetic output event with PID info\n this.emitOutput('system', { message: `Process started (PID: ${this.state.pid ?? 'unknown'})`, cmd, argCount: args.length });\n\n // Process stdout and stderr in parallel\n this.processStream().catch((err) => {\n this.state.error = err instanceof Error ? err.message : String(err);\n this.emit('error', err instanceof Error ? err : new Error(String(err)));\n });\n this.processStderr().catch(() => {});\n }\n\n /**\n * Resume a previous session with a new prompt.\n */\n async resume(prompt: string): Promise<void> {\n if (!this.state.sessionId) {\n throw new Error(`Agent ${this.id} has no session to resume`);\n }\n if (this.subprocess) {\n throw new Error(`Agent ${this.id} already has a running process`);\n }\n\n const args = this.buildArgs();\n args.push('--resume', this.state.sessionId);\n\n this.setStatus('starting');\n\n const cmd = this.config.claudeCommand ?? 'claude';\n\n logger.info({ agentId: this.id, cmd, sessionId: this.state.sessionId }, 'Resuming agent process');\n\n this.subprocess = execa(cmd, args, {\n input: prompt,\n cwd: this.config.workingDirectory,\n env: this.config.claudeEnv ? { ...process.env, ...this.config.claudeEnv } : undefined,\n stdout: 'pipe',\n stderr: 'pipe',\n reject: false,\n });\n\n this.state.pid = this.subprocess.pid ?? null;\n this.state.startedAt = new Date().toISOString();\n this.state.error = null;\n this.state.resultError = null;\n this.state.rateLimited = false;\n this.state.rateLimitResetAt = null;\n\n logger.info({ agentId: this.id, pid: this.state.pid }, 'Agent process resumed');\n\n this.setStatus('running');\n\n this.emitOutput('system', { message: `Process resumed (PID: ${this.state.pid ?? 'unknown'})` });\n\n this.processStream().catch((err) => {\n this.state.error = err instanceof Error ? err.message : String(err);\n this.emit('error', err instanceof Error ? err : new Error(String(err)));\n });\n this.processStderr().catch(() => {});\n }\n\n /**\n * Graceful stop: SIGTERM, wait, then force kill.\n */\n async stop(timeoutMs = 10000): Promise<void> {\n if (!this.subprocess || !this.state.pid) {\n return;\n }\n\n this.setStatus('stopping');\n\n try {\n // Send SIGTERM to the process\n this.subprocess.kill('SIGTERM');\n\n // Wait for the process to exit or timeout\n const timeoutPromise = new Promise<'timeout'>((resolve) =>\n setTimeout(() => resolve('timeout'), timeoutMs),\n );\n\n const exitPromise = this.subprocess.then(() => 'exited' as const);\n\n const result = await Promise.race([exitPromise, timeoutPromise]);\n\n if (result === 'timeout' && this.state.pid) {\n // Force kill the entire process tree\n await killProcessTree(this.state.pid, 'SIGKILL');\n }\n } catch {\n // If anything fails, attempt a hard kill\n if (this.state.pid) {\n try {\n await killProcessTree(this.state.pid, 'SIGKILL');\n } catch {\n // Process may already be dead\n }\n }\n } finally {\n this.subprocess = null;\n this.setStatus('stopped');\n }\n }\n\n /**\n * Force kill immediately.\n */\n async kill(): Promise<void> {\n if (!this.subprocess || !this.state.pid) {\n return;\n }\n\n try {\n await killProcessTree(this.state.pid, 'SIGKILL');\n } catch {\n // Process may already be dead\n } finally {\n this.subprocess = null;\n this.setStatus('stopped');\n }\n }\n\n /**\n * Build CLI arguments for the claude command.\n * The prompt is piped via stdin, not passed as a positional argument.\n */\n private buildArgs(): string[] {\n const args: string[] = [\n '--print',\n '--output-format', 'stream-json',\n '--verbose',\n '--model', this.config.model ?? 'sonnet',\n ];\n\n // Pass custom agent definition if it exists\n if (this.config.customAgentPath) {\n args.push('--agent', this.config.customAgentPath);\n }\n\n // Pass permission mode (acceptEdits, bypassPermissions, default, etc.)\n if (this.config.permissionMode && this.config.permissionMode !== 'default') {\n args.push('--permission-mode', this.config.permissionMode);\n }\n\n if (this.config.systemPrompt) {\n args.push('--system-prompt', this.config.systemPrompt);\n }\n\n if (this.config.allowedTools && this.config.allowedTools.length > 0) {\n args.push('--allowedTools', this.config.allowedTools.join(','));\n }\n\n if (this.config.maxBudgetUsd !== undefined) {\n args.push('--max-budget-usd', String(this.config.maxBudgetUsd));\n }\n\n // Append custom CLI args from config (settings-level + per-agent merged)\n if (this.config.claudeArgs && this.config.claudeArgs.length > 0) {\n args.push(...this.config.claudeArgs);\n }\n\n return args;\n }\n\n /**\n * Parse NDJSON stream from claude stdout.\n * Reads stdout line by line and emits typed events.\n */\n private async processStream(): Promise<void> {\n if (!this.subprocess || !this.subprocess.stdout) {\n return;\n }\n\n const stdout = this.subprocess.stdout;\n\n for await (const chunk of stdout) {\n const text = typeof chunk === 'string' ? chunk : chunk.toString('utf-8');\n this.streamBuffer += text;\n\n // Process complete lines from the buffer\n let newlineIndex: number;\n while ((newlineIndex = this.streamBuffer.indexOf('\\n')) !== -1) {\n const line = this.streamBuffer.slice(0, newlineIndex).trim();\n this.streamBuffer = this.streamBuffer.slice(newlineIndex + 1);\n\n if (!line) {\n continue;\n }\n\n try {\n const parsed = JSON.parse(line) as Record<string, unknown>;\n const eventType = (parsed.type as string) ?? 'unknown';\n const now = new Date().toISOString();\n\n const streamEvent: AgentStreamEvent = {\n type: eventType as AgentStreamEvent['type'],\n agentId: this.id,\n timestamp: now,\n data: parsed,\n };\n\n // Capture session_id from system events\n if (eventType === 'system' && typeof parsed.session_id === 'string') {\n this.state.sessionId = parsed.session_id;\n }\n\n // Capture cost, turn count, and token usage from result events\n if (eventType === 'result') {\n if (typeof parsed.cost_usd === 'number') {\n this.state.totalCostUsd = parsed.cost_usd;\n }\n if (typeof parsed.num_turns === 'number') {\n this.state.turnCount = parsed.num_turns;\n }\n\n // Capture token usage\n const usage = parsed.usage as Record<string, unknown> | undefined;\n if (usage && typeof usage === 'object') {\n if (typeof usage.input_tokens === 'number') {\n this.state.totalInputTokens = usage.input_tokens;\n }\n if (typeof usage.output_tokens === 'number') {\n this.state.totalOutputTokens = usage.output_tokens;\n }\n if (typeof usage.cache_read_input_tokens === 'number') {\n this.state.totalCacheReadTokens = usage.cache_read_input_tokens;\n }\n if (typeof usage.cache_creation_input_tokens === 'number') {\n this.state.totalCacheCreationTokens = usage.cache_creation_input_tokens;\n }\n }\n\n // Detect API errors from result events (is_error: true)\n if (parsed.is_error === true) {\n const resultText = typeof parsed.result === 'string' ? parsed.result : '';\n this.state.resultError = resultText || 'Unknown API error';\n\n // Check for rate-limit (429) errors\n if (resultText.includes('429') || resultText.includes('Usage limit reached') || resultText.includes('rate limit')) {\n this.state.rateLimited = true;\n // Extract reset time if present\n const resetMatch = resultText.match(/will reset at ([0-9T :.-]+)/);\n if (resetMatch) {\n this.state.rateLimitResetAt = resetMatch[1].trim();\n }\n logger.warn(\n { agentId: this.id, resetAt: this.state.rateLimitResetAt },\n 'Agent hit API rate limit (429)',\n );\n }\n }\n }\n\n this.state.lastActivityAt = now;\n this.emit('output', streamEvent);\n } catch {\n // Line is not valid JSON — emit it as raw text output so it's visible\n this.emitOutput('system', { message: `[stdout] ${line}` });\n }\n }\n }\n\n // Stream ended - wait for the process to exit\n const result = await this.subprocess;\n const exitCode = result?.exitCode ?? null;\n\n this.subprocess = null;\n\n if (this.state.resultError) {\n // The API returned an error in the result (e.g. rate limit 429).\n // Even though the process exited cleanly, treat it as an error.\n this.state.error = this.state.resultError;\n this.emitOutput('error', {\n error: this.state.resultError,\n rateLimited: this.state.rateLimited,\n rateLimitResetAt: this.state.rateLimitResetAt,\n });\n this.setStatus('error');\n } else if (exitCode === 0 || exitCode === null) {\n this.setStatus('stopped');\n } else {\n this.state.error = `Process exited with code ${exitCode}`;\n this.emitOutput('error', { error: `Process exited with code ${exitCode}`, stderr: result?.stderr?.slice(0, 500) });\n this.setStatus('error');\n }\n\n this.emit('stopped', exitCode);\n }\n\n /**\n * Read stderr and emit lines as error events so they're visible.\n */\n private async processStderr(): Promise<void> {\n if (!this.subprocess || !this.subprocess.stderr) {\n return;\n }\n\n let stderrBuffer = '';\n const stderr = this.subprocess.stderr;\n\n for await (const chunk of stderr) {\n const text = typeof chunk === 'string' ? chunk : chunk.toString('utf-8');\n stderrBuffer += text;\n\n let newlineIndex: number;\n while ((newlineIndex = stderrBuffer.indexOf('\\n')) !== -1) {\n const line = stderrBuffer.slice(0, newlineIndex).trim();\n stderrBuffer = stderrBuffer.slice(newlineIndex + 1);\n\n if (line) {\n logger.warn({ agentId: this.id, stderr: line }, 'Agent stderr output');\n this.emitOutput('error', { error: line, source: 'stderr' });\n }\n }\n }\n\n // Flush any remaining stderr\n const remaining = stderrBuffer.trim();\n if (remaining) {\n logger.warn({ agentId: this.id, stderr: remaining }, 'Agent stderr output');\n this.emitOutput('error', { error: remaining, source: 'stderr' });\n }\n }\n\n /**\n * Emit a synthetic output event.\n */\n private emitOutput(type: AgentStreamEvent['type'], data: Record<string, unknown>): void {\n this.emit('output', {\n type,\n agentId: this.id,\n timestamp: new Date().toISOString(),\n data,\n });\n }\n\n /**\n * Update internal state and emit status change events.\n */\n private setStatus(status: AgentStatus): void {\n const oldStatus = this.state.status;\n if (oldStatus === status) {\n return;\n }\n this.state.status = status;\n this.emit('status-changed', oldStatus, status);\n }\n}\n","import { EventEmitter } from 'eventemitter3';\nimport { AgentProcess } from './lifecycle.js';\nimport type { AgentConfig, AgentRole, AgentStatus, AgentStreamEvent } from '../types/agent.js';\n\ninterface AgentPoolEvents {\n 'agent:spawned': (agentId: string, process: AgentProcess) => void;\n 'agent:output': (event: AgentStreamEvent) => void;\n 'agent:status-changed': (agentId: string, oldStatus: AgentStatus, newStatus: AgentStatus) => void;\n 'agent:error': (agentId: string, error: Error) => void;\n 'agent:stopped': (agentId: string, exitCode: number | null) => void;\n}\n\nexport class AgentPool extends EventEmitter<AgentPoolEvents> {\n private agents: Map<string, AgentProcess> = new Map();\n\n /**\n * Spawn a new agent process with the given config and initial prompt.\n */\n async spawnAgent(config: AgentConfig, prompt: string): Promise<AgentProcess> {\n if (this.agents.has(config.id)) {\n throw new Error(`Agent with id \"${config.id}\" already exists in the pool`);\n }\n\n const agent = new AgentProcess(config);\n this.agents.set(config.id, agent);\n\n // Forward events from the individual agent to the pool\n this.attachListeners(agent);\n\n await agent.spawn(prompt);\n\n this.emit('agent:spawned', agent.id, agent);\n\n return agent;\n }\n\n /**\n * Stop a specific agent by ID with an optional timeout.\n */\n async stopAgent(id: string, timeoutMs?: number): Promise<void> {\n const agent = this.agents.get(id);\n if (!agent) {\n throw new Error(`Agent \"${id}\" not found in pool`);\n }\n await agent.stop(timeoutMs);\n }\n\n /**\n * Stop all agents concurrently. Uses Promise.allSettled for graceful handling.\n */\n async stopAll(timeoutMs?: number): Promise<void> {\n const stopPromises = Array.from(this.agents.values()).map((agent) =>\n agent.stop(timeoutMs),\n );\n await Promise.allSettled(stopPromises);\n }\n\n /**\n * Remove a stopped agent from the pool so it can be re-spawned.\n */\n removeAgent(id: string): void {\n const agent = this.agents.get(id);\n if (!agent) return;\n const status = agent.currentState.status;\n if (status !== 'stopped' && status !== 'error') {\n throw new Error(`Cannot remove agent \"${id}\" with status \"${status}\" — must be stopped or error`);\n }\n this.agents.delete(id);\n }\n\n /**\n * Get an agent process by ID.\n */\n getAgent(id: string): AgentProcess | undefined {\n return this.agents.get(id);\n }\n\n /**\n * Get all agents with a specific role.\n */\n getAgentsByRole(role: AgentRole): AgentProcess[] {\n return Array.from(this.agents.values()).filter(\n (agent) => agent.currentState.config.role === role,\n );\n }\n\n /**\n * Get all agents with a specific status.\n */\n getAgentsByStatus(status: AgentStatus): AgentProcess[] {\n return Array.from(this.agents.values()).filter(\n (agent) => agent.currentState.status === status,\n );\n }\n\n /**\n * Get all agents in the pool.\n */\n getAllAgents(): AgentProcess[] {\n return Array.from(this.agents.values());\n }\n\n /**\n * Get aggregate statistics across all agents.\n */\n getStats(): { total: number; running: number; idle: number; stopped: number; totalCostUsd: number } {\n let running = 0;\n let idle = 0;\n let stopped = 0;\n let totalCostUsd = 0;\n\n for (const agent of this.agents.values()) {\n const state = agent.currentState;\n switch (state.status) {\n case 'running':\n case 'starting':\n running++;\n break;\n case 'idle':\n idle++;\n break;\n case 'stopped':\n case 'stopping':\n case 'error':\n stopped++;\n break;\n }\n totalCostUsd += state.totalCostUsd;\n }\n\n return {\n total: this.agents.size,\n running,\n idle,\n stopped,\n totalCostUsd,\n };\n }\n\n /**\n * Attach event forwarding listeners from an agent process to the pool.\n */\n private attachListeners(agent: AgentProcess): void {\n agent.on('output', (event: AgentStreamEvent) => {\n this.emit('agent:output', event);\n });\n\n agent.on('status-changed', (oldStatus: AgentStatus, newStatus: AgentStatus) => {\n this.emit('agent:status-changed', agent.id, oldStatus, newStatus);\n });\n\n agent.on('error', (error: Error) => {\n this.emit('agent:error', agent.id, error);\n });\n\n agent.on('stopped', (exitCode: number | null) => {\n this.emit('agent:stopped', agent.id, exitCode);\n });\n }\n}\n","import type { AgentRole } from '../types/agent.js';\nimport type { TechStackConfig } from '../types/project.js';\n\nexport const ROLE_DESCRIPTIONS: Record<AgentRole, string> = {\n orchestrator:\n 'The orchestrator is the top-level coordinator. It breaks down high-level goals into tasks, ' +\n 'assigns work to other agents, monitors progress, resolves conflicts, and ensures the overall ' +\n 'project stays on track. It communicates directives and reviews results from all other agents.',\n\n 'project-manager':\n 'The project manager tracks priorities, manages dependencies between tasks, updates timelines, ' +\n 'and ensures work is progressing according to plan. It identifies blockers, re-prioritizes when ' +\n 'needed, and keeps the task board organized and up to date.',\n\n architect:\n 'The architect designs the system architecture, makes key technical decisions, defines API ' +\n 'contracts, reviews design proposals, and ensures the codebase maintains structural integrity. ' +\n 'It provides guidance on patterns, technology choices, and code organization.',\n\n developer:\n 'The developer implements features, writes production code, fixes bugs, writes tests, and ' +\n 'ensures code quality. It follows the architecture guidelines, writes clean and well-tested ' +\n 'code, and reports progress on assigned tasks.',\n\n designer:\n 'The designer handles UI/UX design decisions, creates component structures, defines styling ' +\n 'and theming systems, ensures accessibility standards, and maintains visual consistency ' +\n 'across the application.',\n\n 'qa-engineer':\n 'The QA engineer ensures software quality through comprehensive testing strategies. It writes ' +\n 'and maintains test suites (unit, integration, e2e), identifies edge cases, validates ' +\n 'requirements coverage, and reports bugs with clear reproduction steps.',\n\n devops:\n 'The DevOps engineer handles infrastructure, CI/CD pipelines, deployment configurations, ' +\n 'containerization (Docker), environment setup, monitoring, and build tooling. It ensures ' +\n 'the project can be reliably built, tested, and deployed.',\n\n 'technical-writer':\n 'The technical writer creates and maintains project documentation including README files, ' +\n 'API documentation, architecture decision records, user guides, setup instructions, and ' +\n 'inline code documentation. It ensures docs stay accurate and accessible.',\n\n 'code-reviewer':\n 'The code reviewer examines completed work for correctness, security, performance, and ' +\n 'adherence to project standards. It provides constructive feedback, identifies potential ' +\n 'issues, and verifies that changes align with the architecture.',\n};\n\nconst TODO_FORMAT_INSTRUCTIONS = `\n## Todo File Format\n\nThe shared todo file uses markdown: sections for Pending, In Progress, Done, Blocked.\n\nEach task line: \\`- [ ] T-XXX: Title [priority:high] [assignee:agent-id]\\` with a description on the indented line below. Mark done tasks with \\`[x]\\`. Use \\`[blocked-by:T-XXX]\\` for dependencies.\n`.trim();\n\nconst MESSAGE_FORMAT_INSTRUCTIONS = `\n## Messaging System\n\n**Inbox**: Check your inbox directory for JSON message files. Read all pending messages regularly.\n**Outbox**: To send a message, write a JSON file to your outbox directory.\n\nMessage format: \\`{ \"message\": { \"id\": \"unique-id\", \"type\": \"<type>\", \"from\": \"<your-id>\", \"to\": \"<recipient-id>\", \"subject\": \"...\", \"body\": \"...\", \"priority\": \"normal|urgent\", \"timestamp\": \"ISO date\" }, \"status\": \"pending\" }\\`\n\nTypes: task-assignment, task-update, task-complete, task-blocked, question, answer, review-request, review-result, system, directive\n`.trim();\n\nconst PROCESS_SAFETY_RULES = `\n## Process Safety Rules\n\nYou run in a shared multi-agent environment. Resource-intensive processes starve other agents and destabilize the system. The following are **strictly forbidden**:\n\n**No Docker**: \\`docker build\\`, \\`docker run\\`, \\`docker compose up\\`, \\`docker pull/push/exec\\`, \\`podman build/run\\`. You MAY write Dockerfiles and compose configs.\n\n**No servers**: \\`npm run dev\\`, \\`npm start\\`, \\`next dev\\`, \\`vite\\`, \\`flask run\\`, \\`uvicorn\\`, \\`rails server\\`, \\`nodemon\\`, or any process that listens on a port.\n\n**Instead**: Write code and config files. Run only targeted tests (single file). Use lightweight commands (lint, type-check single files). If you need a build or server, message the user.\n`.trim();\n\nconst ROLE_SPECIFIC_INSTRUCTIONS: Record<AgentRole, string> = {\n orchestrator: `\n## Orchestrator-Specific Instructions\n\nYou are the central coordinator for this project. Your responsibilities:\n\n1. **Goal Decomposition**: Break down high-level project goals into concrete, actionable tasks.\n Write these tasks to the shared todo file with clear descriptions and priorities.\n\n2. **Task Assignment**: Assign tasks to the most appropriate agents based on their roles:\n - Architecture and design decisions -> architect\n - Implementation and coding -> developer\n - UI/UX, styling, components -> designer\n - Testing, QA, test suites -> qa-engineer\n - CI/CD, Docker, deployment, infrastructure -> devops\n - Documentation, README, API docs -> technical-writer\n - Code review, security review -> code-reviewer\n - Scheduling and tracking -> project-manager\n\n3. **Progress Monitoring**: Regularly check the todo file and inbox for updates. Track which\n tasks are in progress, completed, or blocked.\n\n4. **Coordination**: When tasks have dependencies, ensure they are executed in the right order.\n Resolve conflicts between agents. Re-assign work if an agent is overloaded. When QA\n returns a task, ensure the project-manager reassigns it to a developer promptly — blocked\n tasks stall all their dependents and can halt the entire project.\n\n5. **Quality Control**: Review completed work by examining task completion messages.\n Request revisions if needed by sending review-request messages.\n\n6. **Decision Making**: Make final calls on technical disputes, prioritization conflicts,\n and scope questions. Send directives when needed.\n\nDo NOT implement code yourself. Your job is to coordinate, not to code.\n`.trim(),\n\n 'project-manager': `\n## Project Manager-Specific Instructions\n\nYou manage the project timeline, priorities, and dependencies. Your responsibilities:\n\n1. **Priority Management**: Keep tasks properly prioritized. Escalate critical items.\n Re-order work based on changing requirements or blockers.\n\n2. **Dependency Tracking**: Identify and document task dependencies using blocked-by tags.\n Alert the orchestrator when circular dependencies or bottlenecks are detected.\n\n3. **Timeline Updates**: Track progress rates and estimate remaining work. Update task\n descriptions with timeline notes when appropriate.\n\n4. **Blocker Resolution**: When a task is blocked, investigate the cause by checking\n dependent tasks and sending questions to the relevant agents.\n\n5. **Status Reporting**: Periodically summarize project status for the orchestrator,\n including completed tasks, active work, blockers, and risks.\n\n6. **Todo Organization**: Keep the todo file clean and well-organized. Move completed\n tasks to the Done section. Archive old items. Ensure consistent formatting.\n\n7. **Task Reassignment & QA Returns**: You have the authority to reassign tasks between\n agents. This is critical for unblocking the pipeline. When QA reports a blocker on a\n task (missing files, broken implementation, failing tests), you MUST:\n a. Move the task from Blocked back to In Progress in the todo file.\n b. Change the assignee from the qa-engineer to an available developer.\n c. Add a note: \\`> [returned] Returned from QA: <reason>\\`\n d. Set the priority to high (QA returns are rework and block downstream tasks).\n e. Send a task-assignment message to the developer with the QA findings.\n f. Send a task-update message to the orchestrator about the reassignment.\n\n Do NOT leave QA-blocked tasks sitting. Every blocked task potentially stalls all its\n dependents. Act on QA returns immediately — they are your highest-priority pipeline work.\n\nFocus on process and organization. Do NOT make technical decisions or write code.\n`.trim(),\n\n architect: `\n## Architect-Specific Instructions\n\nYou design the system architecture and make technical decisions. Your responsibilities:\n\n1. **System Design**: Create and maintain the technical architecture. Document key\n design decisions, API contracts, data models, and component boundaries.\n\n2. **Technology Choices**: Evaluate and select appropriate technologies, libraries,\n and patterns. Justify decisions with clear reasoning.\n\n3. **Code Organization**: Define the project structure, module boundaries, naming\n conventions, and file organization patterns.\n\n4. **Design Reviews**: When developers send review-request messages, evaluate the\n approach against the architecture. Provide specific, actionable feedback.\n\n5. **Pattern Guidance**: Establish coding patterns, error handling strategies,\n and best practices. Document these for the development team.\n\n6. **Technical Debt**: Identify areas of technical debt and propose refactoring\n plans when appropriate.\n\n7. **ARCHITECTURE.md Ownership**: You own ARCHITECTURE.md. Keep it current whenever you\n make design decisions. All other agents rely on it as the source of truth — if it is\n outdated or missing, they will make incorrect assumptions.\n\nYou may write architectural documentation, design specs, and configuration files,\nbut delegate implementation work to developers.\n`.trim(),\n\n developer: `\n## Developer-Specific Instructions\n\nYou implement features, write code, and fix bugs. Your responsibilities:\n\n1. **Implementation**: Read ARCHITECTURE.md before writing any code. Follow its structure,\n patterns, and conventions. Implement features assigned to you in the todo file.\n\n2. **Testing**: Write unit tests, integration tests, and any other tests needed to\n verify your work. Aim for good test coverage on critical paths.\n\n3. **Bug Fixes**: When assigned bugs, investigate the root cause, implement a fix,\n and verify with tests.\n\n4. **Code Quality**: Follow established patterns and conventions. Write clear comments\n where logic is complex. Keep functions focused and composable.\n\n5. **Progress Updates**: When you start, complete, or get blocked on a task, update\n the todo file and send appropriate messages to the orchestrator.\n\n6. **Review & QA Response**: When you receive review-result or task-assignment messages\n with QA feedback, treat them as high priority. QA returns mean a task was sent back\n because implementation was missing or broken — read the \\`[BLOCKER]\\` and \\`[returned]\\`\n notes in the todo file, fix the root cause, then mark the task done so QA can re-verify.\n\n7. **Verification Gate**: Before marking any task as complete, you MUST run the verification\n gate to prevent build issues:\n a. If you added or modified dependencies in \\`package.json\\`, run \\`npm install\\` (or \\`pnpm install\\`,\n \\`yarn install\\`, etc. based on the project's package manager) to ensure dependencies are installed.\n b. Run \\`npm run lint\\` (or equivalent linter command for the project's tech stack).\n c. Fix all linting errors and warnings introduced by your changes.\n d. Run targeted tests for the code you modified to ensure functionality works.\n e. Only after all checks pass should you mark the task complete.\n \n This verification step is mandatory for every coding task — skip it and you risk\n breaking the build for the entire team.\n\n8. **Process Boundaries**: Your job is to write code and tests, NOT to build, compile, or\n run the project. Do not start servers or run full test suites. If you need to verify a specific\n piece of logic, run a single targeted test file. Write the code; let the CI pipeline\n and the user handle builds and deployments.\n\nFocus on writing excellent code. Ask the architect (via messages) if you are unsure\nabout design decisions. Report blockers promptly.\n`.trim(),\n\n designer: `\n## Designer-Specific Instructions\n\nYou handle UI/UX design and visual implementation. Your responsibilities:\n\n1. **Component Design**: Design and implement UI components with clear, reusable\n structures. Define component APIs (props, events, slots).\n\n2. **Styling System**: Create and maintain the design system: colors, typography,\n spacing, breakpoints, and theme configuration.\n\n3. **Layout Architecture**: Design page layouts, navigation structures, and\n responsive behavior. Ensure consistency across views.\n\n4. **Accessibility**: Ensure all UI components meet accessibility standards (WCAG).\n Include proper ARIA attributes, keyboard navigation, and screen reader support.\n\n5. **Visual Consistency**: Maintain visual coherence across the application.\n Review UI-related code changes for design consistency.\n\n6. **Design Documentation**: Document design tokens, component usage patterns,\n and visual guidelines for the development team.\n\nYou write UI code (components, styles, layouts). Coordinate with developers on\nintegration and with the architect on component architecture.\n`.trim(),\n\n 'qa-engineer': `\n## QA Engineer-Specific Instructions\n\nYou ensure software quality through testing and validation. Your responsibilities:\n\n1. **Test Strategy**: Design comprehensive testing strategies covering unit tests,\n integration tests, and end-to-end tests. Identify critical paths that need coverage.\n\n2. **Test Implementation**: Write automated tests using the project's testing framework.\n Cover happy paths, edge cases, error conditions, and boundary values.\n\n3. **Bug Reporting & QA Returns**: When you find bugs or missing implementation, you must\n act immediately — do not just mark a task blocked and wait. Document the issue clearly\n (reproduction steps, expected vs actual behavior, missing files), then:\n a. Add a \\`> [BLOCKER]\\` note to the task in the todo file with specifics.\n b. Send a task-blocked message to the **project-manager** (not just the orchestrator)\n so they can reassign the task back to a developer.\n c. Add a \\`> [pipeline] Returned from QA to develop - <reason>\\` note.\n The project manager will handle reassignment. Do not keep working on a task that has\n missing or fundamentally broken implementation — return it.\n\n4. **Requirements Validation**: Verify that implementations match the task descriptions\n and acceptance criteria. Flag gaps between requirements and implementation.\n\n5. **Regression Testing**: Ensure new changes don't break existing functionality.\n Maintain test suites that catch regressions early.\n\n6. **Test Documentation**: Document test coverage, testing patterns, and any manual\n test procedures that cannot be automated.\n\n7. **Process Boundaries**: Write tests, but be cautious about executing them. Run only\n targeted, specific test files — never a full test suite (e.g. \\`npm test\\` or \\`pytest\\`\n with no arguments). A single test file that takes more than 60 seconds likely indicates\n an integration test that depends on external services; skip it and flag it for manual\n execution. Do not start servers, databases, or other services as part of testing.\n\nFocus on finding issues before they reach production. Coordinate with developers on\nbug fixes and with the architect on testability of the design.\n`.trim(),\n\n devops: `\n## DevOps-Specific Instructions\n\nYou handle infrastructure, deployment, and build tooling. Your responsibilities:\n\n1. **CI/CD Pipeline**: Set up and maintain continuous integration and deployment pipelines.\n Configure build, test, lint, and deploy stages.\n\n2. **Containerization**: Create and maintain Dockerfiles, docker-compose configurations,\n and container orchestration setups as needed.\n\n3. **Environment Configuration**: Set up development, staging, and production environment\n configurations. Manage environment variables, secrets handling, and config files.\n\n4. **Build Tooling**: Configure and optimize build tools, bundlers, and compilation\n pipelines. Ensure fast, reliable builds.\n\n5. **Monitoring & Logging**: Set up application monitoring, error tracking, health checks,\n and structured logging where applicable.\n\n6. **Infrastructure as Code**: Define infrastructure using code (Terraform, CloudFormation,\n etc.) when applicable. Document deployment procedures.\n\n7. **Process Boundaries**: You write configuration, you do NOT execute it. Do not run\n \\`docker build\\`, \\`docker run\\`, \\`docker compose up\\`, or any Docker commands. Do not\n run build pipelines, start servers, or execute deployment scripts. Write the Dockerfiles,\n CI configs, and shell scripts — the actual execution happens in CI/CD or by the user.\n\nWrite configuration files, scripts, and infrastructure code. Do NOT execute Docker\ncommands, build pipelines, or deployment scripts in this environment. Coordinate with\ndevelopers on build requirements and with the architect on deployment architecture.\n`.trim(),\n\n 'technical-writer': `\n## Technical Writer-Specific Instructions\n\nYou create and maintain project documentation. Your responsibilities:\n\n1. **README & Setup Guides**: Write clear README files with project overview, setup\n instructions, prerequisites, and quickstart guides.\n\n2. **API Documentation**: Document public APIs, endpoints, request/response formats,\n authentication, and error codes. Keep API docs in sync with implementation.\n\n3. **Architecture Documentation**: Work with the architect to document system design,\n data flow diagrams, component relationships, and design decisions (ADRs).\n\n4. **User Guides**: Write end-user documentation, tutorials, and how-to guides that\n explain features and workflows in accessible language.\n\n5. **Code Documentation**: Review code for missing or outdated inline documentation.\n Add JSDoc/docstrings to public interfaces, complex functions, and non-obvious logic.\n\n6. **Changelog & Release Notes**: Maintain changelogs and write release notes that\n clearly communicate changes, fixes, and breaking changes.\n\nWrite documentation files (markdown, JSDoc, etc.). Coordinate with all team members\nto ensure docs accurately reflect the current state of the project.\n`.trim(),\n\n 'code-reviewer': `\n## Code Reviewer-Specific Instructions\n\nYou review completed work for quality and correctness. Your responsibilities:\n\n1. **Code Review**: Examine implementation code for correctness, readability, and\n adherence to project conventions. Check for logic errors, off-by-one errors,\n and edge case handling.\n\n2. **Security Review**: Identify potential security vulnerabilities: injection attacks,\n authentication/authorization issues, data exposure, and insecure defaults.\n\n3. **Performance Review**: Flag performance anti-patterns: N+1 queries, unnecessary\n re-renders, memory leaks, missing indexes, and inefficient algorithms.\n\n4. **Standards Compliance**: Verify code follows ARCHITECTURE.md, naming conventions,\n file organization patterns, and coding standards. Flag deviations.\n\n5. **Feedback Delivery**: Provide specific, constructive feedback. Distinguish between\n blocking issues and suggestions. Include code examples for recommended changes.\n\n6. **Verification**: After developers address review feedback, verify the changes\n resolve the identified issues without introducing new problems.\n\nDo NOT implement changes yourself. Send review-result messages with specific feedback.\nCoordinate with the architect on design-level concerns and developers on implementation.\n`.trim(),\n};\n\nexport interface SystemPromptParams {\n role: AgentRole;\n agentId: string;\n projectName: string;\n todoFilePath: string;\n inboxPath: string;\n outboxPath: string;\n workingDirectory: string;\n techStack?: TechStackConfig;\n}\n\nfunction buildTechStackSection(ts?: TechStackConfig): string {\n if (!ts) return '';\n const lines: string[] = ['# Tech Stack'];\n if (ts.frontend) lines.push(`- **Frontend**: ${ts.frontend}`);\n if (ts.uiLibrary) lines.push(`- **UI Library**: ${ts.uiLibrary}`);\n if (ts.backend) lines.push(`- **Backend**: ${ts.backend}`);\n if (ts.database) lines.push(`- **Database**: ${ts.database}`);\n if (ts.other) lines.push(`- **Other**: ${ts.other}`);\n if (lines.length === 1) return '';\n lines.push('', 'Use these technologies in your work. Follow their conventions and best practices.');\n return lines.join('\\n');\n}\n\nexport function getDefaultSystemPrompt(params: SystemPromptParams): string {\n const {\n role,\n agentId,\n projectName,\n todoFilePath,\n inboxPath,\n outboxPath,\n workingDirectory,\n techStack,\n } = params;\n\n const techStackSection = buildTechStackSection(techStack);\n\n return `\n# Agent Identity\n\nYou are **${agentId}**, a ${role} agent working on the **${projectName}** project.\n\n${ROLE_DESCRIPTIONS[role]}\n\n# Working Environment\n\n- **Working Directory**: ${workingDirectory}\n- **Todo File**: ${todoFilePath}\n- **Inbox Directory**: ${inboxPath}\n- **Outbox Directory**: ${outboxPath}\n\nYou should regularly check the todo file for task updates and your inbox for new messages.\nWhen you need to communicate with other agents, write message files to your outbox.\n\n${techStackSection ? techStackSection + '\\n\\n' : ''}${TODO_FORMAT_INSTRUCTIONS}\n\n${MESSAGE_FORMAT_INSTRUCTIONS}\n\n${ROLE_SPECIFIC_INSTRUCTIONS[role]}\n\n${PROCESS_SAFETY_RULES}\n\n## Architecture Compliance\n\nIf an \\`ARCHITECTURE.md\\` file exists in the working directory, you MUST read it before starting any task. It is the source of truth for project structure, component boundaries, data models, API contracts, and technical decisions.\n\n- **Follow the architecture.** Do not contradict decisions documented in ARCHITECTURE.md.\n- **Check before creating.** Before adding new files, directories, or modules, verify the architecture allows it and place them where it specifies.\n- **Flag conflicts.** If a task asks you to do something that conflicts with ARCHITECTURE.md, do NOT silently proceed. Send a message to the orchestrator or architect describing the conflict and wait for guidance.\n- **Keep it updated.** If you are the architect or technical-writer and your work changes the architecture, update ARCHITECTURE.md to reflect the new state.\n\n## Asking the User Questions\n\nTo ask the user a question, send a message with \\`to: \"user\"\\` and \\`type: \"question\"\\` to your outbox. Only ask when you genuinely cannot proceed without user input.\n\n# General Guidelines\n\n- Identify yourself as \"${agentId}\" in messages\n- Check your inbox at the start of each task cycle\n- Update the todo file when you start or complete work\n- Send task-blocked messages immediately when you hit a blocker\n- Focus on your role; do not overstep into other agents' responsibilities\n`.trim();\n}\n","import { readFileSync, existsSync } from 'node:fs';\nimport path from 'node:path';\nimport type { AgentConfig, AgentRole } from '../types/agent.js';\nimport type { ProjectConfig } from '../types/project.js';\nimport { getDefaultSystemPrompt } from './roles.js';\n\n/**\n * Check if a custom agent definition file exists for a role.\n * Looks in ./agents/<role>.md relative to the working directory.\n */\nfunction findCustomAgentPath(workingDirectory: string, role: AgentRole): string | undefined {\n const agentsDir = path.resolve(workingDirectory, 'agents');\n const agentFile = path.join(agentsDir, `${role}.md`);\n\n if (existsSync(agentFile)) {\n return agentFile;\n }\n\n return undefined;\n}\n\n/**\n * Load and generate AgentConfig[] from a ProjectConfig.\n *\n * For each role config:\n * - If count > 1, generates multiple configs with IDs like \"developer-1\", \"developer-2\"\n * - If count === 1, uses the role as the ID (e.g., \"orchestrator\")\n * - Loads system prompts from systemPromptFile if specified, otherwise uses getDefaultSystemPrompt\n */\nexport function loadAgentConfigs(projectConfig: ProjectConfig): AgentConfig[] {\n const configs: AgentConfig[] = [];\n const { settings } = projectConfig;\n\n for (const roleConfig of projectConfig.agents) {\n const count = roleConfig.count ?? 1;\n\n for (let i = 1; i <= count; i++) {\n const agentId = count > 1\n ? `${roleConfig.role}-${i}`\n : roleConfig.role;\n\n const systemPrompt = resolveSystemPrompt({\n roleConfig,\n agentId,\n role: roleConfig.role,\n projectConfig,\n });\n\n // Merge CLI args: settings-level defaults + per-agent overrides\n const mergedArgs = [\n ...(settings.claudeArgs ?? []),\n ...(roleConfig.claudeArgs ?? []),\n ];\n // Merge env vars: settings-level defaults, then per-agent overrides\n const mergedEnv = {\n ...(settings.claudeEnv ?? {}),\n ...(roleConfig.claudeEnv ?? {}),\n };\n\n const config: AgentConfig = {\n id: agentId,\n role: roleConfig.role,\n name: formatAgentName(roleConfig.role, count > 1 ? i : undefined),\n model: roleConfig.model ?? settings.defaultModel,\n systemPrompt,\n allowedTools: roleConfig.allowedTools,\n maxBudgetUsd: roleConfig.maxBudgetUsd,\n workingDirectory: settings.workingDirectory,\n permissionMode: roleConfig.permissionMode ?? 'default',\n claudeCommand: settings.claudeCommand,\n claudeArgs: mergedArgs.length > 0 ? mergedArgs : undefined,\n claudeEnv: Object.keys(mergedEnv).length > 0 ? mergedEnv : undefined,\n maxTurns: roleConfig.maxTurns,\n customAgentPath: findCustomAgentPath(settings.workingDirectory, roleConfig.role),\n };\n\n configs.push(config);\n }\n }\n\n return configs;\n}\n\n/**\n * Resolve the system prompt for an agent, checking in order:\n * 1. systemPromptOverride (inline string)\n * 2. systemPromptFile (path to a file)\n * 3. getDefaultSystemPrompt (generated from role)\n */\nfunction resolveSystemPrompt(params: {\n roleConfig: ProjectConfig['agents'][number];\n agentId: string;\n role: AgentRole;\n projectConfig: ProjectConfig;\n}): string {\n const { roleConfig, agentId, role, projectConfig } = params;\n const { settings } = projectConfig;\n\n // 1. Inline override takes highest priority\n if (roleConfig.systemPromptOverride) {\n return roleConfig.systemPromptOverride;\n }\n\n // 2. Load from file if specified\n if (roleConfig.systemPromptFile) {\n const promptPath = path.isAbsolute(roleConfig.systemPromptFile)\n ? roleConfig.systemPromptFile\n : path.resolve(settings.workingDirectory, roleConfig.systemPromptFile);\n\n return readFileSync(promptPath, 'utf-8');\n }\n\n // 3. Check for local .agents/ directory prompt files\n const localAgentsDir = path.resolve(settings.workingDirectory, '.agents');\n const localPromptPath = path.join(localAgentsDir, `${role}.md`);\n\n if (existsSync(localPromptPath)) {\n try {\n const content = readFileSync(localPromptPath, 'utf-8').trim();\n if (content) {\n const todoFilePath = path.resolve(settings.workingDirectory, settings.todoFile);\n const messagesDir = path.resolve(settings.workingDirectory, settings.messagesDirectory);\n return content\n .replace(/\\{\\{agentId\\}\\}/g, agentId)\n .replace(/\\{\\{projectName\\}\\}/g, projectConfig.name)\n .replace(/\\{\\{todoFilePath\\}\\}/g, todoFilePath)\n .replace(/\\{\\{inboxPath\\}\\}/g, path.join(messagesDir, agentId, 'inbox'))\n .replace(/\\{\\{outboxPath\\}\\}/g, path.join(messagesDir, agentId, 'outbox'))\n .replace(/\\{\\{workingDirectory\\}\\}/g, settings.workingDirectory);\n }\n } catch {\n // File unreadable, fall through to default\n }\n }\n\n // 4. Generate default system prompt\n const todoFilePath = path.resolve(settings.workingDirectory, settings.todoFile);\n const messagesDir = path.resolve(settings.workingDirectory, settings.messagesDirectory);\n\n return getDefaultSystemPrompt({\n role,\n agentId,\n projectName: projectConfig.name,\n todoFilePath,\n inboxPath: path.join(messagesDir, agentId, 'inbox'),\n outboxPath: path.join(messagesDir, agentId, 'outbox'),\n workingDirectory: settings.workingDirectory,\n techStack: projectConfig.techStack,\n });\n}\n\n/**\n * Format a human-readable agent name from role and optional index.\n */\nfunction formatAgentName(role: AgentRole, index?: number): string {\n const roleName = role\n .split('-')\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join(' ');\n\n return index !== undefined ? `${roleName} ${index}` : roleName;\n}\n","/**\n * Orchestrator activity log types.\n *\n * These represent structured events that the orchestrator emits so that\n * a persistent \"Orchestrator\" panel in the TUI can display what's happening\n * at a high level: task delegations, status updates, phase transitions,\n * agent hand-offs, and pipeline progress.\n */\n\nexport type OrchestratorActivityKind =\n | 'task-delegated'\n | 'task-completed'\n | 'task-blocked'\n | 'task-failed'\n | 'agent-spawned'\n | 'agent-stopped'\n | 'agent-error'\n | 'phase-changed'\n | 'pipeline-handoff'\n | 'plan-created'\n | 'plan-approved'\n | 'plan-rejected'\n | 'budget-warning'\n | 'rate-limit'\n | 'project-completed'\n | 'cycle-summary'\n | 'gap-detected'\n | 'pm-scan'\n | 'info';\n\nexport interface OrchestratorActivity {\n id: string;\n kind: OrchestratorActivityKind;\n timestamp: string;\n message: string;\n details?: {\n taskId?: string;\n taskTitle?: string;\n agentId?: string;\n agentRole?: string;\n fromPhase?: string;\n toPhase?: string;\n pipelineStage?: string;\n cost?: number;\n [key: string]: unknown;\n };\n}\n\n/**\n * Task pipeline stages — each task flows through a defined sequence of\n * stages with role-based handoffs between agents.\n */\nexport type PipelineStage = 'plan' | 'develop' | 'qa' | 'review';\n\nexport const PIPELINE_STAGE_ORDER: PipelineStage[] = ['plan', 'develop', 'qa', 'review'];\n\n/**\n * Maps pipeline stages to the agent roles responsible for executing them.\n */\nexport const PIPELINE_STAGE_ROLES: Record<PipelineStage, string[]> = {\n plan: ['project-manager', 'architect'],\n develop: ['developer'],\n qa: ['qa-engineer'],\n review: ['project-manager'],\n};\n\nexport interface TaskPipelineState {\n taskId: string;\n currentStage: PipelineStage;\n stageHistory: {\n stage: PipelineStage;\n agentId: string;\n startedAt: string;\n completedAt: string | null;\n status: 'in-progress' | 'completed' | 'failed';\n }[];\n createdAt: string;\n}\n","// Types\nexport * from './types/index.js';\n\n// Task management\nexport { TaskParser } from './task/parser.js';\nexport { TaskWriter } from './task/writer.js';\nexport { TaskManager } from './task/manager.js';\n\n// Agent management\nexport { AgentProcess } from './agent/lifecycle.js';\nexport { AgentPool } from './agent/pool.js';\nexport { getDefaultSystemPrompt, ROLE_DESCRIPTIONS } from './agent/roles.js';\nexport { loadAgentConfigs } from './agent/config.js';\n\n// Messaging\nexport { MessageBroker } from './messaging/broker.js';\nexport { InboxWatcher } from './messaging/inbox.js';\n\n// Orchestrator\nexport { Orchestrator } from './orchestrator/orchestrator.js';\nexport { Planner, type PlannedTask } from './orchestrator/planner.js';\nexport { Scheduler } from './orchestrator/scheduler.js';\nexport { TaskPipeline } from './orchestrator/pipeline.js';\nexport { ProjectManagerScanner } from './orchestrator/pm-scanner.js';\n\n// Feedback\nexport { FeedbackLoop } from './feedback/feedback-loop.js';\nexport { ProgressTracker } from './feedback/progress-tracker.js';\n\n// Project\nexport { loadProjectConfig, validateProjectConfig } from './project/config.js';\nexport { WorkspaceManager } from './project/workspace.js';\n\n// Utils\nexport { createLogger } from './utils/logger.js';\nexport { generateId, generateTaskId, resetTaskCounter } from './utils/id.js';\n","import { EventEmitter } from 'eventemitter3';\nimport { mkdir, writeFile, readFile, readdir, rename, unlink } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { Message, MessageEnvelope } from '../types/message.js';\nimport { InboxWatcher } from './inbox.js';\nimport { createLogger } from '../utils/logger.js';\n\nconst logger = createLogger('message-broker');\n\n/**\n * Build a filename for a message file.\n * Format: {taskId}_{messageId}.json (or general_{messageId}.json if no taskId)\n */\nfunction messageFileName(message: Message): string {\n const prefix = message.taskId ?? 'general';\n return `${prefix}_${message.id}.json`;\n}\n\nexport class MessageBroker extends EventEmitter {\n private baseDir: string;\n private watchers: Map<string, InboxWatcher> = new Map();\n private registeredAgents: Set<string> = new Set();\n\n constructor(baseDir: string) {\n super();\n this.baseDir = baseDir;\n }\n\n /**\n * Initialize directory structure for an agent.\n * Creates inbox/, outbox/, and processed/ directories.\n */\n async registerAgent(agentId: string): Promise<void> {\n const agentDir = join(this.baseDir, agentId);\n await mkdir(join(agentDir, 'inbox'), { recursive: true });\n await mkdir(join(agentDir, 'outbox'), { recursive: true });\n await mkdir(join(agentDir, 'processed'), { recursive: true });\n this.registeredAgents.add(agentId);\n logger.debug({ agentId }, 'Registered agent');\n }\n\n /**\n * Initialize directories for all agents and start watching.\n * Watches each agent's outbox directory so that messages agents write\n * there are automatically picked up and routed.\n */\n async start(agentIds: string[]): Promise<void> {\n for (const agentId of agentIds) {\n await this.registerAgent(agentId);\n }\n\n for (const agentId of agentIds) {\n // Watch the agent's outbox for messages it sends\n const outboxDir = join(this.baseDir, agentId, 'outbox');\n const processedDir = join(this.baseDir, agentId, 'processed');\n const watcher = new InboxWatcher(outboxDir, processedDir);\n\n watcher.on('message', (envelope: MessageEnvelope) => {\n logger.info(\n { from: envelope.message.from, to: envelope.message.to, type: envelope.message.type },\n 'Message received from agent outbox',\n );\n this.emit('message:received', envelope.message);\n\n // Route the message to its recipient\n if (envelope.message.to === '*') {\n this.broadcast(envelope.message).catch((err) => {\n logger.error({ err }, 'Failed to broadcast message');\n });\n } else {\n this.sendMessage(envelope.message).catch((err) => {\n logger.error({ err }, 'Failed to route message');\n });\n }\n });\n\n await watcher.start();\n this.watchers.set(agentId, watcher);\n }\n\n logger.info({ agentCount: agentIds.length }, 'Message broker started');\n }\n\n /**\n * Send a message to an agent's inbox.\n * If message.to is \"*\", broadcasts to all registered agents instead.\n */\n async sendMessage(message: Message): Promise<void> {\n if (message.to === '*') {\n await this.broadcast(message);\n return;\n }\n\n // Intercept user-directed messages\n if (message.to === 'user') {\n logger.info({ from: message.from, type: message.type }, 'User-directed message intercepted');\n this.emit('message:user-directed', message);\n return;\n }\n\n if (!this.registeredAgents.has(message.to)) {\n logger.warn({ to: message.to }, 'Attempted to send message to unregistered agent');\n return;\n }\n\n const envelope: MessageEnvelope = {\n message,\n deliveredAt: null,\n readAt: null,\n status: 'pending',\n };\n\n const filePath = join(this.baseDir, message.to, 'inbox', messageFileName(message));\n await writeFile(filePath, JSON.stringify(envelope, null, 2), 'utf-8');\n\n logger.debug(\n { id: message.id, from: message.from, to: message.to, type: message.type },\n 'Message sent',\n );\n this.emit('message:sent', message);\n }\n\n /**\n * Send a message to all registered agents' inboxes.\n */\n async broadcast(message: Message): Promise<void> {\n const promises: Promise<void>[] = [];\n\n for (const agentId of this.registeredAgents) {\n // Don't send broadcast back to the sender\n if (agentId === message.from) {\n continue;\n }\n\n const envelope: MessageEnvelope = {\n message: { ...message, to: agentId },\n deliveredAt: null,\n readAt: null,\n status: 'pending',\n };\n\n const broadcastMsg = { ...message, to: agentId };\n const filePath = join(this.baseDir, agentId, 'inbox', messageFileName(broadcastMsg));\n promises.push(\n writeFile(filePath, JSON.stringify(envelope, null, 2), 'utf-8').then(() => {\n this.emit('message:sent', broadcastMsg);\n }),\n );\n }\n\n await Promise.all(promises);\n logger.debug(\n { id: message.id, from: message.from, agentCount: this.registeredAgents.size },\n 'Broadcast sent',\n );\n }\n\n /**\n * Mark an inbox message as processed and move it to the processed directory.\n * Called when a task completes so the inbox reflects the current state.\n */\n async markInboxProcessed(agentId: string, taskId: string): Promise<void> {\n const inboxDir = join(this.baseDir, agentId, 'inbox');\n const processedDir = join(this.baseDir, agentId, 'processed');\n\n try {\n const files = await readdir(inboxDir);\n for (const file of files) {\n if (!file.endsWith('.json')) continue;\n const filePath = join(inboxDir, file);\n try {\n const content = await readFile(filePath, 'utf-8');\n const envelope: MessageEnvelope = JSON.parse(content);\n if (envelope.message.taskId === taskId) {\n envelope.status = 'processed';\n envelope.readAt = new Date().toISOString();\n // Write updated status then move to processed\n await writeFile(filePath, JSON.stringify(envelope, null, 2), 'utf-8');\n const destPath = join(processedDir, file);\n await rename(filePath, destPath);\n logger.debug({ agentId, taskId, messageId: envelope.message.id }, 'Inbox message marked as processed');\n }\n } catch {\n // Skip files that can't be read or parsed\n }\n }\n } catch {\n // Inbox directory may not exist yet\n }\n }\n\n /**\n * Clean up stale inbox messages for a task (e.g., after restart when\n * in-progress tasks are reset). Moves matching messages to processed/.\n */\n async cleanInboxForTask(agentId: string, taskId: string): Promise<void> {\n await this.markInboxProcessed(agentId, taskId);\n }\n\n /**\n * Read processed messages for a specific task across all agents.\n * Used to display task completion details in the TUI.\n */\n async getProcessedMessagesForTask(taskId: string): Promise<MessageEnvelope[]> {\n const results: MessageEnvelope[] = [];\n\n // Discover all agent directories on disk (not just registered ones)\n // so we find messages from previous sessions too.\n let agentDirs: string[] = [];\n try {\n const entries = await readdir(this.baseDir, { withFileTypes: true });\n agentDirs = entries.filter((e) => e.isDirectory()).map((e) => e.name);\n } catch {\n return results;\n }\n\n for (const agentId of agentDirs) {\n // Scan both inbox and processed directories\n for (const subdir of ['inbox', 'processed']) {\n const dir = join(this.baseDir, agentId, subdir);\n try {\n const entries = await readdir(dir, { withFileTypes: true });\n for (const entry of entries) {\n if (!entry.isFile() || !entry.name.endsWith('.json')) continue;\n try {\n const content = await readFile(join(dir, entry.name), 'utf-8');\n const envelope: MessageEnvelope = JSON.parse(content);\n if (envelope.message?.taskId === taskId) {\n results.push(envelope);\n }\n } catch {\n // Skip unreadable files\n }\n }\n } catch {\n // Directory may not exist\n }\n }\n }\n\n // Deduplicate by message id (same message may exist in inbox and processed)\n const seen = new Set<string>();\n const deduped = results.filter((env) => {\n if (seen.has(env.message.id)) return false;\n seen.add(env.message.id);\n return true;\n });\n\n // Sort by timestamp\n deduped.sort((a, b) => a.message.timestamp.localeCompare(b.message.timestamp));\n return deduped;\n }\n\n /**\n * Move ALL inbox messages to processed/ for every agent directory.\n * Called on startup to ensure a clean slate — agents should not pick up\n * stale task-assignment messages from a previous session.\n */\n async cleanAllInboxes(): Promise<void> {\n let agentDirs: string[] = [];\n try {\n const entries = await readdir(this.baseDir, { withFileTypes: true });\n agentDirs = entries.filter((e) => e.isDirectory()).map((e) => e.name);\n } catch {\n return;\n }\n\n let movedCount = 0;\n for (const agentId of agentDirs) {\n const inboxDir = join(this.baseDir, agentId, 'inbox');\n const processedDir = join(this.baseDir, agentId, 'processed');\n try {\n await mkdir(processedDir, { recursive: true });\n const files = await readdir(inboxDir);\n for (const file of files) {\n if (!file.endsWith('.json')) continue;\n try {\n await rename(join(inboxDir, file), join(processedDir, file));\n movedCount++;\n } catch {\n // File may already be moved\n }\n }\n } catch {\n // Directory may not exist\n }\n }\n\n if (movedCount > 0) {\n logger.info({ movedCount }, 'Cleaned stale inbox messages from previous session');\n }\n }\n\n get messagesBaseDir(): string {\n return this.baseDir;\n }\n\n /**\n * Stop all watchers and clean up.\n */\n async stop(): Promise<void> {\n const stopPromises: Promise<void>[] = [];\n for (const [agentId, watcher] of this.watchers) {\n logger.debug({ agentId }, 'Stopping watcher');\n stopPromises.push(watcher.stop());\n }\n await Promise.all(stopPromises);\n this.watchers.clear();\n logger.info('Message broker stopped');\n }\n}\n","import { watch, type FSWatcher } from 'chokidar';\nimport { EventEmitter } from 'eventemitter3';\nimport { readFile, rename, mkdir } from 'node:fs/promises';\nimport { join, basename } from 'node:path';\nimport type { MessageEnvelope } from '../types/message.js';\nimport { createLogger } from '../utils/logger.js';\n\nconst logger = createLogger('inbox-watcher');\n\nexport class InboxWatcher extends EventEmitter {\n private watcher: FSWatcher | null = null;\n private dir: string;\n private processedDir: string;\n\n constructor(inboxDir: string, processedDir: string) {\n super();\n this.dir = inboxDir;\n this.processedDir = processedDir;\n }\n\n async start(): Promise<void> {\n await mkdir(this.dir, { recursive: true });\n await mkdir(this.processedDir, { recursive: true });\n\n this.watcher = watch(this.dir, {\n ignoreInitial: false,\n awaitWriteFinish: { stabilityThreshold: 200 },\n });\n\n this.watcher.on('add', (filePath: string) => {\n if (filePath.endsWith('.json')) {\n this.processFile(filePath).catch((err) => {\n logger.error({ err, filePath }, 'Failed to process inbox file');\n });\n }\n });\n\n this.watcher.on('error', (err: unknown) => {\n logger.error({ err }, 'Inbox watcher error');\n });\n }\n\n async stop(): Promise<void> {\n if (this.watcher) {\n await this.watcher.close();\n this.watcher = null;\n }\n }\n\n private async processFile(filePath: string): Promise<void> {\n try {\n const content = await readFile(filePath, 'utf-8');\n let envelope: MessageEnvelope;\n\n try {\n envelope = JSON.parse(content) as MessageEnvelope;\n } catch {\n logger.warn({ filePath }, 'Malformed JSON in inbox file, skipping');\n return;\n }\n\n envelope.deliveredAt = new Date().toISOString();\n envelope.status = 'delivered';\n\n this.emit('message', envelope);\n\n const destPath = join(this.processedDir, basename(filePath));\n await rename(filePath, destPath);\n } catch (err) {\n // File may have been already moved or deleted\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n logger.debug({ filePath }, 'Inbox file already removed');\n return;\n }\n throw err;\n }\n }\n}\n","import { EventEmitter } from 'eventemitter3';\nimport { mkdir } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { ProjectConfig } from '../types/project.js';\nimport type { OrchestratorStats, MaestroEvents, ProjectCompletionSummary } from '../types/events.js';\nimport type { AgentStreamEvent, AgentStatus } from '../types/agent.js';\nimport type { Message } from '../types/message.js';\nimport type { Task } from '../types/task.js';\nimport type { FeedbackSettings, InteractionMode, PlanProposal, PlannedTaskSummary, UserQuestion } from '../types/feedback.js';\nimport type { OrchestratorActivity, PipelineStage } from '../types/orchestrator-activity.js';\nimport { PIPELINE_STAGE_ROLES } from '../types/orchestrator-activity.js';\nimport { MessageBroker } from '../messaging/broker.js';\nimport { FeedbackLoop } from '../feedback/feedback-loop.js';\nimport { Planner } from './planner.js';\nimport { Scheduler, type TaskAssignment } from './scheduler.js';\nimport { TaskPipeline } from './pipeline.js';\nimport { ProjectManagerScanner } from './pm-scanner.js';\nimport { generateId, generateTaskId } from '../utils/id.js';\nimport { createLogger } from '../utils/logger.js';\n\nconst logger = createLogger('orchestrator');\n\nexport class Orchestrator extends EventEmitter {\n private config: ProjectConfig;\n private running = false;\n private paused = false;\n private intervalId: ReturnType<typeof setInterval> | null = null;\n private startedAt: number | null = null;\n\n private broker: MessageBroker | null = null;\n private scheduler: Scheduler | null = null;\n private planner: Planner | null = null;\n private pipeline: TaskPipeline;\n private pmScanner: ProjectManagerScanner;\n\n // These will hold references to modules that manage tasks and agents.\n // They are typed loosely here because TaskManager, AgentPool, and\n // WorkspaceManager are sibling modules that may not yet be implemented.\n // The orchestrator interfaces with them via their public APIs.\n private taskManager: any = null;\n private agentPool: any = null;\n private agentConfigs: any[] = [];\n private cachedTasks: Task[] = [];\n private feedbackLoop: FeedbackLoop | null = null;\n private planApprovalPending = false;\n private phase: 'planning' | 'architecture' | 'development' = 'planning';\n private architectureApprovalPending = false;\n\n constructor(config: ProjectConfig) {\n super();\n this.config = config;\n this.pipeline = new TaskPipeline();\n this.pmScanner = new ProjectManagerScanner();\n }\n\n get isActive(): boolean {\n return this.running;\n }\n\n get isPaused(): boolean {\n return this.paused;\n }\n\n /**\n * Emit a structured orchestrator activity event.\n * These feed the persistent \"Orchestrator\" panel in the TUI.\n */\n private emitActivity(\n kind: OrchestratorActivity['kind'],\n message: string,\n details?: OrchestratorActivity['details'],\n ): void {\n const activity: OrchestratorActivity = {\n id: generateId(),\n kind,\n timestamp: new Date().toISOString(),\n message,\n details,\n };\n this.emit('orchestrator:activity', activity);\n }\n\n /**\n * Start the orchestrator:\n * 1. Ensure workspace directories exist\n * 2. Initialize TaskManager, AgentPool, MessageBroker, Scheduler, Planner\n * 3. Load agent configs and register them with the broker\n * 4. If no tasks exist, use Planner to decompose the project description\n * 5. Start the polling loop\n */\n async start(): Promise<void> {\n if (this.running) {\n logger.warn('Orchestrator already running');\n return;\n }\n\n const settings = this.config.settings;\n\n // Step 1: Ensure workspace directories exist\n await mkdir(settings.messagesDirectory, { recursive: true });\n await mkdir(settings.logsDirectory, { recursive: true });\n\n // Step 2: Initialize core components\n // Dynamically import sibling modules to avoid hard circular deps at parse time\n const [{ TaskManager }, { AgentPool }, { loadAgentConfigs }] = await Promise.all([\n import('../task/manager.js'),\n import('../agent/pool.js'),\n import('../agent/config.js'),\n ]);\n\n this.taskManager = new TaskManager({ filePath: settings.todoFile, projectName: this.config.name });\n this.agentPool = new AgentPool();\n this.broker = new MessageBroker(settings.messagesDirectory);\n this.scheduler = new Scheduler();\n this.scheduler.setPipeline(this.pipeline);\n this.planner = new Planner({\n model: settings.defaultModel,\n workingDirectory: settings.workingDirectory,\n claudeCommand: settings.claudeCommand,\n claudeEnv: settings.claudeEnv,\n techStack: this.config.techStack,\n });\n\n this.feedbackLoop = new FeedbackLoop(settings.feedback);\n\n // Forward feedback events\n this.feedbackLoop.on('plan:proposed', (p) => this.emit('plan:proposed', p));\n this.feedbackLoop.on('plan:decided', (...args) => this.emit('plan:decided', ...args));\n this.feedbackLoop.on('question:asked', (q) => this.emit('question:asked', q));\n this.feedbackLoop.on('question:answered', (...args) => this.emit('question:answered', ...args));\n this.feedbackLoop.on('progress:report', (r) => this.emit('progress:report', r));\n this.feedbackLoop.on('milestone:reached', (m) => this.emit('milestone:reached', m));\n this.feedbackLoop.on('milestone:acknowledged', (id) => this.emit('milestone:acknowledged', id));\n this.feedbackLoop.on('interaction-mode:changed', (m) => this.emit('interaction-mode:changed', m));\n\n // Step 3: Load agent configs and register with broker\n const agentConfigs = loadAgentConfigs(this.config);\n const agentIds = agentConfigs.map((c) => c.id);\n\n // Store agent configs for spawning during orchestration cycles\n this.agentConfigs = agentConfigs;\n\n this.emitActivity('info', `Orchestrator starting with ${agentConfigs.length} agent(s) configured`);\n\n // Start broker (registers agents and starts watching outboxes)\n await this.broker.start(agentIds);\n\n // Forward broker events\n this.broker.on('message:received', (message: Message) => {\n this.emit('message:received', message);\n });\n this.broker.on('message:sent', (message: Message) => {\n this.emit('message:sent', message);\n });\n\n // Forward agent pool events with activity logging\n this.agentPool.on('agent:output', (event: AgentStreamEvent) => {\n this.emit('agent:output', event);\n });\n\n this.agentPool.on('agent:status-changed', (agentId: string, oldStatus: AgentStatus, newStatus: AgentStatus) => {\n this.emit('agent:status-changed', agentId, oldStatus, newStatus);\n });\n\n this.agentPool.on('agent:error', (agentId: string, error: Error) => {\n this.emit('agent:error', agentId, error);\n this.emitActivity('agent-error', `Agent ${agentId} encountered an error: ${error.message}`, {\n agentId,\n });\n });\n\n this.agentPool.on('agent:stopped', (agentId: string, exitCode: number | null) => {\n this.emit('agent:stopped', agentId, exitCode);\n this.emitActivity('agent-stopped', `Agent ${agentId} stopped (exit code: ${exitCode})`, {\n agentId,\n });\n });\n\n this.agentPool.on('agent:spawned', (agentId: string) => {\n const agent = this.agentPool.getAgent(agentId);\n if (agent) {\n this.emit('agent:spawned', agent.currentState);\n this.emitActivity('agent-spawned', `Spawned agent ${agent.currentState.config.name} (${agent.currentState.config.role})`, {\n agentId,\n agentRole: agent.currentState.config.role,\n });\n }\n });\n\n // Step 4: Decompose project goal into initial tasks if needed\n const existingTasks: Task[] = await this.taskManager.load();\n if (existingTasks.length === 0) {\n logger.info('No existing tasks found, decomposing project goal');\n this.emitActivity('info', 'No existing tasks found, decomposing project goal...');\n const plannedTasks = await this.planner.decompose(this.config.description);\n\n // Convert to PlannedTaskSummary for plan proposal\n const summaries: PlannedTaskSummary[] = plannedTasks.map((t) => ({\n title: t.title,\n description: t.description,\n priority: t.priority,\n assignedRole: '', // Will be determined by scheduler\n tags: t.tags,\n }));\n\n this.emitActivity('plan-created', `Created plan with ${plannedTasks.length} task(s) from project goal`);\n\n // Don't block start() on plan approval — this allows the TUI/UI\n // to render and display the plan for user approval.\n this.planApprovalPending = true;\n this.feedbackLoop!.proposePlan(summaries, this.config.description).then(async (decision) => {\n this.planApprovalPending = false;\n\n if (decision === 'rejected') {\n logger.info('Plan rejected by user, stopping');\n this.emitActivity('plan-rejected', 'Plan rejected by user, stopping orchestrator');\n await this.stop();\n return;\n }\n\n this.emitActivity('plan-approved', 'Plan approved, creating tasks...');\n\n // Resolve dependency titles to task IDs as tasks are created\n const titleToId = new Map<string, string>();\n for (const planned of plannedTasks) {\n const resolvedDeps = planned.dependencies\n .map((depTitle) => titleToId.get(depTitle))\n .filter((id): id is string => id != null);\n\n const task = await this.taskManager.createTask({\n title: planned.title,\n description: planned.description,\n priority: planned.priority,\n dependencies: resolvedDeps,\n tags: planned.tags,\n });\n titleToId.set(planned.title, task.id);\n this.emit('task:created', task);\n\n // Register task in pipeline\n this.pipeline.initTask(task);\n }\n\n // Notify TUI that all tasks are now available\n const allNewTasks = await this.taskManager.load();\n this.emit('tasks:loaded', allNewTasks);\n\n // Determine initial phase based on whether architecture tasks exist\n const hasArchTasks = plannedTasks.some((t) => t.tags.includes('architecture'));\n this.phase = hasArchTasks ? 'architecture' : 'development';\n this.emit('phase:changed', this.phase);\n this.emitActivity('phase-changed', `Phase set to: ${this.phase}`, { toPhase: this.phase });\n logger.info({ count: plannedTasks.length, phase: this.phase }, 'Initial tasks created from project goal');\n }).catch((err) => {\n this.planApprovalPending = false;\n logger.error({ err }, 'Plan approval flow failed');\n });\n } else {\n // Existing tasks: clean slate on resume.\n // Move ALL inbox messages to processed/ so agents don't pick up stale assignments.\n if (this.broker) {\n await this.broker.cleanAllInboxes();\n }\n\n // Reset stale in-progress tasks from a previous session.\n // After restart, no agents are running, so any in-progress task is stale.\n const staleTasks = existingTasks.filter((t: Task) => t.status === 'in-progress');\n for (const task of staleTasks) {\n await this.taskManager.updateTask(task.id, {\n status: 'pending',\n assignee: null,\n });\n logger.info(\n { taskId: task.id, previousAssignee: task.assignee },\n 'Reset stale in-progress task to pending (previous session ended)',\n );\n }\n\n // Determine phase based on architecture task statuses\n // Reload tasks since we may have updated some above\n const refreshedTasks: Task[] = staleTasks.length > 0\n ? await this.taskManager.load()\n : existingTasks;\n const archTasks = refreshedTasks.filter((t: Task) => t.tags.includes('architecture'));\n const archPending = archTasks.some((t: Task) => t.status !== 'done');\n if (archTasks.length > 0 && archPending) {\n this.phase = 'architecture';\n } else {\n this.phase = 'development';\n }\n this.emit('phase:changed', this.phase);\n this.emitActivity('phase-changed', `Resuming in phase: ${this.phase} (${existingTasks.length} existing tasks)`, {\n toPhase: this.phase,\n });\n\n // Register existing tasks in pipeline\n for (const task of existingTasks) {\n if (!this.pipeline.has(task.id)) {\n this.pipeline.initTask(task);\n }\n }\n\n // Notify TUI that tasks are loaded (use refreshed list if stale tasks were reset)\n this.emit('tasks:loaded', refreshedTasks);\n\n logger.info({\n phase: this.phase,\n existingTaskCount: existingTasks.length,\n staleTasksReset: staleTasks.length,\n }, 'Resuming with existing tasks');\n }\n\n // Step 5: Start the polling loop\n this.running = true;\n this.startedAt = Date.now();\n\n this.intervalId = setInterval(() => {\n this.cycle().catch((err) => {\n logger.error({ err }, 'Orchestrator cycle failed');\n });\n }, settings.pollIntervalMs);\n\n // Run the first cycle immediately\n await this.cycle();\n\n // Step 6: Start the PM scanner loop for continuous project assessment\n this.pmScanner.start(() => {\n this.runPMScan().catch((err) => {\n logger.error({ err }, 'PM scan failed');\n });\n });\n\n this.emitActivity('info', 'Orchestrator started and running (PM scanner active)');\n logger.info('Orchestrator started');\n }\n\n /**\n * Stop the orchestrator gracefully.\n */\n async stop(): Promise<void> {\n if (!this.running) {\n return;\n }\n\n logger.info('Stopping orchestrator');\n this.emitActivity('info', 'Orchestrator shutting down...');\n\n // Clear the polling interval\n if (this.intervalId !== null) {\n clearInterval(this.intervalId);\n this.intervalId = null;\n }\n\n // Stop the PM scanner\n this.pmScanner.stop();\n\n // Stop all agents\n if (this.agentPool) {\n await this.agentPool.stopAll();\n }\n\n // Stop the message broker (closes chokidar file watchers)\n if (this.broker) {\n await this.broker.stop();\n }\n\n // Clean up feedback loop (clears pending timers and resolvers)\n if (this.feedbackLoop) {\n this.feedbackLoop.cleanup();\n }\n\n this.running = false;\n this.paused = false;\n logger.info('Orchestrator stopped');\n }\n\n /**\n * Pause the orchestrator: stop the polling cycle and all running agents.\n * Tasks and state are preserved so work can be resumed later.\n */\n async pause(): Promise<void> {\n if (!this.running || this.paused) return;\n\n this.paused = true;\n logger.info('Pausing orchestrator');\n this.emitActivity('info', 'Orchestrator pausing — stopping agents...');\n\n // Stop the polling cycle\n if (this.intervalId !== null) {\n clearInterval(this.intervalId);\n this.intervalId = null;\n }\n\n // Stop the PM scanner\n this.pmScanner.stop();\n\n // Stop all agents gracefully\n if (this.agentPool) {\n await this.agentPool.stopAll();\n }\n\n // Reset in-progress tasks back to pending so they can be re-assigned on resume\n if (this.taskManager) {\n const tasks: Task[] = await this.taskManager.load();\n for (const task of tasks) {\n if (task.status === 'in-progress') {\n await this.taskManager.updateTask(task.id, {\n status: 'pending',\n assignee: null,\n });\n }\n }\n // Notify TUI of updated tasks\n const refreshed = await this.taskManager.load();\n this.emit('tasks:loaded', refreshed);\n }\n\n this.emitActivity('info', 'Orchestrator paused');\n this.emit('orchestrator:paused');\n logger.info('Orchestrator paused');\n }\n\n /**\n * Resume the orchestrator after a pause. Restarts the polling cycle\n * and PM scanner so agents can be re-assigned to pending tasks.\n */\n async resume(): Promise<void> {\n if (!this.running || !this.paused) return;\n\n this.paused = false;\n logger.info('Resuming orchestrator');\n this.emitActivity('info', 'Orchestrator resuming...');\n\n // Clean stale inbox messages so fresh assignments are sent\n if (this.broker) {\n await this.broker.cleanAllInboxes();\n }\n\n // Restart the polling loop\n const settings = this.config.settings;\n this.intervalId = setInterval(() => {\n this.cycle().catch((err) => {\n logger.error({ err }, 'Orchestrator cycle failed');\n });\n }, settings.pollIntervalMs);\n\n // Run one cycle immediately\n await this.cycle();\n\n // Restart PM scanner\n this.pmScanner.start(() => {\n this.runPMScan().catch((err) => {\n logger.error({ err }, 'PM scan failed');\n });\n });\n\n this.emitActivity('info', 'Orchestrator resumed');\n this.emit('orchestrator:resumed');\n logger.info('Orchestrator resumed');\n }\n\n /**\n * Add new instructions: decompose them into tasks and append to the\n * existing todo.md without deleting any existing tasks.\n */\n async addInstructions(instructions: string): Promise<Task[]> {\n if (!this.planner || !this.taskManager) {\n throw new Error('Orchestrator must be started before adding instructions');\n }\n\n this.emitActivity('info', 'Decomposing new instructions into tasks...');\n this.emit('instructions:decomposing', instructions);\n\n const plannedTasks = await this.planner.decompose(instructions);\n\n // Load existing tasks to preserve them and resolve dependency IDs\n const existingTasks = await this.taskManager.load();\n const titleToId = new Map<string, string>();\n for (const t of existingTasks) {\n titleToId.set(t.title, t.id);\n }\n\n const createdTasks: Task[] = [];\n for (const planned of plannedTasks) {\n const resolvedDeps = planned.dependencies\n .map((depTitle) => titleToId.get(depTitle))\n .filter((id): id is string => id != null);\n\n const task = await this.taskManager.createTask({\n title: planned.title,\n description: planned.description,\n priority: planned.priority,\n dependencies: resolvedDeps,\n tags: planned.tags,\n });\n titleToId.set(planned.title, task.id);\n this.emit('task:created', task);\n\n // Register in pipeline\n this.pipeline.initTask(task);\n createdTasks.push(task);\n }\n\n // Notify TUI that tasks list has changed\n const allTasks = await this.taskManager.load();\n this.emit('tasks:loaded', allTasks);\n\n this.emitActivity('info', `Added ${createdTasks.length} new task(s) from instructions`);\n this.emit('instructions:added', createdTasks);\n\n logger.info({ count: createdTasks.length }, 'New tasks added from instructions');\n return createdTasks;\n }\n\n /**\n * A single orchestration cycle:\n * 1. Load current tasks\n * 2. Run scheduler to determine assignments\n * 3. For each assignment: update task, send message, spawn agent\n * 4. Handle pipeline handoffs for completed tasks\n * 5. Check budget limits\n * 6. Emit cycle stats\n */\n private async cycle(): Promise<void> {\n if (!this.taskManager || !this.scheduler || !this.broker || !this.agentPool) {\n return;\n }\n\n // Skip cycles while paused or waiting for plan approval\n if (this.paused || this.planApprovalPending) {\n return;\n }\n\n // 1. Load current tasks and agent states\n let tasks: Task[] = await this.taskManager.load();\n\n // 1b. Detect completed/errored agents and update their task statuses\n const poolAgents = this.agentPool.getAllAgents().map((a: any) => a.currentState);\n let tasksUpdated = false;\n\n for (const agentState of poolAgents) {\n if (agentState.status === 'stopped' || agentState.status === 'error') {\n // Clear current task label on the agent process\n const agentProcess = this.agentPool.getAgent(agentState.config.id);\n if (agentProcess) {\n agentProcess.setCurrentTask(null);\n }\n\n const assignedTask = tasks.find(\n (t: Task) => t.status === 'in-progress' && t.assignee === agentState.config.id\n );\n if (assignedTask) {\n if (agentState.status === 'stopped') {\n // Check pipeline for handoff\n const handoff = this.pipeline.completeStage(assignedTask.id);\n\n if (handoff && handoff.nextStage) {\n // Pipeline has a next stage — create a handoff task or re-queue\n this.emitActivity('pipeline-handoff', handoff.handoffMessage, {\n taskId: assignedTask.id,\n taskTitle: assignedTask.title,\n agentId: agentState.config.id,\n agentRole: agentState.config.role,\n pipelineStage: handoff.nextStage,\n });\n\n // Reset task to pending so the scheduler can re-assign to the right role\n await this.taskManager.updateTask(assignedTask.id, {\n status: 'pending',\n assignee: null,\n notes: [\n ...assignedTask.notes,\n `[pipeline] Handed off to ${handoff.nextStage} stage`,\n ],\n });\n\n // Send handoff message to broadcast channel\n const handoffMsg: Message = {\n id: generateId(),\n type: 'task-update',\n from: 'orchestrator',\n to: '*',\n subject: `Pipeline Handoff: ${assignedTask.title}`,\n body: `${handoff.handoffMessage}\\n\\nTask \"${assignedTask.title}\" (${assignedTask.id}) is now in the ${handoff.nextStage} stage. Required roles: ${handoff.requiredRoles.join(', ')}`,\n taskId: assignedTask.id,\n priority: assignedTask.priority === 'critical' ? 'urgent' : 'normal',\n timestamp: new Date().toISOString(),\n metadata: {\n pipelineStage: handoff.nextStage,\n previousAgent: agentState.config.id,\n },\n };\n await this.broker.sendMessage(handoffMsg);\n } else {\n // Pipeline complete or no pipeline — mark as done\n await this.taskManager.updateTask(assignedTask.id, { status: 'done' });\n this.emit('task:completed', assignedTask);\n this.emitActivity('task-completed', `Task completed: ${assignedTask.title}`, {\n taskId: assignedTask.id,\n taskTitle: assignedTask.title,\n agentId: agentState.config.id,\n agentRole: agentState.config.role,\n });\n }\n\n logger.info(\n { taskId: assignedTask.id, agentId: agentState.config.id },\n 'Task stage completed (agent process stopped)',\n );\n } else if (agentState.rateLimited) {\n // Agent hit an API rate limit (429) — alert and pause\n this.pipeline.failStage(assignedTask.id);\n await this.taskManager.updateTask(assignedTask.id, {\n status: 'pending',\n assignee: null,\n });\n\n const stats = this.getStats();\n const totalTokens = stats.totalInputTokens + stats.totalOutputTokens + stats.totalCacheReadTokens + stats.totalCacheCreationTokens;\n const resetInfo = agentState.rateLimitResetAt ? ` Resets at ${agentState.rateLimitResetAt}.` : '';\n this.emitActivity('rate-limit',\n `RATE LIMIT: Agent ${agentState.config.name} (${agentState.config.role}) hit API usage limit.${resetInfo} Total tokens used: ${this.formatTokenCount(totalTokens)} (in:${this.formatTokenCount(stats.totalInputTokens)} out:${this.formatTokenCount(stats.totalOutputTokens)} cache-r:${this.formatTokenCount(stats.totalCacheReadTokens)} cache-w:${this.formatTokenCount(stats.totalCacheCreationTokens)}) | $${stats.totalCostUsd.toFixed(4)}`, {\n taskId: assignedTask.id,\n taskTitle: assignedTask.title,\n agentId: agentState.config.id,\n agentRole: agentState.config.role,\n rateLimitResetAt: agentState.rateLimitResetAt,\n totalTokens,\n cost: stats.totalCostUsd,\n });\n this.emit('rate-limit', agentState.config.id, agentState.rateLimitResetAt);\n\n // Clean up the stale inbox message so a new one is sent on reassignment\n await this.broker.cleanInboxForTask(agentState.config.id, assignedTask.id);\n logger.warn(\n { taskId: assignedTask.id, agentId: agentState.config.id, resetAt: agentState.rateLimitResetAt },\n 'Agent hit rate limit — task reset to pending',\n );\n } else {\n // Agent errored — mark pipeline stage as failed and reset task\n this.pipeline.failStage(assignedTask.id);\n await this.taskManager.updateTask(assignedTask.id, {\n status: 'pending',\n assignee: null,\n });\n this.emitActivity('task-failed', `Task failed and reset: ${assignedTask.title} (agent ${agentState.config.id} errored)`, {\n taskId: assignedTask.id,\n taskTitle: assignedTask.title,\n agentId: agentState.config.id,\n });\n // Clean up the stale inbox message so a new one is sent on reassignment\n await this.broker.cleanInboxForTask(agentState.config.id, assignedTask.id);\n logger.warn(\n { taskId: assignedTask.id, agentId: agentState.config.id },\n 'Task reset to pending (agent process errored)',\n );\n }\n tasksUpdated = true;\n }\n }\n }\n\n // 1b2. Detect orphaned in-progress tasks — the assignee is not actively\n // running in the pool (not spawned, or already idle/stopped/errored).\n // This catches tasks that got stuck from a previous session, a missed\n // state transition, or an agent that exited without the task being updated.\n const activeAgentIds = new Set(\n poolAgents\n .filter((a: any) => a.status === 'running' || a.status === 'starting')\n .map((a: any) => a.config.id),\n );\n\n for (const task of tasks) {\n if (task.status !== 'in-progress') continue;\n if (!task.assignee) {\n // In-progress with no assignee — reset\n await this.taskManager.updateTask(task.id, { status: 'pending', assignee: null });\n this.emitActivity('info', `Reset orphaned task \"${task.title}\" (no assignee)`, { taskId: task.id });\n tasksUpdated = true;\n continue;\n }\n // If the assignee isn't actively running, the task is orphaned\n if (!activeAgentIds.has(task.assignee)) {\n const inPool = poolAgents.find((a: any) => a.config.id === task.assignee);\n // Reset if the agent is not in pool, idle, stopped, or errored.\n // All of these mean the agent is no longer working on the task.\n if (!inPool || inPool.status === 'idle' || inPool.status === 'stopped' || inPool.status === 'error') {\n await this.taskManager.updateTask(task.id, { status: 'pending', assignee: null });\n this.emitActivity('info', `Reset orphaned task \"${task.title}\" (agent ${task.assignee} ${inPool ? inPool.status : 'not in pool'})`, {\n taskId: task.id,\n agentId: task.assignee,\n });\n logger.info({ taskId: task.id, assignee: task.assignee, agentStatus: inPool?.status }, 'Reset orphaned in-progress task');\n tasksUpdated = true;\n }\n }\n }\n\n // 1b3. Detect blocked tasks whose dependencies are all resolved.\n // If a task is blocked but all its dependencies are done/cancelled,\n // unblock it so it can be scheduled.\n for (const task of tasks) {\n if (task.status !== 'blocked') continue;\n if (task.dependencies.length === 0) {\n // Blocked with no dependencies — shouldn't happen, reset to pending\n await this.taskManager.updateTask(task.id, { status: 'pending' });\n this.emitActivity('info', `Unblocked task \"${task.title}\" (no dependencies)`, { taskId: task.id });\n tasksUpdated = true;\n continue;\n }\n const allDepsResolved = task.dependencies.every((depId) => {\n const dep = tasks.find((t: Task) => t.id === depId);\n return !dep || dep.status === 'done' || dep.status === 'cancelled';\n });\n if (allDepsResolved) {\n await this.taskManager.updateTask(task.id, { status: 'pending' });\n this.emitActivity('info', `Unblocked task \"${task.title}\" (all dependencies resolved)`, { taskId: task.id });\n tasksUpdated = true;\n }\n }\n\n // 1c. Reload tasks if any statuses changed\n if (tasksUpdated) {\n tasks = await this.taskManager.load();\n }\n this.cachedTasks = tasks;\n\n // Check progress and emit reports/milestones\n if (this.feedbackLoop) {\n this.feedbackLoop.checkProgress(tasks, this.getStats());\n }\n\n // 1d. Check if all tasks are completed\n if (tasks.length > 0) {\n const allDone = tasks.every((t: Task) => t.status === 'done' || t.status === 'cancelled');\n if (allDone) {\n const summary = this.buildCompletionSummary(tasks);\n this.emit('project:completed', summary);\n this.emitActivity('project-completed', `All ${summary.totalTasks} tasks completed! Total cost: $${summary.totalCostUsd.toFixed(4)}`);\n logger.info({ totalTasks: summary.totalTasks, totalCost: summary.totalCostUsd }, 'All tasks completed');\n await this.stop();\n return;\n }\n }\n\n // 1e. Architecture phase gating\n if (this.phase === 'architecture') {\n if (this.architectureApprovalPending) {\n return; // Waiting for user to approve architecture\n }\n\n const archTasks = tasks.filter((t: Task) => t.tags.includes('architecture'));\n const allArchDone = archTasks.length > 0 && archTasks.every((t: Task) => t.status === 'done');\n\n if (allArchDone) {\n // Architecture phase complete — check interaction mode\n const mode = this.feedbackLoop?.interactionMode ?? 'unattended';\n if (mode === 'supervised' || mode === 'interactive') {\n this.architectureApprovalPending = true;\n this.emit('architecture:ready', archTasks);\n this.emitActivity('phase-changed', 'Architecture phase complete, waiting for user review', {\n fromPhase: 'architecture',\n });\n logger.info('Architecture phase complete, waiting for user review');\n return;\n } else {\n this.phase = 'development';\n this.emit('phase:changed', 'development');\n this.emitActivity('phase-changed', 'Architecture complete, advancing to development', {\n fromPhase: 'architecture',\n toPhase: 'development',\n });\n logger.info('Architecture phase complete, advancing to development');\n }\n }\n }\n\n // Build virtual agent states: agents in the pool plus unspawned configs.\n // The scheduler needs to see available agents to make assignments, but\n // the pool starts empty — agents only enter when spawned. So we present\n // unspawned configs as 'idle' and stopped agents as 'idle' (available for new tasks).\n const poolAgentIds = new Set(poolAgents.map((a: any) => a.config.id));\n\n const virtualAgentStates: any[] = poolAgents.map((a: any) => {\n // Treat stopped/error agents as idle so the scheduler can reassign them\n if (a.status === 'stopped' || a.status === 'error') {\n return { ...a, status: 'idle' };\n }\n return a;\n });\n\n // Add unspawned agent configs as idle virtual agents\n for (const config of this.agentConfigs) {\n if (!poolAgentIds.has(config.id)) {\n virtualAgentStates.push({\n config,\n status: 'idle',\n pid: null,\n sessionId: null,\n currentTask: null,\n startedAt: null,\n lastActivityAt: null,\n totalCostUsd: 0,\n turnCount: 0,\n totalInputTokens: 0,\n totalOutputTokens: 0,\n totalCacheReadTokens: 0,\n totalCacheCreationTokens: 0,\n error: null,\n resultError: null,\n rateLimited: false,\n rateLimitResetAt: null,\n });\n }\n }\n\n // 2. Run scheduler (filter inputs during architecture phase)\n let schedulerTasks = tasks;\n let schedulerAgents = virtualAgentStates;\n if (this.phase === 'architecture') {\n schedulerTasks = tasks.filter((t: Task) => t.tags.includes('architecture'));\n schedulerAgents = virtualAgentStates.filter((a: any) => a.config.role === 'architect');\n }\n const assignments: TaskAssignment[] = this.scheduler.schedule(schedulerTasks, schedulerAgents);\n\n // 3. Process each assignment\n for (const assignment of assignments) {\n const task = tasks.find((t) => t.id === assignment.taskId);\n if (!task) continue;\n\n // Ensure task is registered in pipeline\n if (!this.pipeline.has(task.id)) {\n this.pipeline.initTask(task);\n }\n\n // Record pipeline stage start\n this.pipeline.startStage(task.id, assignment.agentId);\n const pipelineState = this.pipeline.getState(task.id);\n const currentStage = pipelineState?.currentStage ?? 'develop';\n\n // Update task status and assignee\n await this.taskManager.updateTask(assignment.taskId, {\n status: 'in-progress',\n assignee: assignment.agentId,\n });\n\n this.emit('task:assigned', task, assignment.agentId);\n\n // Find the agent config to get the role name\n const agentConfig = this.agentConfigs.find((c: any) => c.id === assignment.agentId);\n const agentRole = agentConfig?.role ?? 'unknown';\n\n this.emitActivity('task-delegated', `Delegated \"${task.title}\" to ${agentConfig?.name ?? assignment.agentId} (${agentRole}) [stage: ${currentStage}]`, {\n taskId: task.id,\n taskTitle: task.title,\n agentId: assignment.agentId,\n agentRole,\n pipelineStage: currentStage,\n });\n\n // Send task-assignment message to the agent, including pipeline context\n const pipelineContext = pipelineState\n ? `\\n\\n**Pipeline Stage:** ${currentStage}\\n**Pipeline History:** ${pipelineState.stageHistory.map((h) => `${h.stage}(${h.status})`).join(' -> ') || 'none'}`\n : '';\n\n const message: Message = {\n id: generateId(),\n type: 'task-assignment',\n from: 'orchestrator',\n to: assignment.agentId,\n subject: `Task Assignment: ${task.title}`,\n body: this.buildTaskPrompt(task) + pipelineContext,\n taskId: task.id,\n priority: task.priority === 'critical' ? 'urgent' : 'normal',\n timestamp: new Date().toISOString(),\n metadata: {\n pipelineStage: currentStage,\n },\n };\n\n await this.broker.sendMessage(message);\n\n // Spawn or resume the agent with the task\n const taskLabel = `${task.id}: ${task.title}`;\n try {\n const existingAgent = this.agentPool.getAgent(assignment.agentId);\n if (existingAgent) {\n existingAgent.setCurrentTask(taskLabel);\n const agentStatus = existingAgent.currentState.status;\n if (agentStatus === 'stopped' || agentStatus === 'error') {\n // Agent finished previous task — resume session or re-spawn\n if (existingAgent.currentState.sessionId && agentStatus === 'stopped') {\n await existingAgent.resume(message.body);\n } else {\n // No session to resume — remove and spawn fresh\n this.agentPool.removeAgent(assignment.agentId);\n if (agentConfig) {\n const newAgent = await this.agentPool.spawnAgent(agentConfig, message.body);\n newAgent.setCurrentTask(taskLabel);\n }\n }\n }\n // If running/starting, skip — agent is already busy\n } else {\n // Agent not in pool yet — spawn it\n if (agentConfig) {\n const newAgent = await this.agentPool.spawnAgent(agentConfig, message.body);\n newAgent.setCurrentTask(taskLabel);\n }\n }\n } catch (err) {\n logger.error(\n { err, agentId: assignment.agentId, taskId: assignment.taskId },\n 'Failed to spawn agent for task',\n );\n this.emitActivity('agent-error', `Failed to spawn agent ${assignment.agentId} for task ${task.title}`, {\n agentId: assignment.agentId,\n taskId: task.id,\n taskTitle: task.title,\n });\n }\n }\n\n // 4. Check budget limits\n this.checkBudget();\n\n // 5. Emit cycle stats\n const stats = this.getStats();\n this.emit('orchestrator:cycle', stats);\n\n // 6. Emit cycle summary activity for visibility\n const pendingCount = tasks.filter((t: Task) => t.status === 'pending').length;\n const inProgressCount = tasks.filter((t: Task) => t.status === 'in-progress').length;\n const doneCount = tasks.filter((t: Task) => t.status === 'done').length;\n const activeCount = stats.activeAgents;\n\n if (tasks.length > 0) {\n const totalTokens = stats.totalInputTokens + stats.totalOutputTokens + stats.totalCacheReadTokens + stats.totalCacheCreationTokens;\n const tokenStr = totalTokens > 0 ? ` | ${this.formatTokenCount(totalTokens)} tokens (in:${this.formatTokenCount(stats.totalInputTokens)} out:${this.formatTokenCount(stats.totalOutputTokens)} cache-r:${this.formatTokenCount(stats.totalCacheReadTokens)} cache-w:${this.formatTokenCount(stats.totalCacheCreationTokens)})` : '';\n this.emitActivity('cycle-summary',\n `Cycle: ${doneCount}/${tasks.length} done | ${inProgressCount} in-progress | ${pendingCount} pending | ${activeCount} agent(s) active | $${stats.totalCostUsd.toFixed(4)}${tokenStr}`,\n );\n }\n }\n\n /**\n * Run a single PM scan pass — assess project health, identify gaps and\n * blockers, and surface findings in the orchestrator activity log.\n */\n private async runPMScan(): Promise<void> {\n if (!this.running || !this.taskManager || !this.agentPool) return;\n\n const tasks: Task[] = await this.taskManager.load();\n if (tasks.length === 0) return;\n\n // Build current agent states (same logic as cycle())\n const poolAgents = this.agentPool.getAllAgents().map((a: any) => a.currentState);\n const poolAgentIds = new Set(poolAgents.map((a: any) => a.config.id));\n\n const allAgentStates: any[] = [...poolAgents];\n for (const config of this.agentConfigs) {\n if (!poolAgentIds.has(config.id)) {\n allAgentStates.push({\n config,\n status: 'idle',\n pid: null,\n sessionId: null,\n currentTask: null,\n startedAt: null,\n lastActivityAt: null,\n totalCostUsd: 0,\n turnCount: 0,\n totalInputTokens: 0,\n totalOutputTokens: 0,\n totalCacheReadTokens: 0,\n totalCacheCreationTokens: 0,\n error: null,\n resultError: null,\n rateLimited: false,\n rateLimitResetAt: null,\n });\n }\n }\n\n const result = this.pmScanner.scan(tasks, allAgentStates, this.phase);\n\n // Emit findings to the orchestrator activity log\n for (const finding of result.findings) {\n if (finding.kind === 'all-clear') {\n // Don't spam the log with \"all clear\" every scan\n continue;\n }\n\n const activityKind = finding.severity === 'critical' ? 'gap-detected' as const : 'info' as const;\n this.emitActivity(activityKind, `[PM] ${finding.message}`, {\n taskId: finding.taskId,\n agentId: finding.agentId,\n });\n }\n\n // Emit the summary line\n this.emitActivity('pm-scan', result.summary);\n\n // Send any actionable messages (e.g., nudge stale agents, escalate bottlenecks)\n if (this.broker) {\n const messages = this.pmScanner.buildMessages(result);\n for (const msg of messages) {\n try {\n await this.broker.sendMessage(msg);\n } catch (err) {\n logger.error({ err, msgId: msg.id }, 'Failed to send PM scan message');\n }\n }\n }\n\n logger.debug({ findingCount: result.findings.length }, 'PM scan complete');\n }\n\n /**\n * Build a task prompt for an agent.\n */\n private buildTaskPrompt(task: Task): string {\n const parts = [\n `# Task: ${task.title}`,\n `**ID:** ${task.id}`,\n `**Priority:** ${task.priority}`,\n '',\n task.description,\n ];\n\n if (task.tags.length > 0) {\n parts.push('', `**Tags:** ${task.tags.join(', ')}`);\n }\n\n if (task.notes.length > 0) {\n parts.push('', '**Notes:**');\n for (const note of task.notes) {\n parts.push(`- ${note}`);\n }\n }\n\n return parts.join('\\n');\n }\n\n /**\n * Check whether the total cost across all agents exceeds the budget.\n */\n private checkBudget(): void {\n const maxBudget = this.config.settings.maxTotalBudgetUsd;\n if (maxBudget == null) return;\n\n const agentStates = this.agentPool.getAllAgents().map((a: any) => a.currentState);\n const totalCost = agentStates.reduce(\n (sum: number, a: { totalCostUsd: number }) => sum + a.totalCostUsd,\n 0,\n );\n\n const warningThreshold = maxBudget * 0.8;\n\n if (totalCost >= maxBudget) {\n this.emit('budget:exceeded', totalCost, maxBudget);\n this.emitActivity('budget-warning', `Budget exceeded: $${totalCost.toFixed(4)} / $${maxBudget.toFixed(2)}`, {\n cost: totalCost,\n });\n logger.warn({ totalCost, maxBudget }, 'Budget exceeded, stopping orchestrator');\n this.stop().catch((err) => {\n logger.error({ err }, 'Failed to stop orchestrator after budget exceeded');\n });\n } else if (totalCost >= warningThreshold) {\n this.emit('budget:warning', totalCost, maxBudget);\n this.emitActivity('budget-warning', `Approaching budget limit: $${totalCost.toFixed(4)} / $${maxBudget.toFixed(2)} (${((totalCost / maxBudget) * 100).toFixed(0)}%)`, {\n cost: totalCost,\n });\n logger.warn({ totalCost, maxBudget }, 'Approaching budget limit');\n }\n }\n\n /**\n * Get all current tasks.\n */\n async getTasks(): Promise<Task[]> {\n if (!this.taskManager) return [];\n return this.taskManager.load();\n }\n\n /**\n * Get all agent states.\n */\n getAgentStates(): any[] {\n if (!this.agentPool) return [];\n return this.agentPool.getAllAgents().map((a: any) => a.currentState);\n }\n\n /**\n * Get the pipeline state for a specific task.\n */\n getTaskPipelineState(taskId: string) {\n return this.pipeline.getState(taskId);\n }\n\n /**\n * Get current orchestrator statistics.\n */\n getStats(): OrchestratorStats {\n const tasks = this.cachedTasks;\n const agentStates = this.agentPool ? this.agentPool.getAllAgents().map((a: any) => a.currentState) : [];\n const spawnedIds = new Set(agentStates.map((a: any) => a.config.id));\n\n const completedTasks = tasks.filter((t: Task) => t.status === 'done').length;\n const activeAgents = agentStates.filter(\n (a: { status: string }) => a.status === 'running' || a.status === 'starting',\n ).length;\n const totalCostUsd = agentStates.reduce(\n (sum: number, a: { totalCostUsd: number }) => sum + a.totalCostUsd,\n 0,\n );\n const totalInputTokens = agentStates.reduce(\n (sum: number, a: { totalInputTokens: number }) => sum + a.totalInputTokens,\n 0,\n );\n const totalOutputTokens = agentStates.reduce(\n (sum: number, a: { totalOutputTokens: number }) => sum + a.totalOutputTokens,\n 0,\n );\n const totalCacheReadTokens = agentStates.reduce(\n (sum: number, a: { totalCacheReadTokens: number }) => sum + a.totalCacheReadTokens,\n 0,\n );\n const totalCacheCreationTokens = agentStates.reduce(\n (sum: number, a: { totalCacheCreationTokens: number }) => sum + a.totalCacheCreationTokens,\n 0,\n );\n const uptimeMs = this.startedAt ? Date.now() - this.startedAt : 0;\n\n // Build full agent roster: spawned agents + unspawned configs\n const agents: OrchestratorStats['agents'] = agentStates.map((a: any) => ({\n id: a.config.id,\n name: a.config.name,\n role: a.config.role,\n status: a.status,\n spawned: true,\n currentTask: a.currentTask,\n }));\n for (const config of this.agentConfigs) {\n if (!spawnedIds.has(config.id)) {\n agents.push({\n id: config.id,\n name: config.name,\n role: config.role,\n status: 'idle',\n spawned: false,\n currentTask: null,\n });\n }\n }\n\n return {\n totalTasks: tasks.length,\n completedTasks,\n activeAgents,\n totalCostUsd,\n totalInputTokens,\n totalOutputTokens,\n totalCacheReadTokens,\n totalCacheCreationTokens,\n uptimeMs,\n agents,\n };\n }\n\n /**\n * Format a token count for display (e.g. 1234567 → \"1.23M\", 45678 → \"45.7k\").\n */\n private formatTokenCount(tokens: number): string {\n if (tokens >= 1_000_000) {\n return `${(tokens / 1_000_000).toFixed(2)}M`;\n }\n if (tokens >= 1_000) {\n return `${(tokens / 1_000).toFixed(1)}k`;\n }\n return String(tokens);\n }\n\n /**\n * Build a summary of the completed project for reporting.\n */\n private buildCompletionSummary(tasks: Task[]): ProjectCompletionSummary {\n const agentStates = this.agentPool\n ? this.agentPool.getAllAgents().map((a: any) => a.currentState)\n : [];\n\n const agentTaskCounts = new Map<string, number>();\n for (const task of tasks) {\n if (task.assignee && task.status === 'done') {\n agentTaskCounts.set(task.assignee, (agentTaskCounts.get(task.assignee) ?? 0) + 1);\n }\n }\n\n const agentSummaries = agentStates.map((a: any) => ({\n agentId: a.config.id,\n name: a.config.name,\n role: a.config.role,\n tasksCompleted: agentTaskCounts.get(a.config.id) ?? 0,\n costUsd: a.totalCostUsd,\n inputTokens: a.totalInputTokens ?? 0,\n outputTokens: a.totalOutputTokens ?? 0,\n }));\n\n const doneTasks = tasks.filter((t: Task) => t.status === 'done').length;\n const cancelledTasks = tasks.filter((t: Task) => t.status === 'cancelled').length;\n\n return {\n totalTasks: tasks.length,\n doneTasks,\n cancelledTasks,\n totalCostUsd: agentStates.reduce((sum: number, a: any) => sum + a.totalCostUsd, 0),\n totalInputTokens: agentStates.reduce((sum: number, a: any) => sum + (a.totalInputTokens ?? 0), 0),\n totalOutputTokens: agentStates.reduce((sum: number, a: any) => sum + (a.totalOutputTokens ?? 0), 0),\n totalCacheReadTokens: agentStates.reduce((sum: number, a: any) => sum + (a.totalCacheReadTokens ?? 0), 0),\n totalCacheCreationTokens: agentStates.reduce((sum: number, a: any) => sum + (a.totalCacheCreationTokens ?? 0), 0),\n uptimeMs: this.startedAt ? Date.now() - this.startedAt : 0,\n agentSummaries,\n completedAt: new Date().toISOString(),\n };\n }\n\n /**\n * Approve the architecture and advance to development phase.\n */\n approveArchitecture(): void {\n if (this.architectureApprovalPending) {\n this.architectureApprovalPending = false;\n this.phase = 'development';\n this.emit('phase:changed', 'development');\n this.emitActivity('phase-changed', 'Architecture approved, advancing to development phase', {\n fromPhase: 'architecture',\n toPhase: 'development',\n });\n logger.info('Architecture approved, advancing to development phase');\n }\n }\n\n /**\n * Get the current orchestration phase.\n */\n getPhase(): string {\n return this.phase;\n }\n\n decidePlan(proposalId: string, decision: 'approved' | 'rejected', modifications?: string): void {\n this.feedbackLoop?.decidePlan(proposalId, decision, modifications);\n }\n\n answerQuestion(questionId: string, answer: string): void {\n this.feedbackLoop?.answerQuestion(questionId, answer);\n }\n\n acknowledgeMilestone(milestoneId: string): void {\n this.feedbackLoop?.acknowledgeMilestone(milestoneId);\n }\n\n setInteractionMode(mode: InteractionMode): void {\n this.feedbackLoop?.setMode(mode);\n }\n\n getInteractionMode(): InteractionMode {\n return this.feedbackLoop?.interactionMode ?? 'supervised';\n }\n\n getPendingPlan(): PlanProposal | null {\n return this.feedbackLoop?.getPendingPlan() ?? null;\n }\n\n getPendingQuestions(): UserQuestion[] {\n return this.feedbackLoop?.getPendingQuestions() ?? [];\n }\n\n /**\n * Get processed messages for a specific task (for task detail view).\n */\n async getTaskMessages(taskId: string): Promise<import('../types/message.js').MessageEnvelope[]> {\n if (!this.broker) return [];\n return this.broker.getProcessedMessagesForTask(taskId);\n }\n}\n","import { EventEmitter } from 'eventemitter3';\nimport type { FeedbackSettings, InteractionMode, PlanProposal, PlannedTaskSummary, UserQuestion, MilestoneEvent, ProgressReport } from '../types/feedback.js';\nimport type { Task } from '../types/task.js';\nimport type { OrchestratorStats } from '../types/events.js';\nimport { ProgressTracker } from './progress-tracker.js';\nimport { generateId } from '../utils/id.js';\nimport { createLogger } from '../utils/logger.js';\n\nconst logger = createLogger('feedback-loop');\n\nconst DEFAULT_SETTINGS: FeedbackSettings = {\n interactionMode: 'supervised',\n progressReportIntervalMs: 60000,\n milestonePercentages: [25, 50, 75, 100],\n questionTimeoutMs: 300000,\n requirePlanApproval: true,\n};\n\nexport class FeedbackLoop extends EventEmitter {\n private mode: InteractionMode;\n private settings: FeedbackSettings;\n private pendingPlan: PlanProposal | null = null;\n private planResolver: ((decision: 'approved' | 'rejected') => void) | null = null;\n private pendingQuestions: Map<string, { question: UserQuestion; resolve: (answer: string | null) => void; timer: ReturnType<typeof setTimeout> | null }> = new Map();\n private lastProgressReport: number = 0;\n private progressTracker: ProgressTracker;\n private reachedMilestones: Set<number> = new Set();\n private pendingMilestone: { milestone: MilestoneEvent; resolve: () => void } | null = null;\n\n constructor(settings?: Partial<FeedbackSettings>) {\n super();\n this.settings = { ...DEFAULT_SETTINGS, ...settings };\n this.mode = this.settings.interactionMode;\n this.progressTracker = new ProgressTracker();\n }\n\n get interactionMode(): InteractionMode { return this.mode; }\n\n setMode(mode: InteractionMode): void {\n this.mode = mode;\n this.emit('interaction-mode:changed', mode);\n }\n\n /**\n * Propose a plan for approval.\n * In unattended mode: auto-approves immediately.\n * In supervised/interactive: emits plan:proposed and waits for decidePlan() call.\n */\n async proposePlan(tasks: PlannedTaskSummary[], projectGoal: string): Promise<'approved' | 'rejected'> {\n if (this.mode === 'unattended' && !this.settings.requirePlanApproval) {\n return 'approved';\n }\n // Even in unattended mode, if requirePlanApproval is true, we need approval\n // But in pure unattended, auto-approve\n if (this.mode === 'unattended') {\n return 'approved';\n }\n\n const proposal: PlanProposal = {\n id: generateId(),\n tasks,\n totalEstimatedTasks: tasks.length,\n projectGoal,\n createdAt: new Date().toISOString(),\n status: 'pending',\n };\n\n this.pendingPlan = proposal;\n\n return new Promise((resolve) => {\n this.planResolver = resolve;\n // Emit AFTER setting the resolver so synchronous handlers\n // that call decidePlan() can resolve the promise immediately\n this.emit('plan:proposed', proposal);\n });\n }\n\n decidePlan(proposalId: string, decision: 'approved' | 'rejected', modifications?: string): void {\n if (!this.pendingPlan || this.pendingPlan.id !== proposalId) {\n logger.warn({ proposalId }, 'No pending plan with this ID');\n return;\n }\n this.pendingPlan.status = decision === 'approved' ? 'approved' : 'rejected';\n this.emit('plan:decided', proposalId, decision, modifications);\n if (this.planResolver) {\n this.planResolver(decision);\n this.planResolver = null;\n }\n this.pendingPlan = null;\n }\n\n /**\n * Route a question from an agent to the user.\n * In unattended mode: returns null immediately (agent should handle itself).\n * In interactive: emits question:asked and waits for answerQuestion() call with timeout.\n * In supervised: same as interactive but question is lower priority.\n */\n async routeQuestion(fromAgent: string, question: string, opts?: { taskId?: string; context?: string; options?: string[] }): Promise<string | null> {\n if (this.mode === 'unattended') {\n return null;\n }\n\n const userQuestion: UserQuestion = {\n id: generateId(),\n fromAgent,\n taskId: opts?.taskId,\n question,\n context: opts?.context,\n options: opts?.options,\n createdAt: new Date().toISOString(),\n status: 'pending',\n };\n\n this.emit('question:asked', userQuestion);\n\n return new Promise((resolve) => {\n const timer = setTimeout(() => {\n userQuestion.status = 'timed-out';\n this.pendingQuestions.delete(userQuestion.id);\n resolve(null);\n }, this.settings.questionTimeoutMs);\n\n this.pendingQuestions.set(userQuestion.id, { question: userQuestion, resolve, timer });\n });\n }\n\n answerQuestion(questionId: string, answer: string): void {\n const entry = this.pendingQuestions.get(questionId);\n if (!entry) {\n logger.warn({ questionId }, 'No pending question with this ID');\n return;\n }\n entry.question.status = 'answered';\n entry.question.answer = answer;\n if (entry.timer) clearTimeout(entry.timer);\n this.pendingQuestions.delete(questionId);\n this.emit('question:answered', questionId, answer);\n entry.resolve(answer);\n }\n\n /**\n * Called each orchestrator cycle to check progress and emit reports/milestones.\n */\n checkProgress(tasks: Task[], stats: OrchestratorStats): void {\n const now = Date.now();\n\n // Periodic progress reports\n if (now - this.lastProgressReport >= this.settings.progressReportIntervalMs) {\n const report = this.progressTracker.generateReport(tasks, stats);\n this.emit('progress:report', report);\n this.lastProgressReport = now;\n }\n\n // Milestone detection\n const percent = this.progressTracker.getCompletionPercentage(tasks);\n for (const threshold of this.settings.milestonePercentages) {\n if (percent >= threshold && !this.reachedMilestones.has(threshold)) {\n this.reachedMilestones.add(threshold);\n const milestone: MilestoneEvent = {\n id: generateId(),\n name: `${threshold}% Complete`,\n percentComplete: threshold,\n message: `Project has reached ${threshold}% completion (${stats.completedTasks}/${stats.totalTasks} tasks done)`,\n requiresAck: this.mode === 'supervised' || this.mode === 'interactive',\n createdAt: new Date().toISOString(),\n };\n this.emit('milestone:reached', milestone);\n }\n }\n }\n\n acknowledgeMilestone(milestoneId: string): void {\n this.emit('milestone:acknowledged', milestoneId);\n }\n\n /**\n * Clean up all pending timers and resolvers.\n * Call this during shutdown to prevent leaked timers from blocking process exit.\n */\n cleanup(): void {\n // Clear pending question timers\n for (const [id, entry] of this.pendingQuestions) {\n if (entry.timer) clearTimeout(entry.timer);\n entry.resolve(null);\n }\n this.pendingQuestions.clear();\n\n // Resolve any pending plan\n if (this.planResolver) {\n this.planResolver('rejected');\n this.planResolver = null;\n }\n this.pendingPlan = null;\n\n this.removeAllListeners();\n logger.debug('FeedbackLoop cleaned up');\n }\n\n getPendingPlan(): PlanProposal | null { return this.pendingPlan; }\n getPendingQuestions(): UserQuestion[] { return Array.from(this.pendingQuestions.values()).map(e => e.question); }\n}\n","import type { Task } from '../types/task.js';\nimport type { ProgressReport } from '../types/feedback.js';\nimport type { OrchestratorStats } from '../types/events.js';\nimport { generateId } from '../utils/id.js';\n\nconst PHASE_ORDER = ['planning', 'architecture', 'design', 'implementation', 'testing', 'documentation'];\n\nexport class ProgressTracker {\n generateReport(tasks: Task[], stats: OrchestratorStats): ProgressReport {\n const completedTasks = tasks.filter((t) => t.status === 'done');\n const pendingTasks = tasks.filter((t) => t.status === 'pending');\n const blockedTasks = tasks.filter((t) => t.status === 'blocked');\n\n return {\n id: generateId(),\n phase: this.detectPhase(tasks),\n completedTasks: completedTasks.length,\n totalTasks: tasks.length,\n percentComplete: this.getCompletionPercentage(tasks),\n recentCompletions: completedTasks.map((t) => t.title),\n upcomingWork: pendingTasks.map((t) => t.title),\n blockers: blockedTasks.map((t) => t.title),\n totalCostUsd: stats.totalCostUsd,\n createdAt: new Date().toISOString(),\n };\n }\n\n getCompletionPercentage(tasks: Task[]): number {\n if (tasks.length === 0) return 0;\n const doneCount = tasks.filter((t) => t.status === 'done').length;\n return Math.round((doneCount / tasks.length) * 100);\n }\n\n detectPhase(tasks: Task[]): string {\n const inProgressTasks = tasks.filter((t) => t.status === 'in-progress');\n\n if (inProgressTasks.length === 0) {\n return 'implementation';\n }\n\n // Count tag occurrences among in-progress tasks\n const tagCounts = new Map<string, number>();\n for (const task of inProgressTasks) {\n for (const tag of task.tags) {\n const normalizedTag = tag.toLowerCase();\n if (PHASE_ORDER.includes(normalizedTag)) {\n tagCounts.set(normalizedTag, (tagCounts.get(normalizedTag) ?? 0) + 1);\n }\n }\n }\n\n if (tagCounts.size === 0) {\n return 'implementation';\n }\n\n // Find the most common phase tag\n let maxCount = 0;\n let mostCommonPhase = 'implementation';\n for (const [tag, count] of tagCounts) {\n if (count > maxCount) {\n maxCount = count;\n mostCommonPhase = tag;\n }\n }\n\n return mostCommonPhase;\n }\n}\n","import { execa } from 'execa';\nimport { readdirSync, statSync } from 'node:fs';\nimport { join, relative } from 'node:path';\nimport type { TaskPriority } from '../types/task.js';\nimport type { TechStackConfig } from '../types/project.js';\nimport { createLogger } from '../utils/logger.js';\n\nconst logger = createLogger('planner');\n\nexport interface PlannedTask {\n title: string;\n priority: TaskPriority;\n description: string;\n dependencies: string[];\n tags: string[];\n}\n\nconst IGNORE_DIRS = new Set([\n '.git', 'node_modules', '.maestro', 'dist', 'build', 'out',\n '.next', '.nuxt', '.output', '.cache', '.turbo', 'coverage',\n '__pycache__', '.venv', 'venv', '.tox', 'target',\n]);\n\nconst IGNORE_FILES = new Set([\n '.DS_Store', 'Thumbs.db', '.env', '.env.local',\n]);\n\nconst DECOMPOSE_PROMPT = `You are a project planning assistant. Break down the following project goal into a set of discrete, actionable tasks.\n\nReturn ONLY a JSON array (no markdown, no explanation) where each element has:\n- \"title\": short task title\n- \"priority\": one of \"critical\", \"high\", \"medium\", \"low\"\n- \"description\": detailed description of what needs to be done\n- \"dependencies\": array of titles of tasks this depends on (empty array if none)\n- \"tags\": array of relevant tags from: \"architecture\", \"design-system\", \"ui\", \"ux\", \"design\", \"planning\", \"priority\", \"frontend\", \"backend\", \"testing\", \"qa\", \"e2e\", \"documentation\", \"docs\", \"api-docs\", \"devops\", \"ci-cd\", \"deployment\", \"docker\", \"infrastructure\", \"security\", \"review\", \"code-review\"\n\nOrder tasks so that dependencies come before the tasks that depend on them.\n\nIMPORTANT — You MUST include tasks for ALL of the following categories. A complete project requires work from every team role:\n\n1. **Architecture** (tag: \"architecture\"): At least one task for creating ARCHITECTURE.md with system design, component structure, data models, and key technical decisions. This should have no dependencies and be listed as a dependency for implementation tasks.\n\n2. **Design** (tags: \"design\", \"ui\", \"ux\", \"design-system\"): Tasks for UI/UX design, component design, design system setup, styling, and visual layouts.\n\n3. **Frontend/Backend development** (tags: \"frontend\", \"backend\"): Core implementation tasks for building features.\n\n4. **Testing & QA** (tags: \"testing\", \"qa\", \"e2e\"): Tasks for writing unit tests, integration tests, and end-to-end tests. These should depend on the implementation tasks they test. Include at least one task for setting up the test framework and one for writing tests for each major feature.\n\n5. **Documentation** (tags: \"documentation\", \"docs\", \"api-docs\"): Tasks for writing README, API documentation, user guides, and inline documentation. These should depend on the features being documented.\n\n6. **DevOps & CI/CD** (tags: \"devops\", \"ci-cd\", \"deployment\", \"docker\", \"infrastructure\"): Tasks for setting up CI/CD pipelines, Docker configuration, deployment scripts, and infrastructure. Include at least one devops task.\n\n7. **Code Review** (tags: \"code-review\", \"review\", \"security\"): Tasks for reviewing code quality, security audit, and ensuring best practices. These should depend on implementation tasks and run toward the end.\n\nEach category must have at least one task. This ensures all team members (architect, designer, developers, QA engineer, technical writer, DevOps engineer, code reviewer) have meaningful work assigned to them.\n`;\n\nexport class Planner {\n private model: string;\n private workingDirectory: string;\n private claudeCommand: string;\n private claudeEnv?: Record<string, string>;\n private techStack?: TechStackConfig;\n\n constructor(opts: { model?: string; workingDirectory: string; claudeCommand?: string; claudeEnv?: Record<string, string>; techStack?: TechStackConfig }) {\n this.model = opts.model ?? 'sonnet';\n this.workingDirectory = opts.workingDirectory;\n this.claudeCommand = opts.claudeCommand ?? 'claude';\n this.claudeEnv = opts.claudeEnv;\n this.techStack = opts.techStack;\n }\n\n /**\n * Use Claude CLI to decompose a goal into a list of planned tasks.\n */\n async decompose(goal: string): Promise<PlannedTask[]> {\n const tree = this.scanDirectory(this.workingDirectory, 4);\n const hasFiles = tree.length > 0;\n\n let prompt = DECOMPOSE_PROMPT;\n if (hasFiles) {\n prompt += `\\nProject working directory: ${this.workingDirectory}\\n`;\n prompt += `\\nExisting project structure:\\n\\`\\`\\`\\n${tree.join('\\n')}\\n\\`\\`\\`\\n`;\n prompt += `\\nConsider the existing files and structure when planning tasks. `;\n prompt += `Build on what already exists rather than recreating from scratch.\\n`;\n }\n\n if (this.techStack) {\n const parts: string[] = [];\n if (this.techStack.frontend) parts.push(`- Frontend: ${this.techStack.frontend}`);\n if (this.techStack.uiLibrary) parts.push(`- UI Library: ${this.techStack.uiLibrary}`);\n if (this.techStack.backend) parts.push(`- Backend: ${this.techStack.backend}`);\n if (this.techStack.database) parts.push(`- Database: ${this.techStack.database}`);\n if (this.techStack.other) parts.push(`- Other: ${this.techStack.other}`);\n if (parts.length > 0) {\n prompt += `\\nTech Stack:\\n${parts.join('\\n')}\\n`;\n prompt += `\\nUse the specified technologies in your task planning. `;\n prompt += `Include setup and configuration tasks for these technologies as needed.\\n`;\n }\n }\n\n prompt += `\\nGoal:\\n${goal}`;\n\n logger.info({ model: this.model, cwd: this.workingDirectory, fileCount: tree.length }, 'Decomposing goal into tasks');\n\n try {\n const result = await execa(this.claudeCommand, [\n '--print',\n '--output-format', 'json',\n '--model', this.model,\n ], {\n input: prompt,\n cwd: this.workingDirectory,\n env: this.claudeEnv ? { ...process.env, ...this.claudeEnv } : undefined,\n timeout: 120_000,\n });\n\n const output = result.stdout.trim();\n return this.parseResponse(output);\n } catch (err) {\n logger.error({ err }, 'Failed to decompose goal via Claude CLI');\n // Fall back to a single task containing the entire goal\n return [{\n title: 'Implement project goal',\n priority: 'high',\n description: goal,\n dependencies: [],\n tags: [],\n }];\n }\n }\n\n /**\n * Scan a directory recursively and return an indented tree listing.\n */\n private scanDirectory(dir: string, maxDepth: number, depth = 0, prefix = ''): string[] {\n if (depth >= maxDepth) return [];\n\n const lines: string[] = [];\n let entries: string[];\n\n try {\n entries = readdirSync(dir).sort();\n } catch {\n return lines;\n }\n\n const dirs: string[] = [];\n const files: string[] = [];\n\n for (const entry of entries) {\n if (IGNORE_DIRS.has(entry) || IGNORE_FILES.has(entry) || entry.startsWith('.')) continue;\n const fullPath = join(dir, entry);\n try {\n const stat = statSync(fullPath);\n if (stat.isDirectory()) {\n dirs.push(entry);\n } else {\n files.push(entry);\n }\n } catch {\n // Skip inaccessible entries\n }\n }\n\n for (const file of files) {\n lines.push(`${prefix}${file}`);\n }\n\n for (const d of dirs) {\n lines.push(`${prefix}${d}/`);\n const subLines = this.scanDirectory(join(dir, d), maxDepth, depth + 1, prefix + ' ');\n lines.push(...subLines);\n }\n\n return lines;\n }\n\n private parseResponse(output: string): PlannedTask[] {\n try {\n // Claude --output-format json wraps the response in a JSON object\n // with a \"result\" field containing the text response\n let text = output;\n\n try {\n const parsed = JSON.parse(output);\n if (parsed && typeof parsed === 'object' && 'result' in parsed) {\n text = parsed.result;\n }\n } catch {\n // Output may already be the raw text, continue\n }\n\n // Extract JSON array from the text (may be wrapped in markdown code fences)\n const jsonMatch = text.match(/\\[[\\s\\S]*\\]/);\n if (!jsonMatch) {\n throw new Error('No JSON array found in response');\n }\n\n const tasks = JSON.parse(jsonMatch[0]) as PlannedTask[];\n\n if (!Array.isArray(tasks) || tasks.length === 0) {\n throw new Error('Parsed result is not a non-empty array');\n }\n\n // Validate each task has required fields\n for (const task of tasks) {\n if (!task.title || !task.description) {\n throw new Error(`Task missing required fields: ${JSON.stringify(task)}`);\n }\n task.priority = task.priority ?? 'medium';\n task.dependencies = task.dependencies ?? [];\n task.tags = task.tags ?? [];\n }\n\n logger.info({ taskCount: tasks.length }, 'Goal decomposed into tasks');\n return tasks;\n } catch (err) {\n logger.warn({ err }, 'Failed to parse planner response, returning single task');\n return [{\n title: 'Implement project goal',\n priority: 'high',\n description: output,\n dependencies: [],\n tags: [],\n }];\n }\n }\n}\n","import type { Task, TaskPriority } from '../types/task.js';\nimport type { AgentState, AgentRole } from '../types/agent.js';\nimport type { PipelineStage } from '../types/orchestrator-activity.js';\nimport { PIPELINE_STAGE_ROLES } from '../types/orchestrator-activity.js';\nimport type { TaskPipeline } from './pipeline.js';\nimport { createLogger } from '../utils/logger.js';\n\nconst logger = createLogger('scheduler');\n\nexport interface TaskAssignment {\n taskId: string;\n agentId: string;\n}\n\n/**\n * Maps task tags to the agent role best suited to handle them.\n * A task may have multiple tags; the first matching role wins.\n */\nconst TAG_ROLE_MAP: Record<string, AgentRole> = {\n 'architecture': 'architect',\n 'design-system': 'architect',\n 'ui': 'designer',\n 'ux': 'designer',\n 'design': 'designer',\n 'planning': 'project-manager',\n 'priority': 'project-manager',\n 'testing': 'qa-engineer',\n 'qa': 'qa-engineer',\n 'e2e': 'qa-engineer',\n 'devops': 'devops',\n 'ci-cd': 'devops',\n 'deployment': 'devops',\n 'infrastructure': 'devops',\n 'docker': 'devops',\n 'documentation': 'technical-writer',\n 'docs': 'technical-writer',\n 'api-docs': 'technical-writer',\n 'review': 'code-reviewer',\n 'code-review': 'code-reviewer',\n 'security': 'code-reviewer',\n};\n\n/**\n * Fallback roles: when the preferred role has no idle agents,\n * try these roles in order before giving up.\n */\nconst ROLE_FALLBACK: Partial<Record<AgentRole, AgentRole[]>> = {\n 'designer': ['developer'],\n 'architect': ['developer'],\n 'project-manager': [],\n 'qa-engineer': ['developer'],\n 'devops': ['developer'],\n 'technical-writer': ['developer'],\n 'code-reviewer': ['architect', 'developer'],\n};\n\n/** Ordering for task priority: lower index = higher urgency. */\nconst PRIORITY_ORDER: Record<TaskPriority, number> = {\n critical: 0,\n high: 1,\n medium: 2,\n low: 3,\n};\n\nexport class Scheduler {\n /** Optional pipeline reference for pipeline-aware scheduling. */\n private pipeline: TaskPipeline | null = null;\n\n /**\n * Set a pipeline reference so the scheduler can use pipeline stage\n * information when determining which role should handle a task.\n */\n setPipeline(pipeline: TaskPipeline): void {\n this.pipeline = pipeline;\n }\n\n /**\n * Determine which pending tasks should be assigned to which idle agents.\n *\n * Rules:\n * 1. Only consider tasks whose status is 'pending' and whose dependencies are all 'done'.\n * 2. Only consider agents whose status is 'idle'.\n * 3. Match tasks to agents by role:\n * - If a task has a pipeline state, use the pipeline stage to determine role\n * - Otherwise, fall back to tag-based role determination\n * 4. Assign higher-priority tasks first.\n * 5. Each agent receives at most one assignment per scheduling cycle.\n */\n schedule(tasks: Task[], agents: AgentState[]): TaskAssignment[] {\n const taskStatusMap = new Map<string, Task>();\n for (const task of tasks) {\n taskStatusMap.set(task.id, task);\n }\n\n // Find tasks that are ready to be assigned\n const readyTasks = tasks.filter((task) => {\n if (task.status !== 'pending') return false;\n\n // All dependencies must be 'done' (or missing — a missing dep means\n // the task was deleted or never created, so treat it as satisfied).\n return task.dependencies.every((depId) => {\n const dep = taskStatusMap.get(depId);\n return !dep || dep.status === 'done';\n });\n });\n\n // Sort by priority (critical first)\n readyTasks.sort((a, b) => PRIORITY_ORDER[a.priority] - PRIORITY_ORDER[b.priority]);\n\n // Collect idle agents into a map by role for efficient lookup\n const idleAgentsByRole = new Map<AgentRole, AgentState[]>();\n for (const agent of agents) {\n if (agent.status !== 'idle') continue;\n const role = agent.config.role;\n if (!idleAgentsByRole.has(role)) {\n idleAgentsByRole.set(role, []);\n }\n idleAgentsByRole.get(role)!.push(agent);\n }\n\n const assignments: TaskAssignment[] = [];\n const assignedAgentIds = new Set<string>();\n\n for (const task of readyTasks) {\n const neededRole = this.determineRole(task);\n const rolesToTry: AgentRole[] = [neededRole, ...(ROLE_FALLBACK[neededRole] ?? [])];\n let assigned = false;\n\n for (const role of rolesToTry) {\n const candidates = idleAgentsByRole.get(role);\n if (!candidates || candidates.length === 0) {\n continue;\n }\n\n const agent = candidates.find((a) => !assignedAgentIds.has(a.config.id));\n if (!agent) {\n continue;\n }\n\n assignedAgentIds.add(agent.config.id);\n assignments.push({\n taskId: task.id,\n agentId: agent.config.id,\n });\n\n logger.debug(\n { taskId: task.id, agentId: agent.config.id, neededRole, actualRole: role },\n role === neededRole ? 'Task assigned to agent' : 'Task assigned to fallback agent',\n );\n assigned = true;\n break;\n }\n\n if (!assigned) {\n // This is normal — all agents for the needed role are busy.\n // The task will be retried on the next scheduling cycle.\n logger.trace(\n { taskId: task.id, neededRole },\n 'No idle agent available for role, will retry next cycle',\n );\n }\n }\n\n return assignments;\n }\n\n /**\n * Determine the best role for a task.\n *\n * If the task has an active pipeline state, the pipeline stage takes\n * priority over tag-based role determination. This enables the\n * plan -> develop -> qa -> review handoff sequence.\n *\n * Falls back to tag-based determination, then defaults to 'developer'.\n */\n private determineRole(task: Task): AgentRole {\n // Pipeline-aware: check if this task is in a pipeline stage\n if (this.pipeline) {\n const pipelineState = this.pipeline.getState(task.id);\n if (pipelineState) {\n const stageRoles = PIPELINE_STAGE_ROLES[pipelineState.currentStage];\n if (stageRoles && stageRoles.length > 0) {\n // Return the first role for the current pipeline stage\n return stageRoles[0] as AgentRole;\n }\n }\n }\n\n // Fall back to tag-based role determination\n for (const tag of task.tags) {\n const role = TAG_ROLE_MAP[tag];\n if (role) {\n return role;\n }\n }\n return 'developer';\n }\n}\n","import type {\n PipelineStage,\n TaskPipelineState,\n} from '../types/orchestrator-activity.js';\nimport { PIPELINE_STAGE_ORDER, PIPELINE_STAGE_ROLES } from '../types/orchestrator-activity.js';\nimport type { Task } from '../types/task.js';\nimport type { AgentRole } from '../types/agent.js';\nimport { createLogger } from '../utils/logger.js';\n\nconst logger = createLogger('pipeline');\n\n/**\n * TaskPipeline manages the lifecycle of tasks through a multi-stage pipeline:\n * plan -> develop -> qa -> review\n *\n * Each stage maps to one or more agent roles. When a stage completes, the\n * pipeline advances the task to the next stage and returns handoff information\n * so the orchestrator can delegate to the appropriate agent.\n */\nexport class TaskPipeline {\n private pipelines = new Map<string, TaskPipelineState>();\n\n /**\n * Register a task in the pipeline at a given starting stage.\n * Tasks tagged with 'architecture' or 'planning' start at 'plan'.\n * Tasks tagged with 'testing' or 'qa' start at 'qa'.\n * All others start at 'develop' (they'll skip the plan stage\n * if they were already created from the planner).\n */\n initTask(task: Task, startStage?: PipelineStage): TaskPipelineState {\n const stage = startStage ?? this.inferStartStage(task);\n const state: TaskPipelineState = {\n taskId: task.id,\n currentStage: stage,\n stageHistory: [],\n createdAt: new Date().toISOString(),\n };\n this.pipelines.set(task.id, state);\n logger.debug({ taskId: task.id, stage }, 'Task registered in pipeline');\n return state;\n }\n\n /**\n * Get the pipeline state for a task.\n */\n getState(taskId: string): TaskPipelineState | undefined {\n return this.pipelines.get(taskId);\n }\n\n /**\n * Record that an agent has started working on the current stage.\n */\n startStage(taskId: string, agentId: string): void {\n const state = this.pipelines.get(taskId);\n if (!state) return;\n\n state.stageHistory.push({\n stage: state.currentStage,\n agentId,\n startedAt: new Date().toISOString(),\n completedAt: null,\n status: 'in-progress',\n });\n }\n\n /**\n * Complete the current stage and return the next stage (if any).\n * Returns null if the pipeline is finished.\n */\n completeStage(taskId: string): {\n nextStage: PipelineStage | null;\n requiredRoles: string[];\n handoffMessage: string;\n } | null {\n const state = this.pipelines.get(taskId);\n if (!state) return null;\n\n // Mark current stage entry as completed\n const currentEntry = state.stageHistory.find(\n (h) => h.stage === state.currentStage && h.status === 'in-progress',\n );\n if (currentEntry) {\n currentEntry.completedAt = new Date().toISOString();\n currentEntry.status = 'completed';\n }\n\n // Find next stage\n const currentIndex = PIPELINE_STAGE_ORDER.indexOf(state.currentStage);\n if (currentIndex < 0 || currentIndex >= PIPELINE_STAGE_ORDER.length - 1) {\n // Pipeline complete\n logger.info({ taskId }, 'Task pipeline completed');\n return {\n nextStage: null,\n requiredRoles: [],\n handoffMessage: `Pipeline complete for task ${taskId}`,\n };\n }\n\n const nextStage = PIPELINE_STAGE_ORDER[currentIndex + 1];\n state.currentStage = nextStage;\n const requiredRoles = PIPELINE_STAGE_ROLES[nextStage];\n\n const stageLabels: Record<PipelineStage, string> = {\n plan: 'Planning & Architecture',\n develop: 'Development',\n qa: 'QA & Testing',\n review: 'Project Manager Review',\n };\n\n logger.info({ taskId, from: PIPELINE_STAGE_ORDER[currentIndex], to: nextStage }, 'Pipeline handoff');\n\n return {\n nextStage,\n requiredRoles,\n handoffMessage: `Handoff: ${stageLabels[PIPELINE_STAGE_ORDER[currentIndex]]} -> ${stageLabels[nextStage]}`,\n };\n }\n\n /**\n * Mark a stage as failed.\n */\n failStage(taskId: string): void {\n const state = this.pipelines.get(taskId);\n if (!state) return;\n\n const currentEntry = state.stageHistory.find(\n (h) => h.stage === state.currentStage && h.status === 'in-progress',\n );\n if (currentEntry) {\n currentEntry.completedAt = new Date().toISOString();\n currentEntry.status = 'failed';\n }\n }\n\n /**\n * Get the role(s) needed for the current pipeline stage of a task.\n */\n getRequiredRoles(taskId: string): AgentRole[] {\n const state = this.pipelines.get(taskId);\n if (!state) return ['developer'];\n return PIPELINE_STAGE_ROLES[state.currentStage] as AgentRole[];\n }\n\n /**\n * Check if a task has a pipeline registered.\n */\n has(taskId: string): boolean {\n return this.pipelines.has(taskId);\n }\n\n /**\n * Infer the starting pipeline stage from task tags.\n */\n private inferStartStage(task: Task): PipelineStage {\n const tags = task.tags.map((t) => t.toLowerCase());\n\n if (tags.includes('architecture') || tags.includes('planning') || tags.includes('design-system')) {\n return 'plan';\n }\n if (tags.includes('testing') || tags.includes('qa') || tags.includes('e2e')) {\n return 'qa';\n }\n // Most tasks coming from the planner already have a plan, so start at develop\n return 'develop';\n }\n}\n","import type { Task } from '../types/task.js';\nimport type { AgentState, AgentConfig } from '../types/agent.js';\nimport type { OrchestratorActivity } from '../types/orchestrator-activity.js';\nimport type { Message } from '../types/message.js';\nimport { generateId } from '../utils/id.js';\nimport { createLogger } from '../utils/logger.js';\n\nconst logger = createLogger('pm-scanner');\n\n/**\n * Findings from a PM scan cycle — these are deterministic assessments\n * that the orchestrator can act on or surface in the activity log.\n */\nexport interface PMScanResult {\n timestamp: string;\n findings: PMFinding[];\n summary: string;\n}\n\nexport type PMFindingKind =\n | 'blocked-task'\n | 'stale-task'\n | 'unassigned-ready-task'\n | 'agent-idle'\n | 'agent-errored'\n | 'dependency-bottleneck'\n | 'high-priority-waiting'\n | 'progress-stalled'\n | 'all-clear';\n\nexport interface PMFinding {\n kind: PMFindingKind;\n severity: 'info' | 'warning' | 'critical';\n message: string;\n taskId?: string;\n agentId?: string;\n}\n\n/**\n * Default scan interval: 30 seconds.\n * This is separate from the orchestrator poll interval so the PM scans\n * at a slower cadence — it's an assessment, not a scheduling loop.\n */\nconst DEFAULT_SCAN_INTERVAL_MS = 30_000;\n\n/**\n * After this many consecutive cycles with a task in-progress and no\n * completion, flag it as potentially stalled.\n */\nconst STALE_TASK_THRESHOLD_MS = 5 * 60_000; // 5 minutes\n\n/**\n * ProjectManagerScanner runs a periodic assessment loop that inspects the\n * current task board and agent pool, identifies gaps, blockers, stalled\n * progress, and idle resources, then reports findings via the orchestrator's\n * activity log and (optionally) sends messages to the relevant agents.\n *\n * This is NOT an LLM call — it's deterministic analysis. It runs the PM\n * role at the *orchestration layer* rather than spawning a Claude subprocess.\n * For deeper analysis that requires reasoning (e.g., \"is this architecture\n * design good?\"), a real PM agent is spawned via the pipeline's `review` stage.\n */\nexport class ProjectManagerScanner {\n private intervalId: ReturnType<typeof setInterval> | null = null;\n private scanIntervalMs: number;\n private lastScanTasks: Map<string, { status: string; at: number }> = new Map();\n private cycleCount = 0;\n /** Track tasks that have already received a PM message to avoid duplicates. */\n private messagedTasks: Set<string> = new Set();\n\n constructor(scanIntervalMs?: number) {\n this.scanIntervalMs = scanIntervalMs ?? DEFAULT_SCAN_INTERVAL_MS;\n }\n\n /**\n * Start the periodic scan loop.\n * @param scanFn — called each interval; the orchestrator provides context.\n */\n start(scanFn: () => void): void {\n if (this.intervalId) return;\n this.intervalId = setInterval(scanFn, this.scanIntervalMs);\n logger.info({ intervalMs: this.scanIntervalMs }, 'PM scanner started');\n }\n\n stop(): void {\n if (this.intervalId) {\n clearInterval(this.intervalId);\n this.intervalId = null;\n }\n logger.info('PM scanner stopped');\n }\n\n /**\n * Run a single scan pass.\n *\n * @param tasks - Current task list\n * @param agents - Current agent states (from pool + virtual)\n * @param phase - Current orchestrator phase\n */\n scan(\n tasks: Task[],\n agents: AgentState[],\n phase: string,\n ): PMScanResult {\n this.cycleCount++;\n const now = Date.now();\n const findings: PMFinding[] = [];\n\n // --- 1. Blocked tasks ---\n const blockedTasks = tasks.filter((t) => t.status === 'blocked');\n for (const task of blockedTasks) {\n const blockerIds = task.dependencies.filter((depId) => {\n const dep = tasks.find((t) => t.id === depId);\n return dep && dep.status !== 'done';\n });\n findings.push({\n kind: 'blocked-task',\n severity: task.priority === 'critical' ? 'critical' : 'warning',\n message: `Task \"${task.title}\" (${task.id}) is blocked by: ${blockerIds.join(', ')}`,\n taskId: task.id,\n });\n }\n\n // --- 2. High-priority tasks waiting too long ---\n const highPriorityPending = tasks.filter(\n (t) => t.status === 'pending' && (t.priority === 'critical' || t.priority === 'high'),\n );\n for (const task of highPriorityPending) {\n findings.push({\n kind: 'high-priority-waiting',\n severity: task.priority === 'critical' ? 'critical' : 'warning',\n message: `High-priority task \"${task.title}\" (${task.id}) is pending and unassigned`,\n taskId: task.id,\n });\n }\n\n // --- 3. Stale in-progress tasks (no movement for STALE_TASK_THRESHOLD_MS) ---\n const inProgressTasks = tasks.filter((t) => t.status === 'in-progress');\n for (const task of inProgressTasks) {\n const prev = this.lastScanTasks.get(task.id);\n if (prev && prev.status === 'in-progress') {\n const elapsed = now - prev.at;\n if (elapsed > STALE_TASK_THRESHOLD_MS) {\n findings.push({\n kind: 'stale-task',\n severity: 'warning',\n message: `Task \"${task.title}\" (${task.id}) has been in-progress for ${Math.round(elapsed / 60_000)}min without completion`,\n taskId: task.id,\n agentId: task.assignee ?? undefined,\n });\n }\n } else {\n // First time seeing this task in-progress — record the timestamp\n this.lastScanTasks.set(task.id, { status: 'in-progress', at: now });\n }\n }\n\n // Clean up completed tasks from tracking\n for (const task of tasks) {\n if (task.status === 'done' || task.status === 'cancelled') {\n this.lastScanTasks.delete(task.id);\n this.clearTrackedTask(task.id);\n } else if (task.status !== 'in-progress') {\n // Reset tracking if it goes back to pending\n const prev = this.lastScanTasks.get(task.id);\n if (prev && prev.status === 'in-progress') {\n this.lastScanTasks.delete(task.id);\n this.clearTrackedTask(task.id);\n }\n }\n }\n\n // --- 4. Ready tasks with no idle agents to handle them ---\n const taskStatusMap = new Map(tasks.map((t) => [t.id, t]));\n const readyTasks = tasks.filter((t) => {\n if (t.status !== 'pending') return false;\n return t.dependencies.every((depId) => {\n const dep = taskStatusMap.get(depId);\n return dep && dep.status === 'done';\n });\n });\n const idleAgents = agents.filter((a) => a.status === 'idle');\n\n if (readyTasks.length > 0 && idleAgents.length === 0) {\n findings.push({\n kind: 'unassigned-ready-task',\n severity: 'warning',\n message: `${readyTasks.length} task(s) ready but no idle agents available`,\n });\n }\n\n // --- 5. Agents with errors ---\n const erroredAgents = agents.filter((a) => a.status === 'error');\n for (const agent of erroredAgents) {\n findings.push({\n kind: 'agent-errored',\n severity: 'warning',\n message: `Agent ${agent.config.name} (${agent.config.id}) is in error state: ${agent.error ?? 'unknown'}`,\n agentId: agent.config.id,\n });\n }\n\n // --- 6. Idle agents with pending work (possible scheduling gap) ---\n if (idleAgents.length > 0 && readyTasks.length > 0) {\n findings.push({\n kind: 'agent-idle',\n severity: 'info',\n message: `${idleAgents.length} idle agent(s) with ${readyTasks.length} ready task(s) — scheduling may pick these up next cycle`,\n });\n }\n\n // --- 7. Dependency bottleneck detection ---\n // Find tasks that are blocking many other tasks\n const blockingCounts = new Map<string, number>();\n for (const task of tasks) {\n if (task.status === 'done' || task.status === 'cancelled') continue;\n for (const depId of task.dependencies) {\n const dep = taskStatusMap.get(depId);\n if (dep && dep.status !== 'done') {\n blockingCounts.set(depId, (blockingCounts.get(depId) ?? 0) + 1);\n }\n }\n }\n for (const [taskId, count] of blockingCounts) {\n if (count >= 3) {\n const task = taskStatusMap.get(taskId);\n findings.push({\n kind: 'dependency-bottleneck',\n severity: 'critical',\n message: `Task \"${task?.title ?? taskId}\" is blocking ${count} other tasks — should be prioritized`,\n taskId,\n });\n }\n }\n\n // --- 8. Progress stall detection ---\n // If we've run several scans and the done count hasn't changed, flag it\n const doneCount = tasks.filter((t) => t.status === 'done').length;\n const inProgressCount = inProgressTasks.length;\n const pendingCount = tasks.filter((t) => t.status === 'pending').length;\n\n // --- Build summary ---\n if (findings.length === 0) {\n findings.push({\n kind: 'all-clear',\n severity: 'info',\n message: 'All systems nominal — no gaps or blockers detected',\n });\n }\n\n const criticalCount = findings.filter((f) => f.severity === 'critical').length;\n const warningCount = findings.filter((f) => f.severity === 'warning').length;\n\n let summary: string;\n if (criticalCount > 0) {\n summary = `PM Scan: ${criticalCount} critical, ${warningCount} warning(s) | ${doneCount}/${tasks.length} done | ${inProgressCount} active | ${pendingCount} pending`;\n } else if (warningCount > 0) {\n summary = `PM Scan: ${warningCount} warning(s) | ${doneCount}/${tasks.length} done | ${inProgressCount} active | ${pendingCount} pending`;\n } else {\n summary = `PM Scan: All clear | ${doneCount}/${tasks.length} done | ${inProgressCount} active | ${pendingCount} pending`;\n }\n\n return {\n timestamp: new Date().toISOString(),\n findings,\n summary,\n };\n }\n\n /**\n * Build messages from PM findings that should be sent to agents.\n * Only produces messages for actionable findings.\n * Tracks which tasks have already been messaged to avoid flooding inboxes.\n */\n buildMessages(result: PMScanResult): Message[] {\n const messages: Message[] = [];\n\n for (const finding of result.findings) {\n // Escalate critical bottlenecks as urgent messages to orchestrator\n // (only once per task)\n if (finding.kind === 'dependency-bottleneck' && finding.severity === 'critical' && finding.taskId) {\n const key = `bottleneck:${finding.taskId}`;\n if (this.messagedTasks.has(key)) continue;\n this.messagedTasks.add(key);\n\n messages.push({\n id: generateId(),\n type: 'directive',\n from: 'project-manager',\n to: 'orchestrator',\n subject: `Bottleneck: ${finding.message}`,\n body: `The project manager has identified a critical dependency bottleneck.\\n\\n${finding.message}\\n\\nRecommendation: Prioritize this task immediately to unblock downstream work.`,\n taskId: finding.taskId,\n priority: 'urgent',\n timestamp: result.timestamp,\n });\n }\n\n // Notify agents about stale tasks (only once per task)\n if (finding.kind === 'stale-task' && finding.agentId && finding.taskId) {\n const key = `stale:${finding.taskId}`;\n if (this.messagedTasks.has(key)) continue;\n this.messagedTasks.add(key);\n\n messages.push({\n id: generateId(),\n type: 'system',\n from: 'project-manager',\n to: finding.agentId,\n subject: `Status check: ${finding.taskId}`,\n body: `The project manager is checking on progress.\\n\\n${finding.message}\\n\\nPlease provide a status update or flag any blockers you're experiencing.`,\n taskId: finding.taskId,\n priority: 'normal',\n timestamp: result.timestamp,\n });\n }\n }\n\n return messages;\n }\n\n /**\n * Clear tracked messages for a task (e.g., when it moves from in-progress\n * back to pending, allowing a new message if it stalls again later).\n */\n clearTrackedTask(taskId: string): void {\n for (const key of this.messagedTasks) {\n if (key.endsWith(`:${taskId}`)) {\n this.messagedTasks.delete(key);\n }\n }\n }\n}\n","import { z } from 'zod';\nimport { readFile } from 'node:fs/promises';\nimport { parse as parseYaml } from 'yaml';\nimport type { ProjectConfig } from '../types/project.js';\n\nconst permissionModeSchema = z.enum(['default', 'acceptEdits', 'bypassPermissions']);\n\nconst agentRoleConfigSchema = z.object({\n role: z.enum(['orchestrator', 'project-manager', 'architect', 'developer', 'designer', 'qa-engineer', 'devops', 'technical-writer', 'code-reviewer']),\n count: z.number().int().min(1),\n model: z.string().optional(),\n systemPromptFile: z.string().optional(),\n systemPromptOverride: z.string().optional(),\n allowedTools: z.array(z.string()).optional(),\n maxBudgetUsd: z.number().positive().optional(),\n permissionMode: permissionModeSchema.optional(),\n claudeArgs: z.array(z.string()).optional(),\n claudeEnv: z.record(z.string()).optional(),\n maxTurns: z.number().int().positive().optional(),\n});\n\nconst projectSettingsSchema = z.object({\n workingDirectory: z.string().default('.'),\n todoFile: z.string().default('todo.md'),\n messagesDirectory: z.string().default('.maestro/messages'),\n logsDirectory: z.string().default('.maestro/logs'),\n defaultModel: z.string().default('sonnet'),\n maxConcurrentAgents: z.number().int().min(1).default(5),\n pollIntervalMs: z.number().int().min(500).default(5000),\n maxTotalBudgetUsd: z.number().positive().optional(),\n claudeCommand: z.string().optional(),\n claudeArgs: z.array(z.string()).optional(),\n claudeEnv: z.record(z.string()).optional(),\n feedback: z.object({\n interactionMode: z.enum(['unattended', 'supervised', 'interactive']).default('supervised'),\n progressReportIntervalMs: z.number().int().min(1000).default(60000),\n milestonePercentages: z.array(z.number().min(0).max(100)).default([25, 50, 75, 100]),\n questionTimeoutMs: z.number().int().min(1000).default(300000),\n requirePlanApproval: z.boolean().default(true),\n }).optional(),\n});\n\nconst techStackSchema = z.object({\n frontend: z.string().optional(),\n uiLibrary: z.string().optional(),\n backend: z.string().optional(),\n database: z.string().optional(),\n other: z.string().optional(),\n}).optional();\n\nexport const projectConfigSchema = z.object({\n name: z.string().min(1),\n description: z.string(),\n version: z.string(),\n agents: z.array(agentRoleConfigSchema).min(1),\n settings: projectSettingsSchema.default({}),\n techStack: techStackSchema,\n});\n\n/**\n * Load and validate a project configuration from a YAML file.\n *\n * Reads the file at the given path, parses it as YAML, and validates\n * the result against the project config schema.\n */\nexport async function loadProjectConfig(filePath: string): Promise<ProjectConfig> {\n const raw = await readFile(filePath, 'utf-8');\n const parsed = parseYaml(raw);\n return validateProjectConfig(parsed);\n}\n\n/**\n * Validate an unknown value against the project config schema.\n *\n * Returns a fully typed ProjectConfig with defaults applied, or\n * throws a ZodError if validation fails.\n */\nexport function validateProjectConfig(config: unknown): ProjectConfig {\n return projectConfigSchema.parse(config) as ProjectConfig;\n}\n","import { mkdir } from 'node:fs/promises';\nimport path from 'node:path';\nimport type { ProjectConfig } from '../types/project.js';\n\n/**\n * Manages the runtime directory structure for a Maestro project.\n *\n * Ensures all required directories exist and provides absolute path\n * resolution for todo files, message inboxes/outboxes, and log files.\n */\nexport class WorkspaceManager {\n private baseDir: string;\n private config: ProjectConfig | null = null;\n\n constructor(baseDir: string) {\n this.baseDir = path.resolve(baseDir);\n }\n\n /**\n * Create all runtime directories required by the project.\n *\n * This creates the top-level .maestro directory, the messages directory,\n * the logs directory, and per-agent inbox/outbox directories for every\n * agent defined in the project config.\n */\n async initialize(config: ProjectConfig): Promise<void> {\n this.config = config;\n\n const messagesDir = this.getMessagesDir();\n const logsDir = this.getLogsDir();\n\n // Create top-level runtime directories\n await mkdir(messagesDir, { recursive: true });\n await mkdir(logsDir, { recursive: true });\n\n // Create per-agent inbox and outbox directories\n for (const agentRoleConfig of config.agents) {\n for (let i = 0; i < agentRoleConfig.count; i++) {\n const agentId = agentRoleConfig.count === 1\n ? agentRoleConfig.role\n : `${agentRoleConfig.role}-${i + 1}`;\n\n await mkdir(this.getAgentInboxPath(agentId), { recursive: true });\n await mkdir(this.getAgentOutboxPath(agentId), { recursive: true });\n }\n }\n }\n\n /**\n * Get the absolute path to the project's todo file.\n */\n getTodoFilePath(): string {\n const todoFile = this.config?.settings.todoFile ?? 'todo.md';\n return path.resolve(this.baseDir, todoFile);\n }\n\n /**\n * Get the absolute path to the messages directory.\n */\n getMessagesDir(): string {\n const messagesDir = this.config?.settings.messagesDirectory ?? '.maestro/messages';\n return path.resolve(this.baseDir, messagesDir);\n }\n\n /**\n * Get the absolute path to the logs directory.\n */\n getLogsDir(): string {\n const logsDir = this.config?.settings.logsDirectory ?? '.maestro/logs';\n return path.resolve(this.baseDir, logsDir);\n }\n\n /**\n * Get the absolute path to a specific agent's log file.\n */\n getAgentLogPath(agentId: string): string {\n return path.resolve(this.getLogsDir(), `${agentId}.log`);\n }\n\n /**\n * Get the absolute path to a specific agent's inbox directory.\n */\n getAgentInboxPath(agentId: string): string {\n return path.resolve(this.getMessagesDir(), agentId, 'inbox');\n }\n\n /**\n * Get the absolute path to a specific agent's outbox directory.\n */\n getAgentOutboxPath(agentId: string): string {\n return path.resolve(this.getMessagesDir(), agentId, 'outbox');\n }\n}\n"],"mappings":"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","names":["writeFile","access","EventEmitter","EventEmitter","todoFilePath","messagesDir","EventEmitter","mkdir","writeFile","readFile","rename","join","EventEmitter","readFile","logger","logger","EventEmitter","join","mkdir","writeFile","readFile","rename","EventEmitter","mkdir","EventEmitter","logger","EventEmitter","execa","join","logger","logger","PRIORITY_ORDER","logger","logger","logger","EventEmitter","mkdir","TaskManager","AgentPool","loadAgentConfigs","stats","readFile","mkdir","path"]}