kantban-cli 0.1.8 → 0.1.11

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.
Files changed (155) hide show
  1. package/dist/chunk-ZCUIGFSP.js +4111 -0
  2. package/dist/chunk-ZCUIGFSP.js.map +1 -0
  3. package/dist/context-7YDNTI3P.js +30 -0
  4. package/dist/context-7YDNTI3P.js.map +1 -0
  5. package/dist/cron-OKQP6QDF.js +112 -0
  6. package/dist/cron-OKQP6QDF.js.map +1 -0
  7. package/dist/index.d.ts +0 -2
  8. package/dist/index.js +179 -44
  9. package/dist/index.js.map +1 -1
  10. package/dist/pipeline-7LG74YA2.js +4098 -0
  11. package/dist/pipeline-7LG74YA2.js.map +1 -0
  12. package/dist/pipeline-init-IGZZOOLK.js +103 -0
  13. package/dist/pipeline-init-IGZZOOLK.js.map +1 -0
  14. package/dist/status-4GFXMVIM.js +128 -0
  15. package/dist/status-4GFXMVIM.js.map +1 -0
  16. package/dist/work-2V33NZAT.js +81 -0
  17. package/dist/work-2V33NZAT.js.map +1 -0
  18. package/package.json +5 -4
  19. package/dist/client.d.ts +0 -38
  20. package/dist/client.d.ts.map +0 -1
  21. package/dist/client.js +0 -163
  22. package/dist/client.js.map +0 -1
  23. package/dist/commands/context.d.ts +0 -3
  24. package/dist/commands/context.d.ts.map +0 -1
  25. package/dist/commands/context.js +0 -27
  26. package/dist/commands/context.js.map +0 -1
  27. package/dist/commands/cron.d.ts +0 -3
  28. package/dist/commands/cron.d.ts.map +0 -1
  29. package/dist/commands/cron.js +0 -106
  30. package/dist/commands/cron.js.map +0 -1
  31. package/dist/commands/pipeline-init.d.ts +0 -2
  32. package/dist/commands/pipeline-init.d.ts.map +0 -1
  33. package/dist/commands/pipeline-init.js +0 -100
  34. package/dist/commands/pipeline-init.js.map +0 -1
  35. package/dist/commands/pipeline.d.ts +0 -4
  36. package/dist/commands/pipeline.d.ts.map +0 -1
  37. package/dist/commands/pipeline.js +0 -1222
  38. package/dist/commands/pipeline.js.map +0 -1
  39. package/dist/commands/status.d.ts +0 -3
  40. package/dist/commands/status.d.ts.map +0 -1
  41. package/dist/commands/status.js +0 -135
  42. package/dist/commands/status.js.map +0 -1
  43. package/dist/commands/work.d.ts +0 -3
  44. package/dist/commands/work.d.ts.map +0 -1
  45. package/dist/commands/work.js +0 -76
  46. package/dist/commands/work.js.map +0 -1
  47. package/dist/index.d.ts.map +0 -1
  48. package/dist/lib/advisor.d.ts +0 -108
  49. package/dist/lib/advisor.d.ts.map +0 -1
  50. package/dist/lib/advisor.js +0 -139
  51. package/dist/lib/advisor.js.map +0 -1
  52. package/dist/lib/checkpoint.d.ts +0 -15
  53. package/dist/lib/checkpoint.d.ts.map +0 -1
  54. package/dist/lib/checkpoint.js +0 -49
  55. package/dist/lib/checkpoint.js.map +0 -1
  56. package/dist/lib/constraint-evaluator.d.ts +0 -40
  57. package/dist/lib/constraint-evaluator.d.ts.map +0 -1
  58. package/dist/lib/constraint-evaluator.js +0 -189
  59. package/dist/lib/constraint-evaluator.js.map +0 -1
  60. package/dist/lib/cost-tracker.d.ts +0 -46
  61. package/dist/lib/cost-tracker.d.ts.map +0 -1
  62. package/dist/lib/cost-tracker.js +0 -120
  63. package/dist/lib/cost-tracker.js.map +0 -1
  64. package/dist/lib/evaluator.d.ts +0 -17
  65. package/dist/lib/evaluator.d.ts.map +0 -1
  66. package/dist/lib/evaluator.js +0 -71
  67. package/dist/lib/evaluator.js.map +0 -1
  68. package/dist/lib/event-emitter.d.ts +0 -28
  69. package/dist/lib/event-emitter.d.ts.map +0 -1
  70. package/dist/lib/event-emitter.js +0 -100
  71. package/dist/lib/event-emitter.js.map +0 -1
  72. package/dist/lib/event-queue.d.ts +0 -28
  73. package/dist/lib/event-queue.d.ts.map +0 -1
  74. package/dist/lib/event-queue.js +0 -73
  75. package/dist/lib/event-queue.js.map +0 -1
  76. package/dist/lib/gate-config.d.ts +0 -7
  77. package/dist/lib/gate-config.d.ts.map +0 -1
  78. package/dist/lib/gate-config.js +0 -68
  79. package/dist/lib/gate-config.js.map +0 -1
  80. package/dist/lib/gate-proxy-server.d.ts +0 -16
  81. package/dist/lib/gate-proxy-server.d.ts.map +0 -1
  82. package/dist/lib/gate-proxy-server.js +0 -385
  83. package/dist/lib/gate-proxy-server.js.map +0 -1
  84. package/dist/lib/gate-proxy.d.ts +0 -46
  85. package/dist/lib/gate-proxy.d.ts.map +0 -1
  86. package/dist/lib/gate-proxy.js +0 -104
  87. package/dist/lib/gate-proxy.js.map +0 -1
  88. package/dist/lib/gate-runner.d.ts +0 -13
  89. package/dist/lib/gate-runner.d.ts.map +0 -1
  90. package/dist/lib/gate-runner.js +0 -104
  91. package/dist/lib/gate-runner.js.map +0 -1
  92. package/dist/lib/gate-snapshot.d.ts +0 -12
  93. package/dist/lib/gate-snapshot.d.ts.map +0 -1
  94. package/dist/lib/gate-snapshot.js +0 -49
  95. package/dist/lib/gate-snapshot.js.map +0 -1
  96. package/dist/lib/light-call.d.ts +0 -37
  97. package/dist/lib/light-call.d.ts.map +0 -1
  98. package/dist/lib/light-call.js +0 -62
  99. package/dist/lib/light-call.js.map +0 -1
  100. package/dist/lib/logger.d.ts +0 -22
  101. package/dist/lib/logger.d.ts.map +0 -1
  102. package/dist/lib/logger.js +0 -98
  103. package/dist/lib/logger.js.map +0 -1
  104. package/dist/lib/mcp-config.d.ts +0 -24
  105. package/dist/lib/mcp-config.d.ts.map +0 -1
  106. package/dist/lib/mcp-config.js +0 -115
  107. package/dist/lib/mcp-config.js.map +0 -1
  108. package/dist/lib/orchestrator.d.ts +0 -392
  109. package/dist/lib/orchestrator.d.ts.map +0 -1
  110. package/dist/lib/orchestrator.js +0 -1636
  111. package/dist/lib/orchestrator.js.map +0 -1
  112. package/dist/lib/parse-utils.d.ts +0 -6
  113. package/dist/lib/parse-utils.d.ts.map +0 -1
  114. package/dist/lib/parse-utils.js +0 -64
  115. package/dist/lib/parse-utils.js.map +0 -1
  116. package/dist/lib/prompt-composer.d.ts +0 -131
  117. package/dist/lib/prompt-composer.d.ts.map +0 -1
  118. package/dist/lib/prompt-composer.js +0 -317
  119. package/dist/lib/prompt-composer.js.map +0 -1
  120. package/dist/lib/ralph-loop.d.ts +0 -123
  121. package/dist/lib/ralph-loop.d.ts.map +0 -1
  122. package/dist/lib/ralph-loop.js +0 -383
  123. package/dist/lib/ralph-loop.js.map +0 -1
  124. package/dist/lib/reaper.d.ts +0 -14
  125. package/dist/lib/reaper.d.ts.map +0 -1
  126. package/dist/lib/reaper.js +0 -114
  127. package/dist/lib/reaper.js.map +0 -1
  128. package/dist/lib/replanner.d.ts +0 -49
  129. package/dist/lib/replanner.d.ts.map +0 -1
  130. package/dist/lib/replanner.js +0 -61
  131. package/dist/lib/replanner.js.map +0 -1
  132. package/dist/lib/run-memory.d.ts +0 -37
  133. package/dist/lib/run-memory.d.ts.map +0 -1
  134. package/dist/lib/run-memory.js +0 -115
  135. package/dist/lib/run-memory.js.map +0 -1
  136. package/dist/lib/stream-parser.d.ts +0 -20
  137. package/dist/lib/stream-parser.d.ts.map +0 -1
  138. package/dist/lib/stream-parser.js +0 -65
  139. package/dist/lib/stream-parser.js.map +0 -1
  140. package/dist/lib/stuck-detector.d.ts +0 -47
  141. package/dist/lib/stuck-detector.d.ts.map +0 -1
  142. package/dist/lib/stuck-detector.js +0 -105
  143. package/dist/lib/stuck-detector.js.map +0 -1
  144. package/dist/lib/tool-profiles.d.ts +0 -19
  145. package/dist/lib/tool-profiles.d.ts.map +0 -1
  146. package/dist/lib/tool-profiles.js +0 -22
  147. package/dist/lib/tool-profiles.js.map +0 -1
  148. package/dist/lib/worktree.d.ts +0 -12
  149. package/dist/lib/worktree.d.ts.map +0 -1
  150. package/dist/lib/worktree.js +0 -29
  151. package/dist/lib/worktree.js.map +0 -1
  152. package/dist/lib/ws-client.d.ts +0 -31
  153. package/dist/lib/ws-client.d.ts.map +0 -1
  154. package/dist/lib/ws-client.js +0 -113
  155. package/dist/lib/ws-client.js.map +0 -1
@@ -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/stream-parser.ts","../src/lib/gate-snapshot.ts","../src/lib/gate-runner.ts","../src/lib/cost-tracker.ts","../src/lib/event-emitter.ts"],"sourcesContent":["import { spawn, execSync, type ChildProcess } from 'node:child_process';\nimport { 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, type ClaudeInvokeOptions } 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 { StreamJsonParser, type StreamJsonEvent } from '../lib/stream-parser.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';\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 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 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 '--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 --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, 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 // 2. Kill orphaned claude -p processes with THIS BOARD's MCP configs\n try {\n const boardDir = pidDir(boardId).replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n const out = execSync(\n `ps aux | grep 'claude.*-p' | grep '${boardDir}' | grep -v grep | awk '{print $2}'`,\n { encoding: 'utf-8', timeout: 5000 },\n ).trim();\n if (out) {\n const pids = out.split('\\n').filter(Boolean);\n for (const pid of pids) {\n try {\n process.kill(parseInt(pid, 10), 'SIGTERM');\n } catch {\n // already dead\n }\n }\n if (pids.length > 0) {\n console.log(`Killed ${String(pids.length)} orphaned claude agent(s)`);\n }\n }\n } catch {\n // ps/grep failed — not critical\n }\n}\n\n// ---------------------------------------------------------------------------\n// invokeClaudeP — spawns a Claude Code process with -p flag\n// Children are spawned in the orchestrator's process group so that killing\n// the group (e.g. on crash) takes all children down with it.\n// ---------------------------------------------------------------------------\n\nconst activeChildProcesses = new Set<ChildProcess>();\nlet currentBoardId = '';\n\nconst CLAUDE_TIMEOUT_MS = 60 * 60 * 1000; // 1 hour max per invocation\n\nasync function invokeClaudeP(\n prompt: string,\n options: ClaudeInvokeOptions,\n): Promise<{ exitCode: number; output: string; toolCallCount: number; tokensIn: number; tokensOut: number }> {\n const args: string[] = ['-p', prompt, '--dangerously-skip-permissions', '--output-format', 'stream-json', '--verbose'];\n\n // MCP config — omit for toolless invocations\n if (options.includeMcpConfig !== false && options.mcpConfigPath) {\n args.push('--mcp-config', options.mcpConfigPath);\n }\n if (options.model) args.push('--model', options.model);\n if (options.maxTurns) {\n args.push('--max-turns', String(options.maxTurns));\n } else if (options.maxBudgetUsd !== undefined && options.maxBudgetUsd !== null) {\n args.push('--max-turns', String(Math.max(1, Math.ceil(options.maxBudgetUsd * 10))));\n }\n if (options.worktree) args.push('--worktree', options.worktree);\n\n // Tool scoping flags\n if (options.tools !== undefined) {\n args.push('--tools', options.tools);\n }\n if (options.allowedTools?.length) {\n args.push('--allowedTools', ...options.allowedTools);\n }\n if (options.disallowedTools?.length) {\n args.push('--disallowedTools', ...options.disallowedTools);\n }\n\n return new Promise((resolve) => {\n const child: ChildProcess = spawn('claude', args, {\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n\n activeChildProcesses.add(child);\n if (child.pid && currentBoardId) appendChildPid(currentBoardId, child.pid);\n\n const parser = new StreamJsonParser();\n parser.on('error', (err: Error) => {\n process.stderr.write(`[stream-parser] ${err.message}\\n`);\n });\n let lastOutput = '';\n let tokensIn = 0;\n let tokensOut = 0;\n\n parser.on('event', (event: StreamJsonEvent) => {\n // Capture final result metadata\n if (event.type === 'result') {\n const usage = event.usage as { input_tokens?: number; output_tokens?: number } | undefined;\n tokensIn += usage?.input_tokens ?? 0;\n tokensOut += usage?.output_tokens ?? 0;\n if (typeof event.result === 'string') lastOutput = event.result;\n }\n\n // Forward to stream callback if provided\n options.onStreamEvent?.(event);\n });\n\n child.stdout?.on('data', (chunk: Buffer) => {\n parser.feed(chunk.toString());\n });\n\n // Capture stderr for error diagnostics\n let stderr = '';\n child.stderr?.on('data', (chunk: Buffer) => {\n stderr += chunk.toString();\n });\n\n // Close stdin immediately (we pass prompt via -p flag)\n child.stdin?.end();\n\n // Set up timeout\n let killTimer: ReturnType<typeof setTimeout> | undefined;\n const timeoutHandle = setTimeout(() => {\n try { child.kill('SIGTERM'); } catch { /* already dead */ }\n // Escalate to SIGKILL if process doesn't exit within 5s\n killTimer = setTimeout(() => {\n if (!resolved) {\n try { child.kill('SIGKILL'); } catch { /* already dead */ }\n }\n }, 5000);\n }, CLAUDE_TIMEOUT_MS);\n\n let resolved = false;\n child.on('close', (code) => {\n if (resolved) return;\n resolved = true;\n clearTimeout(timeoutHandle);\n if (killTimer) clearTimeout(killTimer);\n activeChildProcesses.delete(child);\n if (child.pid && currentBoardId) removeChildPid(currentBoardId, child.pid);\n parser.flush();\n\n resolve({\n exitCode: code ?? 1,\n output: lastOutput || stderr,\n toolCallCount: parser.getToolCallCount(),\n tokensIn,\n tokensOut,\n });\n });\n\n child.on('error', (err) => {\n if (resolved) return;\n resolved = true;\n clearTimeout(timeoutHandle);\n if (killTimer) clearTimeout(killTimer);\n activeChildProcesses.delete(child);\n if (child.pid && currentBoardId) removeChildPid(currentBoardId, child.pid);\n parser.flush();\n\n resolve({\n exitCode: 1,\n output: err.message,\n toolCallCount: parser.getToolCallCount(),\n tokensIn,\n tokensOut,\n });\n });\n });\n}\n\nfunction killAllChildProcesses(): void {\n for (const child of activeChildProcesses) {\n try {\n if (child.pid) {\n try {\n process.kill(-child.pid, 'SIGTERM');\n } catch {\n try { child.kill('SIGTERM'); } catch { /* already dead */ }\n }\n } else {\n try { child.kill('SIGTERM'); } catch { /* already dead */ }\n }\n } catch {\n // Process already exited — safe to ignore\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 currentBoardId = opts.boardId;\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 // 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 once upfront so we can select the right MCP config.\n // This also pre-warms cachedColumnName for onPostIterationGates below.\n const colScopeForName = await client.get<{ column: { name: string } }>(\n `/projects/${projectId}/pipeline-context`, { columnId },\n );\n const resolvedColumnName = colScopeForName.column.name;\n\n // Choose MCP config: gate-proxy variant when gates are configured for this column,\n // global variant otherwise.\n const columnGates = resolveGatesForColumn(gateConfig, resolvedColumnName);\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 )\n : mcpConfigPath;\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 invokeClaudeP,\n mcpConfigPath: effectiveMcpConfigPath,\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 await deps.setFieldValue!(tid, 'loop_checkpoint', checkpoint);\n } catch {\n // Fire-and-forget\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 { exitCode, output } = await invokeClaudeP(prompt, {\n mcpConfigPath,\n model: 'haiku',\n maxBudgetUsd: 0.01,\n tools: '',\n includeMcpConfig: false,\n });\n if (exitCode !== 0) {\n throw new Error(`Stuck detection call failed (exit ${String(exitCode)})`);\n }\n return parseStuckDetectionResponse(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 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 { exitCode, output, tokensIn, tokensOut } = await invokeClaudeP(prompt, {\n mcpConfigPath,\n model: 'haiku',\n maxBudgetUsd: 0.01,\n maxTurns: 3,\n tools: '', // Strip all built-in tools\n includeMcpConfig: false, // No MCP tools either\n });\n\n costTracker?.record({ ticketId, columnId, model: 'haiku', tokensIn, tokensOut, type: 'light' });\n\n if (exitCode !== 0) {\n throw new Error(`Light call exited with code ${exitCode}: ${output.slice(0, 200)}`);\n }\n\n const response = parseLightResponse(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 { exitCode, output, tokensIn, tokensOut } = await invokeClaudeP(prompt, {\n mcpConfigPath,\n model: 'haiku',\n maxBudgetUsd: 0.01,\n tools: '',\n includeMcpConfig: false,\n });\n\n costTracker?.record({ ticketId: input.ticketId, columnId: '', model: 'haiku', tokensIn, tokensOut, type: 'advisor' });\n\n if (exitCode !== 0) {\n throw new Error(`Advisor call exited with code ${exitCode}: ${output.slice(0, 200)}`);\n }\n\n const response = parseAdvisorResponse(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 ctx = await client.get<{ field_values: Array<{ field_name: string; value: unknown }> }>(\n `/projects/${projectId}/pipeline-context`, { ticketId },\n );\n return ctx.field_values;\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 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 { exitCode, output, tokensIn, tokensOut } = await invokeClaudeP(prompt, {\n mcpConfigPath,\n model: 'haiku',\n maxBudgetUsd: 0.01,\n tools: '',\n includeMcpConfig: false,\n });\n costTracker?.record({ ticketId: 'replanner', columnId: 'pipeline', model: 'haiku', tokensIn, tokensOut, type: 'orchestrator' });\n if (exitCode !== 0) throw new Error(`Replanner failed`);\n return parseReplannerResponse(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();\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 killAllChildProcesses();\n\n // Wait for children to actually exit (up to 5 seconds)\n const deadline = Date.now() + 5000;\n while (activeChildProcesses.size > 0 && Date.now() < deadline) {\n await new Promise(r => setTimeout(r, 200));\n }\n\n if (activeChildProcesses.size > 0) {\n console.error(`Warning: ${String(activeChildProcesses.size)} child process(es) did not exit. Sending SIGKILL...`);\n for (const child of activeChildProcesses) {\n try {\n if (child.pid) {\n try {\n process.kill(-child.pid, 'SIGKILL');\n } catch {\n try { child.kill('SIGKILL'); } catch { /* already dead */ }\n }\n } else {\n try { child.kill('SIGKILL'); } catch { /* already dead */ }\n }\n } catch {\n // Process already exited\n }\n }\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) {\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 } 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\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 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 * 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 // 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 // Merge worktree branch into integration branch without checking it out.\n // Use a temporary index to avoid disrupting the working directory.\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 (worktree branch is descendant of integration)\n const { stdout: integrationSha } = await execPromise(exec, 'git', ['rev-parse', integrationBranch]);\n if (integrationSha.trim() === mergeBase) {\n // Fast-forward: just update the integration branch ref\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 — need a real merge. Use a temp worktree to avoid disrupting main.\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 const parsed = LoopCheckpointSchema.safeParse(entry.value);\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, null);\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 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 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(): 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 const pipelineCols = boardScope.columns.filter(\n (col) => (col.has_prompt || col.type === 'evaluator') && col.type !== 'done',\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: create signals for blocked constraints with notify=true\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.createColumnSignal) {\n void this.deps.createColumnSignal(\n columnId,\n `Firing constraint \"${r.name}\" blocked column: ` +\n `resolved=${String(r.resolved_value)} ${r.threshold.operator} ${String(r.threshold.value)}`,\n ).catch((err) => {\n const msg = err instanceof Error ? err.message : String(err);\n console.error(` [warn] Failed to create 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 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 };\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 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 // 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 if (colConfig?.checkpointEnabled && this.deps.setFieldValue) {\n await this.safeAction(ticketId, 'clearCheckpoint', () =>\n this.deps.setFieldValue!(ticketId, 'loop_checkpoint', null),\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';\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 }\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. Returns '' if not initialized or on error.\n */\n async getContent(): Promise<string> {\n if (this._documentId === null) {\n return '';\n }\n try {\n return await this.deps.getDocument(this._documentId);\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 */\n async needsCompaction(threshold: number = DEFAULT_COMPACTION_THRESHOLD): Promise<boolean> {\n const content = await this.getContent();\n if (!content) return false;\n const lineCount = content.split('\\n').length;\n return lineCount > threshold;\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 stopped = false;\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.cleanupPing();\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}`;\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 // Start heartbeat\n this.pingTimer = setInterval(() => this.send({ type: 'ping', payload: {} }), 30000);\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 // 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.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.cleanupPing();\n this.options.onDisconnect();\n if (!resolved) {\n resolved = true;\n reject(new Error(`WebSocket closed before handshake (code ${code})`));\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.stopped = true;\n this.cleanupPing();\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 }\n }\n\n private cleanupPing(): void {\n if (this.pingTimer) {\n clearInterval(this.pingTimer);\n this.pingTimer = 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 // 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 { EventEmitter } from 'node:events';\n\nexport interface StreamJsonEvent {\n type: string;\n subtype?: string;\n [key: string]: unknown;\n}\n\n/**\n * Parses newline-delimited JSON from a readable stream (Claude --output-format stream-json).\n * Emits 'event' for each parsed line, 'error' for parse failures.\n */\nexport class StreamJsonParser extends EventEmitter {\n private buffer = '';\n private toolCallCount = 0;\n\n feed(chunk: string): void {\n this.buffer += chunk;\n const lines = this.buffer.split('\\n');\n // Keep the last incomplete line in the buffer\n this.buffer = lines.pop() ?? '';\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n try {\n const event = JSON.parse(trimmed) as StreamJsonEvent;\n // Count tool_use blocks within assistant events only — the assistant event is\n // the authoritative source. Standalone top-level tool_use events are duplicates.\n if (event.type === 'assistant' && Array.isArray(event.content)) {\n for (const block of event.content as Array<{ type?: string }>) {\n if (block.type === 'tool_use') this.toolCallCount++;\n }\n }\n this.emit('event', event);\n } catch {\n this.emit('error', new Error(`Failed to parse stream-json line: ${trimmed.slice(0, 100)}`));\n }\n }\n }\n\n /** Flush any remaining buffer content (call after stream ends). */\n flush(): void {\n const trimmed = this.buffer.trim();\n this.buffer = '';\n if (!trimmed) return;\n try {\n const event = JSON.parse(trimmed) as StreamJsonEvent;\n // Count tool_use blocks within assistant events only — the assistant event is\n // the authoritative source. Standalone top-level tool_use events are duplicates.\n if (event.type === 'assistant' && Array.isArray(event.content)) {\n for (const block of event.content as Array<{ type?: string }>) {\n if (block.type === 'tool_use') this.toolCallCount++;\n }\n }\n this.emit('event', event);\n } catch {\n // Ignore incomplete final line\n }\n }\n\n getToolCallCount(): number {\n return this.toolCallCount;\n }\n\n reset(): void {\n this.buffer = '';\n this.toolCallCount = 0;\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 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 { execFile } from 'node:child_process';\nimport { parseTimeout } from './gate-config.js';\nimport type { GateDefinition, GateResult } from '@kantban/types';\n\nexport interface RunOptions {\n timeoutMs?: number;\n totalTimeoutMs?: number;\n cwd?: string;\n env?: Record<string, string>;\n maxBuffer?: number;\n}\n\nexport async function runGate(\n gate: GateDefinition,\n options: RunOptions = {},\n): Promise<GateResult> {\n const timeoutMs = gate.timeout ? parseTimeout(gate.timeout) : (options.timeoutMs ?? 60_000);\n const start = Date.now();\n\n return new Promise<GateResult>((resolve) => {\n // SECURITY: gate.run is an operator-authored shell command from pipeline.gates.yaml.\n // It is executed with full process privileges via `sh -c`. This is intentional —\n // gates are trusted operator code, not user input. If gate config sources are ever\n // extended to accept user-supplied values, sanitization must be added here.\n const child = execFile('sh', ['-c', gate.run], {\n timeout: timeoutMs,\n cwd: options.cwd,\n env: { ...process.env, ...options.env },\n maxBuffer: options.maxBuffer ?? 1024 * 1024, // 1MB output cap\n }, (error, stdout, stderr) => {\n const duration_ms = Date.now() - start;\n const output = (stdout + stderr).trim();\n const timed_out = error?.killed === true;\n const buffer_exceeded = (error as NodeJS.ErrnoException)?.code === 'ERR_CHILD_PROCESS_STDIO_MAXBUFFER';\n\n if (error) {\n let annotation = '';\n if (timed_out) annotation = `\\n[TIMED OUT after ${timeoutMs}ms]`;\n else if (buffer_exceeded) annotation = `\\n[OUTPUT TRUNCATED — buffer limit exceeded]`;\n\n resolve({\n name: gate.name,\n passed: false,\n required: gate.required ?? true,\n duration_ms,\n output: output + annotation,\n stderr: stderr.trim(),\n exit_code: child.exitCode ?? (typeof error.code === 'number' ? error.code : 1),\n timed_out: timed_out || buffer_exceeded,\n });\n return;\n }\n\n resolve({\n name: gate.name,\n passed: true,\n required: gate.required ?? true,\n duration_ms,\n output,\n stderr: stderr.trim(),\n exit_code: 0,\n timed_out: false,\n });\n });\n });\n}\n\n/** Format gate failures into a structured error string for agent/CLI display. */\nexport function formatGateErrors(results: GateResult[]): string {\n const failures = results.filter((r) => !r.passed);\n if (failures.length === 0) return 'All gates passed.';\n\n return failures\n .map((r) => {\n const lines = [`Gate \"${r.name}\" (${r.required ? 'required' : 'advisory'}): FAILED`];\n lines.push(` Exit code: ${r.exit_code}`);\n if (r.timed_out) lines.push(' Timed out: yes');\n if (r.output) {\n const stderr = r.output.split('\\n').slice(-20).join('\\n');\n lines.push(` Output:\\n ${stderr.replace(/\\n/g, '\\n ')}`);\n }\n return lines.join('\\n');\n })\n .join('\\n\\n');\n}\n\nexport async function runGates(\n gates: GateDefinition[],\n options: RunOptions = {},\n): Promise<GateResult[]> {\n const results: GateResult[] = [];\n const totalStart = Date.now();\n\n for (const gate of gates) {\n // Check total timeout\n if (options.totalTimeoutMs) {\n const elapsed = Date.now() - totalStart;\n if (elapsed >= options.totalTimeoutMs) {\n // Remaining gates get timed-out results\n results.push({\n name: gate.name,\n passed: false,\n required: gate.required ?? true,\n duration_ms: 0,\n output: '[SKIPPED — total timeout exceeded]',\n stderr: '',\n exit_code: -1,\n timed_out: true,\n });\n continue;\n }\n // Reduce per-gate timeout by elapsed time\n const remainingMs = options.totalTimeoutMs - elapsed;\n const gateTimeout = gate.timeout ? parseTimeout(gate.timeout) : (options.timeoutMs ?? 60_000);\n const effectiveTimeout = Math.min(gateTimeout, remainingMs);\n results.push(await runGate(gate, { ...options, timeoutMs: effectiveTimeout }));\n } else {\n results.push(await runGate(gate, options));\n }\n }\n\n return results;\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') 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"],"mappings":"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","names":["spawn","mkdirSync","writeFileSync","readFileSync","unlinkSync","appendFileSync","join","col","passed","err","msg","colScope","ticket","colConfig","z","z","z","z","writeFileSync","join","mkdirSync","writeFileSync","unlinkSync","appendFileSync","readFileSync","spawn"]}