kantban-cli 0.1.24 → 0.1.25

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/pipeline.ts","../src/lib/tool-profiles.ts","../src/lib/worktree.ts","../src/lib/constraint-evaluator.ts","../src/lib/checkpoint.ts","../src/lib/evaluator.ts","../src/lib/replanner.ts","../src/lib/orchestrator.ts","../src/lib/run-memory.ts","../src/lib/event-queue.ts","../src/lib/ws-client.ts","../src/lib/logger.ts","../src/lib/light-call.ts","../src/lib/advisor.ts","../src/lib/reaper.ts","../src/lib/gate-snapshot.ts","../src/lib/cost-tracker.ts","../src/lib/event-emitter.ts","../src/providers/registry.ts","../src/providers/codex-provider.ts","../src/providers/codex-jsonl-parser.ts","../src/providers/gemini-provider.ts","../src/providers/gemini-jsonl-parser.ts"],"sourcesContent":["import { mkdirSync, writeFileSync, readFileSync, unlinkSync, existsSync, appendFileSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport type { KantBanCLIClient } from '../client.js';\nimport { PipelineOrchestrator, type OrchestratorDeps } from '../lib/orchestrator.js';\nimport { RalphLoop, type LoopConfig, type RalphLoopDeps } from '../lib/ralph-loop.js';\nimport { RunMemory } from '../lib/run-memory.js';\nimport { EventQueue, type PipelineEvent, type ErrorHandler } from '../lib/event-queue.js';\nimport { PipelineWsClient } from '../lib/ws-client.js';\nimport { generateMcpConfig, generateGateProxyMcpConfig, cleanupMcpConfig, cleanupGateProxyConfigs } from '../lib/mcp-config.js';\nimport { PipelineLogger } from '../lib/logger.js';\nimport type { ColumnContext, TicketContext } from '../lib/prompt-composer.js';\nimport type { TicketFingerprint } from '@kantban/types';\nimport { composeLightPrompt, parseLightResponse, type LightCallContext } from '../lib/light-call.js';\nimport { composeAdvisorPrompt, parseAdvisorResponse, type AdvisorInput } from '../lib/advisor.js';\nimport { composeStuckDetectionPrompt, parseStuckDetectionResponse, type StuckDetectionInput } from '../lib/stuck-detector.js';\nimport { cleanupWorktree, mergeWorktreeBranch } from '../lib/worktree.js';\nimport { spawnReaper, killReaper } from '../lib/reaper.js';\nimport { parseGateConfig, resolveGatesForColumn, parseTimeout } from '../lib/gate-config.js';\nimport { GateSnapshotStore } from '../lib/gate-snapshot.js';\nimport { runGates, type RunOptions as GateRunOptions } from '../lib/gate-runner.js';\nimport { PipelineCostTracker } from '../lib/cost-tracker.js';\nimport { composeReplannerPrompt, parseReplannerResponse } from '../lib/replanner.js';\nimport { PipelineEventEmitter } from '../lib/event-emitter.js';\nimport type { GateConfig } from '@kantban/types';\nimport { ProviderRegistry, type BoardProviderConfig } from '../providers/registry.js';\nimport { ClaudeProvider } from '../providers/claude-provider.js';\nimport { CodexProvider } from '../providers/codex-provider.js';\nimport { GeminiProvider } from '../providers/gemini-provider.js';\nimport type { AgentProvider, McpConfig } from '../providers/types.js';\n\n// ---------------------------------------------------------------------------\n// Provider registry setup\n// ---------------------------------------------------------------------------\n\nfunction createProviderRegistry(): ProviderRegistry {\n const registry = new ProviderRegistry();\n registry.register(new ClaudeProvider());\n registry.register(new CodexProvider());\n registry.register(new GeminiProvider());\n return registry;\n}\n\n/**\n * Read an MCP config JSON file (written by generateMcpConfig / generateGateProxyMcpConfig)\n * and convert it to the provider McpConfig format.\n * On-disk format: { mcpServers: { ... } }\n * Provider format: { servers: { ... } }\n */\nfunction readMcpConfigAsProviderConfig(filePath: string): McpConfig {\n const raw = JSON.parse(readFileSync(filePath, 'utf-8')) as { mcpServers: McpConfig['servers'] };\n return { servers: raw.mcpServers };\n}\n\n// ---------------------------------------------------------------------------\n// Arg parsing\n// ---------------------------------------------------------------------------\n\ninterface PipelineArgs {\n boardId: string;\n once: boolean;\n dryRun: boolean;\n columnFilter: string | null;\n maxIterations: number | null;\n maxBudget: number | null;\n model: string | null;\n provider: string | null;\n concurrency: number | null;\n logRetention: number;\n yes: boolean;\n}\n\nfunction parseArgs(args: string[]): PipelineArgs {\n const positional: string[] = [];\n let once = false;\n let dryRun = false;\n let columnFilter: string | null = null;\n let maxIterations: number | null = null;\n let maxBudget: number | null = null;\n let model: string | null = null;\n let provider: string | null = null;\n let concurrency: number | null = null;\n let logRetention = 7;\n let yes = false;\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i]!;\n switch (arg) {\n case '--once':\n once = true;\n break;\n case '--dry-run':\n dryRun = true;\n break;\n case '--yes':\n case '-y':\n yes = true;\n break;\n case '--column':\n columnFilter = args[++i] ?? null;\n break;\n case '--max-iterations': {\n const val = Number(args[++i]);\n if (isNaN(val) || val <= 0) {\n console.error(`Error: --max-iterations requires a positive number, got: ${args[i]}`);\n process.exit(1);\n }\n maxIterations = val;\n break;\n }\n case '--max-budget': {\n const val = Number(args[++i]);\n if (isNaN(val) || val < 0) {\n console.error(`Error: --max-budget requires a non-negative number, got: ${args[i]}`);\n process.exit(1);\n }\n maxBudget = val;\n break;\n }\n case '--model':\n model = args[++i] ?? null;\n break;\n case '--provider':\n provider = args[++i] ?? null;\n break;\n case '--concurrency': {\n const val = Number(args[++i]);\n if (isNaN(val) || val <= 0) {\n console.error(`Error: --concurrency requires a positive number, got: ${args[i]}`);\n process.exit(1);\n }\n concurrency = val;\n break;\n }\n case '--log-retention':\n logRetention = Number(args[++i]) || 7;\n break;\n default:\n if (!arg.startsWith('--')) positional.push(arg);\n break;\n }\n }\n\n const boardId = positional[0] ?? '';\n const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n if (boardId && !UUID_RE.test(boardId)) {\n console.error(`Error: invalid board ID \"${boardId}\" — expected UUID`);\n process.exit(1);\n }\n if (!boardId) {\n console.error(`Usage: kantban pipeline <board-id> [flags]\n\nFlags:\n --once Run one scan, wait for loops, then exit\n --dry-run Show config without starting\n --column <id> Filter to a single column\n --max-iterations <n> Override max iterations per ticket\n --max-budget <usd> Per-ticket budget cap (USD)\n --model <model> Override model preference\n --provider <id> Override default provider (claude, codex, gemini)\n --concurrency <n> Override concurrency per column\n --log-retention <d> Log retention in days (default: 7)\n --yes, -y Skip safety confirmation`);\n process.exit(1);\n }\n\n return { boardId, once, dryRun, columnFilter, maxIterations, maxBudget, model, provider, concurrency, logRetention, yes };\n}\n\n// ---------------------------------------------------------------------------\n// PID file helpers\n// ---------------------------------------------------------------------------\n\nfunction pidDir(boardId: string): string {\n return join(homedir(), '.kantban', 'pipelines', boardId);\n}\n\nfunction pidFilePath(boardId: string): string {\n return join(pidDir(boardId), 'orchestrator.pid');\n}\n\nfunction writePidFile(boardId: string): void {\n const dir = pidDir(boardId);\n mkdirSync(dir, { recursive: true, mode: 0o700 });\n writeFileSync(pidFilePath(boardId), String(process.pid), { mode: 0o600 });\n}\n\nfunction removePidFile(boardId: string): void {\n try {\n unlinkSync(pidFilePath(boardId));\n } catch {\n /* already removed */\n }\n}\n\n// ---------------------------------------------------------------------------\n// Child PID manifest helpers — tracks spawned child PIDs on disk for orphan\n// cleanup by the watchdog reaper or next-startup cleanup.\n// ---------------------------------------------------------------------------\n\nfunction childManifestPath(boardId: string): string {\n return join(pidDir(boardId), 'children.pid');\n}\n\nfunction appendChildPid(boardId: string, pid: number): void {\n const dir = pidDir(boardId);\n mkdirSync(dir, { recursive: true, mode: 0o700 });\n appendFileSync(childManifestPath(boardId), `${String(pid)}\\n`, { mode: 0o600 });\n}\n\nfunction removeChildPid(boardId: string, pid: number): void {\n const manifestPath = childManifestPath(boardId);\n try {\n const contents = readFileSync(manifestPath, 'utf-8');\n const pids = contents.split('\\n').filter(l => l.trim() !== '' && l.trim() !== String(pid));\n writeFileSync(manifestPath, pids.length > 0 ? pids.join('\\n') + '\\n' : '', { mode: 0o600 });\n } catch {\n /* manifest doesn't exist or unreadable — nothing to remove */\n }\n}\n\nfunction readChildManifest(boardId: string): number[] {\n try {\n const contents = readFileSync(childManifestPath(boardId), 'utf-8');\n return contents\n .split('\\n')\n .map(l => l.trim())\n .filter(l => l !== '')\n .map(Number)\n .filter(n => !isNaN(n) && n > 0);\n } catch {\n return [];\n }\n}\n\nfunction removeChildManifest(boardId: string): void {\n try {\n unlinkSync(childManifestPath(boardId));\n } catch {\n /* already removed */\n }\n}\n\n/**\n * Kill any orphaned pipeline processes from a previous run.\n * Reads the stale PID file, kills that process tree, then removes the file.\n * Also kills any lingering `claude -p` processes that reference our MCP config dir.\n */\nfunction cleanupOrphanedProcesses(boardId: string): void {\n // 1. Kill stale orchestrator from PID file\n const pidPath = pidFilePath(boardId);\n if (existsSync(pidPath)) {\n try {\n const stalePid = parseInt(readFileSync(pidPath, 'utf-8').trim(), 10);\n if (stalePid && stalePid !== process.pid) {\n try {\n process.kill(stalePid, 0); // test if alive\n process.kill(stalePid, 'SIGTERM');\n console.log(`Killed stale orchestrator (PID ${String(stalePid)})`);\n } catch {\n // already dead\n }\n }\n } catch {\n // can't read PID file\n }\n removePidFile(boardId);\n }\n\n // 1.5. Kill children from the PID manifest (more targeted than grep)\n const manifestPids = readChildManifest(boardId);\n if (manifestPids.length > 0) {\n for (const pid of manifestPids) {\n try {\n process.kill(pid, 0); // test if alive\n process.kill(pid, 'SIGTERM');\n } catch {\n // already dead\n }\n }\n console.log(`Killed ${String(manifestPids.length)} orphaned child process(es) from manifest`);\n removeChildManifest(boardId);\n }\n\n // 1.6. Kill stale reaper if still running\n const staleReaperPath = join(pidDir(boardId), 'reaper.pid');\n try {\n if (existsSync(staleReaperPath)) {\n const reaperPid = parseInt(readFileSync(staleReaperPath, 'utf-8').trim(), 10);\n if (reaperPid && !isNaN(reaperPid)) {\n try {\n process.kill(reaperPid, 0);\n process.kill(reaperPid, 'SIGTERM');\n console.log(`Killed stale reaper (PID ${String(reaperPid)})`);\n } catch {\n // already dead\n }\n }\n unlinkSync(staleReaperPath);\n }\n } catch {\n // can't read reaper PID — not critical\n }\n\n}\n\n// ---------------------------------------------------------------------------\n// Safety confirmation\n// ---------------------------------------------------------------------------\n\nfunction printSafetyWarning(): void {\n console.log(`\n=== SAFETY WARNING ===\n\nThis pipeline will run Claude Code agents with --dangerously-skip-permissions.\nAgents will have unrestricted access to tools, file system, and MCP servers.\n\nBefore proceeding:\n 1. Review all prompt documents linked to pipeline columns\n 2. Ensure your project signals/guardrails are configured correctly\n 3. Verify your MCP server configuration is appropriate\n\nPress Ctrl+C to cancel, or re-run with --yes to skip this warning.\n`);\n}\n\nfunction waitForConfirmation(): Promise<boolean> {\n return new Promise((resolve) => {\n // Non-TTY (piped input) — read from stdin instead of rejecting\n process.stdout.write('Continue? [y/N] ');\n process.stdin.setEncoding('utf8');\n process.stdin.once('data', (data: string) => {\n const answer = data.trim().toLowerCase();\n resolve(answer === 'y' || answer === 'yes');\n });\n // If stdin ends without data (empty pipe), default to no\n process.stdin.once('end', () => resolve(false));\n });\n}\n\n// ---------------------------------------------------------------------------\n// runPipeline — main entry point\n// ---------------------------------------------------------------------------\n\nexport async function runPipeline(client: KantBanCLIClient, args: string[]): Promise<void> {\n // Handle subcommands\n if (args[0] === 'init') {\n const { runPipelineInit } = await import('./pipeline-init.js');\n await runPipelineInit();\n return;\n }\n\n const opts = parseArgs(args);\n\n // Create provider registry\n const registry = createProviderRegistry();\n\n // Safety confirmation\n if (!opts.yes && !opts.dryRun) {\n printSafetyWarning();\n const confirmed = await waitForConfirmation();\n if (!confirmed) {\n console.log('Aborted.');\n return;\n }\n }\n\n // Validate gate file\n const gateFilePath = join(process.cwd(), 'pipeline.gates.yaml');\n let gateConfig: GateConfig;\n if (!existsSync(gateFilePath)) {\n console.error(`Error: pipeline.gates.yaml not found in ${process.cwd()}`);\n console.error('Run \"kantban pipeline init\" to generate a starter gate file.');\n process.exit(1);\n }\n try {\n const gateYaml = readFileSync(gateFilePath, 'utf-8');\n gateConfig = parseGateConfig(gateYaml);\n console.log(`Gate config loaded: ${gateConfig.default.length} default gate(s)`);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n console.error(`Error: Invalid pipeline.gates.yaml: ${message}`);\n process.exit(1);\n }\n\n // Create cost tracker if budget is configured\n const costTracker = gateConfig.settings?.budget\n ? new PipelineCostTracker(crypto.randomUUID(), gateConfig.settings.budget)\n : undefined;\n\n // Gate snapshot store — per-ticket gate history for gutter detection and advisor\n const gateSnapshotStore = new GateSnapshotStore();\n\n // Resolve project ID\n let projectId = process.env['KANTBAN_PROJECT_ID'] ?? '';\n if (!projectId) {\n try {\n const result = await client.getBoardProject(opts.boardId);\n projectId = result.project_id;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n console.error(`Error: Could not resolve project ID for board ${opts.boardId}: ${message}`);\n console.error('Set KANTBAN_PROJECT_ID environment variable or ensure the board exists.');\n process.exit(1);\n }\n }\n\n // Generate MCP config (stable path per board — survives restarts)\n const mcpConfigPath = generateMcpConfig(client.baseUrl, client.token, opts.boardId);\n\n // Board-level provider config — used to resolve per-column and intelligence providers.\n // Seeded from --provider flag if provided; future: fetch from board settings.\n const boardProviderConfig: BoardProviderConfig = {\n default_provider: opts.provider ?? undefined,\n intelligence_provider: opts.provider ?? undefined,\n };\n\n // Resolve the intelligence provider (used for advisor, replanner, stuck-detection, light-call)\n const intelligenceProvider: AgentProvider = registry.resolveForIntelligence(boardProviderConfig);\n\n // Initialize logger\n const logBaseDir = join(homedir(), '.kantban', 'pipelines');\n const logger = new PipelineLogger(logBaseDir, opts.boardId);\n logger.pruneOldLogs(opts.logRetention);\n\n // Declared early so closures in deps can capture it by reference before initialization\n let runMemory: RunMemory | null = null;\n\n // Stable session ID for all pipeline events in this run\n const pipelineSessionId = crypto.randomUUID();\n\n const eventEmitter = new PipelineEventEmitter(\n client.baseUrl,\n projectId,\n client.token,\n opts.boardId,\n pipelineSessionId,\n );\n\n // Wire up OrchestratorDeps\n const deps: OrchestratorDeps = {\n fetchBoardScope: (boardId: string) =>\n client.get(`/projects/${projectId}/pipeline-context`, { boardId }),\n\n fetchColumnScope: (columnId: string) =>\n client.get(`/projects/${projectId}/pipeline-context`, { columnId }),\n\n startLoop: async (ticketId: string, columnId: string, config: LoopConfig) => {\n // Apply CLI overrides\n const effectiveConfig: LoopConfig = {\n ...config,\n ...(opts.maxIterations !== null && { maxIterations: opts.maxIterations }),\n ...(opts.maxBudget !== null && { maxBudgetUsd: opts.maxBudget }),\n ...(opts.model !== null && { model: opts.model }),\n };\n\n // Capture run memory ref before async work so closures below see the same instance\n const mem = runMemory;\n\n // Resolve column name and agent_config once upfront so we can select the right\n // MCP config and provider. This also pre-warms cachedColumnName for onPostIterationGates.\n const colScopeForName = await client.get<{\n column: { name: string };\n agent_config: { provider?: string } | null;\n }>(\n `/projects/${projectId}/pipeline-context`, { columnId },\n );\n const resolvedColumnName = colScopeForName.column.name;\n\n // Resolve per-column provider (falls back to board default → 'claude')\n const columnProviderOverride = colScopeForName.agent_config?.provider;\n const columnProvider = registry.resolveForColumn(\n boardProviderConfig,\n columnProviderOverride ? { provider: columnProviderOverride } : {},\n );\n\n // Resolve model tier (e.g. \"fast\") to provider-specific model ID (e.g. \"claude-haiku-4-5-20251001\")\n if (effectiveConfig.model) {\n effectiveConfig.model = registry.resolveModel(columnProvider, effectiveConfig.model);\n }\n\n // Choose MCP config: gate-proxy variant when gates are configured for this column.\n // All providers get the gate proxy — KANTBAN_HIDDEN_TOOLS on the kantban server\n // hides move tools so agents can only reach the gate-enforced versions.\n const columnGates = resolveGatesForColumn(gateConfig, resolvedColumnName);\n // Resolve worktree absolute path so the gate proxy runs gates in the agent's\n // checked-out code, not the root repo.\n const gateCwd = effectiveConfig.worktreeName\n ? join(process.cwd(), effectiveConfig.worktreeName)\n : undefined;\n const effectiveMcpConfigPath =\n columnGates.length > 0\n ? generateGateProxyMcpConfig(\n client.baseUrl,\n client.token,\n opts.boardId,\n gateFilePath,\n columnId,\n resolvedColumnName,\n projectId,\n gateCwd,\n ticketId,\n )\n : mcpConfigPath;\n\n // Convert on-disk MCP config to provider McpConfig object\n const columnMcpConfig = readMcpConfigAsProviderConfig(effectiveMcpConfigPath);\n\n const loopDeps: RalphLoopDeps = {\n fetchTicketContext: (tid: string) =>\n client.get<TicketContext>(`/projects/${projectId}/pipeline-context`, { ticketId: tid }),\n fetchColumnContext: (cid: string) =>\n client.get<ColumnContext>(`/projects/${projectId}/pipeline-context`, { columnId: cid }),\n fetchFingerprint: (tid: string) =>\n client.getFingerprint(projectId, tid) as Promise<TicketFingerprint>,\n provider: columnProvider,\n mcpConfig: columnMcpConfig,\n projectId,\n log: (msg: string) => {\n logger.orchestrator(`[${ticketId}] ${msg}`);\n },\n\n // Run memory enrichment — inject accumulated discoveries into each iteration prompt\n fetchRunMemoryContent: mem\n ? async () => {\n const content = await mem.getContent();\n const lines = content.split('\\n');\n if (lines.length > 500) {\n return lines.slice(-500).join('\\n');\n }\n return content;\n }\n : undefined,\n\n // Lookahead enrichment — fetch next-column prompt doc so agent can anticipate exit criteria\n fetchLookaheadDocument: effectiveConfig.lookaheadColumnId\n ? async () => {\n const colScope = await client.get<{ prompt_document: { title: string; content: string } | null }>(\n `/projects/${projectId}/pipeline-context`, { columnId: effectiveConfig.lookaheadColumnId },\n );\n if (!colScope.prompt_document) return undefined;\n return { title: colScope.prompt_document.title, content: colScope.prompt_document.content };\n }\n : undefined,\n\n // Pipeline event emission — forward stream/session events to WS for browser delivery\n onStreamEvent: deps.emitPipelineEvent\n ? (event, context) => {\n deps.emitPipelineEvent!({\n type: 'pipeline:stream',\n payload: {\n boardId: opts.boardId,\n ticketId: context.ticketId,\n columnId: context.columnId,\n runId: context.runId,\n sessionId: pipelineSessionId,\n event: event as unknown as Record<string, unknown>,\n },\n });\n }\n : undefined,\n onSessionStart: deps.emitPipelineEvent\n ? (meta) => {\n deps.emitPipelineEvent!({\n type: 'pipeline:session-start',\n payload: {\n boardId: opts.boardId,\n ticketId,\n columnId,\n runId: meta.runId,\n sessionId: pipelineSessionId,\n model: meta.model,\n invocationType: 'heavy',\n iteration: meta.iteration,\n },\n });\n }\n : undefined,\n onSessionEnd: (meta) => {\n // Cost tracking — always active\n costTracker?.record({\n ticketId,\n columnId,\n model: effectiveConfig.model ?? 'default',\n tokensIn: meta.tokensIn,\n tokensOut: meta.tokensOut,\n type: 'heavy',\n });\n\n // Pipeline event emission — only when WS client is connected\n if (deps.emitPipelineEvent) {\n deps.emitPipelineEvent({\n type: 'pipeline:session-end',\n payload: {\n boardId: opts.boardId,\n runId: meta.runId,\n exitReason: null,\n tokensIn: meta.tokensIn,\n tokensOut: meta.tokensOut,\n toolCallCount: meta.toolCallCount,\n durationMs: meta.durationMs,\n },\n });\n }\n },\n };\n\n // Wire checkpoint callback when setFieldValue is available\n if (deps.setFieldValue) {\n effectiveConfig.onCheckpoint = async (tid: string, checkpoint) => {\n try {\n const serialized = JSON.stringify(checkpoint);\n await deps.setFieldValue!(tid, 'loop_checkpoint', serialized);\n } catch (err) {\n console.error(` [checkpoint] Failed to write for ${tid}: ${err instanceof Error ? err.message : String(err)}`);\n }\n };\n }\n\n // Wire stuck detection — invokes a lightweight LLM to classify trajectory mid-run\n if (effectiveConfig.stuckDetection) {\n effectiveConfig.invokeStuckDetection = async (input: StuckDetectionInput) => {\n const prompt = composeStuckDetectionPrompt(input);\n const result = await intelligenceProvider.invoke({\n prompt,\n model: registry.resolveModel(intelligenceProvider, 'fast'),\n maxTurns: 1,\n });\n if (result.exitCode !== 0) {\n throw new Error(`Stuck detection call failed (exit ${String(result.exitCode)})`);\n }\n return parseStuckDetectionResponse(result.output);\n };\n }\n\n // Wire post-iteration gate runner — runs all gates after each Claude invocation\n // resolvedColumnName is already fetched above — no per-iteration API call needed.\n effectiveConfig.onPostIterationGates = async (tid: string, iteration: number) => {\n const gates = resolveGatesForColumn(gateConfig, resolvedColumnName);\n if (gates.length === 0) {\n // No gates — return a synthetic all-pass snapshot\n return gateSnapshotStore.record(tid, iteration, []);\n }\n const runOpts: GateRunOptions = {};\n if (gateConfig.settings?.cwd) runOpts.cwd = gateConfig.settings.cwd;\n if (gateConfig.settings?.env) runOpts.env = gateConfig.settings.env;\n if (gateConfig.settings?.total_timeout) {\n runOpts.totalTimeoutMs = parseTimeout(gateConfig.settings.total_timeout);\n }\n const results = await runGates(gates, runOpts);\n return gateSnapshotStore.record(tid, iteration, results);\n };\n\n const loop = new RalphLoop(ticketId, columnId, effectiveConfig, loopDeps);\n // Track active loops for graceful shutdown\n activeRalphLoops.add(loop);\n return loop.run().finally(() => {\n activeRalphLoops.delete(loop);\n });\n },\n\n createComment: (ticketId: string, body: string) =>\n client.post(`/projects/${projectId}/tickets/${ticketId}/comments`, { body }),\n\n createSignal: (ticketId: string, body: string) =>\n client.post(`/projects/${projectId}/signals`, {\n scopeType: 'ticket',\n scopeId: ticketId,\n content: body,\n }),\n\n createColumnSignal: (columnId: string, body: string) =>\n client.post(`/projects/${projectId}/signals`, {\n scopeType: 'column',\n scopeId: columnId,\n content: body,\n }),\n\n upsertColumnSignal: (columnId: string, contentPrefix: string, body: string) =>\n client.put(`/projects/${projectId}/signals/upsert`, {\n scopeType: 'column',\n scopeId: columnId,\n contentPrefix,\n content: body,\n }),\n\n claimTicket: (ticketId: string) =>\n client.claimTicket(projectId, ticketId),\n\n fetchBlockedTickets: (ticketId: string) =>\n client.get<Array<{ id: string; column_id: string | null }>>(\n `/projects/${projectId}/tickets/${ticketId}/blocked-tickets`,\n ),\n\n hasUnresolvedBlockers: async (ticketId: string) => {\n const blockers = await client.get<Array<{ id: string }>>(\n `/projects/${projectId}/tickets/${ticketId}/unresolved-blockers`,\n );\n return blockers.length > 0;\n },\n\n dispatchLightCall: async (ticketId: string, columnId: string) => {\n // Fetch minimal context for light call (parallel)\n const [ticketCtx, colScope, boardScope] = await Promise.all([\n client.get<TicketContext>(`/projects/${projectId}/pipeline-context`, { ticketId }),\n client.get<ColumnContext>(`/projects/${projectId}/pipeline-context`, { columnId }),\n client.get<{ columns: Array<{ id: string; name: string }> }>(\n `/projects/${projectId}/pipeline-context`,\n { boardId: opts.boardId },\n ),\n ]);\n\n const lightCtx: LightCallContext = {\n ticketId,\n ticketNumber: ticketCtx.ticket.ticket_number,\n ticketTitle: ticketCtx.ticket.title,\n ...(ticketCtx.ticket.description ? { ticketDescription: ticketCtx.ticket.description } : {}),\n columnName: colScope.column.name,\n fieldValues: ticketCtx.field_values,\n toolPrefix: colScope.tool_prefix,\n projectId,\n ...(colScope.transition_rules ? { transitionRules: colScope.transition_rules } : {}),\n ...(boardScope.columns && boardScope.columns.length > 0 && {\n availableColumns: boardScope.columns.map((col) => ({ id: col.id, name: col.name })),\n }),\n };\n\n const prompt = composeLightPrompt(lightCtx);\n logger.orchestrator(`[${ticketId}] Light call: composing prompt for column \"${colScope.column.name}\"`);\n\n const lightModel = registry.resolveModel(intelligenceProvider, 'fast');\n const lightResult = await intelligenceProvider.invoke({\n prompt,\n model: lightModel,\n maxTurns: 3,\n });\n\n costTracker?.record({\n ticketId, columnId, model: lightModel,\n tokensIn: lightResult.usage.inputTokens, tokensOut: lightResult.usage.outputTokens,\n type: 'light',\n });\n\n if (lightResult.exitCode !== 0) {\n throw new Error(`Light call exited with code ${lightResult.exitCode}: ${lightResult.output.slice(0, 200)}`);\n }\n\n const response = parseLightResponse(lightResult.output);\n logger.orchestrator(`[${ticketId}] Light call result: ${response.action} — ${response.reason}`);\n return response;\n },\n\n // Advisor invocation — recovers from failure exits (stalled/error/max_iterations)\n invokeAdvisor: async (input: AdvisorInput) => {\n const prompt = composeAdvisorPrompt(input);\n logger.orchestrator(`[${input.ticketId}] Advisor: invoking for ${input.exitReason}`);\n\n const advisorModel = registry.resolveModel(intelligenceProvider, 'fast');\n const advisorResult = await intelligenceProvider.invoke({\n prompt,\n model: advisorModel,\n maxTurns: 1,\n });\n\n costTracker?.record({\n ticketId: input.ticketId, columnId: '', model: advisorModel,\n tokensIn: advisorResult.usage.inputTokens, tokensOut: advisorResult.usage.outputTokens,\n type: 'advisor',\n });\n\n if (advisorResult.exitCode !== 0) {\n throw new Error(`Advisor call exited with code ${advisorResult.exitCode}: ${advisorResult.output.slice(0, 200)}`);\n }\n\n const response = parseAdvisorResponse(advisorResult.output);\n logger.orchestrator(`[${input.ticketId}] Advisor: ${response.action} — ${response.reason}`);\n return response;\n },\n\n // Field value management — used for debt items, checkpoint writes, and escalation metadata\n setFieldValue: async (ticketId: string, fieldName: string, value: unknown) => {\n await client.put(`/projects/${projectId}/tickets/${ticketId}/field-values`, {\n values: { [fieldName]: value },\n });\n },\n\n getFieldValues: async (ticketId: string) => {\n const data = await client.get<Array<{ field_name: string; text_value: string | null; number_value: number | null; json_value: unknown }>>(\n `/projects/${projectId}/tickets/${ticketId}/field-values`,\n );\n return data.map((fv) => ({\n field_name: fv.field_name,\n value: fv.text_value ?? fv.json_value ?? fv.number_value,\n }));\n },\n\n // Ticket management for advisor actions (ESCALATE, SPLIT_TICKET)\n moveTicketToColumn: async (ticketId: string, columnId: string, handoff: Record<string, unknown>) => {\n await client.patch(`/projects/${projectId}/tickets/${ticketId}/move`, {\n column_id: columnId,\n position: 0,\n handoff,\n });\n },\n\n createTickets: async (parentTicketId: string, specs: Array<{ title: string; description: string }>) => {\n const ids: string[] = [];\n for (const spec of specs) {\n const result = await client.post<{ id: string }>(\n `/projects/${projectId}/tickets`,\n { title: spec.title, description: spec.description, parent_id: parentTicketId },\n );\n ids.push(result.id);\n }\n return ids;\n },\n\n archiveTicket: async (ticketId: string) => {\n await client.post(`/projects/${projectId}/tickets/${ticketId}/archive`, {});\n },\n\n // Run memory append — closure captures runMemory by reference (set after initialization)\n appendRunMemory: (section: string, content: string) =>\n runMemory ? runMemory.append(section, content) : Promise.resolve(),\n\n cleanupWorktree: (name: string) => cleanupWorktree(name),\n mergeWorktree: (name: string, integrationBranch: string) => mergeWorktreeBranch(name, integrationBranch),\n\n // Pipeline event emission — wsClient captured by reference (set later before any loops run)\n emitPipelineEvent: (event) => {\n wsClient?.send(event);\n },\n boardId: opts.boardId,\n eventEmitter,\n costTracker,\n gateSnapshotStore,\n invokeReplanner: async (state) => {\n const prompt = composeReplannerPrompt(state);\n const replannerModel = registry.resolveModel(intelligenceProvider, 'fast');\n const replannerResult = await intelligenceProvider.invoke({\n prompt,\n model: replannerModel,\n maxTurns: 1,\n });\n costTracker?.record({\n ticketId: 'replanner', columnId: 'pipeline', model: replannerModel,\n tokensIn: replannerResult.usage.inputTokens, tokensOut: replannerResult.usage.outputTokens,\n type: 'replanner',\n });\n if (replannerResult.exitCode !== 0) throw new Error(`Replanner failed`);\n return parseReplannerResponse(replannerResult.output);\n },\n };\n\n // Create orchestrator\n const orchestrator = new PipelineOrchestrator(opts.boardId, projectId, deps);\n\n // Initialize — discovers pipeline columns\n console.log(`Initializing pipeline for board ${opts.boardId}...`);\n logger.orchestrator('Initializing pipeline');\n try {\n await orchestrator.initialize(opts.columnFilter);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n console.error(`Error: Failed to initialize pipeline: ${message}`);\n console.error('Check that the board exists, has pipeline columns configured, and the API is reachable.');\n cleanupMcpConfig(mcpConfigPath);\n cleanupGateProxyConfigs(pidDir(opts.boardId));\n process.exit(1);\n }\n\n const columnIds = orchestrator.pipelineColumnIds;\n\n // Initialize run memory if any pipeline column has run_memory enabled\n try {\n for (const colId of columnIds) {\n const colScope = await client.get<{ agent_config: { run_memory?: boolean } | null }>(\n `/projects/${projectId}/pipeline-context`, { columnId: colId },\n );\n if (colScope.agent_config?.run_memory) {\n // Fetch board name for the run memory document title\n const boardScope = await client.get<{ board: { name: string } }>(\n `/projects/${projectId}/pipeline-context`, { boardId: opts.boardId },\n );\n // Resolve a space to store the run memory document — use first available space\n const spaces = await client.get<Array<{ id: string; name: string }>>(\n `/projects/${projectId}/spaces`,\n );\n const spaceId = spaces[0]?.id;\n if (!spaceId) {\n logger.orchestrator('Run memory: no spaces found in project — skipping run memory');\n console.warn('Warning: Run memory requires at least one document space in the project — skipping.');\n break;\n }\n runMemory = new RunMemory(opts.boardId, boardScope.board.name, {\n createDocument: async (content: string, title: string) => {\n const result = await client.post<{ id: string }>(\n `/projects/${projectId}/spaces/${spaceId}/documents`,\n { title, content },\n );\n return result.id;\n },\n getDocument: async (docId: string) => {\n const doc = await client.get<{ content: string }>(\n `/projects/${projectId}/documents/${docId}`,\n );\n return doc.content;\n },\n updateDocument: async (docId: string, content: string) => {\n await client.patch(`/projects/${projectId}/documents/${docId}`, { content });\n },\n });\n await runMemory.initialize();\n logger.orchestrator(`Run memory initialized (doc=${runMemory.documentId ?? 'none'})`);\n console.log(`Run memory enabled (document: ${runMemory.documentId ?? 'none'})`);\n break;\n }\n }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n logger.orchestrator(`Run memory init failed (non-fatal): ${msg}`);\n console.error(`Warning: Run memory initialization failed: ${msg}`);\n }\n\n if (columnIds.length === 0) {\n console.log('No pipeline columns found (columns need has_prompt=true and type !== \"done\").');\n cleanupMcpConfig(mcpConfigPath);\n cleanupGateProxyConfigs(pidDir(opts.boardId));\n return;\n }\n\n console.log(`Discovered ${String(columnIds.length)} pipeline column(s).`);\n logger.orchestrator(`Discovered ${String(columnIds.length)} pipeline columns: ${columnIds.join(', ')}`);\n\n // Dry-run: print config summary and exit\n if (opts.dryRun) {\n console.log('\\n--- Dry Run Configuration ---');\n console.log(`Board ID: ${opts.boardId}`);\n console.log(`Project ID: ${projectId}`);\n console.log(`Pipeline cols: ${String(columnIds.length)}`);\n console.log(`Column filter: ${opts.columnFilter ?? '(none)'}`);\n console.log(`Max iterations: ${opts.maxIterations !== null ? String(opts.maxIterations) : '(per-column default)'}`);\n console.log(`Max budget: ${opts.maxBudget !== null ? `$${String(opts.maxBudget)}` : '(per-column default)'}`);\n console.log(`Model: ${opts.model ?? '(per-column default)'}`);\n console.log(`Concurrency: ${opts.concurrency !== null ? String(opts.concurrency) : '(per-column default)'}`);\n console.log(`Mode: ${opts.once ? 'once' : 'persistent'}`);\n console.log(`Log retention: ${String(opts.logRetention)} days`);\n console.log(`MCP config: ${mcpConfigPath}`);\n console.log('\\n[Dry run -- no agents started]');\n cleanupMcpConfig(mcpConfigPath);\n cleanupGateProxyConfigs(pidDir(opts.boardId));\n return;\n }\n\n // --- Live mode ---\n\n // Set up graceful shutdown\n let shutdownInProgress = false;\n\n const shutdown = async (signal: string): Promise<void> => {\n if (shutdownInProgress) return;\n shutdownInProgress = true;\n\n console.log(`\\nReceived ${signal}. Shutting down gracefully...`);\n logger.orchestrator(`Shutdown initiated (${signal})`);\n\n if (rescanTimer) clearInterval(rescanTimer);\n eventQueue?.stop();\n\n // Notify browser clients that the pipeline is stopping (before closing WS)\n wsClient?.send({ type: 'pipeline:stopped', payload: { boardId: opts.boardId } });\n // Give the WS a moment to flush the stop notification\n await new Promise(r => setTimeout(r, 200));\n\n await eventEmitter.close();\n wsClient?.stop();\n\n for (const loop of activeRalphLoops) {\n loop.stop();\n }\n\n // Give active loops a moment to wind down (providers manage their own child processes)\n const deadline = Date.now() + 5000;\n while (activeRalphLoops.size > 0 && Date.now() < deadline) {\n await new Promise(r => setTimeout(r, 200));\n }\n\n // Print cost report\n if (costTracker) {\n console.log('\\n--- Pipeline Cost Report ---');\n console.log(costTracker.generateReport(gateConfig.settings?.pricing));\n }\n\n cleanupMcpConfig(mcpConfigPath);\n cleanupGateProxyConfigs(pidDir(opts.boardId));\n killReaper(reaperPidPath);\n removePidFile(opts.boardId);\n removeChildManifest(opts.boardId);\n\n logger.orchestrator('Shutdown complete');\n console.log('Pipeline stopped.');\n process.exit(0);\n };\n\n process.on('SIGTERM', () => {\n shutdown('SIGTERM').catch((err) => {\n console.error('Error during shutdown:', err);\n process.exit(1);\n });\n });\n process.on('SIGINT', () => {\n shutdown('SIGINT').catch((err) => {\n console.error('Error during shutdown:', err);\n process.exit(1);\n });\n });\n process.on('SIGHUP', () => {\n shutdown('SIGHUP').catch((err) => {\n console.error('Error during shutdown:', err);\n process.exit(1);\n });\n });\n\n // Clean up orphaned processes from a previous run before starting\n cleanupOrphanedProcesses(opts.boardId);\n\n // Write PID file\n writePidFile(opts.boardId);\n logger.orchestrator(`PID file written: ${String(process.pid)}`);\n\n // Spawn watchdog reaper — kills children if orchestrator dies unexpectedly\n const reaperPidPath = join(pidDir(opts.boardId), 'reaper.pid');\n const reaperProcess = spawnReaper({\n orchestratorPid: process.pid,\n manifestPath: childManifestPath(opts.boardId),\n pidFilePath: pidFilePath(opts.boardId),\n reaperPidPath,\n mcpConfigPath,\n pipelineDir: pidDir(opts.boardId),\n });\n logger.orchestrator(`Watchdog reaper spawned (PID ${String(reaperProcess.pid ?? 'unknown')})`);\n\n // Set up event queue and WS client\n let eventQueue: EventQueue | null = null;\n let wsClient: PipelineWsClient | null = null;\n let rescanTimer: ReturnType<typeof setInterval> | null = null;\n\n const onEventError: ErrorHandler = (event, err) => {\n const msg = err instanceof Error ? err.message : String(err);\n logger.orchestrator(`Event handler error for ${event.type} ticket=${event.ticketId}: ${msg}`);\n console.error(`Event handler error: ${msg}`);\n };\n eventQueue = new EventQueue(\n (event: PipelineEvent) => orchestrator.handleEvent(event),\n {\n drainRateMs: 100,\n onError: onEventError,\n },\n );\n\n wsClient = new PipelineWsClient(client, {\n boardId: opts.boardId,\n projectId,\n onEvent: (wsEvent) => {\n // Map WS events to pipeline events\n const payload = wsEvent.payload;\n\n // ticket:moved and ticket:created nest the id inside payload.ticket\n // ticket:deleted and ticket:archived have payload.ticketId directly\n const ticket = payload['ticket'] as Record<string, unknown> | undefined;\n const ticketId =\n (typeof payload['ticketId'] === 'string' ? payload['ticketId'] : null) ??\n (ticket && typeof ticket['id'] === 'string' ? ticket['id'] : null);\n\n // ticket:created has payload.columnId; ticket:moved has the new column in ticket.column_id\n const columnId =\n (typeof payload['columnId'] === 'string' ? payload['columnId'] : null) ??\n (ticket && typeof ticket['column_id'] === 'string' ? ticket['column_id'] : null);\n\n // Handle firing constraint changes — refresh constraint caches\n if (\n wsEvent.type === 'firing_constraint:created' ||\n wsEvent.type === 'firing_constraint:updated' ||\n wsEvent.type === 'firing_constraint:deleted'\n ) {\n logger.orchestrator(`WS event: ${wsEvent.type} — refreshing constraint caches`);\n void orchestrator.refreshConstraints().catch((err) => {\n const msg = err instanceof Error ? err.message : String(err);\n logger.orchestrator(`Constraint cache refresh failed: ${msg}`);\n });\n return;\n }\n\n if (!ticketId) return;\n\n const eventType = wsEvent.type as PipelineEvent['type'];\n if (\n eventType === 'ticket:created' ||\n eventType === 'ticket:moved' ||\n eventType === 'ticket:updated' ||\n eventType === 'ticket:archived' ||\n eventType === 'ticket:deleted'\n ) {\n const pipelineEvent: PipelineEvent = { type: eventType, ticketId, columnId };\n eventQueue!.push(pipelineEvent);\n logger.orchestrator(`WS event: ${eventType} ticket=${ticketId} column=${columnId ?? 'null'}`);\n }\n },\n onConnect: () => {\n console.log('WebSocket connected. Listening for board events...');\n logger.orchestrator('WebSocket connected');\n },\n onDisconnect: () => {\n logger.orchestrator('WebSocket disconnected');\n },\n });\n\n // Try initial WS connection (non-fatal)\n try {\n await wsClient.connect();\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n console.error(`Warning: WebSocket connection failed: ${message}`);\n console.error('Pipeline will poll for changes and retry WS periodically.');\n logger.orchestrator(`WebSocket connection failed: ${message}`);\n }\n\n // Start event queue\n eventQueue.start();\n\n // Initial scan and spawn\n console.log('Scanning pipeline columns for tickets...');\n logger.orchestrator('Starting scan and spawn');\n try {\n await orchestrator.scanAndSpawn();\n logger.orchestrator(`Scan complete. Active loops: ${String(orchestrator.activeLoopCount)}`);\n console.log(`Scan complete. Active loops: ${String(orchestrator.activeLoopCount)}`);\n } catch (scanErr) {\n const scanMsg = scanErr instanceof Error ? scanErr.message : String(scanErr);\n logger.orchestrator(`Scan error: ${scanMsg}`);\n console.error(`Scan error: ${scanMsg}`);\n }\n\n if (opts.once) {\n // Wait for all active loops to complete, then exit\n console.log('Running in --once mode. Waiting for all loops to complete...');\n logger.orchestrator('Once mode: waiting for loops to complete');\n\n // Poll until no active loops or queued work remain\n await waitForAllLoops(orchestrator);\n\n // Print cost report\n if (costTracker) {\n console.log('\\n--- Pipeline Cost Report ---');\n console.log(costTracker.generateReport(gateConfig.settings?.pricing));\n }\n\n // Notify browser clients that the pipeline has finished\n wsClient.send({ type: 'pipeline:stopped', payload: { boardId: opts.boardId } });\n await new Promise(r => setTimeout(r, 200));\n\n // Cleanup\n await eventEmitter.close();\n wsClient.stop();\n eventQueue.stop();\n cleanupMcpConfig(mcpConfigPath);\n cleanupGateProxyConfigs(pidDir(opts.boardId));\n killReaper(reaperPidPath);\n removePidFile(opts.boardId);\n removeChildManifest(opts.boardId);\n\n logger.orchestrator('Once mode complete. Exiting.');\n console.log('All loops complete. Pipeline exiting.');\n } else {\n // Persistent mode — unified poll loop: rescan columns and try to\n // reconnect WS if disconnected. This replaces the separate polling\n // fallback and rescan timer with a single 30s heartbeat.\n let consecutiveScanFailures = 0;\n rescanTimer = setInterval(() => {\n void (async () => {\n try {\n await orchestrator.scanAndSpawn();\n if (consecutiveScanFailures > 0) {\n console.log(`Rescan recovered after ${String(consecutiveScanFailures)} failure(s)`);\n }\n consecutiveScanFailures = 0;\n } catch (err: unknown) {\n consecutiveScanFailures++;\n const msg = err instanceof Error ? err.message : String(err);\n logger.orchestrator(`Periodic rescan error (${String(consecutiveScanFailures)}x): ${msg}`);\n if (consecutiveScanFailures === 1 || consecutiveScanFailures % 10 === 0) {\n console.error(`Warning: Rescan has failed ${String(consecutiveScanFailures)} consecutive time(s): ${msg}`);\n }\n }\n if (wsClient && !wsClient.connected) {\n const reconnected = await wsClient.tryReconnect();\n if (reconnected) {\n logger.orchestrator('WS reconnected via poll cycle');\n }\n }\n })();\n }, 30_000);\n\n console.log(`Pipeline running (PID ${String(process.pid)}). Use 'kantban pipeline stop ${opts.boardId}' to stop.`);\n logger.orchestrator('Pipeline running in persistent mode');\n }\n}\n\n// ---------------------------------------------------------------------------\n// Active loop tracking for graceful shutdown\n// ---------------------------------------------------------------------------\n\nconst activeRalphLoops: Set<RalphLoop> = new Set();\n\nasync function waitForAllLoops(\n orchestrator: PipelineOrchestrator,\n timeoutMs = 4 * 60 * 60 * 1000, // 4 hours default\n): Promise<void> {\n let consecutiveIdle = 0;\n const startTime = Date.now();\n let lastProgressLog = 0;\n\n while (consecutiveIdle < 2) {\n if (Date.now() - startTime > timeoutMs) {\n console.error(\n `Warning: waitForAllLoops timed out after ${String(Math.round(timeoutMs / 60_000))}m. ` +\n `Active: ${String(activeRalphLoops.size)}, orchestrator: ${String(orchestrator.activeLoopCount)}, ` +\n `queued: ${String(orchestrator.hasQueuedWork)}`,\n );\n return;\n }\n\n await new Promise((resolve) => setTimeout(resolve, 1000));\n\n if (activeRalphLoops.size === 0 && orchestrator.activeLoopCount === 0 && !orchestrator.hasActiveQueuedWork && !orchestrator.hasCompletingWork) {\n consecutiveIdle++;\n } else {\n consecutiveIdle = 0;\n const now = Date.now();\n if (now - lastProgressLog > 30_000) {\n lastProgressLog = now;\n console.log(\n `Waiting... Active loops: ${String(activeRalphLoops.size)}, ` +\n `queued work: ${String(orchestrator.hasQueuedWork)}`,\n );\n }\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// stopPipeline — sends SIGTERM to a running pipeline\n// ---------------------------------------------------------------------------\n\nexport async function stopPipeline(args: string[]): Promise<void> {\n const boardId = args[0];\n if (!boardId) {\n console.error('Usage: kantban pipeline stop <board-id>');\n process.exit(1);\n }\n\n const pidFile = pidFilePath(boardId);\n let pid: number;\n\n try {\n const content = readFileSync(pidFile, 'utf8').trim();\n pid = Number(content);\n if (isNaN(pid) || pid <= 0) {\n throw new Error('Invalid PID');\n }\n } catch {\n console.error(`No running pipeline found for board ${boardId}.`);\n console.error(`Expected PID file at: ${pidFile}`);\n process.exit(1);\n return; // unreachable, but helps TS\n }\n\n try {\n // Kill the entire process group to take down child claude -p processes too\n try {\n process.kill(-pid, 'SIGTERM');\n console.log(`Sent SIGTERM to pipeline process group (pgid ${String(pid)}) for board ${boardId}.`);\n } catch {\n // Process group kill failed (not a group leader) — fall back to direct kill\n process.kill(pid, 'SIGTERM');\n console.log(`Sent SIGTERM to pipeline process ${String(pid)} for board ${boardId}.`);\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n console.error(`Failed to stop pipeline (PID ${String(pid)}): ${message}`);\n console.error('The process may have already exited. Removing stale PID file.');\n removePidFile(boardId);\n process.exit(1);\n }\n}\n","export interface ToolRestrictions {\n /** Value for --tools flag. undefined = all (default), '' = strip all built-in tools */\n tools?: string;\n /** Values for --allowedTools flag */\n allowedTools?: string[];\n /** Values for --disallowedTools flag */\n disallowedTools?: string[];\n /** Whether to include --mcp-config in the invocation */\n includeMcpConfig: boolean;\n}\n\n/**\n * Resolve tool restrictions from per-column agent_config fields.\n * No presets — the user directly configures allowed_tools/disallowed_tools/builtin_tools.\n *\n * If none of the three fields are set, returns no restrictions (full tool access).\n * This means agents have ALL tools by default unless the user explicitly restricts them.\n */\nexport function resolveToolRestrictions(\n builtinTools?: string,\n allowedTools?: string[],\n disallowedTools?: string[],\n): ToolRestrictions {\n const hasRestrictions = builtinTools !== undefined\n || (allowedTools && allowedTools.length > 0)\n || (disallowedTools && disallowedTools.length > 0);\n\n if (!hasRestrictions) {\n return { includeMcpConfig: true };\n }\n\n return {\n ...(builtinTools !== undefined && { tools: builtinTools }),\n ...(allowedTools && allowedTools.length > 0 && { allowedTools }),\n ...(disallowedTools && disallowedTools.length > 0 && { disallowedTools }),\n includeMcpConfig: true,\n };\n}\n","import { execFile as defaultExecFile, execFileSync } from 'node:child_process';\n\n/**\n * Generate a deterministic worktree name from ticket context.\n * Claude CLI's --worktree flag accepts a name (not a path).\n */\nexport function generateWorktreeName(ticketNumber: number, columnName: string): string {\n const slug = columnName\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-|-$/g, '');\n return `kantban-${ticketNumber}-${slug}`;\n}\n\n/**\n * Check if a URL looks like a plausible git remote URL.\n * Valid git URLs contain at least one of: `/`, `@`, or `://`.\n * Bare words like \"origin\" or plain hostnames like \"github.com\" are invalid.\n */\nexport function isPlausibleRemoteUrl(url: string): boolean {\n return url.includes('/') || url.includes('@') || url.includes('://');\n}\n\n/**\n * Ensure a git worktree has the origin remote configured with a valid URL.\n * Standard worktrees share .git/config with the main repo so remotes should\n * propagate automatically. If they don't (e.g. EnterWorktree edge case),\n * copy origin from the main repo. Also validates that the existing origin URL\n * is plausible — bare words or hostnames without paths are replaced.\n */\nexport function ensureWorktreeRemote(worktreePath: string): void {\n try {\n const remotes = execFileSync('git', ['-C', worktreePath, 'remote'], {\n stdio: 'pipe',\n encoding: 'utf-8',\n }).trim();\n\n if (remotes.split('\\n').includes('origin')) {\n // Origin exists — validate its URL\n const currentUrl = execFileSync('git', ['-C', worktreePath, 'remote', 'get-url', 'origin'], {\n stdio: 'pipe',\n encoding: 'utf-8',\n }).trim();\n\n if (isPlausibleRemoteUrl(currentUrl)) return; // valid URL, nothing to do\n\n // Invalid URL — remove it so we can re-add from main repo\n console.error(`[worktree] Invalid origin URL in ${worktreePath}: \"${currentUrl}\" — fixing`);\n execFileSync('git', ['-C', worktreePath, 'remote', 'remove', 'origin'], {\n stdio: 'pipe',\n });\n }\n\n // Get origin URL from main repo\n const originUrl = execFileSync('git', ['remote', 'get-url', 'origin'], {\n stdio: 'pipe',\n encoding: 'utf-8',\n }).trim();\n\n if (originUrl && isPlausibleRemoteUrl(originUrl)) {\n execFileSync('git', ['-C', worktreePath, 'remote', 'add', 'origin', originUrl], {\n stdio: 'pipe',\n });\n console.error(`[worktree] Added missing origin remote to ${worktreePath}: ${originUrl}`);\n } else {\n console.error(`[worktree] WARNING: main repo origin URL is also invalid: \"${originUrl}\"`);\n }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n console.error(`[worktree] Failed to ensure remote for ${worktreePath}: ${msg}`);\n }\n}\n\ntype ExecFn = (cmd: string, args: string[], cb: (err: Error | null, stdout: string, stderr: string) => void) => void;\n\n/**\n * Remove a git worktree. Fire-and-forget — never throws.\n */\nexport async function cleanupWorktree(\n worktreeName: string,\n exec: ExecFn = defaultExecFile as unknown as ExecFn,\n): Promise<boolean> {\n // Guard: check if this is actually a registered git worktree before removing\n try {\n const path = await findWorktreeForBranch(exec, worktreeName);\n if (!path) return true; // Not a git worktree — nothing to clean up\n } catch {\n return true;\n }\n return new Promise((resolve) => {\n exec('git', ['worktree', 'remove', '--force', worktreeName], (err) => {\n if (err) {\n console.error(`[worktree] cleanup failed for ${worktreeName}: ${err.message}`);\n resolve(false);\n } else {\n resolve(true);\n }\n });\n });\n}\n\nfunction execPromise(exec: ExecFn, cmd: string, args: string[]): Promise<{ stdout: string; stderr: string }> {\n return new Promise((resolve, reject) => {\n exec(cmd, args, (err, stdout, stderr) => {\n if (err) reject(Object.assign(err, { stdout, stderr }));\n else resolve({ stdout, stderr });\n });\n });\n}\n\n/**\n * Find the worktree path where a branch is currently checked out, or null if not checked out.\n */\nasync function findWorktreeForBranch(exec: ExecFn, branch: string): Promise<string | null> {\n try {\n const { stdout } = await execPromise(exec, 'git', ['worktree', 'list', '--porcelain']);\n const targetRef = `refs/heads/${branch}`;\n let currentPath: string | null = null;\n for (const line of stdout.split('\\n')) {\n if (line.startsWith('worktree ')) currentPath = line.slice('worktree '.length);\n if (line.startsWith('branch ') && line.slice('branch '.length) === targetRef && currentPath) {\n return currentPath;\n }\n }\n return null;\n } catch {\n return null;\n }\n}\n\n/**\n * Merge a worktree branch into an integration branch.\n * Creates the integration branch from HEAD if it doesn't exist.\n * Returns true on success, false on failure (e.g. merge conflict).\n */\nexport async function mergeWorktreeBranch(\n worktreeName: string,\n integrationBranch: string,\n exec: ExecFn = defaultExecFile as unknown as ExecFn,\n): Promise<boolean> {\n try {\n // Guard: if the worktree branch doesn't exist (e.g. Codex created a plain dir),\n // skip the merge — there's nothing to merge.\n try {\n await execPromise(exec, 'git', ['rev-parse', '--verify', worktreeName]);\n } catch {\n return true; // No branch to merge — not an error\n }\n\n // Ensure integration branch exists (no-op if it already does)\n await execPromise(exec, 'git', ['branch', integrationBranch, 'HEAD']).catch(() => {\n /* branch already exists — fine */\n });\n\n // If the integration branch is checked out somewhere, merge directly there.\n // This avoids the update-ref desync (stages without committing) and the\n // \"branch already checked out\" error from git worktree add.\n const checkedOutPath = await findWorktreeForBranch(exec, integrationBranch);\n if (checkedOutPath) {\n await execPromise(exec, 'git', ['-C', checkedOutPath, 'merge', '--no-edit', worktreeName]);\n console.error(`[worktree] merged ${worktreeName} → ${integrationBranch}`);\n return true;\n }\n\n // Branch is not checked out anywhere — use detached approaches.\n // Step 1: Find the merge base\n const { stdout: baseOut } = await execPromise(exec, 'git', ['merge-base', integrationBranch, worktreeName]);\n const mergeBase = baseOut.trim();\n\n // Step 2: Check if this is a fast-forward\n const { stdout: integrationSha } = await execPromise(exec, 'git', ['rev-parse', integrationBranch]);\n if (integrationSha.trim() === mergeBase) {\n const { stdout: worktreeSha } = await execPromise(exec, 'git', ['rev-parse', worktreeName]);\n await execPromise(exec, 'git', ['update-ref', `refs/heads/${integrationBranch}`, worktreeSha.trim()]);\n console.error(`[worktree] fast-forward merged ${worktreeName} → ${integrationBranch}`);\n return true;\n }\n\n // Step 3: Non-fast-forward — temp worktree (safe since branch is not checked out)\n const tmpWorktree = `merge-tmp-${Date.now()}`;\n try {\n await execPromise(exec, 'git', ['worktree', 'add', tmpWorktree, integrationBranch]);\n await execPromise(exec, 'git', ['-C', tmpWorktree, 'merge', '--no-edit', worktreeName]);\n console.error(`[worktree] merged ${worktreeName} → ${integrationBranch}`);\n } finally {\n await execPromise(exec, 'git', ['worktree', 'remove', '--force', tmpWorktree]).catch(() => {});\n }\n return true;\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n console.error(`[worktree] merge failed for ${worktreeName} → ${integrationBranch}: ${msg}`);\n return false;\n }\n}\n","/**\n * Pure firing constraint evaluator for the pipeline orchestrator.\n *\n * Ported from apps/api/src/services/firing-constraints.service.ts with\n * orchestrator-specific enhancements:\n * - `last_fired_at` resolved from in-memory Map (seconds since last fire)\n * - `active_loops` resolved from orchestrator runtime state\n *\n * This module has ZERO side-effects and ZERO external dependencies beyond\n * @kantban/types. All data flows in via the BoardState parameter.\n */\n\nimport type {\n FiringConstraint,\n EvaluateFiringConstraintResult,\n} from '@kantban/types';\n\n// ── Public Types ─────────────────────────────────────────────────────────────\n\nexport interface ColumnState {\n id: string;\n name: string;\n position: number;\n column_type: string;\n wip_limit: number | null;\n ticket_count: number;\n}\n\nexport interface BoardState {\n columns: ColumnState[];\n active_loops: Map<string, number>;\n /** Seconds since last fire per column. Missing key = never fired. */\n last_fired_at: Map<string, number>;\n circuit_breaker_count: number;\n backlog_ticket_count: number;\n}\n\nexport interface EvalSummary {\n total: number;\n passed: number;\n failed: number;\n errors: number;\n}\n\nexport interface EvalResult {\n results: EvaluateFiringConstraintResult[];\n summary: EvalSummary;\n}\n\n// ── Column Ref Resolution ────────────────────────────────────────────────────\n\nfunction resolveColumn(\n board: BoardState,\n columnId: string,\n subjectRef: string | null,\n): { column: ColumnState | null; error: string | null } {\n const ref = subjectRef ?? 'self';\n\n if (ref === 'self' || ref === null) {\n const col = board.columns.find((c) => c.id === columnId) ?? null;\n return { column: col, error: col ? null : `Column ${columnId} not found` };\n }\n\n if (ref === 'next') {\n const sorted = [...board.columns].sort((a, b) => a.position - b.position);\n const idx = sorted.findIndex((c) => c.id === columnId);\n const next = idx >= 0 && idx < sorted.length - 1 ? sorted[idx + 1]! : null;\n return { column: next, error: next ? null : 'No next column exists' };\n }\n\n if (ref === 'prev') {\n const sorted = [...board.columns].sort((a, b) => a.position - b.position);\n const idx = sorted.findIndex((c) => c.id === columnId);\n const prev = idx > 0 ? sorted[idx - 1]! : null;\n return { column: prev, error: prev ? null : 'No prev column exists' };\n }\n\n // UUID reference\n const col = board.columns.find((c) => c.id === ref) ?? null;\n return { column: col, error: col ? null : `Column ${ref} not found` };\n}\n\n// ── Operator Evaluation ──────────────────────────────────────────────────────\n\nfunction applyOperator(\n resolved: number | string | boolean,\n operator: string,\n threshold: number | string | boolean,\n): boolean {\n // For eq/neq: try numeric comparison when both sides are valid numbers\n // (DB may store numbers as strings e.g. resolved=3 vs threshold=\"3\")\n if (operator === 'eq' || operator === 'neq') {\n const rn = Number(resolved);\n const tn = Number(threshold);\n const bothNumeric = !isNaN(rn) && !isNaN(tn) && resolved !== '' && threshold !== '';\n const equal = bothNumeric ? rn === tn : resolved === threshold;\n return operator === 'eq' ? equal : !equal;\n }\n\n // For ordering operators, coerce to number\n const r = Number(resolved);\n const t = Number(threshold);\n if (isNaN(r) || isNaN(t)) return false;\n\n switch (operator) {\n case 'lt': return r < t;\n case 'lte': return r <= t;\n case 'gt': return r > t;\n case 'gte': return r >= t;\n default: return false;\n }\n}\n\n// ── Pure Evaluation Engine ───────────────────────────────────────────────────\n\nexport function evaluateConstraints(\n constraints: FiringConstraint[],\n board: BoardState,\n columnId: string,\n now?: Date,\n): EvalResult {\n // Filter to enabled column-scope only, sort by position ascending\n const enabled = constraints\n .filter((c) => c.enabled && c.scope === 'column')\n .sort((a, b) => a.position - b.position);\n\n const results: EvaluateFiringConstraintResult[] = [];\n const summary: EvalSummary = { total: 0, passed: 0, failed: 0, errors: 0 };\n\n for (const constraint of enabled) {\n summary.total++;\n\n let resolvedValue: number | string | boolean | null = null;\n let resolveError: string | null = null;\n\n const subjectType = constraint.subject_type;\n const subjectRef = constraint.subject_ref;\n\n switch (subjectType) {\n case 'column.ticket_count': {\n const { column, error } = resolveColumn(board, columnId, subjectRef);\n if (error || !column) {\n resolveError = error ?? 'Column resolution failed';\n } else {\n resolvedValue = column.ticket_count;\n }\n break;\n }\n\n case 'column.active_loops': {\n const { column, error } = resolveColumn(board, columnId, subjectRef);\n if (error || !column) {\n resolveError = error ?? 'Column resolution failed';\n } else {\n resolvedValue = board.active_loops.get(column.id) ?? 0;\n }\n break;\n }\n\n case 'column.wip_remaining': {\n const { column, error } = resolveColumn(board, columnId, subjectRef);\n if (error || !column) {\n resolveError = error ?? 'Column resolution failed';\n } else {\n resolvedValue = column.wip_limit === null ? 999999 : column.wip_limit - column.ticket_count;\n }\n break;\n }\n\n case 'column.last_fired_at': {\n const { column, error } = resolveColumn(board, columnId, subjectRef);\n if (error || !column) {\n resolveError = error ?? 'Column resolution failed';\n } else {\n // Seconds since last fire. If never fired, treat as Infinity (999999).\n const secondsSinceLastFire = board.last_fired_at.get(column.id);\n resolvedValue = secondsSinceLastFire ?? 999999;\n }\n break;\n }\n\n case 'board.total_active_loops': {\n let total = 0;\n for (const v of board.active_loops.values()) {\n total += v;\n }\n resolvedValue = total;\n break;\n }\n\n case 'board.circuit_breaker_count': {\n resolvedValue = board.circuit_breaker_count;\n break;\n }\n\n case 'backlog.ticket_count': {\n resolvedValue = board.backlog_ticket_count;\n break;\n }\n\n case 'ticket.field_value': {\n resolveError = 'ticket.field_value requires ticket context (ticket-scope only)';\n resolvedValue = null;\n break;\n }\n\n case 'time.hour': {\n const date = now ?? new Date();\n resolvedValue = date.getUTCHours();\n break;\n }\n\n default: {\n resolveError = `Unknown subject type: ${subjectType as string}`;\n break;\n }\n }\n\n // Fail-closed by default, unless fail_open explicitly set\n if (resolveError !== null) {\n summary.errors++;\n const failOpen = constraint.fail_open === true;\n const passed = failOpen;\n results.push({\n constraint_id: constraint.id,\n name: constraint.name,\n column_id: constraint.column_id,\n passed,\n resolved_value: null,\n threshold: { operator: constraint.operator, value: constraint.value },\n error: failOpen\n ? `Unresolvable (fail_open=true): ${resolveError}`\n : `Unresolvable (fail-closed): ${resolveError}`,\n });\n if (passed) {\n summary.passed++;\n } else {\n summary.failed++;\n }\n continue;\n }\n\n const passed = applyOperator(resolvedValue!, constraint.operator, constraint.value);\n results.push({\n constraint_id: constraint.id,\n name: constraint.name,\n column_id: constraint.column_id,\n passed,\n resolved_value: resolvedValue,\n threshold: { operator: constraint.operator, value: constraint.value },\n });\n\n if (passed) {\n summary.passed++;\n } else {\n summary.failed++;\n }\n }\n\n return { results, summary };\n}\n","import { LoopCheckpointSchema, type LoopCheckpoint } from '@kantban/types';\nexport type { LoopCheckpoint };\n\nexport const CHECKPOINT_FIELD = 'loop_checkpoint';\n/** Default stale threshold in minutes. 600 minutes = 10 hours. */\nconst DEFAULT_STALE_THRESHOLD_MINUTES = 600;\n\nexport interface CheckpointDeps {\n setFieldValue: (ticketId: string, fieldName: string, value: unknown) => Promise<void>;\n getFieldValues: (ticketId: string) => Promise<Array<{ field_name: string; value: unknown }>>;\n emitEvent?: (eventType: string, summary: string, ticketId: string) => void;\n}\n\nexport async function writeCheckpoint(\n deps: CheckpointDeps,\n ticketId: string,\n checkpoint: LoopCheckpoint,\n): Promise<void> {\n try {\n await deps.setFieldValue(ticketId, CHECKPOINT_FIELD, checkpoint);\n } catch (err) {\n // Fire-and-forget: checkpoint writes must never block the loop\n const msg = err instanceof Error ? err.message : String(err);\n console.warn(`[checkpoint] writeCheckpoint failed for ${ticketId}: ${msg}`);\n deps.emitEvent?.('checkpoint_write_failed', `Checkpoint write failed: ${msg}`, ticketId);\n }\n}\n\nexport async function readCheckpoint(\n deps: CheckpointDeps,\n ticketId: string,\n currentColumnId: string,\n staleMinutes?: number,\n): Promise<LoopCheckpoint | null> {\n try {\n const fields = await deps.getFieldValues(ticketId);\n const entry = fields.find((f) => f.field_name === CHECKPOINT_FIELD);\n if (!entry) return null;\n\n // Value is stored as a JSON string in a long_text field — parse it first\n let raw = entry.value;\n if (typeof raw === 'string') {\n if (!raw.trim()) return null;\n try { raw = JSON.parse(raw); } catch { return null; }\n }\n\n const parsed = LoopCheckpointSchema.safeParse(raw);\n if (!parsed.success) return null;\n\n const checkpoint = parsed.data;\n\n if (checkpoint.column_id !== currentColumnId) return null;\n\n const threshold = Math.max(staleMinutes ?? DEFAULT_STALE_THRESHOLD_MINUTES, 1);\n const updatedAt = new Date(checkpoint.updated_at).getTime();\n const ageMinutes = (Date.now() - updatedAt) / (1000 * 60);\n if (ageMinutes > threshold) return null;\n\n return checkpoint;\n } catch (err) {\n console.warn(`[checkpoint] readCheckpoint failed for ${ticketId}: ${err instanceof Error ? err.message : String(err)}`);\n return null;\n }\n}\n\nexport async function clearCheckpoint(\n deps: CheckpointDeps,\n ticketId: string,\n): Promise<void> {\n try {\n await deps.setFieldValue(ticketId, CHECKPOINT_FIELD, '');\n } catch (err) {\n // Fire-and-forget: checkpoint clears must never block the loop\n console.warn(`[checkpoint] clearCheckpoint failed for ${ticketId}: ${err instanceof Error ? err.message : String(err)}`);\n }\n}\n","import { VerdictSchema, type Verdict, type GateResult } from '@kantban/types';\nimport { parseJsonFromLlmOutput } from './parse-utils.js';\n\nconst ADVERSARIAL_PREAMBLE = `You are an ADVERSARIAL REVIEWER. Your job is to find problems, not to approve.\n\nRules:\n1. You MUST return a structured verdict using submit_verdict (see below).\n2. Finding no problems is acceptable but suspicious — look harder before approving.\n3. The agent that did this work will tell you it's great. It's lying. Check everything.\n4. You have full tool access. Use it to probe claims — run tests, read code, check builds.\n5. Gate results show objective pass/fail. Your job is everything gates CAN'T check:\n code quality, architecture fit, edge cases, security, naming, duplication.\n6. Do NOT fix problems. Document them in your verdict. The worker agent will fix them.`;\n\ninterface EvaluatorPromptInput {\n ticketTitle: string;\n ticketNumber: number;\n columnPrompt: string;\n diff: string;\n gateResults: GateResult[];\n handoff: Record<string, unknown>;\n}\n\nexport function composeEvaluatorPrompt(input: EvaluatorPromptInput): string {\n const parts: string[] = [];\n\n parts.push(ADVERSARIAL_PREAMBLE);\n parts.push(`\\n## Ticket: #${input.ticketNumber} \"${input.ticketTitle}\"`);\n\n // Column prompt (review instructions)\n parts.push(`\\n## Review Instructions\\n${input.columnPrompt}`);\n\n // Handoff data from worker\n if (Object.keys(input.handoff).length > 0) {\n parts.push(`\\n## Handoff Data\\n${JSON.stringify(input.handoff, null, 2)}`);\n }\n\n // Gate results from worker column\n if (input.gateResults.length > 0) {\n parts.push(`\\n## Worker Gate Results`);\n for (const r of input.gateResults) {\n parts.push(`- ${r.name}: ${r.passed ? 'PASS' : 'FAIL'}${r.required ? ' (required)' : ''}`);\n }\n }\n\n // Diff\n if (input.diff) {\n parts.push(`\\n## Code Changes\\n\\`\\`\\`diff\\n${input.diff}\\n\\`\\`\\``);\n }\n\n parts.push(`\\n## Verdict Format\nCall submit_verdict with a JSON object:\n{\n \"decision\": \"approve\" | \"reject\",\n \"summary\": \"one-line summary\",\n \"findings\": [\n { \"severity\": \"blocker\" | \"warning\" | \"nit\", \"description\": \"...\", \"file\": \"...\", \"line\": N }\n ]\n}\n\nIf you do NOT call submit_verdict, the harness will treat this as a reject.`);\n\n return parts.join('\\n');\n}\n\nexport function parseVerdict(raw: string): Verdict & { parseFailed?: boolean } {\n try {\n const parsed = parseJsonFromLlmOutput(raw);\n return VerdictSchema.parse(parsed);\n } catch (err) {\n const msg = err instanceof Error ? err.message : 'unknown';\n return {\n decision: 'reject',\n summary: `Evaluator verdict parse error: ${msg.slice(0, 100)}`,\n findings: [{ severity: 'blocker', description: `Verdict parse error — raw output did not contain valid JSON verdict. Error: ${msg.slice(0, 200)}` }],\n parseFailed: true,\n };\n }\n}\n\nexport type VerdictAction = 'forward' | 'reject' | 'forward_with_signals';\n\nexport function resolveVerdictAction(verdict: Verdict): VerdictAction {\n if (verdict.decision === 'approve') return 'forward';\n\n const hasBlockers = verdict.findings.some((f) => f.severity === 'blocker');\n if (hasBlockers || verdict.findings.length === 0) return 'reject';\n\n // Reject with only warnings/nits → forward with signals\n return 'forward_with_signals';\n}\n","import { z } from 'zod';\nimport { parseJsonFromLlmOutput } from './parse-utils.js';\n\nexport interface ReplannerTriggers {\n escalation_count: number;\n cost_threshold_pct: number;\n repeated_gate_failure_count: number;\n duration_threshold_minutes: number;\n}\n\nexport interface PipelineState {\n escalatedTickets: number;\n totalTokensIn: number;\n maxInputTokens: number;\n repeatedGateFailures: Record<string, number>; // gate name → failure count across tickets\n durationMinutes: number;\n}\n\nexport function shouldFireReplanner(triggers: ReplannerTriggers, state: PipelineState): boolean {\n if (state.escalatedTickets >= triggers.escalation_count) return true;\n if (state.maxInputTokens > 0) {\n const pct = (state.totalTokensIn / state.maxInputTokens) * 100;\n if (pct >= triggers.cost_threshold_pct) return true;\n }\n for (const count of Object.values(state.repeatedGateFailures)) {\n if (count >= triggers.repeated_gate_failure_count) return true;\n }\n if (state.durationMinutes >= triggers.duration_threshold_minutes) return true;\n return false;\n}\n\nconst ReplannerActionSchema = z.enum([\n 'CONTINUE', 'PAUSE_PIPELINE', 'ARCHIVE_TICKETS', 'CREATE_SIGNAL', 'ADJUST_BUDGET', 'ESCALATE_ALL',\n]);\n\nconst ReplannerResponseSchema = z.object({\n action: ReplannerActionSchema,\n reason: z.string(),\n ticket_ids: z.array(z.string()).optional(),\n signal_content: z.string().optional(),\n new_max_input_tokens: z.number().optional(),\n});\nexport type ReplannerResponse = z.infer<typeof ReplannerResponseSchema>;\n\nexport function composeReplannerPrompt(state: PipelineState & {\n ticketSummaries: Array<{ id: string; title: string; column: string; status: string; iterations: number; gatePassRate: number }>;\n triggerReason: string;\n}): string {\n const parts: string[] = [];\n parts.push('You are a pipeline replanner. A trigger threshold has been crossed.');\n parts.push(`\\nTrigger: ${state.triggerReason}`);\n parts.push(`\\nPipeline State:`);\n parts.push(`- Escalated tickets: ${state.escalatedTickets}`);\n parts.push(`- Token usage: ${state.totalTokensIn} / ${state.maxInputTokens}`);\n parts.push(`- Duration: ${state.durationMinutes} minutes`);\n\n if (Object.keys(state.repeatedGateFailures).length > 0) {\n parts.push(`\\nRepeated gate failures:`);\n for (const [gate, count] of Object.entries(state.repeatedGateFailures)) {\n parts.push(`- ${gate}: ${count} tickets failing`);\n }\n }\n\n parts.push(`\\nTicket summaries:`);\n for (const t of state.ticketSummaries) {\n parts.push(`- ${t.title} [${t.column}] status=${t.status} iterations=${t.iterations} gate_pass=${t.gatePassRate}%`);\n }\n\n parts.push(`\\nActions available: CONTINUE, PAUSE_PIPELINE, ARCHIVE_TICKETS, CREATE_SIGNAL, ADJUST_BUDGET, ESCALATE_ALL`);\n parts.push(`\\nBe conservative. Primary value is knowing when to stop.`);\n parts.push(`\\nRespond with a JSON object: { \"action\": \"...\", \"reason\": \"...\" }`);\n\n return parts.join('\\n');\n}\n\nexport function parseReplannerResponse(raw: string): ReplannerResponse {\n try {\n const parsed = parseJsonFromLlmOutput(raw);\n return ReplannerResponseSchema.parse(parsed);\n } catch {\n return { action: 'PAUSE_PIPELINE', reason: 'Failed to parse replanner response — defaulting to pause for safety' };\n }\n}\n","import type { LoopConfig, LoopResult } from './ralph-loop.js';\nimport { resolveToolRestrictions } from './tool-profiles.js';\nimport { generateWorktreeName } from './worktree.js';\nimport type { PipelineEvent } from './event-queue.js';\nimport type { PipelineEventEmitter } from './event-emitter.js';\nimport type { PipelineCostTracker } from './cost-tracker.js';\nimport { evaluateConstraints, type BoardState, type EvalResult } from './constraint-evaluator.js';\nimport type { FiringConstraint, TicketFingerprint } from '@kantban/types';\nimport type { AdvisorInput, AdvisorResponse } from './advisor.js';\nimport type { GateSnapshotStore } from './gate-snapshot.js';\nimport { classifyTrajectory } from './stuck-detector.js';\nimport { readCheckpoint } from './checkpoint.js';\nimport { parseVerdict, resolveVerdictAction } from './evaluator.js';\nimport { shouldFireReplanner, type ReplannerTriggers, type PipelineState, type ReplannerResponse } from './replanner.js';\n\n/**\n * Shape of a board-scope column as returned by fetchBoardScope.\n */\ninterface BoardColumn {\n id: string;\n name: string;\n type: string;\n position: number;\n wip_limit: number | null;\n goal: string;\n ticket_count: number;\n has_prompt: boolean;\n}\n\n/**\n * Shape of the board-scope response.\n */\ninterface BoardScope {\n scope: string;\n board: { id: string; name: string };\n columns: BoardColumn[];\n circuit_breaker: { threshold: number | null; target_column_id: string | null };\n backlog_ticket_count: number;\n tool_prefix: string;\n}\n\n/**\n * Firing constraint shape as returned by column scope (snake_case from API).\n */\ninterface FiringConstraintLite {\n id: string;\n name: string;\n enabled: boolean;\n subject_type: string;\n subject_ref: string | null;\n operator: string;\n value: number | string | boolean;\n scope: string;\n notify: boolean;\n column_id: string | null;\n fail_open?: boolean;\n system?: boolean;\n}\n\n/**\n * Shape of a ticket summary in column scope.\n */\ninterface ColumnTicket {\n id: string;\n ticket_number: number;\n title: string;\n}\n\n/**\n * Agent config from column scope.\n */\ninterface ColumnAgentConfig {\n execution_mode?: string | undefined;\n model_preference?: string | undefined;\n max_iterations?: number | undefined;\n max_budget_usd?: number | null | undefined;\n concurrency?: number | undefined;\n gutter_threshold?: number | undefined;\n poll_interval_seconds?: number | undefined;\n worktree?: { enabled: boolean; path_pattern?: string; on_move?: string; on_done?: string; integration_branch?: string } | undefined;\n invocation_tier?: string | undefined;\n lookahead_column_id?: string | undefined;\n run_memory?: boolean | undefined;\n advisor?: { enabled: boolean; max_invocations?: number; model?: string } | undefined;\n checkpoint?: boolean | undefined;\n model_routing?: { initial: string; escalation: string[]; escalate_after?: number } | undefined;\n stuck_detection?: { enabled: boolean; first_check?: number; interval?: number } | undefined;\n builtin_tools?: string | undefined;\n allowed_tools?: string[] | undefined;\n disallowed_tools?: string[] | undefined;\n}\n\n/**\n * Shape of the column-scope response.\n */\ninterface ColumnScope {\n scope: string;\n column: { id: string; name: string; goal: string };\n prompt_document: { id: string; title: string; content: string } | null;\n agent_config: ColumnAgentConfig | null;\n tickets: ColumnTicket[];\n transition_rules: string;\n signals: unknown[];\n field_definitions: unknown[];\n firing_constraints?: FiringConstraintLite[];\n tool_prefix: string;\n}\n\n/**\n * Per-column configuration cached after initialization.\n */\ninterface ColumnConfig {\n columnId: string;\n name: string;\n columnType?: string | undefined;\n concurrency: number;\n maxIterations: number;\n gutterThreshold: number;\n modelPreference?: string | undefined;\n maxBudgetUsd?: number | null | undefined;\n worktreeEnabled?: boolean | undefined;\n worktreeOnMove?: 'keep' | 'merge' | 'cleanup' | undefined;\n worktreeOnDone?: 'pr' | 'merge' | 'cleanup' | undefined;\n worktreeIntegrationBranch?: string | undefined;\n invocationTier?: 'auto' | 'light' | 'heavy' | undefined;\n lookaheadColumnId?: string | undefined;\n runMemory?: boolean | undefined;\n advisorEnabled?: boolean | undefined;\n advisorMaxInvocations?: number | undefined;\n advisorModel?: string | undefined;\n checkpointEnabled?: boolean | undefined;\n modelRouting?: { initial: string; escalation: string[]; escalateAfter: number } | undefined;\n stuckDetection?: { enabled: boolean; firstCheck: number; interval: number } | undefined;\n builtinTools?: string | undefined;\n allowedTools?: string[] | undefined;\n disallowedTools?: string[] | undefined;\n}\n\n/**\n * Active loop tracking entry.\n */\ninterface ActiveLoop {\n columnId: string;\n promise: Promise<LoopResult>;\n}\n\n/**\n * A ticket that is blocked by another ticket, with its current column.\n */\ninterface BlockedTicket {\n id: string;\n column_id: string | null;\n}\n\n/**\n * Injectable dependencies for the PipelineOrchestrator.\n * Allows full testability via dependency injection.\n */\nexport interface OrchestratorDeps {\n fetchBoardScope: (boardId: string) => Promise<BoardScope>;\n fetchColumnScope: (columnId: string) => Promise<ColumnScope>;\n startLoop: (ticketId: string, columnId: string, config: LoopConfig) => Promise<LoopResult>;\n createComment: (ticketId: string, body: string) => Promise<void>;\n createSignal: (ticketId: string, body: string) => Promise<void>;\n /** Create a signal on a column when a firing constraint blocks with notify=true */\n createColumnSignal?: (columnId: string, body: string) => Promise<void>;\n /** Create-or-replace a signal keyed by content prefix. Used for ephemeral constraint notifications. */\n upsertColumnSignal?: (columnId: string, contentPrefix: string, body: string) => Promise<void>;\n claimTicket: (ticketId: string) => Promise<void>;\n fetchBlockedTickets: (ticketId: string) => Promise<BlockedTicket[]>;\n hasUnresolvedBlockers: (ticketId: string) => Promise<boolean>;\n /** Dispatch a light call for simple ticket operations. Returns the parsed response. */\n dispatchLightCall?: ((ticketId: string, columnId: string) => Promise<{\n action: string;\n params: Record<string, unknown>;\n reason: string;\n }>) | undefined;\n /** Invoke the advisor for failure recovery */\n invokeAdvisor?: ((input: AdvisorInput) => Promise<AdvisorResponse>) | undefined;\n /** Set a field value on a ticket (for debt items, checkpoint) */\n setFieldValue?: ((ticketId: string, fieldName: string, value: unknown) => Promise<void>) | undefined;\n /** Move ticket to a specific column (for ESCALATE) */\n moveTicketToColumn?: ((ticketId: string, columnId: string, handoff: Record<string, unknown>) => Promise<void>) | undefined;\n /** Create child tickets (for SPLIT_TICKET) */\n createTickets?: ((parentTicketId: string, specs: Array<{ title: string; description: string }>) => Promise<string[]>) | undefined;\n /** Archive a ticket (for SPLIT_TICKET — archive parent) */\n archiveTicket?: ((ticketId: string) => Promise<void>) | undefined;\n /** Get field values for a ticket (for checkpoint reads) */\n getFieldValues?: ((ticketId: string) => Promise<Array<{ field_name: string; value: unknown }>>) | undefined;\n /** Append a discovery to the run memory document */\n appendRunMemory?: ((section: string, content: string) => Promise<void>) | undefined;\n /** Clean up a git worktree after terminal loop exit */\n cleanupWorktree?: ((worktreeName: string) => Promise<boolean>) | undefined;\n /** Merge a worktree branch into an integration branch */\n mergeWorktree?: ((worktreeName: string, integrationBranch: string) => Promise<boolean>) | undefined;\n /** Forward pipeline events to the WS client for browser delivery */\n emitPipelineEvent?: ((event: { type: string; payload: Record<string, unknown> }) => void) | undefined;\n /** Board ID for pipeline event context */\n boardId?: string | undefined;\n /** Cost tracker for token budget enforcement */\n costTracker?: PipelineCostTracker | undefined;\n /** Gate snapshot store for tracking per-ticket gate history */\n gateSnapshotStore?: GateSnapshotStore | undefined;\n /** Emit structured pipeline events to the API for introspection */\n eventEmitter?: PipelineEventEmitter | undefined;\n /** Invoke the replanner for pipeline-wide trigger evaluation */\n invokeReplanner?: ((state: PipelineState & { ticketSummaries: Array<{ id: string; title: string; column: string; status: string; iterations: number; gatePassRate: number }>; triggerReason: string }) => Promise<ReplannerResponse>) | undefined;\n}\n\ninterface TierClassificationInput {\n hasPromptDocument: boolean;\n invocationTier: 'auto' | 'light' | 'heavy' | undefined;\n}\n\nexport function classifyTier(input: TierClassificationInput): 'light' | 'heavy' {\n if (input.invocationTier === 'light') return 'light';\n if (input.invocationTier === 'heavy') return 'heavy';\n if (!input.hasPromptDocument) return 'light';\n return 'heavy';\n}\n\n/**\n * PipelineOrchestrator — coordination layer for Ralph Loops.\n *\n * Discovers pipeline columns (has_prompt=true, type !== 'done'),\n * spawns loops for tickets with concurrency limits per column,\n * and handles WebSocket events for dynamic ticket arrivals.\n */\nexport class PipelineOrchestrator {\n private boardId: string;\n private projectId: string;\n private deps: OrchestratorDeps;\n\n /** Column ID -> column configuration */\n private pipelineColumns: Map<string, ColumnConfig> = new Map();\n\n /** Column ID -> cached column scope (from initialize) */\n private columnScopes: Map<string, ColumnScope> = new Map();\n\n /** Ticket ID -> active loop tracking */\n private activeLoops: Map<string, ActiveLoop> = new Map();\n\n /** Column ID -> queued ticket IDs (FIFO) */\n private loopQueues: Map<string, string[]> = new Map();\n\n /** Ticket IDs that have been spawned or queued (prevents re-processing) */\n private knownTickets: Set<string> = new Set();\n\n /** Tickets deferred because they have unresolved blockers. Re-queued when a blocker reaches Done. */\n private deferredTickets: Map<string, string> = new Map(); // ticketId → columnId\n\n /** Ticket IDs currently in the spawning process (prevents double-spawn race) */\n private spawning: Set<string> = new Set();\n\n /** Ticket IDs currently in onLoopComplete (prevents double-spawn during async advisor recovery) */\n private completing: Set<string> = new Set();\n\n /** Per-column reservation count for in-flight spawns (prevents concurrency overshoot) */\n private columnReservations: Map<string, number> = new Map();\n\n /** Cached board scope for constraint evaluation — refreshed each scan cycle */\n private cachedBoardScope: BoardScope | null = null;\n\n /** Last time a loop was spawned per column — for column.last_fired_at subject */\n private lastFiredAt: Map<string, Date> = new Map();\n\n /** Column IDs currently blocked by firing constraints (prevents redundant re-evaluation within a scan) */\n private blockedColumns: Set<string> = new Set();\n\n /** Per-ticket advisor invocation count for the current column transit */\n private advisorBudget: Map<string, number> = new Map();\n\n /** Per-ticket model override (set by RETRY_DIFFERENT_MODEL, consumed by startTrackedLoop) */\n private ticketModelOverrides: Map<string, string> = new Map();\n\n /** Stable session ID for this orchestrator instance (pipeline run) */\n private readonly sessionId: string;\n\n /** Replanner invocation count for the current pipeline run */\n private replannerInvocations = 0;\n\n /** Maximum replanner invocations before auto-pause */\n private replannerMaxInvocations = 3;\n\n /** When true, pipeline is paused — scanAndSpawn and spawnOrQueue will skip */\n private pipelinePaused = false;\n\n /** Per-column consecutive scope refresh failure counts — auto-pauses after 3 for any column */\n private columnScopeRefreshFailures = new Map<string, number>();\n\n /** Consecutive board scope refresh failure count — auto-pauses after 3 */\n private boardScopeRefreshFailures = 0;\n\n /** Timestamp when the pipeline started (for duration-based replanner triggers) */\n private pipelineStartTime = Date.now();\n\n constructor(boardId: string, projectId: string, deps: OrchestratorDeps) {\n this.boardId = boardId;\n this.projectId = projectId;\n this.deps = deps;\n this.sessionId = crypto.randomUUID();\n }\n\n /**\n * Execute an async action with logged error handling.\n * Returns true if the action succeeded, false if it threw.\n * Non-blocking — callers can ignore the return value for fire-and-forget.\n */\n private async safeAction(ticketId: string, label: string, fn: () => Promise<unknown>): Promise<boolean> {\n try {\n await fn();\n return true;\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n console.error(` [error] ${label} failed for ${ticketId}: ${msg}`);\n return false;\n }\n }\n\n /** Returns the IDs of all discovered pipeline columns. */\n get pipelineColumnIds(): string[] {\n return Array.from(this.pipelineColumns.keys());\n }\n\n /** Returns the total number of active loops. */\n get activeLoopCount(): number {\n return this.activeLoops.size;\n }\n\n /** Returns true if any tickets are queued or deferred (waiting for a slot). */\n get hasQueuedWork(): boolean {\n for (const [, queue] of this.loopQueues) {\n if (queue.length > 0) return true;\n }\n return this.deferredTickets.size > 0 || this.spawning.size > 0;\n }\n\n /** Returns true if any tickets are queued (waiting for a slot) or spawning — excludes deferred tickets. */\n get hasActiveQueuedWork(): boolean {\n for (const [, queue] of this.loopQueues) {\n if (queue.length > 0) return true;\n }\n return this.spawning.size > 0;\n }\n\n /** Returns true if any onLoopComplete callbacks are still running (for --once mode drain). */\n get hasCompletingWork(): boolean {\n return this.completing.size > 0;\n }\n\n /** Returns the number of queued (waiting) tickets for a column. */\n queuedCount(columnId: string): number {\n return this.loopQueues.get(columnId)?.length ?? 0;\n }\n\n /**\n * Initialize the orchestrator: fetch board scope, identify pipeline columns,\n * and fetch column-level agent configs.\n */\n async initialize(columnFilter?: string | null): Promise<void> {\n const boardScope = await this.deps.fetchBoardScope(this.boardId);\n this.cachedBoardScope = boardScope;\n\n // Identify pipeline columns: (has_prompt=true OR type=evaluator) AND type !== 'done'\n let pipelineCols = boardScope.columns.filter(\n (col) => (col.has_prompt || col.type === 'evaluator') && col.type !== 'done',\n );\n\n // Apply column filter if specified (matches by ID or name)\n if (columnFilter) {\n pipelineCols = pipelineCols.filter(\n (col) => col.id === columnFilter || col.name.toLowerCase() === columnFilter.toLowerCase(),\n );\n }\n\n // Fetch column scope for each pipeline column to get agent_config and tickets\n await Promise.all(\n pipelineCols.map(async (col) => {\n const colScope = await this.deps.fetchColumnScope(col.id);\n const cfg = colScope.agent_config;\n\n this.pipelineColumns.set(col.id, {\n columnId: col.id,\n name: col.name,\n columnType: col.type,\n concurrency: cfg?.concurrency ?? 1,\n maxIterations: cfg?.max_iterations ?? 10,\n gutterThreshold: cfg?.gutter_threshold ?? 3,\n modelPreference: cfg?.model_preference,\n maxBudgetUsd: cfg?.max_budget_usd,\n worktreeEnabled: cfg?.worktree?.enabled,\n worktreeOnMove: cfg?.worktree?.on_move as ColumnConfig['worktreeOnMove'],\n worktreeOnDone: cfg?.worktree?.on_done as ColumnConfig['worktreeOnDone'],\n worktreeIntegrationBranch: cfg?.worktree?.integration_branch,\n invocationTier: cfg?.invocation_tier as 'auto' | 'light' | 'heavy' | undefined,\n lookaheadColumnId: cfg?.lookahead_column_id as string | undefined,\n runMemory: cfg?.run_memory as boolean | undefined,\n advisorEnabled: cfg?.advisor?.enabled,\n advisorMaxInvocations: cfg?.advisor?.max_invocations ?? 2,\n advisorModel: cfg?.advisor?.model ?? 'haiku',\n checkpointEnabled: cfg?.checkpoint,\n modelRouting: cfg?.model_routing ? {\n initial: cfg.model_routing.initial,\n escalation: cfg.model_routing.escalation,\n escalateAfter: cfg.model_routing.escalate_after ?? 2,\n } : undefined,\n stuckDetection: cfg?.stuck_detection?.enabled ? {\n enabled: true,\n firstCheck: cfg.stuck_detection.first_check ?? 3,\n interval: cfg.stuck_detection.interval ?? 2,\n } : undefined,\n builtinTools: cfg?.builtin_tools,\n allowedTools: cfg?.allowed_tools as string[] | undefined,\n disallowedTools: cfg?.disallowed_tools as string[] | undefined,\n });\n\n // Cache column scope for scanAndSpawn\n this.columnScopes.set(col.id, colScope);\n\n // Initialize the queue for this column\n this.loopQueues.set(col.id, []);\n }),\n );\n }\n\n /**\n * Refresh the cached column scope for a single column.\n * Keeps stale scope on error rather than crashing.\n */\n async refreshColumnScope(columnId: string): Promise<void> {\n try {\n const colScope = await this.deps.fetchColumnScope(columnId);\n this.columnScopes.set(columnId, colScope);\n this.columnScopeRefreshFailures.delete(columnId);\n } catch (err) {\n const count = (this.columnScopeRefreshFailures.get(columnId) ?? 0) + 1;\n this.columnScopeRefreshFailures.set(columnId, count);\n const msg = err instanceof Error ? err.message : String(err);\n console.error(` [warn] refreshColumnScope failed for ${columnId} (attempt ${count}, keeping stale): ${msg}`);\n if (count >= 3) {\n console.error(` [error] 3 consecutive scope refresh failures for column ${columnId} — pausing pipeline`);\n this.pipelinePaused = true;\n }\n }\n }\n\n /**\n * Refresh the cached board scope. Called at the start of each scan cycle\n * to get fresh ticket counts for constraint evaluation.\n */\n private async refreshBoardScope(): Promise<void> {\n try {\n this.cachedBoardScope = await this.deps.fetchBoardScope(this.boardId);\n this.boardScopeRefreshFailures = 0;\n // Auto-unpause if pipeline was paused due to scope refresh failures\n if (this.pipelinePaused) {\n const anyColumnFailing = Array.from(this.columnScopeRefreshFailures.values()).some(c => c >= 3);\n if (!anyColumnFailing) {\n console.error(' [info] Scope refresh succeeded — unpausing pipeline');\n this.pipelinePaused = false;\n }\n }\n } catch (err) {\n this.boardScopeRefreshFailures++;\n const msg = err instanceof Error ? err.message : String(err);\n console.error(` [warn] refreshBoardScope failed (attempt ${this.boardScopeRefreshFailures}, keeping stale): ${msg}`);\n if (this.boardScopeRefreshFailures >= 3) {\n console.error(' [error] 3 consecutive scope refresh failures — pausing pipeline');\n this.pipelinePaused = true;\n }\n }\n }\n\n /**\n * Public method to invalidate constraint caches when WS events arrive\n * (firing_constraint:created/updated/deleted). Forces re-fetch on next access.\n */\n async refreshConstraints(): Promise<void> {\n // Re-fetch column scopes to get updated firing_constraints arrays\n await Promise.all(\n Array.from(this.pipelineColumns.keys()).map((colId) => this.refreshColumnScope(colId)),\n );\n this.blockedColumns.clear();\n }\n\n /**\n * Build the BoardState required by the constraint evaluator from current\n * orchestrator state + cached board scope.\n */\n private buildBoardState(): BoardState {\n const bs = this.cachedBoardScope;\n if (!bs) {\n return {\n columns: [],\n active_loops: new Map(),\n last_fired_at: new Map(),\n circuit_breaker_count: 0,\n backlog_ticket_count: 0,\n };\n }\n\n // Compute active loops per column\n const activeLoopsPerColumn = new Map<string, number>();\n for (const [, loop] of this.activeLoops) {\n activeLoopsPerColumn.set(loop.columnId, (activeLoopsPerColumn.get(loop.columnId) ?? 0) + 1);\n }\n\n // Compute seconds since last fire per column\n const now = Date.now();\n const lastFiredSeconds = new Map<string, number>();\n for (const [colId, firedAt] of this.lastFiredAt) {\n lastFiredSeconds.set(colId, Math.floor((now - firedAt.getTime()) / 1000));\n }\n\n // Circuit breaker count = ticket count in circuit breaker target column\n let circuitBreakerCount = 0;\n if (bs.circuit_breaker.target_column_id) {\n const targetCol = bs.columns.find((c) => c.id === bs.circuit_breaker.target_column_id);\n if (targetCol) circuitBreakerCount = targetCol.ticket_count;\n }\n\n return {\n columns: bs.columns.map((c) => ({\n id: c.id,\n name: c.name,\n position: c.position,\n column_type: c.type,\n wip_limit: c.wip_limit,\n ticket_count: c.ticket_count,\n })),\n active_loops: activeLoopsPerColumn,\n last_fired_at: lastFiredSeconds,\n circuit_breaker_count: circuitBreakerCount,\n backlog_ticket_count: bs.backlog_ticket_count,\n };\n }\n\n /**\n * Convert FiringConstraintLite from column scope to full FiringConstraint\n * expected by the evaluator.\n */\n private toFiringConstraints(lites: FiringConstraintLite[]): FiringConstraint[] {\n return lites.map((c) => ({\n id: c.id,\n project_id: this.projectId,\n board_id: this.boardId,\n column_id: c.column_id,\n name: c.name,\n description: null,\n enabled: c.enabled,\n subject_type: c.subject_type as FiringConstraint['subject_type'],\n subject_ref: c.subject_ref,\n subject_param: null,\n operator: c.operator as FiringConstraint['operator'],\n value: c.value,\n scope: c.scope as FiringConstraint['scope'],\n notify: c.notify,\n position: 0,\n fail_open: c.fail_open ?? false,\n system: c.system ?? false,\n created_at: '',\n updated_at: '',\n }));\n }\n\n /**\n * Evaluate firing constraints for a column. Returns the EvalResult if any\n * constraint failed, or null if all passed (column is clear to fire).\n *\n * Handles logging and optional signal creation for blocked columns.\n */\n private evaluateColumnConstraints(columnId: string): EvalResult | null {\n const colScope = this.columnScopes.get(columnId);\n\n // Build constraint list: user-defined + synthetic safety net\n let constraints: FiringConstraint[] = [];\n\n if (colScope?.firing_constraints && colScope.firing_constraints.length > 0) {\n constraints = this.toFiringConstraints(colScope.firing_constraints);\n }\n\n // Synthetic safety net: if this is a pipeline column with a prompt but no\n // user-defined column.ticket_count constraint, inject one to prevent\n // firing on empty lanes. This is the runtime guarantee — even if the\n // persisted system constraint is deleted, we never waste tokens.\n const hasTicketCountConstraint = constraints.some(\n (c) => c.enabled && c.scope === 'column' && c.subject_type === 'column.ticket_count'\n && (c.subject_ref === null || c.subject_ref === 'self'),\n );\n if (!hasTicketCountConstraint && this.pipelineColumns.has(columnId)) {\n constraints.push({\n id: '00000000-0000-0000-0000-000000000000',\n project_id: this.projectId,\n board_id: this.boardId,\n column_id: columnId,\n name: 'Minimum tickets (synthetic)',\n description: null,\n enabled: true,\n subject_type: 'column.ticket_count',\n subject_ref: null,\n subject_param: null,\n operator: 'gt',\n value: 0,\n scope: 'column',\n notify: false,\n position: -1,\n fail_open: false,\n system: true,\n created_at: '',\n updated_at: '',\n });\n }\n\n if (constraints.length === 0) {\n return null;\n }\n\n const boardState = this.buildBoardState();\n const result = evaluateConstraints(constraints, boardState, columnId);\n\n if (result.summary.failed === 0) {\n return null; // All passed\n }\n\n // Log each failed constraint clearly\n const colName = colScope?.column.name ?? columnId;\n for (const r of result.results) {\n if (!r.passed && !r.error) {\n console.error(\n ` [blocked] Column \"${colName}\" (${columnId}): constraint \"${r.name}\" ` +\n `FAILED — resolved=${String(r.resolved_value)} ${r.threshold.operator} ${String(r.threshold.value)}`,\n );\n }\n }\n\n // Emit constraint events\n for (const r of result.results) {\n if (!r.passed && !r.error) {\n this.deps.eventEmitter?.emit({\n layer: 'constraint',\n eventType: 'constraint_blocked',\n severity: 'failure',\n summary: `Constraint \"${r.name}\" blocked [${colName}]`,\n detail: {\n constraint_name: r.name,\n constraint_id: r.constraint_id,\n resolved_value: r.resolved_value,\n threshold: { operator: r.threshold.operator, value: r.threshold.value },\n fail_open: false,\n blocked_tickets: [],\n column_name: colName,\n },\n columnId,\n });\n }\n }\n\n if (result.summary.errors > 0) {\n for (const r of result.results) {\n if (r.error) {\n console.error(\n ` [constraint-error] Column \"${colName}\" (${columnId}): \"${r.name}\" — ${r.error} (fail-open)`,\n );\n }\n }\n }\n\n // Handle notify flag: upsert signals for blocked constraints (replace, don't accumulate)\n const constraintMap = new Map(constraints.map((c) => [c.id, c]));\n for (const r of result.results) {\n if (!r.passed && !r.error) {\n const constraint = constraintMap.get(r.constraint_id);\n if (constraint?.notify && this.deps.upsertColumnSignal) {\n const prefix = `Firing constraint \"${r.name}\" blocked`;\n const body = `${prefix} column: resolved=${String(r.resolved_value)} ${r.threshold.operator} ${String(r.threshold.value)}`;\n void this.deps.upsertColumnSignal(columnId, prefix, body).catch((err) => {\n const msg = err instanceof Error ? err.message : String(err);\n console.error(` [warn] Failed to upsert constraint signal: ${msg}`);\n });\n }\n }\n }\n\n return result;\n }\n\n /**\n * Check if a column is blocked by firing constraints.\n * Returns true if blocked (should not fire), false if clear.\n */\n isColumnBlocked(columnId: string): boolean {\n const result = this.evaluateColumnConstraints(columnId);\n return result !== null;\n }\n\n /**\n * Scan all pipeline columns for existing tickets and spawn loops.\n * Refreshes column scopes before scanning to avoid stale ticket lists.\n * Evaluates firing constraints per column before processing tickets.\n * Respects per-column concurrency limits — excess tickets are queued.\n */\n async scanAndSpawn(): Promise<void> {\n if (this.pipelinePaused) {\n console.error(' [scan] Pipeline paused by replanner — skipping scan');\n return;\n }\n\n if (this.deps.costTracker?.isExhausted()) {\n if (!this.pipelinePaused) {\n this.pipelinePaused = true;\n console.error('[budget] Token budget exhausted — pausing pipeline');\n }\n return;\n }\n\n // Reset knownTickets each scan cycle so that completed loops can be\n // re-evaluated on the next poll. The activeLoops and spawning checks\n // already prevent true double-spawns; knownTickets only deduplicates\n // within a single scan (e.g. ticket appearing in stale column scope).\n this.knownTickets.clear();\n\n // Re-populate with tickets that are actively running or queued\n for (const ticketId of this.activeLoops.keys()) {\n this.knownTickets.add(ticketId);\n }\n for (const [, queue] of this.loopQueues) {\n for (const ticketId of queue) {\n this.knownTickets.add(ticketId);\n }\n }\n // Re-evaluate deferred tickets — their blockers may have resolved (H12)\n // Note: deferred tickets are NOT added to knownTickets so they can be re-spawned\n for (const [ticketId, columnId] of Array.from(this.deferredTickets)) {\n try {\n const stillBlocked = await this.deps.hasUnresolvedBlockers(ticketId);\n if (!stillBlocked) {\n this.deferredTickets.delete(ticketId);\n await this.spawnOrQueue(ticketId, columnId, true);\n } else {\n // Still blocked — add to knownTickets so the column scan doesn't re-process it\n this.knownTickets.add(ticketId);\n }\n } catch (err) {\n // Leave deferred — will re-evaluate next cycle\n const msg = err instanceof Error ? err.message : String(err);\n console.error(` [warn] Deferred blocker re-evaluation failed for ${ticketId}: ${msg}`);\n this.knownTickets.add(ticketId);\n }\n }\n\n // Refresh board scope for fresh ticket counts used by constraint evaluation\n await this.refreshBoardScope();\n this.blockedColumns.clear();\n\n for (const [columnId] of this.pipelineColumns) {\n await this.refreshColumnScope(columnId);\n const colScope = this.columnScopes.get(columnId);\n if (!colScope) {\n console.error(` [scan] Column ${columnId}: no cached scope`);\n continue;\n }\n\n // Evaluate column-scope firing constraints BEFORE processing tickets\n if (this.isColumnBlocked(columnId)) {\n this.blockedColumns.add(columnId);\n console.error(` [scan] Column ${columnId} (${colScope.column.name}): BLOCKED by firing constraints — skipping ${String(colScope.tickets.length)} ticket(s)`);\n continue;\n }\n\n console.error(` [scan] Column ${columnId} (${colScope.column.name}): ${String(colScope.tickets.length)} ticket(s)`);\n for (const ticket of colScope.tickets) {\n await this.spawnOrQueue(ticket.id, columnId);\n }\n }\n }\n\n /**\n * Handle a pipeline event (typically from WebSocket via EventQueue).\n */\n async handleEvent(event: PipelineEvent): Promise<void> {\n // Refresh board scope so constraint evaluation uses fresh ticket counts,\n // not stale data from the last scanAndSpawn cycle.\n await this.refreshBoardScope();\n\n switch (event.type) {\n case 'ticket:moved':\n case 'ticket:created': {\n if (event.columnId && this.pipelineColumns.has(event.columnId)) {\n // Check firing constraints before spawning\n if (this.isColumnBlocked(event.columnId)) {\n console.error(` [event] ${event.type} ${event.ticketId} → column ${event.columnId}: BLOCKED by firing constraints — deferred`);\n this.deferredTickets.set(event.ticketId, event.columnId);\n // Don't break — still need to re-evaluate blockers below for ticket:moved\n } else {\n await this.spawnOrQueue(event.ticketId, event.columnId, true);\n }\n }\n\n if (event.type === 'ticket:moved') {\n let blockedIds: Set<string> | null = null;\n try {\n const blocked = await this.deps.fetchBlockedTickets(event.ticketId);\n blockedIds = new Set(blocked.map(b => b.id));\n for (const dep of blocked) {\n if (dep.id === event.ticketId) continue;\n if (dep.column_id && this.pipelineColumns.has(dep.column_id)) {\n this.knownTickets.delete(dep.id);\n this.deferredTickets.delete(dep.id);\n await this.spawnOrQueue(dep.id, dep.column_id, true);\n }\n }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n console.error(` [warn] Failed to fetch blocked tickets for ${event.ticketId}: ${msg}`);\n }\n\n // Re-evaluate deferred tickets scoped to those blocked by the moved ticket.\n // Falls back to re-evaluating all if fetchBlockedTickets failed (blockedIds is null).\n const toReEvaluate = Array.from(this.deferredTickets).filter(\n ([deferredId]) => deferredId !== event.ticketId && (!blockedIds || blockedIds.has(deferredId)),\n );\n for (const [deferredId, deferredCol] of toReEvaluate) {\n this.knownTickets.delete(deferredId);\n this.deferredTickets.delete(deferredId);\n await this.spawnOrQueue(deferredId, deferredCol, true);\n }\n }\n break;\n }\n\n case 'ticket:updated': {\n // Re-evaluate the ticket if it's deferred in a pipeline column\n if (event.columnId && this.pipelineColumns.has(event.columnId)) {\n if (this.deferredTickets.has(event.ticketId)) {\n this.knownTickets.delete(event.ticketId);\n this.deferredTickets.delete(event.ticketId);\n await this.spawnOrQueue(event.ticketId, event.columnId, true);\n }\n }\n break;\n }\n\n case 'ticket:deleted':\n case 'ticket:archived': {\n // If there's an active loop for this ticket, it will detect the\n // change via fingerprint/404. We just clean up our tracking.\n this.activeLoops.delete(event.ticketId);\n this.knownTickets.delete(event.ticketId);\n this.deferredTickets.delete(event.ticketId);\n this.spawning.delete(event.ticketId);\n this.advisorBudget.delete(event.ticketId);\n // Also remove from any queue\n for (const [, queue] of this.loopQueues) {\n const idx = queue.indexOf(event.ticketId);\n if (idx !== -1) {\n queue.splice(idx, 1);\n }\n }\n break;\n }\n }\n }\n\n /**\n * Spawn a loop for a ticket if under concurrency limit, otherwise queue it.\n * @param skipKnownCheck - true for event-driven spawns (bypass scan dedup)\n */\n private async spawnOrQueue(ticketId: string, columnId: string, skipKnownCheck = false, skipCompletingCheck = false): Promise<void> {\n if (this.pipelinePaused) return;\n // Don't double-spawn\n if (this.activeLoops.has(ticketId)) return;\n // Prevent double-spawn race: two rapid events passing the activeLoops check\n if (this.spawning.has(ticketId)) return;\n // Prevent double-spawn during async advisor recovery (H1)\n // Skipped for retry paths that call spawnOrQueue from within onLoopComplete.\n if (!skipCompletingCheck && this.completing.has(ticketId)) return;\n // During scanAndSpawn, prevent re-processing tickets seen in other columns\n if (!skipKnownCheck && this.knownTickets.has(ticketId)) return;\n\n const colConfig = this.pipelineColumns.get(columnId);\n if (!colConfig) return;\n\n // Belt-and-suspenders: check firing constraints even if already checked at column level.\n // This catches paths like blocker re-evaluation and deferred ticket re-queue.\n if (this.isColumnBlocked(columnId)) {\n return;\n }\n\n // Count active loops for this column\n const activeInColumn = this.activeCountForColumn(columnId);\n\n // Mark as known to prevent re-processing\n this.knownTickets.add(ticketId);\n\n if (activeInColumn >= colConfig.concurrency) {\n // Queue it\n const queue = this.loopQueues.get(columnId);\n if (queue && !queue.includes(ticketId)) {\n queue.push(ticketId);\n }\n return;\n }\n\n // Mark as in-progress spawning to prevent double-spawn race\n this.spawning.add(ticketId);\n // Reserve the concurrency slot before the async claimTicket call\n this.reserveSlot(columnId);\n\n try {\n const blocked = await this.deps.hasUnresolvedBlockers(ticketId);\n if (blocked) {\n this.spawning.delete(ticketId);\n this.releaseSlot(columnId);\n this.deferredTickets.set(ticketId, columnId);\n console.error(` [skip] ${ticketId} has unresolved blockers — deferred`);\n void this.drainQueue(columnId).catch((err) => {\n const msg = err instanceof Error ? err.message : String(err);\n console.error(` [error] drainQueue failed for column ${columnId}: ${msg}`);\n });\n return;\n }\n } catch (err) {\n // Defer rather than proceed — cost of false-defer (retried next scan) is\n // lower than cost of wasted agent iterations on a blocked ticket (H5)\n const msg = err instanceof Error ? err.message : String(err);\n console.error(` [warn] Blocker check failed for ${ticketId}, deferring: ${msg}`);\n this.spawning.delete(ticketId);\n this.releaseSlot(columnId);\n this.deferredTickets.set(ticketId, columnId);\n void this.drainQueue(columnId).catch((err) => {\n const msg = err instanceof Error ? err.message : String(err);\n console.error(` [error] drainQueue failed for column ${columnId}: ${msg}`);\n });\n return;\n }\n\n // Spawn the loop\n try {\n await this.deps.claimTicket(ticketId);\n this.startTrackedLoop(ticketId, columnId, colConfig);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n console.error(` [error] Failed to claim ticket ${ticketId}: ${msg}`);\n this.knownTickets.delete(ticketId);\n this.deferredTickets.set(ticketId, columnId); // Re-evaluate on next move/scan\n } finally {\n this.spawning.delete(ticketId);\n this.releaseSlot(columnId);\n }\n }\n\n /**\n * Start a loop and track it. Attach completion handler for cleanup + queue drain.\n */\n private startTrackedLoop(ticketId: string, columnId: string, config: ColumnConfig): void {\n // Evaluator columns always use heavy tier (need full tool access for adversarial review)\n const tier = config.columnType === 'evaluator' ? 'heavy' : classifyTier({\n hasPromptDocument: this.columnScopes.get(columnId)?.prompt_document != null,\n invocationTier: config.invocationTier,\n });\n\n if (tier === 'light' && this.deps.dispatchLightCall) {\n const promise = this.deps.dispatchLightCall(ticketId, columnId).then(\n async (response): Promise<LoopResult> => {\n try {\n switch (response.action) {\n case 'move_ticket': {\n const targetColId = response.params.column_id as string | undefined;\n if (targetColId && this.deps.moveTicketToColumn) {\n await this.deps.moveTicketToColumn(ticketId, targetColId, {\n reason: response.reason,\n source: 'light_call',\n });\n }\n return { reason: 'moved', iterations: 1, gutterCount: 0 };\n }\n case 'set_field_value': {\n if (this.deps.setFieldValue) {\n const fieldName = response.params.field_name as string;\n const value = response.params.value;\n if (fieldName) await this.deps.setFieldValue(ticketId, fieldName, value);\n }\n return { reason: 'stalled', iterations: 1, gutterCount: 0 };\n }\n case 'archive_ticket': {\n if (this.deps.archiveTicket) {\n await this.deps.archiveTicket(ticketId);\n }\n return { reason: 'moved', iterations: 1, gutterCount: 0 };\n }\n case 'create_comment': {\n const body = response.params.body as string;\n if (body) await this.deps.createComment(ticketId, body);\n return { reason: 'stalled', iterations: 1, gutterCount: 0 };\n }\n case 'no_action':\n default:\n return { reason: 'stalled', iterations: 1, gutterCount: 0 };\n }\n } catch (err) {\n return {\n reason: 'error',\n iterations: 1,\n gutterCount: 0,\n lastError: err instanceof Error ? err.message : String(err),\n };\n }\n },\n (err): LoopResult => ({\n reason: 'error' as const,\n iterations: 1,\n gutterCount: 0,\n lastError: err instanceof Error ? err.message : String(err),\n }),\n );\n this.activeLoops.set(ticketId, { columnId, promise });\n // Track last fire time for column.last_fired_at constraint subject\n this.lastFiredAt.set(columnId, new Date());\n void promise.then(\n (result) => this.onLoopComplete(ticketId, columnId, result).catch((err) => {\n console.error(`onLoopComplete error for ${ticketId}:`, err);\n }),\n );\n return;\n }\n\n // Consume any model override (set by RETRY_DIFFERENT_MODEL advisor action)\n const modelOverride = this.ticketModelOverrides.get(ticketId);\n this.ticketModelOverrides.delete(ticketId);\n\n // Read checkpoint if enabled — resume from saved iteration/gutter/model state\n if (config.checkpointEnabled && this.deps.getFieldValues) {\n // Placeholder to prevent double-spawn during async checkpoint read.\n // Times out after 30s as a safety net — if checkpoint read hangs,\n // the ticket won't be permanently locked.\n let timeoutId: ReturnType<typeof setTimeout>;\n const placeholder = new Promise<LoopResult>((_, reject) => {\n timeoutId = setTimeout(() => {\n // Set completing guard FIRST to prevent scanAndSpawn from grabbing this ticket\n this.completing.add(ticketId);\n this.activeLoops.delete(ticketId);\n this.knownTickets.delete(ticketId);\n // Clear completing — ticket is fully released now, guard was only needed during cleanup\n this.completing.delete(ticketId);\n console.error(` [warn] Checkpoint read timed out for ${ticketId} — releasing lock`);\n reject(new Error('Checkpoint read timeout'));\n }, 30_000);\n });\n placeholder.catch(() => {}); // Prevent unhandled rejection\n this.activeLoops.set(ticketId, { columnId, promise: placeholder });\n this.lastFiredAt.set(columnId, new Date());\n\n // Note: setFieldValue is required by CheckpointDeps interface but only used by\n // writeCheckpoint/clearCheckpoint, not readCheckpoint.\n void readCheckpoint(\n {\n setFieldValue: async () => {},\n getFieldValues: this.deps.getFieldValues,\n },\n ticketId,\n columnId,\n ).then((checkpoint) => {\n clearTimeout(timeoutId!);\n if (checkpoint) {\n console.error(` [checkpoint] Resuming ${ticketId} at iteration ${String(checkpoint.iteration + 1)} (model: ${checkpoint.model_tier})`);\n this.startLoopWithConfig(ticketId, columnId, config, checkpoint.iteration + 1, checkpoint.gutter_count, modelOverride ?? checkpoint.model_tier, checkpoint.last_fingerprint);\n } else {\n this.startLoopWithConfig(ticketId, columnId, config, undefined, undefined, modelOverride);\n }\n }).catch((err) => {\n clearTimeout(timeoutId!);\n const msg = err instanceof Error ? err.message : String(err);\n console.error(` [warn] Checkpoint read failed for ${ticketId} (starting fresh): ${msg}`);\n this.startLoopWithConfig(ticketId, columnId, config, undefined, undefined, modelOverride);\n });\n return;\n }\n\n // No checkpoint — start directly\n this.startLoopWithConfig(ticketId, columnId, config, undefined, undefined, modelOverride);\n }\n\n /**\n * Build a LoopConfig and start a loop, tracking it in activeLoops.\n * Handles model routing resolution: resumeModelTier > modelRouting.initial > modelPreference.\n */\n private startLoopWithConfig(\n ticketId: string,\n columnId: string,\n config: ColumnConfig,\n startIteration?: number,\n startGutterCount?: number,\n resumeModelTier?: string,\n startFingerprint?: TicketFingerprint,\n ): void {\n // Resolve effective model: resume tier > routing initial > column preference\n const effectiveModel = resumeModelTier\n ?? config.modelRouting?.initial\n ?? config.modelPreference;\n\n const loopConfig: LoopConfig = {\n maxIterations: config.maxIterations,\n gutterThreshold: config.gutterThreshold,\n ...(effectiveModel !== undefined && { model: effectiveModel }),\n ...(config.maxBudgetUsd !== undefined && { maxBudgetUsd: config.maxBudgetUsd }),\n // Resolve worktree name from ticket context\n ...((() => {\n const colScope = this.columnScopes.get(columnId);\n const ticket = colScope?.tickets.find(t => t.id === ticketId);\n const wName = config.worktreeEnabled && ticket\n ? generateWorktreeName(ticket.ticket_number, config.name)\n : undefined;\n return wName !== undefined ? { worktreeName: wName } : {};\n })()),\n ...(config.lookaheadColumnId !== undefined && { lookaheadColumnId: config.lookaheadColumnId }),\n // Resume from checkpoint iteration/gutter if provided\n ...(startIteration !== undefined && { startIteration }),\n ...(startGutterCount !== undefined && { startGutterCount }),\n ...(startFingerprint !== undefined && { startFingerprint }),\n ...(config.stuckDetection && { stuckDetection: config.stuckDetection }),\n ...(this.deps.costTracker && { isBudgetExhausted: () => this.deps.costTracker!.isExhausted() }),\n };\n\n // Resolve tool profile for this column\n const toolRestrictions = resolveToolRestrictions(\n config.builtinTools,\n config.allowedTools,\n config.disallowedTools,\n );\n if (toolRestrictions.tools !== undefined || toolRestrictions.allowedTools || toolRestrictions.disallowedTools) {\n loopConfig.toolRestrictions = toolRestrictions;\n }\n\n const promise = this.deps.startLoop(ticketId, columnId, loopConfig);\n\n this.activeLoops.set(ticketId, { columnId, promise });\n\n // Track last fire time for column.last_fired_at constraint subject\n this.lastFiredAt.set(columnId, new Date());\n\n // Attach completion handler — do NOT await\n void promise.then(\n (result) => this.onLoopComplete(ticketId, columnId, result).catch((err) => {\n console.error(`onLoopComplete error for ${ticketId}:`, err);\n }),\n (err) => this.onLoopComplete(ticketId, columnId, {\n reason: 'error',\n iterations: 0,\n gutterCount: 0,\n lastError: err instanceof Error ? err.message : String(err),\n }).catch((completionErr) => {\n console.error(`onLoopComplete error for ${ticketId}:`, completionErr);\n }),\n );\n }\n\n /**\n * Phase 2: Invoke the advisor for failure recovery.\n * Returns true if the ticket should be retried, false if handled.\n */\n private async invokeAdvisorRecovery(\n ticketId: string,\n columnId: string,\n result: LoopResult,\n colConfig: ColumnConfig,\n ): Promise<boolean> {\n if (!this.deps.invokeAdvisor) return false;\n if (!colConfig.advisorEnabled) return false;\n\n const remaining = this.advisorBudget.get(ticketId) ?? colConfig.advisorMaxInvocations ?? 2;\n if (remaining <= 0) return false;\n\n const colScope = this.columnScopes.get(columnId);\n\n // ticketDescription: ColumnTicket does not carry a description field (only id, ticket_number,\n // title). The full description is fetched lazily by the loop itself and is not propagated back\n // in LoopResult. Leave empty — the advisor prompt shows the title and field values instead.\n const input: AdvisorInput = {\n ticketTitle: '',\n ticketDescription: '',\n ticketId,\n ticketNumber: 0,\n columnName: colScope?.column.name ?? columnId,\n exitReason: result.reason as 'stalled' | 'error' | 'max_iterations',\n iterations: result.iterations,\n gutterCount: result.gutterCount,\n ...(result.lastError !== undefined && { lastError: result.lastError }),\n // recentComments: LoopResult does not carry comments; leave empty.\n recentComments: [],\n fieldValues: [],\n failurePatterns: '',\n remainingBudget: remaining,\n modelTier: result.model ?? colConfig.modelPreference ?? 'default',\n escalationModels: colConfig.modelRouting?.escalation ?? [],\n ...(this.cachedBoardScope?.circuit_breaker.target_column_id != null && {\n circuitBreakerTargetId: this.cachedBoardScope.circuit_breaker.target_column_id,\n }),\n };\n\n const ticket = colScope?.tickets.find((t) => t.id === ticketId);\n if (ticket) {\n input.ticketTitle = ticket.title;\n input.ticketNumber = ticket.ticket_number;\n }\n\n // Populate failurePatterns from the latest gate snapshot — gives the advisor concrete\n // signal about which gates are failing and what their output looks like.\n if (this.deps.gateSnapshotStore) {\n const latest = this.deps.gateSnapshotStore.getLatest(ticketId);\n if (latest) {\n const failedGates = latest.results.filter((r) => !r.passed);\n if (failedGates.length > 0) {\n input.failurePatterns = failedGates\n .map((r) => {\n const label = r.required ? `${r.name} (required)` : r.name;\n const snippet = r.output ? ` — ${r.output.slice(0, 300)}` : '';\n return `${label}${snippet}`;\n })\n .join('\\n');\n }\n }\n }\n\n // Enrich advisor context with field values\n if (this.deps.getFieldValues) {\n try {\n input.fieldValues = await this.deps.getFieldValues(ticketId);\n } catch (err) {\n // Non-blocking — advisor works with partial context\n const msg = err instanceof Error ? err.message : String(err);\n console.error(` [warn] Advisor getFieldValues failed for ${ticketId}: ${msg}`);\n }\n }\n\n // Enrich with gate data from snapshot store\n if (this.deps.gateSnapshotStore) {\n const recentSnapshots = this.deps.gateSnapshotStore.getRecent(ticketId, 3);\n if (recentSnapshots.length > 0) {\n input.gateHistory = recentSnapshots;\n const latest = this.deps.gateSnapshotStore.getLatest(ticketId);\n if (latest) {\n input.currentGateResults = latest.results;\n }\n input.trajectory = classifyTrajectory(recentSnapshots);\n }\n }\n\n let response: AdvisorResponse;\n try {\n response = await this.deps.invokeAdvisor(input);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n console.error(` [advisor] Failed for ${ticketId}: ${msg} — falling back to default behavior`);\n return false;\n }\n\n // Decrement after successful call — transient errors don't waste budget\n this.advisorBudget.set(ticketId, remaining - 1);\n\n // Emit advisor event\n const gateSnapshot = this.deps.gateSnapshotStore?.getLatest(ticketId);\n const gatePassed = gateSnapshot ? gateSnapshot.results.filter(r => r.passed).length : 0;\n const gateTotal = gateSnapshot ? gateSnapshot.results.length : 0;\n this.deps.eventEmitter?.emit({\n layer: 'advisor',\n eventType: `advisor_${response.action.toLowerCase()}`,\n severity: response.action === 'ESCALATE' ? 'failure' : response.action === 'RETRY_WITH_FEEDBACK' || response.action === 'RETRY_DIFFERENT_MODEL' ? 'info' : 'warning',\n summary: `Advisor: ${response.action} — ${response.reason.slice(0, 200)}`,\n detail: {\n action: response.action,\n reason: response.reason,\n feedback: response.feedback ?? null,\n budget_remaining: `${String(remaining - 1)}/${String(colConfig.advisorMaxInvocations ?? 2)}`,\n gate_summary: gateTotal > 0 ? { passed: gatePassed, total: gateTotal } : null,\n trajectory: input.trajectory ? { status: input.trajectory.status, confidence: input.trajectory.confidence } : null,\n ticket_number: ticket?.ticket_number ?? null,\n },\n ticketId,\n columnId,\n });\n\n // Hard guard: never auto-advance via RELAX_WITH_DEBT when agent exhausted\n // iterations without completing work — override to ESCALATE\n if (response.action === 'RELAX_WITH_DEBT' && result.reason === 'max_iterations') {\n console.error(` [advisor] Overriding RELAX_WITH_DEBT → ESCALATE for ${ticketId} (max_iterations — work incomplete)`);\n response = { ...response, action: 'ESCALATE', reason: `${response.reason} [overridden: max_iterations cannot auto-advance]` };\n }\n\n switch (response.action) {\n case 'RETRY_WITH_FEEDBACK': {\n if (response.feedback) {\n await this.safeAction(ticketId, 'advisor:createComment', () =>\n this.deps.createComment(ticketId, `ADVISOR FEEDBACK:\\n${response.feedback}`),\n );\n }\n // activeLoops.delete already ran at top of onLoopComplete.\n this.knownTickets.delete(ticketId);\n await this.spawnOrQueue(ticketId, columnId, true, true);\n // Clear completing guard AFTER spawnOrQueue to prevent concurrent scanAndSpawn racing in.\n this.completing.delete(ticketId);\n return true;\n }\n\n case 'RETRY_DIFFERENT_MODEL': {\n // Resolve next model from escalation ladder\n const currentModel = result.model ?? colConfig.modelPreference ?? 'default';\n const escalation = colConfig.modelRouting?.escalation ?? [];\n let nextModel: string | undefined;\n\n // Find current model's position in the full ladder [initial, ...escalation]\n const fullLadder = colConfig.modelRouting\n ? [colConfig.modelRouting.initial, ...colConfig.modelRouting.escalation]\n : [];\n const currentIdx = fullLadder.indexOf(currentModel);\n if (currentIdx >= 0 && currentIdx < fullLadder.length - 1) {\n nextModel = fullLadder[currentIdx + 1];\n } else if (escalation.length > 0) {\n // Current model not in ladder — use first escalation model\n nextModel = escalation[0];\n }\n\n const escalatedModel = nextModel ?? currentModel;\n if (escalatedModel === currentModel) {\n // Already at top of escalation ladder — cannot escalate further\n return false;\n }\n await this.safeAction(ticketId, 'advisor:createComment', () =>\n this.deps.createComment(\n ticketId,\n `ADVISOR: Escalating model ${currentModel} → ${escalatedModel} — ${response.reason}`,\n ),\n );\n\n this.knownTickets.delete(ticketId);\n // Store model override and go through spawnOrQueue to respect concurrency\n this.ticketModelOverrides.set(ticketId, escalatedModel);\n await this.spawnOrQueue(ticketId, columnId, true, true);\n // Clear completing guard AFTER spawnOrQueue to prevent concurrent scanAndSpawn racing in.\n this.completing.delete(ticketId);\n return true;\n }\n\n case 'RELAX_WITH_DEBT': {\n // Hard guard: never auto-advance out of merge or done columns\n const isMergeColumn = colConfig.name.toLowerCase().includes('merge');\n const isDoneColumn = colConfig.columnType === 'done';\n if (isMergeColumn || isDoneColumn) {\n console.error(` [advisor] RELAX_WITH_DEBT blocked for ${colConfig.name}`);\n await this.safeAction(ticketId, 'advisor:createComment', () =>\n this.deps.createComment(\n ticketId,\n `ADVISOR: RELAX_WITH_DEBT blocked — cannot auto-advance from \"${colConfig.name}\". ${isMergeColumn ? 'Merge must succeed before the ticket can proceed.' : 'Done-type columns cannot be relaxed past.'} Manual intervention needed.`,\n ),\n );\n return false;\n }\n\n // Extract waived gates once — used for both field storage and move metadata\n const waivedGates = (response.debt_items ?? [])\n .filter((d) => d.type === 'waived_gate')\n .map((d) => d.description);\n\n if (response.debt_items && response.debt_items.length > 0 && this.deps.setFieldValue) {\n const items = response.debt_items.map((d) => ({ ...d, source_column: colScope?.column.name ?? '' }));\n await this.safeAction(ticketId, 'advisor:setFieldValue:debt_items', () =>\n this.deps.setFieldValue!(ticketId, 'debt_items', items),\n );\n\n // Record waived gates on ticket — gate proxy will skip these\n if (waivedGates.length > 0) {\n await this.safeAction(ticketId, 'advisor:setFieldValue:gate_waiver', () =>\n this.deps.setFieldValue!(ticketId, 'gate_waiver', waivedGates),\n );\n }\n\n await this.safeAction(ticketId, 'advisor:createSignal:debt', () =>\n this.deps.createSignal(\n ticketId,\n `DEBT: This ticket advanced with ${String(items.length)} unresolved items (${String(items.filter((d) => d.severity === 'high').length)} high, ${String(items.filter((d) => d.severity === 'medium').length)} medium).`,\n ),\n );\n\n // G4: Propagate upstream debt signal to blocked tickets\n if (this.deps.fetchBlockedTickets) {\n try {\n const blocked = await this.deps.fetchBlockedTickets(ticketId);\n const ticketNum = colScope?.tickets.find((t) => t.id === ticketId)?.ticket_number;\n for (const dep of blocked) {\n if (dep.id === ticketId) continue;\n await this.safeAction(dep.id, 'advisor:createSignal:upstream_debt', () =>\n this.deps.createSignal(\n dep.id,\n `UPSTREAM DEBT: Blocking ticket #${String(ticketNum ?? '?')} advanced with debt. Review debt_items before building on its interfaces.`,\n ),\n );\n }\n } catch (err) {\n // Non-blocking\n const msg = err instanceof Error ? err.message : String(err);\n console.error(` [warn] Upstream debt signal propagation failed for ${ticketId}: ${msg}`);\n }\n }\n }\n await this.safeAction(ticketId, 'advisor:createComment', () =>\n this.deps.createComment(ticketId, `ADVISOR: Relaxing with debt — ${response.reason}`),\n );\n\n // G3: Move ticket to next column (by board position)\n if (this.deps.moveTicketToColumn) {\n const nextColumn = this.findNextColumn(columnId);\n if (nextColumn) {\n const moved = await this.safeAction(ticketId, 'advisor:moveTicket', () =>\n this.deps.moveTicketToColumn!(ticketId, nextColumn.columnId, {\n relaxed_with_debt: true,\n source_column: colScope?.column.name,\n debt_item_count: response.debt_items?.length ?? 0,\n gate_waivers: waivedGates,\n }),\n );\n if (!moved) {\n await this.safeAction(ticketId, 'advisor:failComment', () =>\n this.deps.createComment(ticketId, `ADVISOR: Attempted to move ticket but the operation failed. Manual intervention needed.`),\n );\n }\n }\n }\n return false;\n }\n\n case 'SPLIT_TICKET': {\n if (response.split_specs && response.split_specs.length > 0 && this.deps.createTickets) {\n try {\n await this.deps.createTickets(ticketId, response.split_specs);\n // Only archive parent after children are successfully created\n if (this.deps.archiveTicket) {\n await this.safeAction(ticketId, 'advisor:archiveTicket', () =>\n this.deps.archiveTicket!(ticketId),\n );\n }\n } catch (err) {\n // createTickets failed — do not archive the parent\n const msg = err instanceof Error ? err.message : String(err);\n console.error(` [warn] SPLIT_TICKET createTickets failed for ${ticketId}: ${msg}`);\n }\n }\n await this.safeAction(ticketId, 'advisor:createComment', () =>\n this.deps.createComment(ticketId, `ADVISOR: Split ticket — ${response.reason}`),\n );\n return false;\n }\n\n case 'ESCALATE': {\n const targetColId = this.cachedBoardScope?.circuit_breaker.target_column_id;\n if (targetColId && this.deps.moveTicketToColumn) {\n const moved = await this.safeAction(ticketId, 'advisor:moveTicket', () =>\n this.deps.moveTicketToColumn!(ticketId, targetColId, {\n escalation_reason: response.reason,\n source_column: colScope?.column.name,\n }),\n );\n if (!moved) {\n await this.safeAction(ticketId, 'advisor:failComment', () =>\n this.deps.createComment(ticketId, `ADVISOR: Attempted to move ticket but the operation failed. Manual intervention needed.`),\n );\n }\n }\n await this.safeAction(ticketId, 'advisor:createComment', () =>\n this.deps.createComment(ticketId, `ADVISOR: Escalated for human review — ${response.reason}`),\n );\n return false;\n }\n }\n\n return false;\n }\n\n /**\n * Handle evaluator column verdict: parse the output, determine action, move ticket accordingly.\n */\n private async handleEvaluatorVerdict(\n ticketId: string,\n columnId: string,\n result: LoopResult,\n colConfig: ColumnConfig,\n ): Promise<void> {\n const verdict = parseVerdict(result.output ?? '');\n\n // Circuit breaker: if verdict parse failed, hold ticket for manual review instead of bouncing\n if ('parseFailed' in verdict && verdict.parseFailed) {\n await this.deps.createComment(ticketId, `EVALUATOR: Verdict could not be parsed — ticket held for manual review.\\n\\nRaw output: ${(result.output ?? '').slice(0, 500)}`).catch((e) => {\n console.error(` [warn] Failed to write parse-failure comment for ${ticketId}: ${e instanceof Error ? e.message : String(e)}`);\n });\n return;\n }\n\n const action = resolveVerdictAction(verdict);\n\n // Emit evaluator verdict event\n const blockers = verdict.findings.filter((f) => f.severity === 'blocker');\n const warnings = verdict.findings.filter((f) => f.severity === 'warning');\n const nits = verdict.findings.filter((f) => f.severity === 'nit');\n this.deps.eventEmitter?.emit({\n layer: 'evaluator',\n eventType: action === 'forward' ? 'evaluator_approved'\n : action === 'reject' ? 'evaluator_rejected'\n : 'evaluator_forwarded',\n severity: action === 'forward' ? 'info'\n : action === 'reject' ? 'failure'\n : 'warning',\n summary: `Evaluator: ${action} (${String(blockers.length)} blockers, ${String(warnings.length)} warnings, ${String(nits.length)} nits)`,\n detail: {\n decision: verdict.decision,\n summary: verdict.summary,\n findings: verdict.findings,\n ticket_number: this.columnScopes.get(columnId)?.tickets.find(t => t.id === ticketId)?.ticket_number ?? null,\n },\n ticketId,\n columnId,\n });\n\n switch (action) {\n case 'forward': {\n // Move to next column with verdict in handoff\n if (this.deps.moveTicketToColumn) {\n const nextColumn = this.findNextColumn(columnId);\n if (nextColumn) {\n const moved = await this.safeAction(ticketId, 'evaluator:moveTicket:forward', () =>\n this.deps.moveTicketToColumn!(ticketId, nextColumn.columnId, {\n evaluator_verdict: 'approved',\n verdict_summary: verdict.summary,\n }),\n );\n if (!moved) {\n await this.safeAction(ticketId, 'evaluator:failComment', () =>\n this.deps.createComment(ticketId, `EVALUATOR: Attempted to move ticket forward but the operation failed. Manual intervention needed.`),\n );\n }\n }\n }\n await this.safeAction(ticketId, 'evaluator:createComment', () =>\n this.deps.createComment(ticketId, `EVALUATOR: Approved — ${verdict.summary}`),\n );\n break;\n }\n case 'reject': {\n // Move BACK to previous column (source column) with rejection comment\n if (this.deps.moveTicketToColumn) {\n const prevColumn = this.findPreviousColumn(columnId);\n if (prevColumn) {\n const moved = await this.safeAction(ticketId, 'evaluator:moveTicket:reject', () =>\n this.deps.moveTicketToColumn!(ticketId, prevColumn.columnId, {\n evaluator_verdict: 'rejected',\n verdict_summary: verdict.summary,\n findings: verdict.findings,\n }),\n );\n if (!moved) {\n await this.safeAction(ticketId, 'evaluator:failComment', () =>\n this.deps.createComment(ticketId, `EVALUATOR: Attempted to reject ticket but the move operation failed. Manual intervention needed.`),\n );\n }\n }\n }\n const findingsText = verdict.findings\n .map((f) => `- [${f.severity}] ${f.description}${f.file ? ` (${f.file}${f.line ? `:${String(f.line)}` : ''})` : ''}`)\n .join('\\n');\n await this.safeAction(ticketId, 'evaluator:createComment', () =>\n this.deps.createComment(ticketId, `EVALUATOR: Rejected — ${verdict.summary}\\n\\n${findingsText}`),\n );\n break;\n }\n case 'forward_with_signals': {\n // Move forward, attach findings as signals\n if (this.deps.moveTicketToColumn) {\n const nextColumn = this.findNextColumn(columnId);\n if (nextColumn) {\n const moved = await this.safeAction(ticketId, 'evaluator:moveTicket:forward_with_signals', () =>\n this.deps.moveTicketToColumn!(ticketId, nextColumn.columnId, {\n evaluator_verdict: 'approved_with_warnings',\n verdict_summary: verdict.summary,\n }),\n );\n if (!moved) {\n await this.safeAction(ticketId, 'evaluator:failComment', () =>\n this.deps.createComment(ticketId, `EVALUATOR: Attempted to move ticket forward but the operation failed. Manual intervention needed.`),\n );\n }\n }\n }\n // Create signals for each finding\n for (const f of verdict.findings) {\n await this.safeAction(ticketId, 'evaluator:createSignal', () =>\n this.deps.createSignal(ticketId, `EVALUATOR: [${f.severity}] ${f.description}`),\n );\n }\n await this.safeAction(ticketId, 'evaluator:createComment', () =>\n this.deps.createComment(ticketId, `EVALUATOR: Forwarded with ${String(verdict.findings.length)} warning(s) — ${verdict.summary}`),\n );\n break;\n }\n }\n }\n\n /**\n * Find the previous pipeline column by board position (for evaluator rejections — send back to worker).\n * Returns null if current column is the first pipeline column.\n */\n private findPreviousColumn(currentColumnId: string): ColumnConfig | null {\n const bs = this.cachedBoardScope;\n if (!bs) return null;\n\n const currentBoardCol = bs.columns.find((c) => c.id === currentColumnId);\n if (!currentBoardCol) return null;\n\n // Find previous column by position that is a pipeline column\n const prevBoardCol = bs.columns\n .filter((c) => c.position < currentBoardCol.position && this.pipelineColumns.has(c.id))\n .sort((a, b) => b.position - a.position)[0]; // sort descending, take first (closest)\n\n return prevBoardCol ? this.pipelineColumns.get(prevBoardCol.id) ?? null : null;\n }\n\n /**\n * Find the next pipeline column by board position (for RELAX_WITH_DEBT forward moves).\n * Returns null if current column is the last pipeline column.\n */\n private findNextColumn(currentColumnId: string): ColumnConfig | null {\n const bs = this.cachedBoardScope;\n if (!bs) return null;\n\n const currentBoardCol = bs.columns.find((c) => c.id === currentColumnId);\n if (!currentBoardCol) return null;\n\n // Find next column by position that is a pipeline column\n const nextBoardCol = bs.columns\n .filter((c) => c.position > currentBoardCol.position && this.pipelineColumns.has(c.id))\n .sort((a, b) => a.position - b.position)[0];\n\n return nextBoardCol ? this.pipelineColumns.get(nextBoardCol.id) ?? null : null;\n }\n\n /**\n * Called when a loop finishes. Cleans up tracking and drains the queue.\n */\n private async onLoopComplete(\n ticketId: string,\n columnId: string,\n result: LoopResult,\n ): Promise<void> {\n // H1: Mark as completing before removing from activeLoops.\n // Guards the async window (advisor LLM call, replanner, etc.) against double-spawn.\n this.completing.add(ticketId);\n this.activeLoops.delete(ticketId);\n\n try {\n // Resolve ticket_number and invocation_type for event detail\n const colScope = this.columnScopes.get(columnId);\n const ticket = colScope?.tickets.find(t => t.id === ticketId);\n const colCfg = this.pipelineColumns.get(columnId);\n const invocationType = colCfg?.columnType === 'evaluator' ? 'evaluator'\n : colCfg?.invocationTier === 'light' ? 'light' : 'heavy';\n\n // Emit session-end event\n this.deps.eventEmitter?.emit({\n layer: 'session',\n eventType: result.reason === 'error' ? 'session_error' : 'session_ended',\n severity: result.reason === 'error' ? 'failure' : 'info',\n summary: `Session ended: ${result.reason} (${String(result.iterations)} iter${result.model ? `, ${result.model}` : ''})`,\n detail: {\n model: result.model ?? null,\n invocation_type: invocationType,\n duration_ms: result.durationMs ?? null,\n tokens_in: result.tokensIn ?? null,\n tokens_out: result.tokensOut ?? null,\n tool_call_count: result.toolCallCount ?? null,\n exit_reason: result.reason,\n gutter_count: result.gutterCount,\n worktree_name: colCfg?.worktreeEnabled && ticket\n ? generateWorktreeName(ticket.ticket_number, colCfg.name) : null,\n ticket_number: ticket?.ticket_number ?? null,\n },\n ticketId,\n columnId,\n iteration: result.iterations,\n });\n\n // Emit gate events from final snapshot\n if (result.finalGateSnapshot && this.deps.eventEmitter) {\n const gateSnapshots = this.deps.gateSnapshotStore?.getRecent(ticketId, 10) ?? [];\n const trajectory = gateSnapshots.length > 0 ? classifyTrajectory(gateSnapshots) : null;\n for (const gate of result.finalGateSnapshot.results) {\n const history = gateSnapshots.map(s => {\n const gr = s.results.find(r => r.name === gate.name);\n return gr ? { passed: gr.passed, iteration: s.iteration } : null;\n }).filter(Boolean);\n this.deps.eventEmitter.emit({\n layer: 'gate',\n eventType: gate.passed ? 'gate_passed' : 'gate_failed',\n severity: gate.passed ? 'info' : 'failure',\n summary: `Gate \"${gate.name}\" ${gate.passed ? 'passed' : gate.timed_out ? 'timed out' : 'failed'} for ${ticket ? `PET-${String(ticket.ticket_number)}` : ticketId.slice(0, 8)}`,\n detail: {\n gate_name: gate.name,\n exit_code: gate.exit_code,\n duration_ms: gate.duration_ms,\n required: gate.required,\n timed_out: gate.timed_out,\n output: gate.output.slice(0, 2000),\n gate_history: history,\n trajectory: trajectory?.status ?? null,\n ticket_number: ticket?.ticket_number ?? null,\n },\n ticketId,\n columnId,\n iteration: result.iterations,\n });\n }\n }\n\n // Emit cost event\n if (this.deps.eventEmitter && this.deps.costTracker) {\n const tc = this.deps.costTracker.getTicketCost(ticketId);\n if (tc) {\n const totalIn = this.deps.costTracker.totalTokensIn;\n const totalOut = this.deps.costTracker.totalTokensOut;\n const maxIn = this.deps.costTracker.maxInputTokens;\n const pctUsed = maxIn > 0 ? Math.round(((totalIn + totalOut) / (maxIn * 2)) * 100) : 0;\n const severity = this.deps.costTracker.isExhausted() ? 'failure' as const\n : this.deps.costTracker.isWarning() ? 'warning' as const : 'info' as const;\n this.deps.eventEmitter.emit({\n layer: 'cost',\n eventType: this.deps.costTracker.isExhausted() ? 'budget_exhausted'\n : this.deps.costTracker.isWarning() ? 'budget_warning' : 'tokens_tracked',\n severity,\n summary: `Token usage: ${String(result.tokensIn ?? 0)} in / ${String(result.tokensOut ?? 0)} out`,\n detail: {\n tokens_in: result.tokensIn ?? 0,\n tokens_out: result.tokensOut ?? 0,\n pct_used: pctUsed,\n max_tokens: maxIn,\n ticket_number: ticket?.ticket_number ?? null,\n },\n ticketId,\n columnId,\n iteration: result.iterations,\n });\n }\n }\n\n // Evaluator verdict handling — overrides normal loop completion\n const colConfig = this.pipelineColumns.get(columnId);\n\n // Shared terminal cleanup — runs for ALL exit paths including evaluator\n const terminalCleanup = async () => {\n this.advisorBudget.delete(ticketId);\n\n // Clear checkpoint for terminal exits. Preserve on 'stopped' (SIGTERM)\n // so restarts can resume from the last checkpoint.\n if (colConfig?.checkpointEnabled && this.deps.setFieldValue && result.reason !== 'stopped') {\n await this.safeAction(ticketId, 'clearCheckpoint', () =>\n this.deps.setFieldValue!(ticketId, 'loop_checkpoint', ''),\n );\n }\n\n const isTerminal = result.reason === 'moved' || result.reason === 'max_iterations' || result.reason === 'error' || result.reason === 'stalled' || result.reason === 'stopped' || result.reason === 'deleted' || result.reason === 'budget';\n if (isTerminal && colConfig) {\n const colScope = this.columnScopes.get(columnId);\n const ticket = colScope?.tickets.find(t => t.id === ticketId);\n if (ticket) {\n const worktreeName = generateWorktreeName(ticket.ticket_number, colConfig.name);\n\n if (colConfig.worktreeOnDone === 'merge' && colConfig.worktreeIntegrationBranch && this.deps.mergeWorktree) {\n void this.deps.mergeWorktree(worktreeName, colConfig.worktreeIntegrationBranch).then((success) => {\n if (!success) {\n console.error(` [warn] Worktree merge failed for ${worktreeName} → ${colConfig.worktreeIntegrationBranch} — may need manual resolution`);\n }\n }).catch((err) => {\n console.error(` [warn] Worktree merge error for ${worktreeName}: ${err instanceof Error ? err.message : String(err)}`);\n });\n } else if (colConfig.worktreeOnDone === 'cleanup' && this.deps.cleanupWorktree) {\n void this.deps.cleanupWorktree(worktreeName).then((success) => {\n if (!success) {\n console.error(` [warn] Worktree cleanup failed for ${worktreeName} — may need manual removal`);\n }\n }).catch((err) => {\n console.error(` [warn] Worktree cleanup error for ${worktreeName}: ${err instanceof Error ? err.message : String(err)}`);\n });\n }\n }\n }\n\n this.deps.gateSnapshotStore?.clear(ticketId);\n };\n\n if (colConfig?.columnType === 'evaluator') {\n await this.handleEvaluatorVerdict(ticketId, columnId, result, colConfig);\n await this.drainQueue(columnId);\n await terminalCleanup();\n return;\n }\n\n // Advisor recovery for failure exits — runs before drain\n // so the retry slot isn't filled by a queued ticket\n const isFailure = result.reason === 'stalled' || result.reason === 'error' || result.reason === 'max_iterations';\n if (isFailure && colConfig) {\n const retried = await this.invokeAdvisorRecovery(ticketId, columnId, result, colConfig);\n if (retried) return; // Advisor re-spawned the loop — skip drain + default behavior\n }\n\n // Drain queue to minimize slot idle time (H13) — after advisor to preserve retry slot\n await this.drainQueue(columnId);\n\n // Check replanner triggers after advisor recovery, before comments\n if (this.deps.invokeReplanner && !this.pipelinePaused) {\n const state = this.buildPipelineState();\n const triggers: ReplannerTriggers = {\n escalation_count: 3,\n cost_threshold_pct: 75,\n repeated_gate_failure_count: 3,\n duration_threshold_minutes: 480,\n };\n if (shouldFireReplanner(triggers, state) && this.replannerInvocations < this.replannerMaxInvocations) {\n this.replannerInvocations++;\n try {\n // Build ticket summaries from cached column scopes\n const ticketSummaries: Array<{ id: string; title: string; column: string; status: string; iterations: number; gatePassRate: number }> = [];\n for (const [colId, scope] of this.columnScopes) {\n const colConfig = this.pipelineColumns.get(colId);\n const columnName = colConfig?.name ?? colId;\n const colQueue = this.loopQueues.get(colId) ?? [];\n for (const ticket of scope.tickets) {\n const isActive = this.activeLoops.has(ticket.id);\n const isQueued = colQueue.includes(ticket.id);\n const status = isActive ? 'active' : isQueued ? 'queued' : 'idle';\n // Get gate pass rate from snapshot store if available\n let gatePassRate = 0;\n if (this.deps.gateSnapshotStore) {\n const latest = this.deps.gateSnapshotStore.getLatest(ticket.id);\n if (latest) {\n const total = latest.results.length;\n const passed = latest.results.filter(r => r.passed).length;\n gatePassRate = total > 0 ? passed / total : 0;\n }\n }\n ticketSummaries.push({\n id: ticket.id,\n title: ticket.title,\n column: columnName,\n status,\n iterations: 0, // Not tracked at orchestrator level\n gatePassRate,\n });\n }\n }\n\n const triggerReason = this.identifyTriggerReason(triggers, state);\n const response = await this.deps.invokeReplanner({\n ...state,\n ticketSummaries,\n triggerReason,\n });\n\n // Emit replanner event\n this.deps.eventEmitter?.emit({\n layer: 'replanner',\n eventType: `replanner_${response.action.toLowerCase()}`,\n severity: response.action === 'CONTINUE' ? 'info'\n : response.action === 'PAUSE_PIPELINE' ? 'warning' : 'info',\n summary: `Replanner: ${response.action} — ${response.reason.slice(0, 200)}`,\n detail: {\n action: response.action,\n reason: response.reason,\n },\n });\n\n await this.executeReplannerAction(response);\n // Only count non-CONTINUE responses toward the auto-pause limit\n if (response.action === 'CONTINUE') {\n this.replannerInvocations--; // Don't count CONTINUE toward limit\n }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n console.error(` [replanner] Failed: ${msg} — pausing pipeline for safety`);\n this.pipelinePaused = true;\n }\n }\n if (this.replannerInvocations >= this.replannerMaxInvocations) {\n this.pipelinePaused = true;\n console.error('Replanner fired 3 non-CONTINUE actions — auto-pausing pipeline');\n }\n }\n\n // Write reason-specific comment\n let comment: string;\n switch (result.reason) {\n case 'moved':\n comment = `Pipeline agent advanced ticket after ${result.iterations} iteration(s).`;\n // Append loop success to run memory\n if (this.deps.appendRunMemory) {\n await this.safeAction(ticketId, 'appendRunMemory', () =>\n this.deps.appendRunMemory!(\n 'Discovered Interfaces',\n `- Ticket ${ticketId} completed in ${colConfig?.name ?? columnId} after ${String(result.iterations)} iteration(s)`,\n ),\n );\n }\n break;\n case 'max_iterations':\n comment = `Pipeline agent reached iteration limit (${result.iterations}) without advancing. Manual review needed.`;\n break;\n case 'stalled':\n comment = `Pipeline agent stalled — no progress for ${result.gutterCount} consecutive iterations (of ${result.iterations} total). Manual review needed.`;\n break;\n case 'error':\n comment = `Pipeline agent encountered an error after ${result.iterations} iteration(s): ${result.lastError ?? 'unknown error'}`;\n break;\n case 'stopped':\n comment = `Pipeline agent was stopped externally after ${result.iterations} iteration(s).`;\n break;\n case 'deleted':\n comment = `Pipeline agent stopped — ticket was deleted or archived during iteration ${result.iterations}.`;\n break;\n case 'budget':\n comment = `Pipeline budget exhausted after ${result.iterations} iteration(s). Increase token budget in pipeline.gates.yaml settings.budget to continue.`;\n break;\n }\n if (result.reason !== 'deleted') {\n await this.deps.createComment(ticketId, comment).catch((err) => {\n const msg = err instanceof Error ? err.message : String(err);\n console.error(` [warn] Failed to write completion comment for ${ticketId}: ${msg}`);\n });\n }\n\n // Create signal for failure exits so future agents inherit the context\n if (result.reason === 'stalled') {\n await this.deps.createSignal(\n ticketId,\n `Previous pipeline run stalled after ${result.iterations} iterations with no progress. Review comments for details before retrying.`,\n ).catch((err) => {\n const msg = err instanceof Error ? err.message : String(err);\n console.error(` [warn] Failed to write signal for ${ticketId}: ${msg}`);\n });\n } else if (result.reason === 'error') {\n await this.deps.createSignal(\n ticketId,\n `Previous pipeline run failed after ${result.iterations} iteration(s): ${result.lastError ?? 'unknown error'}. Review comments for details before retrying.`,\n ).catch((err) => {\n const msg = err instanceof Error ? err.message : String(err);\n console.error(` [warn] Failed to write signal for ${ticketId}: ${msg}`);\n });\n }\n\n // Shared terminal cleanup — advisor budget, checkpoint, worktree, snapshot memory\n await terminalCleanup();\n } finally {\n this.completing.delete(ticketId);\n }\n }\n\n /**\n * Build PipelineState from orchestrator internals for replanner evaluation.\n */\n private buildPipelineState(): PipelineState {\n const costTracker = this.deps.costTracker;\n const totalTokensIn = costTracker ? costTracker.totalTokensIn : 0;\n const maxInputTokens = costTracker ? costTracker.maxInputTokens : 5_000_000;\n\n // Count escalated tickets — those moved to circuit breaker target column\n let escalatedTickets = 0;\n const targetColId = this.cachedBoardScope?.circuit_breaker.target_column_id;\n if (targetColId) {\n const targetCol = this.cachedBoardScope?.columns.find((c) => c.id === targetColId);\n if (targetCol) escalatedTickets = targetCol.ticket_count;\n }\n\n // Compute repeated gate failures from snapshot store\n const repeatedGateFailures: Record<string, number> = {};\n if (this.deps.gateSnapshotStore) {\n const ticketIds = this.deps.gateSnapshotStore.getAllTicketIds();\n for (const tid of ticketIds) {\n const latest = this.deps.gateSnapshotStore.getLatest(tid);\n if (latest) {\n for (const r of latest.results) {\n if (!r.passed) {\n repeatedGateFailures[r.name] = (repeatedGateFailures[r.name] ?? 0) + 1;\n }\n }\n }\n }\n }\n\n const durationMinutes = (Date.now() - this.pipelineStartTime) / 60_000;\n\n return { escalatedTickets, totalTokensIn, maxInputTokens, repeatedGateFailures, durationMinutes };\n }\n\n /**\n * Identify which trigger condition caused the replanner to fire.\n */\n private identifyTriggerReason(triggers: ReplannerTriggers, state: PipelineState): string {\n const reasons: string[] = [];\n if (state.escalatedTickets >= triggers.escalation_count) {\n reasons.push(`${String(state.escalatedTickets)} tickets escalated (threshold: ${String(triggers.escalation_count)})`);\n }\n if (state.maxInputTokens > 0) {\n const pct = (state.totalTokensIn / state.maxInputTokens) * 100;\n if (pct >= triggers.cost_threshold_pct) {\n reasons.push(`Token usage at ${pct.toFixed(0)}% (threshold: ${String(triggers.cost_threshold_pct)}%)`);\n }\n }\n for (const [gate, count] of Object.entries(state.repeatedGateFailures)) {\n if (count >= triggers.repeated_gate_failure_count) {\n reasons.push(`Gate \"${gate}\" failing on ${String(count)} ticket(s) (threshold: ${String(triggers.repeated_gate_failure_count)})`);\n }\n }\n if (state.durationMinutes >= triggers.duration_threshold_minutes) {\n reasons.push(`Pipeline running for ${state.durationMinutes.toFixed(0)}min (threshold: ${String(triggers.duration_threshold_minutes)}min)`);\n }\n return reasons.length > 0 ? reasons.join('; ') : 'Unknown trigger';\n }\n\n /**\n * Execute the action returned by the replanner.\n */\n private async executeReplannerAction(response: ReplannerResponse): Promise<void> {\n switch (response.action) {\n case 'CONTINUE':\n break;\n case 'PAUSE_PIPELINE':\n this.pipelinePaused = true;\n break;\n case 'ARCHIVE_TICKETS':\n if (response.ticket_ids && this.deps.archiveTicket) {\n for (const id of response.ticket_ids) {\n await this.safeAction(id, 'replanner:archiveTicket', () =>\n this.deps.archiveTicket!(id),\n );\n }\n }\n break;\n case 'CREATE_SIGNAL':\n if (response.signal_content && this.deps.createColumnSignal) {\n for (const colId of this.pipelineColumns.keys()) {\n await this.safeAction(colId, 'replanner:createColumnSignal', () =>\n this.deps.createColumnSignal!(colId, response.signal_content!),\n );\n }\n }\n break;\n case 'ESCALATE_ALL':\n this.pipelinePaused = true;\n break;\n case 'ADJUST_BUDGET':\n console.error(' [replanner] ADJUST_BUDGET requested but not yet implemented — treating as CONTINUE');\n break;\n }\n }\n\n /**\n * Start queued tickets for a column until concurrency limit is reached (H16: fills multiple slots).\n */\n private async drainQueue(columnId: string): Promise<void> {\n const colConfig = this.pipelineColumns.get(columnId);\n if (!colConfig) return;\n\n const queue = this.loopQueues.get(columnId);\n if (!queue || queue.length === 0) return;\n\n // Check firing constraints before draining — if column is now blocked, stop\n if (this.isColumnBlocked(columnId)) {\n console.error(` [drain] Column ${columnId}: BLOCKED by firing constraints — ${String(queue.length)} ticket(s) remain queued`);\n return;\n }\n\n // Loop to fill all available slots (H16)\n while (queue.length > 0) {\n const activeInColumn = this.activeCountForColumn(columnId);\n if (activeInColumn >= colConfig.concurrency) return;\n\n const nextTicketId = queue.shift()!;\n\n // Guard against double-spawn race with concurrent scanAndSpawn (C2)\n if (this.spawning.has(nextTicketId) || this.activeLoops.has(nextTicketId)) {\n continue;\n }\n this.spawning.add(nextTicketId);\n this.reserveSlot(columnId);\n\n try {\n const blocked = await this.deps.hasUnresolvedBlockers(nextTicketId);\n if (blocked) {\n this.deferredTickets.set(nextTicketId, columnId);\n this.spawning.delete(nextTicketId);\n this.releaseSlot(columnId);\n continue; // try next ticket in queue\n }\n } catch (err) {\n // If check fails, defer rather than proceeding with potentially blocked ticket\n const msg = err instanceof Error ? err.message : String(err);\n console.error(` [warn] drainQueue blocker check failed for ${nextTicketId}: ${msg} — deferring`);\n this.deferredTickets.set(nextTicketId, columnId);\n this.spawning.delete(nextTicketId);\n this.releaseSlot(columnId);\n continue;\n }\n\n try {\n await this.deps.claimTicket(nextTicketId);\n this.startTrackedLoop(nextTicketId, columnId, colConfig);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n console.error(` [error] Failed to claim/start queued ticket ${nextTicketId}: ${msg}`);\n this.knownTickets.delete(nextTicketId);\n } finally {\n this.spawning.delete(nextTicketId);\n this.releaseSlot(columnId);\n }\n }\n }\n\n /**\n * Count active loops + in-flight reservations for a specific column.\n */\n private activeCountForColumn(columnId: string): number {\n let count = 0;\n for (const [, loop] of this.activeLoops) {\n if (loop.columnId === columnId) count++;\n }\n return count + (this.columnReservations.get(columnId) ?? 0);\n }\n\n private reserveSlot(columnId: string): void {\n this.columnReservations.set(columnId, (this.columnReservations.get(columnId) ?? 0) + 1);\n }\n\n private releaseSlot(columnId: string): void {\n const current = this.columnReservations.get(columnId) ?? 0;\n if (current > 0) this.columnReservations.set(columnId, current - 1);\n }\n}\n","export interface RunMemoryDeps {\n createDocument: (content: string, title: string) => Promise<string>; // returns doc ID\n getDocument: (documentId: string) => Promise<string>; // returns content\n updateDocument: (documentId: string, content: string) => Promise<void>;\n}\n\nconst DEFAULT_COMPACTION_THRESHOLD = 500;\n\nexport class RunMemory {\n private boardName: string;\n private deps: RunMemoryDeps;\n private _documentId: string | null = null;\n private _writeQueue: Promise<void> = Promise.resolve();\n\n constructor(_boardId: string, boardName: string, deps: RunMemoryDeps) {\n this.boardName = boardName;\n this.deps = deps;\n }\n\n get documentId(): string | null {\n return this._documentId;\n }\n\n /**\n * Create the run memory document. Optional seedContent prepopulates the\n * Codebase Conventions section.\n */\n async initialize(seedContent?: string): Promise<void> {\n if (this._documentId !== null) return; // Already initialized\n const date = new Date().toISOString().slice(0, 10); // YYYY-MM-DD\n const title = `Pipeline Run Memory — ${this.boardName} — ${date}`;\n const content = buildTemplate(seedContent);\n this._documentId = await this.deps.createDocument(content, title);\n }\n\n /**\n * Get current document content, truncated to last 500 lines.\n * Returns '' if not initialized or on error.\n */\n async getContent(): Promise<string> {\n if (this._documentId === null) {\n return '';\n }\n try {\n const content = await this.deps.getDocument(this._documentId);\n const lines = content.split('\\n');\n if (lines.length > DEFAULT_COMPACTION_THRESHOLD) {\n const truncated = lines.slice(-DEFAULT_COMPACTION_THRESHOLD);\n return '[Run memory truncated — compaction needed]\\n' + truncated.join('\\n');\n }\n return content;\n } catch (err) {\n console.warn(`[run-memory] getContent failed: ${err instanceof Error ? err.message : String(err)}`);\n return '';\n }\n }\n\n /**\n * Check if document exceeds line threshold (default 500).\n * Reads the raw document directly — getContent() truncates, so checking\n * truncated output would cap the visible line count and miss the real size.\n */\n async needsCompaction(threshold: number = DEFAULT_COMPACTION_THRESHOLD): Promise<boolean> {\n if (this._documentId === null) return false;\n try {\n const content = await this.deps.getDocument(this._documentId);\n if (!content) return false;\n return content.split('\\n').length > threshold;\n } catch {\n return false;\n }\n }\n\n /**\n * Append content under a specific section heading.\n * Agents call this after successful iterations to share discoveries.\n */\n async append(section: string, content: string): Promise<void> {\n if (this._documentId === null) return;\n this._writeQueue = this._writeQueue.then(async () => {\n try {\n const current = await this.deps.getDocument(this._documentId!);\n const sectionHeader = `## ${section}`;\n const idx = current.indexOf(sectionHeader);\n if (idx === -1) {\n await this.deps.updateDocument(this._documentId!, current + `\\n\\n${sectionHeader}\\n\\n${content}`);\n } else {\n const afterHeader = idx + sectionHeader.length;\n const nextSection = current.indexOf('\\n## ', afterHeader);\n const insertAt = nextSection === -1 ? current.length : nextSection;\n const updated = current.slice(0, insertAt) + `\\n${content}\\n` + current.slice(insertAt);\n await this.deps.updateDocument(this._documentId!, updated);\n }\n } catch (err) {\n // Fire-and-forget — run memory writes must never block the loop\n console.warn(`[run-memory] append failed (section=\"${section}\"): ${err instanceof Error ? err.message : String(err)}`);\n }\n }).catch(() => {\n // Ensure queue is never in rejected state — individual failures are logged inside\n });\n await this._writeQueue;\n }\n\n /**\n * Replace document content with a compacted version.\n * Called by the orchestrator after a Haiku summarization call.\n */\n async compact(compactedContent: string): Promise<void> {\n if (this._documentId === null) return;\n this._writeQueue = this._writeQueue.then(async () => {\n try {\n await this.deps.updateDocument(this._documentId!, compactedContent);\n } catch (err) {\n // Fire-and-forget\n console.warn(`[run-memory] compact failed: ${err instanceof Error ? err.message : String(err)}`);\n }\n }).catch(() => {\n // Ensure queue is never in rejected state — individual failures are logged inside\n });\n await this._writeQueue;\n }\n}\n\nfunction buildTemplate(seedContent?: string): string {\n const conventionsSection = seedContent\n ? `## Codebase Conventions\\n\\n${seedContent}`\n : `## Codebase Conventions`;\n\n return [\n conventionsSection,\n `## Discovered Interfaces`,\n `## Failure Patterns`,\n `## QA Rejection History`,\n ].join('\\n\\n');\n}\n","export interface PipelineEvent {\n type: 'ticket:created' | 'ticket:moved' | 'ticket:updated' | 'ticket:archived' | 'ticket:deleted';\n ticketId: string;\n columnId: string | null;\n}\n\nexport type EventHandler = (event: PipelineEvent) => void | Promise<void>;\nexport type ErrorHandler = (event: PipelineEvent, error: unknown) => void;\n\ninterface EventQueueOptions {\n drainRateMs?: number;\n onError?: ErrorHandler;\n}\n\nfunction isDestructive(type: PipelineEvent['type']): boolean {\n return type === 'ticket:archived' || type === 'ticket:deleted';\n}\n\nexport class EventQueue {\n private queue: Map<string, PipelineEvent> = new Map(); // keyed by ticketId for coalescing\n private handler: EventHandler;\n private onError: ErrorHandler;\n private timer: ReturnType<typeof setInterval> | null = null;\n private drainRateMs: number;\n private running = false;\n private draining = false;\n\n constructor(handler: EventHandler, options: EventQueueOptions = {}) {\n this.handler = handler;\n this.drainRateMs = options.drainRateMs ?? 100;\n this.onError = options.onError ?? ((event, error) => console.error('EventQueue handler error for event', event, error));\n }\n\n start(): void {\n this.running = true;\n this.timer = setInterval(() => void this.drain(), this.drainRateMs);\n }\n\n stop(): void {\n this.running = false;\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n this.queue.clear();\n }\n\n push(event: PipelineEvent): void {\n if (!this.running) return;\n // Coalesce move/create events (latest wins), but never overwrite\n // destructive events (archived/deleted) with non-destructive ones.\n const existing = this.queue.get(event.ticketId);\n if (existing && isDestructive(existing.type) && !isDestructive(event.type)) {\n return; // don't overwrite a deletion with a move\n }\n this.queue.set(event.ticketId, event);\n }\n\n pushPriority(event: PipelineEvent): void {\n if (!this.running) return;\n // Priority events bypass the queue — execute immediately\n // Also remove from queue to prevent double-processing\n this.queue.delete(event.ticketId);\n const result = this.handler(event);\n if (result instanceof Promise) {\n result.catch((error: unknown) => this.onError(event, error));\n }\n }\n\n private async drain(): Promise<void> {\n if (this.draining) return;\n if (this.queue.size === 0) return;\n this.draining = true;\n try {\n // Take the first event (FIFO from Map insertion order)\n const [ticketId, event] = this.queue.entries().next().value as [string, PipelineEvent];\n this.queue.delete(ticketId);\n try {\n await this.handler(event);\n } catch (error: unknown) {\n this.onError(event, error);\n }\n } finally {\n this.draining = false;\n }\n }\n}\n","import WebSocket from 'ws';\nimport type { KantBanCLIClient } from '../client.js';\n\nexport interface WsClientOptions {\n boardId: string;\n projectId: string;\n onEvent: (event: { type: string; payload: Record<string, unknown> }) => void;\n onConnect: () => void;\n onDisconnect: () => void;\n}\n\nexport class PipelineWsClient {\n private ws: WebSocket | null = null;\n private client: KantBanCLIClient;\n private options: WsClientOptions;\n private pingTimer: ReturnType<typeof setInterval> | null = null;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private reconnectAttempt = 0;\n private lastPong = 0;\n private stopped = false;\n private sendBuffer: Array<{ data: unknown; critical: boolean; timestamp: number }> = [];\n private static readonly CRITICAL_TYPES = new Set([\n 'pipeline:session-start',\n 'pipeline:session-end',\n 'pipeline:stopped',\n 'board:subscribe',\n ]);\n private static readonly BUFFER_MAX = 100;\n private static readonly BUFFER_TTL_MS = 30_000; // 30 seconds\n private static readonly PING_INTERVAL_MS = 30_000;\n private static readonly PONG_TIMEOUT_MS = 45_000; // dead if no pong in 45s\n\n constructor(client: KantBanCLIClient, options: WsClientOptions) {\n this.client = client;\n this.options = options;\n }\n\n /** Whether the WebSocket is currently open. */\n get connected(): boolean {\n return this.ws?.readyState === WebSocket.OPEN;\n }\n\n async connect(): Promise<void> {\n // Close any existing connection before creating a new one\n if (this.ws) {\n try { this.ws.removeAllListeners(); this.ws.close(); } catch { /* ignore */ }\n this.ws = null;\n }\n this.cleanupTimers();\n\n // Get WS ticket\n const { ticket } = await this.client.post<{ ticket: string }>('/ws-ticket');\n\n // Build WS URL\n const wsUrl = this.client.baseUrl.replace(/^http/, 'ws') + `/ws?ticket=${ticket}&clientType=cli`;\n\n return new Promise((resolve, reject) => {\n let resolved = false;\n this.ws = new WebSocket(wsUrl);\n let subscribed = false;\n\n this.ws.on('open', () => {\n this.lastPong = Date.now();\n this.reconnectAttempt = 0;\n // Start heartbeat with pong-based dead connection detection\n this.pingTimer = setInterval(() => {\n if (Date.now() - this.lastPong > PipelineWsClient.PONG_TIMEOUT_MS) {\n console.warn('[WS] No pong in 45s — connection dead, forcing reconnect');\n this.ws?.close();\n return;\n }\n this.send({ type: 'ping', payload: {} });\n }, PipelineWsClient.PING_INTERVAL_MS);\n });\n\n this.ws.on('message', (data: WebSocket.Data) => {\n try {\n const event = JSON.parse(data.toString()) as { type: string; payload: Record<string, unknown> };\n\n if (event.type === 'pong') {\n this.lastPong = Date.now();\n }\n\n // Send board:subscribe after the first server message proves the handler is ready\n if (!subscribed) {\n subscribed = true;\n this.send({ type: 'board:subscribe', payload: { boardId: this.options.boardId, projectId: this.options.projectId } });\n this.flushBuffer();\n this.options.onConnect();\n if (!resolved) {\n resolved = true;\n resolve();\n }\n }\n\n this.options.onEvent(event);\n } catch (err) {\n console.error('WS message parse error:', err);\n }\n });\n\n this.ws.on('close', (code: number) => {\n this.cleanupTimers();\n this.options.onDisconnect();\n if (!resolved) {\n resolved = true;\n reject(new Error(`WebSocket closed before handshake (code ${code})`));\n } else {\n // Auto-reconnect with exponential backoff (post-handshake disconnects)\n this.scheduleReconnect();\n }\n });\n\n this.ws.on('error', (err: Error) => {\n if (!resolved) {\n resolved = true;\n reject(err);\n }\n });\n });\n }\n\n /**\n * Attempt to reconnect. Called by the polling fallback on each cycle.\n * Returns true if reconnected, false if it failed (polling continues).\n */\n async tryReconnect(): Promise<boolean> {\n if (this.stopped || this.connected) return this.connected;\n try {\n await this.connect();\n return true;\n } catch {\n return false;\n }\n }\n\n stop(): void {\n this.sendBuffer = [];\n this.stopped = true;\n this.cleanupTimers();\n if (this.ws) {\n try { this.ws.removeAllListeners(); this.ws.close(); } catch { /* ignore */ }\n this.ws = null;\n }\n }\n\n send(data: unknown): void {\n if (this.ws?.readyState === WebSocket.OPEN) {\n this.ws.send(JSON.stringify(data));\n return;\n }\n\n const event = data as { type?: string };\n const isCritical = PipelineWsClient.CRITICAL_TYPES.has(event.type ?? '');\n\n if (isCritical) {\n if (this.sendBuffer.length < PipelineWsClient.BUFFER_MAX) {\n this.sendBuffer.push({ data, critical: true, timestamp: Date.now() });\n }\n console.warn(`[WS] Buffered critical event (WS not open): ${event.type}`);\n } else if (event.type !== 'ping') {\n console.debug?.(`[WS] Dropped non-critical event (WS not open): ${event.type}`);\n }\n }\n\n private flushBuffer(): void {\n const now = Date.now();\n const valid = this.sendBuffer.filter((e) => now - e.timestamp < PipelineWsClient.BUFFER_TTL_MS);\n this.sendBuffer = [];\n\n for (const entry of valid) {\n if (this.ws?.readyState === WebSocket.OPEN) {\n this.ws.send(JSON.stringify(entry.data));\n const event = entry.data as { type?: string };\n console.log(`[WS] Replayed buffered event: ${event.type}`);\n }\n }\n }\n\n private scheduleReconnect(): void {\n if (this.stopped || this.reconnectTimer) return;\n const delay = Math.min(1000 * Math.pow(2, this.reconnectAttempt), 30_000);\n this.reconnectAttempt++;\n console.log(`[WS] Reconnecting in ${delay}ms (attempt ${this.reconnectAttempt})`);\n this.reconnectTimer = setTimeout(() => {\n this.reconnectTimer = null;\n if (this.stopped) return;\n this.connect().then(() => {\n console.log('[WS] Reconnected successfully');\n }).catch((err: unknown) => {\n const msg = err instanceof Error ? err.message : String(err);\n console.warn(`[WS] Reconnect failed: ${msg}`);\n this.scheduleReconnect();\n });\n }, delay);\n }\n\n private cleanupTimers(): void {\n if (this.pingTimer) {\n clearInterval(this.pingTimer);\n this.pingTimer = null;\n }\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n }\n}\n","import { mkdirSync, writeFileSync, appendFileSync, readdirSync, rmSync, statSync, renameSync } from 'node:fs';\nimport { join } from 'node:path';\n\nexport interface IterationLogData {\n promptSize: number;\n exitCode: number;\n duration: number;\n tokenUsage?: { input: number; output: number; cost?: number };\n outcome: string;\n}\n\n/** Maximum orchestrator.log size before rotation (5 MB). */\nconst MAX_LOG_BYTES = 5 * 1024 * 1024;\n/** Number of rotated log files to keep (orchestrator.log.1, .2, .3). */\nconst MAX_ROTATED_FILES = 3;\n/** How often (in write count) to check file size — avoids stat on every write. */\nconst ROTATION_CHECK_INTERVAL = 100;\n\nexport class PipelineLogger {\n private boardDir: string;\n private writeCount = 0;\n\n constructor(baseDir: string, boardId: string) {\n this.boardDir = join(baseDir, boardId);\n mkdirSync(this.boardDir, { recursive: true });\n }\n\n orchestrator(message: string): void {\n const logPath = join(this.boardDir, 'orchestrator.log');\n const entry = `[${new Date().toISOString()}] ${message}\\n`;\n appendFileSync(logPath, entry);\n\n // Periodically check if log needs rotation\n this.writeCount++;\n if (this.writeCount >= ROTATION_CHECK_INTERVAL) {\n this.writeCount = 0;\n this.rotateIfNeeded(logPath);\n }\n }\n\n private rotateIfNeeded(logPath: string): void {\n try {\n const stat = statSync(logPath);\n if (stat.size < MAX_LOG_BYTES) return;\n\n // Rotate: .3 → delete, .2 → .3, .1 → .2, current → .1\n for (let i = MAX_ROTATED_FILES; i >= 1; i--) {\n const from = i === 1 ? logPath : `${logPath}.${String(i - 1)}`;\n const to = `${logPath}.${String(i)}`;\n try {\n if (i === MAX_ROTATED_FILES) {\n try { rmSync(to, { force: true }); } catch { /* ignore */ }\n }\n renameSync(from, to);\n } catch { /* file may not exist */ }\n }\n } catch { /* stat failed — file doesn't exist yet */ }\n }\n\n iteration(ticketNumber: string, iterationNum: number, data: IterationLogData): void {\n const ticketDir = join(this.boardDir, ticketNumber);\n mkdirSync(ticketDir, { recursive: true });\n const padded = String(iterationNum).padStart(3, '0');\n const logPath = join(ticketDir, `iteration-${padded}.log`);\n const entry = {\n timestamp: new Date().toISOString(),\n iteration: iterationNum,\n ...data,\n };\n writeFileSync(logPath, JSON.stringify(entry, null, 2));\n }\n\n formatConsole(ticketNumber: string, columnName: string, iteration: number, status: string): string {\n const time = new Date().toLocaleTimeString('en-US', { hour12: false });\n const ticket = ticketNumber.padEnd(10);\n const col = columnName.padEnd(12);\n return `[${time}] ${ticket} ${col} iter:${iteration} ${status}`;\n }\n\n pruneOldLogs(retentionDays: number): void {\n const cutoff = Date.now() - (retentionDays * 24 * 60 * 60 * 1000);\n try {\n const entries = readdirSync(this.boardDir, { withFileTypes: true });\n for (const entry of entries) {\n const fullPath = join(this.boardDir, entry.name);\n if (entry.isDirectory() && entry.name !== '.') {\n try {\n const stat = statSync(fullPath);\n if (stat.mtimeMs < cutoff) {\n rmSync(fullPath, { recursive: true, force: true });\n }\n } catch { /* skip if stat fails */ }\n }\n // Prune old rotated orchestrator logs\n if (entry.isFile() && /^orchestrator\\.log\\.\\d+$/.test(entry.name)) {\n try {\n const stat = statSync(fullPath);\n if (stat.mtimeMs < cutoff) {\n rmSync(fullPath, { force: true });\n }\n } catch { /* skip if stat fails */ }\n }\n }\n } catch { /* skip if dir doesn't exist */ }\n }\n}\n","import { z } from 'zod';\nimport { parseJsonFromLlmOutput } from './parse-utils.js';\n\nexport interface LightCallContext {\n ticketId: string;\n ticketNumber: number;\n ticketTitle: string;\n ticketDescription?: string;\n columnName: string;\n fieldValues: Array<{ field_name: string; value: unknown }>;\n toolPrefix: string;\n projectId: string;\n availableColumns?: Array<{ id: string; name: string }>;\n transitionRules?: string;\n}\n\nconst LightResponseSchema = z.object({\n action: z.enum(['move_ticket', 'set_field_value', 'create_comment', 'archive_ticket', 'no_action']),\n params: z.record(z.string(), z.unknown()),\n reason: z.string(),\n});\n\nexport type LightResponse = z.infer<typeof LightResponseSchema>;\n\nexport function composeLightPrompt(ctx: LightCallContext): string {\n const fieldLines = ctx.fieldValues.length > 0\n ? ctx.fieldValues.map(f => ` ${f.field_name}: ${f.value != null ? JSON.stringify(f.value) : '(not set)'}`).join('\\n')\n : ' (none)';\n\n const parts: string[] = [];\n\n parts.push(`Ticket #${String(ctx.ticketNumber)}: \"${ctx.ticketTitle}\"\nColumn: ${ctx.columnName}\nProject: ${ctx.projectId}\nTool prefix: ${ctx.toolPrefix}`);\n\n if (ctx.ticketDescription) {\n const truncated = ctx.ticketDescription.length > 300\n ? ctx.ticketDescription.slice(0, 300) + '...'\n : ctx.ticketDescription;\n parts.push(`Description: ${truncated}`);\n }\n\n parts.push(`\\nField values:\\n${fieldLines}`);\n\n if (ctx.availableColumns && ctx.availableColumns.length > 0) {\n const colLines = ctx.availableColumns.map(c => ` ${c.name} (${c.id})`).join('\\n');\n parts.push(`Available columns:\\n${colLines}`);\n }\n\n if (ctx.transitionRules) {\n parts.push(`Transition rules:\\n${ctx.transitionRules}`);\n }\n\n parts.push(`Decide the single best next action for this ticket.\nRespond with ONLY a JSON object — no markdown, no explanation outside the JSON:\n\n{\n \"action\": \"<move_ticket|set_field_value|create_comment|archive_ticket|no_action>\",\n \"params\": { /* action-specific params */ },\n \"reason\": \"<one sentence>\"\n}\n\nAction params shapes:\n- move_ticket: { column_id: string }\n- set_field_value: { field_name: string, value: unknown }\n- create_comment: { body: string }\n- archive_ticket: {}\n- no_action: {}`);\n\n return parts.join('\\n');\n}\n\nexport function parseLightResponse(raw: string): LightResponse {\n let parsed: unknown;\n try {\n parsed = parseJsonFromLlmOutput(raw);\n } catch (err) {\n throw new Error(`LightResponse: ${err instanceof Error ? err.message : String(err)}`);\n }\n\n const result = LightResponseSchema.safeParse(parsed);\n if (!result.success) {\n throw new Error(`LightResponse: validation failed — ${result.error.message}`);\n }\n\n return result.data;\n}\n","import { z } from 'zod';\nimport { DebtItemSchema } from '@kantban/types';\nimport type { GateSnapshot, GateResult } from '@kantban/types';\nimport type { StuckPattern } from './stuck-detector.js';\nimport { parseJsonFromLlmOutput } from './parse-utils.js';\n\nexport interface AdvisorInput {\n ticketTitle: string;\n ticketDescription: string;\n ticketId: string;\n ticketNumber: number;\n columnName: string;\n exitReason: 'stalled' | 'error' | 'max_iterations';\n iterations: number;\n gutterCount: number;\n lastError?: string;\n recentComments: Array<{ author: string; body: string }>;\n fieldValues: Array<{ field_name: string; value: unknown }>;\n failurePatterns: string;\n remainingBudget: number;\n modelTier: string;\n escalationModels: string[];\n circuitBreakerTargetId?: string;\n gateHistory?: GateSnapshot[];\n currentGateResults?: GateResult[];\n trajectory?: StuckPattern;\n diffStats?: { files_changed: number; insertions: number; deletions: number };\n}\n\nconst AdvisorResponseSchema = z.object({\n action: z.enum([\n 'RETRY_WITH_FEEDBACK',\n 'RETRY_DIFFERENT_MODEL',\n 'RELAX_WITH_DEBT',\n 'SPLIT_TICKET',\n 'ESCALATE',\n ]),\n reason: z.string(),\n feedback: z.string().nullish().transform(v => v ?? undefined),\n debt_items: z.array(z.object({\n type: z.string(),\n description: z.string(),\n severity: z.enum(['high', 'medium', 'low']).default('medium'),\n })).nullish().transform(v => v ?? undefined),\n split_specs: z.array(z.object({\n title: z.string(),\n description: z.string(),\n })).nullish().transform(v => v ?? undefined),\n});\n\nexport type AdvisorResponse = z.infer<typeof AdvisorResponseSchema>;\n\nexport function composeAdvisorPrompt(input: AdvisorInput): string {\n const parts: string[] = [];\n\n parts.push(`You are a pipeline recovery advisor. A Ralph Loop has exited without moving the ticket.\nAnalyze the failure context and choose the single best recovery action.`);\n\n parts.push(`\\nTicket: #${String(input.ticketNumber)} \"${input.ticketTitle}\"`);\n parts.push(`Column: ${input.columnName}`);\n parts.push(`Model: ${input.modelTier}`);\n\n // Full description — not truncated\n if (input.ticketDescription) {\n parts.push(`\\nDescription:\\n${input.ticketDescription}`);\n }\n\n // Failure context\n parts.push(`\\nFailure context:`);\n parts.push(` Exit reason: ${input.exitReason}`);\n parts.push(` Iterations completed: ${input.iterations}`);\n parts.push(` Gutter (no-progress) count: ${input.gutterCount}`);\n if (input.lastError) {\n parts.push(` Last error: ${input.lastError}`);\n }\n\n // Gate history — objective data\n if (input.gateHistory && input.gateHistory.length > 0) {\n parts.push(`\\n## Gate History (last ${String(input.gateHistory.length)} iterations)`);\n for (const snap of input.gateHistory) {\n const passed = snap.results.filter(r => r.passed).length;\n const total = snap.results.length;\n const deltaLabel = snap.delta_from_previous === 'first_check' ? 'first check (no baseline)' : snap.delta_from_previous;\n parts.push(`- Iter ${String(snap.iteration)}: ${String(passed)}/${String(total)} gates passed (delta: ${deltaLabel})`);\n }\n }\n\n // Current gate results with error output\n if (input.currentGateResults && input.currentGateResults.length > 0) {\n parts.push(`\\n## Current Gate Results`);\n for (const r of input.currentGateResults) {\n const status = r.passed ? 'PASS' : 'FAIL';\n parts.push(`- ${r.name}: ${status}${r.required ? ' (required)' : ''}`);\n if (!r.passed && r.output) {\n parts.push(` Output: ${r.output.slice(0, 500)}`);\n }\n }\n }\n\n // Trajectory classification\n if (input.trajectory) {\n parts.push(`\\nTrajectory: ${input.trajectory.status} — ${input.trajectory.evidence}`);\n }\n\n // Diff stats\n if (input.diffStats) {\n parts.push(`\\nGit diff: ${String(input.diffStats.files_changed)} files, +${String(input.diffStats.insertions)}/-${String(input.diffStats.deletions)}`);\n }\n\n // Recent comments (kept but now secondary to gate data)\n const commentLines = input.recentComments.length > 0\n ? input.recentComments.map(c => ` [${c.author}] ${c.body.slice(0, 150)}`).join('\\n')\n : ' (none)';\n parts.push(`\\nRecent comments:\\n${commentLines}`);\n\n // Field values\n const fieldLines = input.fieldValues.length > 0\n ? input.fieldValues.map(f => ` ${f.field_name}: ${f.value != null ? JSON.stringify(f.value) : '(not set)'}`).join('\\n')\n : ' (none)';\n parts.push(`\\nField values:\\n${fieldLines}`);\n\n // Failure patterns\n parts.push(`\\nFailure patterns from run memory:\\n${input.failurePatterns}`);\n\n // Decision matrix\n parts.push(`\\n## Decision Guide\n| Gate pattern | Recommended action |\n|---|---|\n| Same test failing, different error each time | RETRY_WITH_FEEDBACK |\n| Same exact error every iteration | RETRY_DIFFERENT_MODEL |\n| All gates pass but agent didn't move | RETRY_WITH_FEEDBACK (\"Gates pass — call move_ticket\") |\n| Gates regressing across iterations | SPLIT_TICKET |\n| Zero gates pass after max iterations | ESCALATE |\n| Most gates pass, one stubborn failure | RELAX_WITH_DEBT |\n\n**IMPORTANT**: RELAX_WITH_DEBT is NOT allowed when the exit reason is \\`max_iterations\\`. If the agent exhausted its iteration limit without moving the ticket, the work is incomplete — do NOT auto-advance. Use ESCALATE or RETRY instead.`);\n\n // Model context\n const escalationSection = input.escalationModels.length > 0\n ? `Available escalation models: ${input.escalationModels.join(', ')}`\n : `Available escalation models: none — RETRY_DIFFERENT_MODEL is unavailable`;\n\n const budgetNote = input.remainingBudget <= 1\n ? `\\nThis is your final invocation (remaining budget: ${String(input.remainingBudget)}). Prefer RELAX_WITH_DEBT or ESCALATE.`\n : `Remaining advisor budget: ${String(input.remainingBudget)}`;\n\n parts.push(`\\nModel context:`);\n parts.push(` Current model: ${input.modelTier}`);\n parts.push(` ${escalationSection}`);\n parts.push(` ${budgetNote}`);\n\n if (input.circuitBreakerTargetId) {\n parts.push(` Circuit breaker target column ID: ${input.circuitBreakerTargetId}`);\n }\n\n parts.push(`\\nChoose one of the following actions. Respond with ONLY a JSON object — no markdown, no explanation outside the JSON:\n\n{\n \"action\": \"<action>\",\n \"reason\": \"<one sentence>\",\n \"feedback\": \"<optional: guidance for retry>\",\n \"debt_items\": [{ \"type\": \"...\", \"description\": \"...\", \"severity\": \"high|medium|low\" }],\n \"split_specs\": [{ \"title\": \"...\", \"description\": \"...\" }]\n}\n\nActions:\n- RETRY_WITH_FEEDBACK — Retry the loop with targeted feedback in the prompt. Include \"feedback\" field.\n- RETRY_DIFFERENT_MODEL — Retry using a higher-capability model. Only valid if escalation models are available.\n- RELAX_WITH_DEBT — Accept partial progress; log unmet criteria as debt. Include \"debt_items\" array.\n- SPLIT_TICKET — Ticket is too broad; propose sub-tickets. Include \"split_specs\" array.\n- ESCALATE — Surface to a human; cannot be resolved automatically.`);\n\n return parts.join('\\n');\n}\n\nexport function parseAdvisorResponse(raw: string): AdvisorResponse {\n let parsed: unknown;\n try {\n parsed = parseJsonFromLlmOutput(raw);\n } catch (err) {\n throw new Error(`AdvisorResponse: ${err instanceof Error ? err.message : String(err)}`);\n }\n\n const result = AdvisorResponseSchema.safeParse(parsed);\n if (!result.success) {\n throw new Error(`AdvisorResponse: validation failed — ${result.error.message}`);\n }\n\n return result.data;\n}\n","import { spawn } from 'node:child_process';\nimport { writeFileSync, unlinkSync, readFileSync } from 'node:fs';\nimport type { ChildProcess } from 'node:child_process';\n\nexport const REAPER_POLL_MS = 3000;\n\nexport interface ReaperConfig {\n orchestratorPid: number;\n manifestPath: string;\n pidFilePath: string;\n reaperPidPath: string;\n mcpConfigPath: string;\n pipelineDir: string;\n}\n\nexport function buildReaperScript(config: ReaperConfig): string {\n return `\nconst fs = require('fs');\nconst path = require('path');\n\nconst ORCHESTRATOR_PID = ${config.orchestratorPid};\nconst MANIFEST_PATH = ${JSON.stringify(config.manifestPath)};\nconst PID_FILE_PATH = ${JSON.stringify(config.pidFilePath)};\nconst REAPER_PID_PATH = ${JSON.stringify(config.reaperPidPath)};\nconst MCP_CONFIG_PATH = ${JSON.stringify(config.mcpConfigPath)};\nconst PIPELINE_DIR = ${JSON.stringify(config.pipelineDir)};\nconst POLL_MS = ${REAPER_POLL_MS};\n\nfunction isAlive(pid) {\n try { process.kill(pid, 0); return true; } catch { return false; }\n}\n\nfunction readManifest() {\n try {\n return fs.readFileSync(MANIFEST_PATH, 'utf-8')\n .split('\\\\n')\n .map(l => parseInt(l.trim(), 10))\n .filter(p => !isNaN(p) && p > 0);\n } catch { return []; }\n}\n\nfunction killPid(pid, signal) {\n try { process.kill(pid, signal); } catch { /* already dead */ }\n}\n\nfunction cleanup() {\n const pids = readManifest();\n for (const pid of pids) {\n killPid(pid, 'SIGTERM');\n try { process.kill(-pid, 'SIGTERM'); } catch { /* ignore */ }\n }\n\n setTimeout(() => {\n for (const pid of pids) {\n if (isAlive(pid)) {\n killPid(pid, 'SIGKILL');\n try { process.kill(-pid, 'SIGKILL'); } catch { /* ignore */ }\n }\n }\n\n try { fs.unlinkSync(MANIFEST_PATH); } catch {}\n try { fs.unlinkSync(PID_FILE_PATH); } catch {}\n try { fs.unlinkSync(REAPER_PID_PATH); } catch {}\n try { fs.unlinkSync(MCP_CONFIG_PATH); } catch {}\n\n try {\n const files = fs.readdirSync(PIPELINE_DIR);\n for (const f of files) {\n if (f.startsWith('mcp-config-') && f.endsWith('.json')) {\n try { fs.unlinkSync(path.join(PIPELINE_DIR, f)); } catch {}\n }\n }\n } catch {}\n\n process.exit(0);\n }, 5000);\n}\n\nfunction pidFileExists() {\n try { fs.accessSync(PID_FILE_PATH); return true; } catch { return false; }\n}\n\nconst timer = setInterval(() => {\n if (!pidFileExists()) {\n clearInterval(timer);\n process.exit(0);\n return;\n }\n\n if (!isAlive(ORCHESTRATOR_PID)) {\n clearInterval(timer);\n cleanup();\n }\n}, POLL_MS);\n`;\n}\n\nexport function spawnReaper(config: ReaperConfig): ChildProcess {\n const script = buildReaperScript(config);\n\n const child = spawn(process.execPath, ['-e', script], {\n detached: true,\n stdio: 'ignore',\n });\n\n child.unref();\n\n if (child.pid) {\n writeFileSync(config.reaperPidPath, String(child.pid), { mode: 0o600 });\n }\n\n return child;\n}\n\nexport function killReaper(reaperPidPath: string): void {\n try {\n const pid = parseInt(\n readFileSync(reaperPidPath, 'utf-8').trim(),\n 10,\n );\n if (pid && !isNaN(pid)) {\n process.kill(pid, 'SIGTERM');\n }\n } catch {\n /* reaper already dead or PID file gone */\n }\n try {\n unlinkSync(reaperPidPath);\n } catch {\n /* already removed */\n }\n}\n","import type { GateResult, GateSnapshot, GateDelta } from '@kantban/types';\n\nconst MAX_SNAPSHOTS_PER_TICKET = 100;\n\nexport function computeDelta(\n previous: GateSnapshot | undefined,\n currentResults: GateResult[],\n): GateDelta {\n if (!previous) return 'first_check';\n\n const prevPassing = previous.results.filter((r) => r.passed).length;\n const currPassing = currentResults.filter((r) => r.passed).length;\n\n if (currPassing > prevPassing) return 'improved';\n if (currPassing < prevPassing) return 'regressed';\n\n // Same pass count — check if failing gate outputs changed (agent making different progress)\n const prevFailing = previous.results.filter((r) => !r.passed);\n const currFailing = currentResults.filter((r) => !r.passed);\n for (const curr of currFailing) {\n const prev = prevFailing.find((r) => r.name === curr.name);\n if (prev && prev.output !== curr.output) return 'improved';\n }\n\n return 'same';\n}\n\nexport class GateSnapshotStore {\n private snapshots: Map<string, GateSnapshot[]> = new Map();\n\n record(ticketId: string, iteration: number, results: GateResult[]): GateSnapshot {\n const previous = this.getLatest(ticketId);\n const delta = computeDelta(previous, results);\n\n const snapshot: GateSnapshot = {\n timestamp: new Date().toISOString(),\n iteration,\n results,\n all_required_passed: results.filter((r) => r.required).every((r) => r.passed),\n delta_from_previous: delta,\n };\n\n const existing = this.snapshots.get(ticketId) ?? [];\n existing.push(snapshot);\n if (existing.length > MAX_SNAPSHOTS_PER_TICKET) {\n existing.splice(0, existing.length - MAX_SNAPSHOTS_PER_TICKET);\n }\n this.snapshots.set(ticketId, existing);\n\n return snapshot;\n }\n\n getLatest(ticketId: string): GateSnapshot | undefined {\n const snaps = this.snapshots.get(ticketId);\n return snaps?.[snaps.length - 1];\n }\n\n getRecent(ticketId: string, count: number): GateSnapshot[] {\n const snaps = this.snapshots.get(ticketId) ?? [];\n return snaps.slice(-count);\n }\n\n clear(ticketId: string): void {\n this.snapshots.delete(ticketId);\n }\n\n /** Returns all ticket IDs that have at least one snapshot recorded. */\n getAllTicketIds(): string[] {\n return Array.from(this.snapshots.keys());\n }\n}\n","import type { BudgetConfig, InvocationType } from '@kantban/types';\n\ninterface InvocationRecord {\n ticketId: string;\n columnId: string;\n model: string;\n tokensIn: number;\n tokensOut: number;\n type: InvocationType;\n}\n\ninterface TicketCost {\n tokens_in: number;\n tokens_out: number;\n iterations: number;\n advisor_calls: number;\n}\n\ninterface ColumnCost {\n tokens_in: number;\n tokens_out: number;\n light_calls: number;\n heavy_calls: number;\n advisor_calls: number;\n}\n\ninterface ModelCost {\n tokens_in: number;\n tokens_out: number;\n calls: number;\n}\n\nexport class PipelineCostTracker {\n private readonly runId: string;\n private readonly budget: BudgetConfig | undefined;\n private _totalIn = 0;\n private _totalOut = 0;\n private readonly ticketCosts: Map<string, TicketCost> = new Map();\n private readonly columnCosts: Map<string, ColumnCost> = new Map();\n private readonly modelCosts: Map<string, ModelCost> = new Map();\n\n constructor(runId: string, budget: BudgetConfig | undefined) {\n this.runId = runId;\n this.budget = budget;\n }\n\n get totalTokensIn(): number {\n return this._totalIn;\n }\n\n get totalTokensOut(): number {\n return this._totalOut;\n }\n\n get maxInputTokens(): number {\n return this.budget?.max_input_tokens ?? 5_000_000;\n }\n\n record(inv: InvocationRecord): void {\n this._totalIn += inv.tokensIn;\n this._totalOut += inv.tokensOut;\n\n // Per-ticket\n const tc = this.ticketCosts.get(inv.ticketId) ?? {\n tokens_in: 0,\n tokens_out: 0,\n iterations: 0,\n advisor_calls: 0,\n };\n tc.tokens_in += inv.tokensIn;\n tc.tokens_out += inv.tokensOut;\n if (inv.type === 'heavy') tc.iterations++;\n if (inv.type === 'advisor') tc.advisor_calls++;\n this.ticketCosts.set(inv.ticketId, tc);\n\n // Per-column\n const cc = this.columnCosts.get(inv.columnId) ?? {\n tokens_in: 0,\n tokens_out: 0,\n light_calls: 0,\n heavy_calls: 0,\n advisor_calls: 0,\n };\n cc.tokens_in += inv.tokensIn;\n cc.tokens_out += inv.tokensOut;\n if (inv.type === 'light') cc.light_calls++;\n if (inv.type === 'heavy') cc.heavy_calls++;\n if (inv.type === 'advisor' || inv.type === 'stuck_detection' || inv.type === 'replanner') cc.advisor_calls++;\n this.columnCosts.set(inv.columnId, cc);\n\n // Per-model\n const mc = this.modelCosts.get(inv.model) ?? { tokens_in: 0, tokens_out: 0, calls: 0 };\n mc.tokens_in += inv.tokensIn;\n mc.tokens_out += inv.tokensOut;\n mc.calls++;\n this.modelCosts.set(inv.model, mc);\n }\n\n getTicketCost(ticketId: string): TicketCost | undefined {\n return this.ticketCosts.get(ticketId);\n }\n\n getColumnCost(columnId: string): ColumnCost | undefined {\n return this.columnCosts.get(columnId);\n }\n\n isWarning(): boolean {\n if (!this.budget) return false;\n const inPct = (this._totalIn / this.budget.max_input_tokens) * 100;\n const outPct = (this._totalOut / this.budget.max_output_tokens) * 100;\n return inPct >= this.budget.warn_pct || outPct >= this.budget.warn_pct;\n }\n\n isExhausted(): boolean {\n if (!this.budget) return false;\n return (\n this._totalIn >= this.budget.max_input_tokens ||\n this._totalOut >= this.budget.max_output_tokens\n );\n }\n\n generateReport(\n pricing?: Record<string, { input_per_mtok: number; output_per_mtok: number }>,\n ): string {\n const fmt = (n: number): string => {\n if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`;\n if (n >= 1_000) return `${(n / 1_000).toFixed(0)}K`;\n return String(n);\n };\n\n const lines: string[] = [];\n\n const budgetStr = this.budget\n ? ` (of ${fmt(this.budget.max_input_tokens)} / ${fmt(this.budget.max_output_tokens)} budget)`\n : '';\n lines.push(`Tokens: ${fmt(this._totalIn)} in / ${fmt(this._totalOut)} out${budgetStr}`);\n\n if (this.columnCosts.size > 0) {\n const colParts = Array.from(this.columnCosts.entries()).map(\n ([id, c]) => `${id.slice(0, 8)} ${fmt(c.tokens_in)}/${fmt(c.tokens_out)}`,\n );\n lines.push(` By column: ${colParts.join(', ')}`);\n }\n\n if (this.modelCosts.size > 0) {\n const modelParts = Array.from(this.modelCosts.entries()).map(\n ([model, c]) => `${model} ${fmt(c.tokens_in)}/${fmt(c.tokens_out)} (${c.calls} calls)`,\n );\n lines.push(` By model: ${modelParts.join(', ')}`);\n }\n\n // Dollar estimate only if pricing provided\n if (pricing) {\n let totalCost = 0;\n for (const [model, mc] of this.modelCosts) {\n const p = pricing[model];\n if (p) {\n totalCost += (mc.tokens_in / 1_000_000) * p.input_per_mtok;\n totalCost += (mc.tokens_out / 1_000_000) * p.output_per_mtok;\n }\n }\n if (totalCost > 0) {\n lines.push(` Estimated cost: $${totalCost.toFixed(2)} (user-provided pricing)`);\n }\n }\n\n return lines.join('\\n');\n }\n}\n","import type { CreatePipelineEvent, PipelineEventLayer, PipelineEventSeverity } from '@kantban/types';\n\nconst SIGNIFICANT_TYPES = new Set([\n 'advisor_escalate',\n 'evaluator_rejected',\n 'budget_exhausted',\n 'replanner_paused',\n]);\n\nconst FLUSH_INTERVAL_MS = 5_000;\nconst MAX_BATCH_SIZE = 100;\n\nexport class PipelineEventEmitter {\n private buffer: CreatePipelineEvent[] = [];\n private flushTimer: ReturnType<typeof setInterval> | null = null;\n private closed = false;\n private inFlight = false;\n private static readonly MAX_BUFFER_SIZE = 10_000;\n\n constructor(\n private apiBaseUrl: string,\n private projectId: string,\n private apiToken: string,\n private boardId: string,\n private runId: string,\n ) {\n this.flushTimer = setInterval(() => void this.flush(), FLUSH_INTERVAL_MS);\n }\n\n emit(opts: {\n layer: PipelineEventLayer;\n eventType: string;\n severity: PipelineEventSeverity;\n summary: string;\n detail?: Record<string, unknown> | null;\n ticketId?: string | null;\n columnId?: string | null;\n sessionId?: string | null;\n iteration?: number | null;\n }): void {\n if (this.closed) return;\n\n const event: CreatePipelineEvent = {\n board_id: this.boardId,\n ticket_id: opts.ticketId ?? null,\n column_id: opts.columnId ?? null,\n run_id: this.runId,\n session_id: opts.sessionId ?? null,\n layer: opts.layer,\n event_type: opts.eventType,\n severity: opts.severity,\n summary: opts.summary,\n detail: opts.detail ?? null,\n iteration: opts.iteration ?? null,\n };\n\n this.buffer.push(event);\n\n if (SIGNIFICANT_TYPES.has(opts.eventType) || this.buffer.length >= MAX_BATCH_SIZE) {\n void this.flush();\n }\n }\n\n async flush(): Promise<void> {\n if (this.inFlight || this.buffer.length === 0) return;\n this.inFlight = true;\n\n const batch = this.buffer.splice(0, MAX_BATCH_SIZE);\n\n try {\n const res = await fetch(`${this.apiBaseUrl}/projects/${this.projectId}/pipeline-events`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.apiToken}`,\n },\n body: JSON.stringify({ events: batch }),\n });\n\n if (!res.ok) {\n if (res.status >= 500) {\n // Retryable server error — re-queue\n this.buffer.unshift(...batch);\n if (this.buffer.length > PipelineEventEmitter.MAX_BUFFER_SIZE) {\n this.buffer.splice(0, this.buffer.length - PipelineEventEmitter.MAX_BUFFER_SIZE);\n }\n } else {\n // Permanent client error (4xx) — drop batch, log\n console.error(`[event-emitter] Dropping ${batch.length} events: HTTP ${res.status}`);\n }\n }\n } catch {\n this.buffer.unshift(...batch);\n if (this.buffer.length > PipelineEventEmitter.MAX_BUFFER_SIZE) {\n this.buffer.splice(0, this.buffer.length - PipelineEventEmitter.MAX_BUFFER_SIZE);\n }\n } finally {\n this.inFlight = false;\n }\n }\n\n async close(): Promise<void> {\n this.closed = true;\n if (this.flushTimer) {\n clearInterval(this.flushTimer);\n this.flushTimer = null;\n }\n // Wait for any in-flight flush to settle\n while (this.inFlight) {\n await new Promise((r) => setTimeout(r, 50));\n }\n await this.flush();\n }\n}\n","import type { AgentProvider, PreflightResult, ModelTier } from './types.js';\n\nexport interface BoardProviderConfig {\n default_provider?: string;\n intelligence_provider?: string;\n}\n\nexport interface ColumnProviderConfig {\n provider?: string;\n}\n\nexport interface PreflightEntry {\n providerId: string;\n result: PreflightResult;\n}\n\nconst TIER_VALUES: ModelTier[] = ['fast', 'default', 'thorough'];\n\nexport class ProviderRegistry {\n private providers = new Map<string, AgentProvider>();\n\n register(provider: AgentProvider): void {\n this.providers.set(provider.id, provider);\n }\n\n get(id: string): AgentProvider {\n const provider = this.providers.get(id);\n if (!provider) throw new Error(`Unknown provider: ${id}. Registered: ${[...this.providers.keys()].join(', ')}`);\n return provider;\n }\n\n list(): AgentProvider[] {\n return [...this.providers.values()];\n }\n\n resolveForColumn(board: BoardProviderConfig, column: ColumnProviderConfig): AgentProvider {\n const id = column.provider ?? board.default_provider ?? 'claude';\n return this.get(id);\n }\n\n resolveForIntelligence(board: BoardProviderConfig): AgentProvider {\n const id = board.intelligence_provider ?? board.default_provider ?? 'claude';\n return this.get(id);\n }\n\n async preflightAll(providerIds: string[]): Promise<PreflightEntry[]> {\n const unique = [...new Set(providerIds)];\n const results = await Promise.all(\n unique.map(async (id) => {\n const provider = this.get(id);\n const result = await provider.preflight();\n return { providerId: id, result };\n }),\n );\n return results;\n }\n\n resolveModel(provider: AgentProvider, preference: string): string {\n if (TIER_VALUES.includes(preference as ModelTier)) {\n const model = provider.capabilities().supportedModels.find(m => m.tier === preference);\n if (model) return model.id;\n }\n return preference;\n }\n}\n","import { spawn, type ChildProcess, execFileSync } from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport type {\n AgentProvider, AgentRequest, AgentResult, PreflightResult, ProviderCapabilities, McpConfig,\n} from './types.js';\nimport { CodexJsonlParser } from './codex-jsonl-parser.js';\nimport { ensureWorktreeRemote } from '../lib/worktree.js';\n\nconst CODEX_TIMEOUT_MS = 60 * 60 * 1000; // 1 hour\n\nexport class CodexProvider implements AgentProvider {\n readonly id = 'codex';\n readonly displayName = 'Codex CLI';\n\n capabilities(): ProviderCapabilities {\n return {\n supportsToolAllowlist: false,\n supportsToolDenylist: false,\n supportsBuiltinToolStripping: false,\n supportsMaxTurns: false,\n supportsMcpConfigInjection: false,\n supportsMcpConfigOverride: true,\n supportsWorktreeFlag: false,\n supportsSandboxModes: true,\n supportedModels: [\n { id: 'gpt-5.1-codex-mini', displayName: 'Codex Mini', tier: 'fast' },\n { id: 'gpt-5.3-codex', displayName: 'GPT-5.3 Codex', tier: 'default' },\n { id: 'gpt-5.4', displayName: 'GPT-5.4', tier: 'thorough' },\n ],\n streamFormat: 'jsonl',\n };\n }\n\n async invoke(request: AgentRequest): Promise<AgentResult> {\n const degraded: string[] = [];\n const args = this.buildArgs(request, degraded);\n const env = this.buildEnv();\n const startTime = Date.now();\n\n // Codex doesn't support --worktree — create/reuse a git worktree for isolation.\n if (request.workingDirectory) {\n if (!existsSync(request.workingDirectory)) {\n // Directory doesn't exist — try creating a new worktree\n try {\n execFileSync('git', ['worktree', 'add', '-b', request.workingDirectory, request.workingDirectory, 'HEAD'], {\n stdio: 'pipe',\n });\n } catch {\n // Branch may already exist from a previous run — try without -b\n try {\n execFileSync('git', ['worktree', 'add', request.workingDirectory, request.workingDirectory], {\n stdio: 'pipe',\n });\n } catch {\n degraded.push('worktreeCreation');\n }\n }\n } else {\n // Directory exists — verify it's a valid git worktree, not a stale directory\n try {\n execFileSync('git', ['-C', request.workingDirectory, 'rev-parse', '--git-dir'], {\n stdio: 'pipe',\n });\n // Valid worktree — reuse it\n } catch {\n // Not a valid git dir — remove and recreate\n try {\n execFileSync('rm', ['-rf', request.workingDirectory], { stdio: 'pipe' });\n execFileSync('git', ['worktree', 'add', '-b', request.workingDirectory, request.workingDirectory, 'HEAD'], {\n stdio: 'pipe',\n });\n } catch {\n try {\n execFileSync('git', ['worktree', 'add', request.workingDirectory, request.workingDirectory], {\n stdio: 'pipe',\n });\n } catch {\n degraded.push('worktreeCreation');\n }\n }\n }\n }\n // Verify origin remote exists in the worktree — git worktree add should\n // inherit remotes from the main repo, but edge cases exist\n if (!degraded.includes('worktreeCreation') && existsSync(request.workingDirectory)) {\n ensureWorktreeRemote(request.workingDirectory);\n }\n }\n\n return new Promise((resolve) => {\n const child: ChildProcess = spawn('codex', args, {\n stdio: ['ignore', 'pipe', 'pipe'],\n env: { ...process.env, ...env },\n });\n\n const parser = new CodexJsonlParser();\n parser.onEvent = (event) => request.onStreamEvent?.(event);\n parser.onError = (err) => process.stderr.write(`[codex-jsonl] ${err.message}\\n`);\n\n let stderr = '';\n\n child.stdout?.on('data', (chunk: Buffer) => parser.feed(chunk.toString()));\n child.stderr?.on('data', (chunk: Buffer) => { stderr += chunk.toString(); });\n if (request.abortSignal) {\n request.abortSignal.addEventListener('abort', () => {\n try { child.kill('SIGTERM'); } catch { /* already dead */ }\n }, { once: true });\n }\n\n let killTimer: ReturnType<typeof setTimeout> | undefined;\n const timeoutHandle = setTimeout(() => {\n try { child.kill('SIGTERM'); } catch { /* already dead */ }\n killTimer = setTimeout(() => {\n try { child.kill('SIGKILL'); } catch { /* already dead */ }\n }, 5000);\n }, CODEX_TIMEOUT_MS);\n\n let resolved = false;\n const finish = (code: number | null, errorMsg?: string) => {\n if (resolved) return;\n resolved = true;\n clearTimeout(timeoutHandle);\n if (killTimer) clearTimeout(killTimer);\n parser.flush();\n\n const usage = parser.getUsage();\n const result: AgentResult = {\n exitCode: code ?? 1,\n output: errorMsg ?? (parser.getLastOutput() || stderr),\n toolCallCount: parser.getToolCallCount(),\n usage,\n durationMs: Date.now() - startTime,\n };\n if (degraded.length > 0) result.degradedCapabilities = degraded;\n resolve(result);\n };\n\n child.on('close', (code) => finish(code));\n child.on('error', (err) => finish(1, err.message));\n });\n }\n\n async preflight(): Promise<PreflightResult> {\n try {\n const which = await import('which');\n // Handle CJS interop: which exports the function as default with .sync attached.\n // In test environments the mock may only expose named `sync`.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- CJS interop, shape varies by env\n const w = which as any;\n const whichSync: (cmd: string) => string = w.sync ?? w.default?.sync ?? w.default;\n whichSync('codex');\n return { available: true, authenticated: true };\n } catch {\n return { available: false, authenticated: false, error: 'codex binary not found on PATH' };\n }\n }\n\n private buildArgs(request: AgentRequest, degraded: string[]): string[] {\n const args: string[] = [\n 'exec',\n '--json',\n '--dangerously-bypass-approvals-and-sandbox',\n ];\n\n if (request.model) args.push('-m', request.model);\n\n if (request.workingDirectory) {\n args.push('-C', request.workingDirectory);\n }\n\n // MCP config via -c flags — each server gets command, args, and env overrides.\n // This avoids CODEX_CONFIG_DIR which breaks Codex's state file resolution.\n if (request.mcpConfig && Object.keys(request.mcpConfig.servers).length > 0) {\n for (const [name, server] of Object.entries(request.mcpConfig.servers)) {\n args.push('-c', `mcp_servers.${name}.command=${JSON.stringify(server.command)}`);\n args.push('-c', `mcp_servers.${name}.args=${JSON.stringify(server.args)}`);\n if (Object.keys(server.env).length > 0) {\n for (const [key, value] of Object.entries(server.env)) {\n args.push('-c', `mcp_servers.${name}.env.${key}=${JSON.stringify(value)}`);\n }\n }\n }\n }\n\n // Tool restrictions — best-effort degradation.\n // Codex only supports sandbox modes (full/read-only), not per-tool restrictions.\n // Map common write-capable tool names to read-only sandbox.\n if (request.toolRestrictions) {\n const tr = request.toolRestrictions;\n const writingTools = ['Write', 'Edit', 'Bash', 'NotebookEdit', 'shell', 'file_write', 'file_edit'];\n if (tr.tools === '') {\n args.push('--sandbox', 'read-only');\n degraded.push('builtinToolStripping');\n } else if (tr.disallowedTools?.some(t => writingTools.includes(t))) {\n args.push('--sandbox', 'read-only');\n degraded.push('toolDenylist');\n }\n if (tr.allowedTools?.length) {\n degraded.push('toolAllowlist');\n }\n if (tr.disallowedTools?.length && !degraded.includes('toolDenylist')) {\n degraded.push('toolDenylist');\n }\n }\n\n if (request.maxTurns) {\n degraded.push('maxTurns');\n }\n\n // Prompt is the last positional argument\n args.push(request.prompt);\n\n return args;\n }\n\n private buildEnv(): Record<string, string> {\n const env: Record<string, string> = {};\n // Disable the MCP elicitation feature that causes the exec mode regression (#16685)\n env.CODEX_FEATURE_TOOL_CALL_MCP_ELICITATION = 'false';\n return env;\n }\n}\n","import type { NormalizedStreamEvent } from './types.js';\n\n/**\n * Parses Codex CLI --json output (newline-delimited JSON events)\n * and translates to NormalizedStreamEvents.\n *\n * Codex event types: thread.started, turn.started, turn.completed, turn.failed,\n * item.started, item.updated, item.completed, error.\n *\n * Item types: agent_message, command_execution, file_change, mcp_tool_call,\n * web_search, reasoning, todo_list, error.\n */\nexport class CodexJsonlParser {\n private buffer = '';\n private toolCallCount = 0;\n private inputTokens = 0;\n private outputTokens = 0;\n private lastOutput = '';\n\n onEvent: (event: NormalizedStreamEvent) => void = () => {};\n onError: (error: Error) => void = () => {};\n\n feed(chunk: string): void {\n this.buffer += chunk;\n const lines = this.buffer.split('\\n');\n this.buffer = lines.pop() ?? '';\n for (const line of lines) {\n this.parseLine(line.trim());\n }\n }\n\n flush(): void {\n const trimmed = this.buffer.trim();\n this.buffer = '';\n if (trimmed) this.parseLine(trimmed);\n }\n\n getToolCallCount(): number {\n return this.toolCallCount;\n }\n\n getUsage(): { inputTokens: number; outputTokens: number } {\n return { inputTokens: this.inputTokens, outputTokens: this.outputTokens };\n }\n\n getLastOutput(): string {\n return this.lastOutput;\n }\n\n reset(): void {\n this.buffer = '';\n this.toolCallCount = 0;\n this.inputTokens = 0;\n this.outputTokens = 0;\n this.lastOutput = '';\n }\n\n private parseLine(line: string): void {\n if (!line) return;\n try {\n const raw = JSON.parse(line) as Record<string, unknown>;\n this.translateEvent(raw);\n } catch {\n this.onError(new Error(`Failed to parse Codex JSONL: ${line.slice(0, 100)}`));\n }\n }\n\n private translateEvent(raw: Record<string, unknown>): void {\n const eventType = raw.type as string;\n const item = raw.item as Record<string, unknown> | undefined;\n\n if (eventType === 'item.started' && item) {\n const itemType = item.type as string;\n if (itemType === 'command_execution') {\n this.toolCallCount++;\n this.onEvent({ type: 'tool_call', tool: 'shell', input: { command: item.command } });\n } else if (itemType === 'mcp_tool_call') {\n this.toolCallCount++;\n this.onEvent({\n type: 'tool_call',\n tool: (item.tool as string) ?? 'unknown',\n input: item.arguments,\n });\n }\n } else if (eventType === 'item.completed' && item) {\n const itemType = item.type as string;\n if (itemType === 'agent_message') {\n const text = (item.text as string) ?? '';\n this.lastOutput = text;\n this.onEvent({ type: 'text', text });\n } else if (itemType === 'command_execution') {\n this.onEvent({\n type: 'tool_result',\n tool: 'shell',\n output: item.aggregated_output ?? '',\n });\n } else if (itemType === 'mcp_tool_call') {\n this.onEvent({\n type: 'tool_result',\n tool: (item.tool as string) ?? 'unknown',\n output: item.result !== undefined ? item.result : item.error,\n });\n }\n } else if (eventType === 'turn.completed') {\n const usage = raw.usage as { input_tokens?: number; output_tokens?: number } | undefined;\n const inTok = usage?.input_tokens ?? 0;\n const outTok = usage?.output_tokens ?? 0;\n this.inputTokens += inTok;\n this.outputTokens += outTok;\n if (inTok || outTok) {\n this.onEvent({ type: 'usage', inputTokens: inTok, outputTokens: outTok });\n }\n } else if (eventType === 'turn.failed') {\n const err = raw.error as { message?: string } | undefined;\n const msg = err?.message ?? 'turn failed';\n this.lastOutput = msg;\n this.onEvent({ type: 'error', message: msg });\n } else if (eventType === 'error') {\n const msg = (raw.message as string) ?? 'unknown error';\n this.lastOutput = msg;\n this.onEvent({ type: 'error', message: msg });\n }\n }\n}\n","// packages/cli/src/providers/gemini-provider.ts\nimport { spawn, type ChildProcess, execFileSync } from 'node:child_process';\nimport { existsSync, writeFileSync, mkdirSync, unlinkSync } from 'node:fs';\nimport { join, dirname } from 'node:path';\nimport { homedir, tmpdir } from 'node:os';\nimport { fileURLToPath } from 'node:url';\nimport { readFileSync } from 'node:fs';\nimport type {\n AgentProvider, AgentRequest, AgentResult, PreflightResult, ProviderCapabilities,\n} from './types.js';\nimport { GeminiJsonlParser } from './gemini-jsonl-parser.js';\nimport { ensureWorktreeRemote } from '../lib/worktree.js';\n\nconst GEMINI_TIMEOUT_MS = 60 * 60 * 1000; // 1 hour\n\n/** Map Claude-style tool names to Gemini CLI built-in tool names. */\nconst TOOL_NAME_MAP: Record<string, string> = {\n Write: 'write_file',\n Edit: 'replace',\n Read: 'read_file',\n Bash: 'run_shell_command',\n Grep: 'grep_search',\n Glob: 'glob',\n WebFetch: 'web_fetch',\n WebSearch: 'google_web_search',\n LS: 'list_directory',\n};\n\n/** Translate an array of tool names from Claude-style to Gemini-style, passing through unknowns. */\nfunction translateToolNames(tools: string[]): string[] {\n return tools.map(t => TOOL_NAME_MAP[t] ?? t);\n}\n\n/** Resolve the path to the gemini-hooks.mjs script.\n * At runtime import.meta.url points to a chunk inside dist/, so:\n * - dist/lib/gemini-hooks.mjs (copied during build)\n * - src/lib/gemini-hooks.mjs (development / source)\n */\nfunction resolveHookScriptPath(): string | null {\n try {\n const thisDir = dirname(fileURLToPath(import.meta.url));\n const candidates = [\n join(thisDir, 'lib', 'gemini-hooks.mjs'), // dist/lib/ (flat bundle)\n join(thisDir, '..', 'lib', 'gemini-hooks.mjs'), // dist/../lib/ (nested)\n join(thisDir, '..', 'src', 'lib', 'gemini-hooks.mjs'), // source from dist/\n join(thisDir, '..', '..', 'src', 'lib', 'gemini-hooks.mjs'), // source from dist/providers/\n ];\n for (const p of candidates) {\n if (existsSync(p)) return p;\n }\n return null;\n } catch {\n return null;\n }\n}\n\nexport class GeminiProvider implements AgentProvider {\n readonly id = 'gemini';\n readonly displayName = 'Gemini CLI';\n\n capabilities(): ProviderCapabilities {\n return {\n supportsToolAllowlist: true,\n supportsToolDenylist: true,\n supportsBuiltinToolStripping: true,\n supportsMaxTurns: true,\n supportsMcpConfigInjection: false,\n supportsMcpConfigOverride: true,\n supportsWorktreeFlag: false,\n supportsSandboxModes: true,\n supportedModels: [\n { id: 'gemini-2.5-flash-lite', displayName: 'Flash Lite', tier: 'fast' },\n { id: 'gemini-2.5-flash', displayName: 'Flash', tier: 'default' },\n { id: 'gemini-2.5-pro', displayName: 'Pro', tier: 'thorough' },\n ],\n streamFormat: 'jsonl',\n };\n }\n\n async invoke(request: AgentRequest): Promise<AgentResult> {\n const degraded: string[] = [];\n const args = this.buildArgs(request);\n const startTime = Date.now();\n\n // Worktree — manual creation, same as CodexProvider\n if (request.workingDirectory) {\n if (!existsSync(request.workingDirectory)) {\n try {\n execFileSync('git', ['worktree', 'add', '-b', request.workingDirectory, request.workingDirectory, 'HEAD'], {\n stdio: 'pipe',\n });\n } catch {\n try {\n execFileSync('git', ['worktree', 'add', request.workingDirectory, request.workingDirectory], {\n stdio: 'pipe',\n });\n } catch {\n degraded.push('worktreeCreation');\n }\n }\n } else {\n try {\n execFileSync('git', ['-C', request.workingDirectory, 'rev-parse', '--git-dir'], {\n stdio: 'pipe',\n });\n } catch {\n try {\n execFileSync('rm', ['-rf', request.workingDirectory], { stdio: 'pipe' });\n execFileSync('git', ['worktree', 'add', '-b', request.workingDirectory, request.workingDirectory, 'HEAD'], {\n stdio: 'pipe',\n });\n } catch {\n try {\n execFileSync('git', ['worktree', 'add', request.workingDirectory, request.workingDirectory], {\n stdio: 'pipe',\n });\n } catch {\n degraded.push('worktreeCreation');\n }\n }\n }\n }\n if (!degraded.includes('worktreeCreation') && existsSync(request.workingDirectory)) {\n ensureWorktreeRemote(request.workingDirectory);\n }\n }\n\n // Write .gemini/settings.json with MCP servers + hooks\n const settingsDir = this.writeGeminiSettings(request, degraded);\n const cwd = request.workingDirectory ?? settingsDir;\n\n // If using worktree, write settings inside it instead\n if (request.workingDirectory && settingsDir) {\n this.copySettingsToDir(settingsDir, request.workingDirectory);\n }\n\n return new Promise((resolve) => {\n const child: ChildProcess = spawn('gemini', args, {\n stdio: ['pipe', 'pipe', 'pipe'],\n cwd: cwd || undefined,\n });\n\n const parser = new GeminiJsonlParser();\n parser.onEvent = (event) => request.onStreamEvent?.(event);\n parser.onError = (err) => process.stderr.write(`[gemini-jsonl] ${err.message}\\n`);\n\n let stderr = '';\n\n child.stdout?.on('data', (chunk: Buffer) => parser.feed(chunk.toString()));\n child.stderr?.on('data', (chunk: Buffer) => { stderr += chunk.toString(); });\n child.stdin?.end();\n\n // Abort signal support\n if (request.abortSignal) {\n request.abortSignal.addEventListener('abort', () => {\n try { child.kill('SIGTERM'); } catch { /* already dead */ }\n }, { once: true });\n }\n\n // Timeout\n let killTimer: ReturnType<typeof setTimeout> | undefined;\n const timeoutHandle = setTimeout(() => {\n try { child.kill('SIGTERM'); } catch { /* already dead */ }\n killTimer = setTimeout(() => {\n try { child.kill('SIGKILL'); } catch { /* already dead */ }\n }, 5000);\n }, GEMINI_TIMEOUT_MS);\n\n let resolved = false;\n const finish = (code: number | null, errorMsg?: string) => {\n if (resolved) return;\n resolved = true;\n clearTimeout(timeoutHandle);\n if (killTimer) clearTimeout(killTimer);\n parser.flush();\n\n const usage = parser.getUsage();\n const result: AgentResult = {\n exitCode: (code === 53 ? 0 : code) ?? 1,\n output: errorMsg ?? (parser.getLastOutput() || stderr),\n toolCallCount: parser.getToolCallCount(),\n usage,\n durationMs: Date.now() - startTime,\n };\n if (degraded.length > 0) result.degradedCapabilities = degraded;\n resolve(result);\n };\n\n child.on('close', (code) => finish(code));\n child.on('error', (err) => finish(1, err.message));\n });\n }\n\n async preflight(): Promise<PreflightResult> {\n try {\n const whichModule = await import('which');\n const syncFn = whichModule.default?.sync ?? whichModule.sync;\n syncFn('gemini');\n return { available: true, authenticated: true };\n } catch {\n return { available: false, authenticated: false, error: 'gemini binary not found on PATH' };\n }\n }\n\n private buildArgs(request: AgentRequest): string[] {\n const args: string[] = [\n '-p', request.prompt,\n '--yolo',\n '--output-format', 'json',\n ];\n\n if (request.model) args.push('--model', request.model);\n\n // No --max-turns, --allowedTools, --disallowedTools, --tools\n // All handled by hooks in .gemini/settings.json\n\n return args;\n }\n\n private writeGeminiSettings(request: AgentRequest, degraded: string[]): string | null {\n try {\n const baseDir = join(homedir(), '.kantban', 'pipelines', 'gemini-tmp');\n const dir = join(baseDir, `session-${Date.now()}`);\n const geminiDir = join(dir, '.gemini');\n mkdirSync(geminiDir, { recursive: true, mode: 0o700 });\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- dynamic settings object\n const settings: Record<string, any> = {};\n\n // MCP servers\n if (request.mcpConfig && Object.keys(request.mcpConfig.servers).length > 0) {\n settings.mcpServers = {};\n for (const [name, server] of Object.entries(request.mcpConfig.servers)) {\n settings.mcpServers[name] = {\n command: server.command,\n args: server.args,\n env: server.env,\n trust: true,\n };\n }\n }\n\n // Hooks — Gemini CLI format: { matcher, hooks: [{ type, command, timeout }] }\n // Gemini ignores the `args` field, so we generate per-session wrapper scripts.\n const hookPath = resolveHookScriptPath();\n if (hookPath) {\n const hooks: Record<string, unknown[]> = {};\n const hookConfig: Record<string, unknown> = {};\n\n // BeforeToolSelection — tool scoping\n if (request.toolRestrictions) {\n const tr = request.toolRestrictions;\n hookConfig.allowedTools = tr.allowedTools ? translateToolNames(tr.allowedTools) : null;\n hookConfig.disallowedTools = tr.disallowedTools ? translateToolNames(tr.disallowedTools) : null;\n if (tr.tools !== undefined) hookConfig.builtinToolsMode = tr.tools;\n\n const wrapperPath = join(dir, '.kantban-hook-before-tool.sh');\n writeFileSync(wrapperPath, this.generateHookWrapper(hookPath, 'BeforeToolSelection', join(dir, '.kantban-hook-config.json')), { mode: 0o755 });\n hooks.BeforeToolSelection = [{ matcher: '*', hooks: [{ type: 'command', command: wrapperPath, timeout: 30000 }] }];\n }\n\n // AfterAgent — turn limit\n if (request.maxTurns) {\n hookConfig.maxTurns = request.maxTurns;\n hookConfig.turnFile = join(dir, '.kantban-turn-counter');\n\n const wrapperPath = join(dir, '.kantban-hook-after-agent.sh');\n writeFileSync(wrapperPath, this.generateHookWrapper(hookPath, 'AfterAgent', join(dir, '.kantban-hook-config.json')), { mode: 0o755 });\n hooks.AfterAgent = [{ matcher: '*', hooks: [{ type: 'command', command: wrapperPath, timeout: 30000 }] }];\n }\n\n if (Object.keys(hookConfig).length > 0) {\n writeFileSync(join(dir, '.kantban-hook-config.json'), JSON.stringify(hookConfig), { mode: 0o600 });\n }\n if (Object.keys(hooks).length > 0) {\n settings.hooks = hooks;\n }\n } else {\n // Hook script not found — degrade\n if (request.maxTurns) degraded.push('maxTurns');\n if (request.toolRestrictions?.allowedTools?.length) degraded.push('toolAllowlist');\n if (request.toolRestrictions?.disallowedTools?.length) degraded.push('toolDenylist');\n if (request.toolRestrictions?.tools !== undefined) degraded.push('builtinToolStripping');\n process.stderr.write(`[gemini] Hook script not found — tool scoping and turn limits unavailable\\n`);\n }\n\n writeFileSync(join(geminiDir, 'settings.json'), JSON.stringify(settings, null, 2), { mode: 0o600 });\n return dir;\n } catch (err) {\n process.stderr.write(`[gemini] Failed to write settings.json: ${err}\\n`);\n if (request.maxTurns) degraded.push('maxTurns');\n if (request.toolRestrictions?.allowedTools?.length) degraded.push('toolAllowlist');\n if (request.toolRestrictions?.disallowedTools?.length) degraded.push('toolDenylist');\n if (request.toolRestrictions?.tools !== undefined) degraded.push('builtinToolStripping');\n return null;\n }\n }\n\n /** Generate a per-session bash wrapper that invokes the Node hook script.\n * Gemini CLI ignores `args` in hook definitions, so we embed all arguments. */\n private generateHookWrapper(hookScript: string, event: string, configFile: string): string {\n return `#!/bin/bash\n# KantBan pipeline hook wrapper — Gemini CLI does not pass args, so we embed them.\nSTDIN_FILE=$(mktemp)\ntrap 'rm -f \"$STDIN_FILE\"' EXIT\ncat > \"$STDIN_FILE\"\nnode \"${hookScript}\" \"${event}\" \"${configFile}\" < \"$STDIN_FILE\"\n`;\n }\n\n private copySettingsToDir(settingsDir: string, targetDir: string): void {\n try {\n const sourceFile = join(settingsDir, '.gemini', 'settings.json');\n const targetGeminiDir = join(targetDir, '.gemini');\n mkdirSync(targetGeminiDir, { recursive: true, mode: 0o700 });\n const content = readFileSync(sourceFile, 'utf-8');\n writeFileSync(join(targetGeminiDir, 'settings.json'), content, { mode: 0o600 });\n } catch {\n // Best-effort — settings in the temp dir will still be discovered\n }\n }\n}\n","// packages/cli/src/providers/gemini-jsonl-parser.ts\nimport type { NormalizedStreamEvent } from './types.js';\n\n/**\n * Parses Gemini CLI --output-format json (newline-delimited JSON events)\n * and translates to NormalizedStreamEvents.\n *\n * Gemini event types: init, message, tool_use, tool_result, error, result.\n */\nexport class GeminiJsonlParser {\n private buffer = '';\n /** Accumulates lines that failed individual JSON parse (multi-line object) */\n private jsonAccum = '';\n private toolCallCount = 0;\n private inputTokens = 0;\n private outputTokens = 0;\n private lastOutput = '';\n\n onEvent: (event: NormalizedStreamEvent) => void = () => {};\n onError: (error: Error) => void = () => {};\n\n feed(chunk: string): void {\n this.buffer += chunk;\n const lines = this.buffer.split('\\n');\n this.buffer = lines.pop() ?? '';\n for (const line of lines) {\n this.parseLine(line.trim());\n }\n }\n\n flush(): void {\n const trimmed = this.buffer.trim();\n this.buffer = '';\n if (trimmed) this.parseLine(trimmed);\n // Try to parse any accumulated multi-line JSON\n this.tryFlushAccum();\n }\n\n getToolCallCount(): number {\n return this.toolCallCount;\n }\n\n getUsage(): { inputTokens: number; outputTokens: number } {\n return { inputTokens: this.inputTokens, outputTokens: this.outputTokens };\n }\n\n getLastOutput(): string {\n return this.lastOutput;\n }\n\n reset(): void {\n this.buffer = '';\n this.toolCallCount = 0;\n this.inputTokens = 0;\n this.outputTokens = 0;\n this.lastOutput = '';\n }\n\n private parseLine(line: string): void {\n if (!line) return;\n\n // If we're accumulating a multi-line JSON object, keep appending\n if (this.jsonAccum) {\n this.jsonAccum += '\\n' + line;\n if (this.tryFlushAccum()) return;\n return; // keep accumulating\n }\n\n try {\n const raw = JSON.parse(line) as Record<string, unknown>;\n this.translateEvent(raw);\n } catch {\n // Could be the start of a multi-line JSON object\n if (line.startsWith('{') || line.startsWith('[')) {\n this.jsonAccum = line;\n }\n // Silently skip non-JSON lines (don't spam stderr)\n }\n }\n\n /** Try to parse the accumulated multi-line buffer as JSON. Returns true if successful. */\n private tryFlushAccum(): boolean {\n if (!this.jsonAccum) return false;\n try {\n const raw = JSON.parse(this.jsonAccum) as Record<string, unknown>;\n this.jsonAccum = '';\n this.translateEvent(raw);\n return true;\n } catch {\n return false;\n }\n }\n\n private translateEvent(raw: Record<string, unknown>): void {\n const eventType = raw.type as string;\n\n if (eventType === 'message') {\n if (raw.role === 'assistant' && typeof raw.content === 'string') {\n this.onEvent({ type: 'text', text: raw.content });\n }\n } else if (eventType === 'tool_use') {\n this.toolCallCount++;\n this.onEvent({\n type: 'tool_call',\n tool: (raw.name as string) ?? 'unknown',\n input: raw.args ?? raw.input,\n });\n } else if (eventType === 'tool_result') {\n this.onEvent({\n type: 'tool_result',\n tool: (raw.name as string) ?? 'unknown',\n output: raw.output ?? raw.result,\n });\n } else if (eventType === 'result' || (raw.session_id && raw.stats)) {\n // Gemini final output: { session_id, response, stats: { models: { ... } } }\n const { inTok, outTok } = this.extractTokens(raw);\n this.inputTokens += inTok;\n this.outputTokens += outTok;\n if (inTok || outTok) {\n this.onEvent({ type: 'usage', inputTokens: inTok, outputTokens: outTok });\n }\n // Extract tool call count from stats.tools.totalCalls\n const tools = (raw.stats as Record<string, unknown>)?.tools as Record<string, number> | undefined;\n if (tools?.totalCalls) this.toolCallCount = Math.max(this.toolCallCount, tools.totalCalls);\n if (typeof raw.response === 'string') {\n this.lastOutput = raw.response;\n this.onEvent({ type: 'done', result: raw.response });\n }\n } else if (eventType === 'error') {\n const msg = (raw.message as string) ?? 'unknown error';\n this.lastOutput = msg;\n this.onEvent({ type: 'error', message: msg });\n }\n // 'init' and unknown types are silently ignored\n }\n\n /** Extract token counts from Gemini's nested stats structure */\n private extractTokens(raw: Record<string, unknown>): { inTok: number; outTok: number } {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- dynamic stats traversal\n const stats = raw.stats as any;\n if (!stats) return { inTok: 0, outTok: 0 };\n\n // Flat stats: { promptTokenCount, candidatesTokenCount } or { input_tokens, output_tokens }\n if (stats.promptTokenCount || stats.input_tokens) {\n return {\n inTok: stats.promptTokenCount ?? stats.input_tokens ?? 0,\n outTok: stats.candidatesTokenCount ?? stats.output_tokens ?? 0,\n };\n }\n\n // Nested Gemini stats: { models: { \"gemini-2.5-flash\": { tokens: { prompt, candidates } } } }\n if (stats.models && typeof stats.models === 'object') {\n let inTok = 0;\n let outTok = 0;\n for (const model of Object.values(stats.models) as Record<string, unknown>[]) {\n const tokens = model?.tokens as Record<string, number> | undefined;\n if (tokens) {\n inTok += tokens.prompt ?? tokens.input ?? 0;\n outTok += tokens.candidates ?? tokens.output ?? 0;\n }\n }\n return { inTok, outTok };\n }\n\n return { inTok: 0, outTok: 0 };\n }\n}\n"],"mappings":"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","names":["mkdirSync","writeFileSync","readFileSync","unlinkSync","existsSync","appendFileSync","homedir","join","col","passed","err","msg","colScope","ticket","colConfig","z","z","z","z","writeFileSync","spawn","execFileSync","execFileSync","spawn","spawn","execFileSync","existsSync","writeFileSync","mkdirSync","join","readFileSync","join","existsSync","execFileSync","spawn","mkdirSync","writeFileSync","readFileSync","readFileSync","join","homedir","mkdirSync","writeFileSync","unlinkSync","readFileSync","unlinkSync","existsSync","join","homedir"]}