kantban-cli 0.1.35 → 0.1.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-4VT3TGJ5.js +68 -0
- package/dist/chunk-4VT3TGJ5.js.map +1 -0
- package/dist/{chunk-ZTQJMXJM.js → chunk-DAFLEMLK.js} +1 -1
- package/dist/chunk-DAFLEMLK.js.map +1 -0
- package/dist/{chunk-2P25AHSD.js → chunk-GCDCGOWL.js} +12 -7
- package/dist/chunk-GCDCGOWL.js.map +1 -0
- package/dist/{chunk-7HJZFR7Y.js → chunk-YFBFQAFI.js} +17 -13
- package/dist/chunk-YFBFQAFI.js.map +1 -0
- package/dist/{cron-RG4VCGME.js → cron-HKGLRBVM.js} +4 -3
- package/dist/{cron-RG4VCGME.js.map → cron-HKGLRBVM.js.map} +1 -1
- package/dist/index.js +4 -4
- package/dist/lib/gate-proxy-server.js +3 -2
- package/dist/lib/gate-proxy-server.js.map +1 -1
- package/dist/{pipeline-ZI7Y25IA.js → pipeline-N7Z43P6P.js} +70 -53
- package/dist/pipeline-N7Z43P6P.js.map +1 -0
- package/dist/{work-2V33NZAT.js → work-RECDDPXT.js} +7 -2
- package/dist/work-RECDDPXT.js.map +1 -0
- package/package.json +4 -3
- package/dist/chunk-2P25AHSD.js.map +0 -1
- package/dist/chunk-7HJZFR7Y.js.map +0 -1
- package/dist/chunk-ZTQJMXJM.js.map +0 -1
- package/dist/pipeline-ZI7Y25IA.js.map +0 -1
- package/dist/work-2V33NZAT.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/lib/gate-proxy-server.ts","../../src/lib/gate-proxy.ts"],"sourcesContent":["#!/usr/bin/env node\n\n/**\n * gate-proxy-server.ts — MCP stdio server for gate enforcement.\n *\n * Spawned by the pipeline orchestrator as a child process. Reads gate config\n * from env vars, instantiates GateProxy, and exposes three MCP tools over\n * JSON-RPC on stdin/stdout:\n *\n * - kantban_run_gates — Run column gates and report results\n * - kantban_move_ticket — Run gates then forward move to KantBan API\n * - kantban_complete_task — Run gates then forward complete to KantBan API\n *\n * Uses raw JSON-RPC (no @modelcontextprotocol/sdk dependency).\n */\n\nimport { readFileSync } from 'node:fs';\nimport { createInterface } from 'node:readline';\nimport { parseGateConfig } from './gate-config.js';\nimport { runGates, formatGateErrors } from './gate-runner.js';\nimport { GateProxy } from './gate-proxy.js';\nimport { fetchWithRetry } from '../client.js';\nimport type { GateProxyDeps } from './gate-proxy.js';\n\n// ── UUID validation ──────────────────────────────────────────────────────\n\nconst UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\nfunction validateUuid(value: unknown, name: string): string {\n if (typeof value !== 'string' || !UUID_RE.test(value)) {\n throw new Error(`Invalid ${name}: expected UUID, got \"${String(value)}\"`);\n }\n return value;\n}\n\n// ── env ──────────────────────────────────────────────────────────────────\n\nconst GATE_CONFIG_PATH = process.env['GATE_CONFIG_PATH'];\nconst COLUMN_ID = process.env['COLUMN_ID'];\nconst COLUMN_NAME = process.env['COLUMN_NAME'];\nconst PROJECT_ID = process.env['PROJECT_ID'];\nconst API_TOKEN = process.env['KANTBAN_API_TOKEN'];\nconst API_URL = process.env['KANTBAN_API_URL'];\n\nfunction requireEnv(name: string, value: string | undefined): string {\n if (!value) {\n process.stderr.write(`gate-proxy-server: missing required env var ${name}\\n`);\n process.exit(1);\n }\n return value;\n}\n\nconst gateConfigPath = requireEnv('GATE_CONFIG_PATH', GATE_CONFIG_PATH);\nconst columnId = requireEnv('COLUMN_ID', COLUMN_ID);\nconst columnName = requireEnv('COLUMN_NAME', COLUMN_NAME);\nconst projectId = requireEnv('PROJECT_ID', PROJECT_ID);\nconst apiToken = requireEnv('KANTBAN_API_TOKEN', API_TOKEN);\nconst apiUrl = requireEnv('KANTBAN_API_URL', API_URL);\n\n// ── gate config ──────────────────────────────────────────────────────────\n\nconst yamlContent = readFileSync(gateConfigPath, 'utf-8');\nconst gateConfig = parseGateConfig(yamlContent);\n\n// GATE_CWD overrides the YAML settings.cwd — set by the orchestrator to the\n// agent's worktree path so gates run against the agent's checked-out code,\n// not the root repo.\nconst GATE_CWD = process.env['GATE_CWD'];\nif (GATE_CWD) {\n if (!gateConfig.settings) gateConfig.settings = {};\n gateConfig.settings.cwd = GATE_CWD;\n}\n\n// ── API helpers ──────────────────────────────────────────────────────────\n\nfunction apiHeaders(): Record<string, string> {\n return {\n 'Authorization': `Bearer ${apiToken}`,\n 'Content-Type': 'application/json',\n 'X-KantBan-Via': 'cli-gate-proxy',\n };\n}\n\nasync function apiPost(path: string, body: Record<string, unknown>): Promise<unknown> {\n const url = new URL(path, apiUrl);\n const res = await fetchWithRetry(url.toString(), {\n method: 'POST',\n headers: apiHeaders(),\n body: JSON.stringify(body),\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`API error ${res.status}: ${text}`);\n }\n const json = (await res.json()) as { success: boolean; data: unknown };\n if (!json.success) throw new Error('API responded with success: false');\n return json.data;\n}\n\nasync function apiPatch(path: string, body: Record<string, unknown>): Promise<unknown> {\n const url = new URL(path, apiUrl);\n const res = await fetchWithRetry(url.toString(), {\n method: 'PATCH',\n headers: apiHeaders(),\n body: JSON.stringify(body),\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`API error ${res.status}: ${text}`);\n }\n const json = (await res.json()) as { success: boolean; data: unknown };\n if (!json.success) throw new Error('API responded with success: false');\n return json.data;\n}\n\nasync function apiGet(path: string, params?: Record<string, string>): Promise<unknown> {\n const url = new URL(path, apiUrl);\n if (params) {\n for (const [k, v] of Object.entries(params)) {\n url.searchParams.set(k, v);\n }\n }\n const res = await fetchWithRetry(url.toString(), {\n headers: apiHeaders(),\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`API error ${res.status}: ${text}`);\n }\n const json = (await res.json()) as { success: boolean; data: unknown };\n if (!json.success) throw new Error('API responded with success: false');\n return json.data;\n}\n\n// ── GateProxy deps ──────────────────────────────────────────────────────\n\nconst deps: GateProxyDeps = {\n runGates,\n\n async forwardMoveTicket(args: Record<string, unknown>): Promise<unknown> {\n const ticketProjectId = validateUuid(args['projectId'], 'projectId');\n const ticketId = validateUuid(args['ticketId'], 'ticketId');\n const body = { ...args };\n delete body['projectId'];\n delete body['ticketId'];\n return apiPatch(`/projects/${ticketProjectId}/tickets/${ticketId}/move`, body);\n },\n\n async forwardCompleteTask(args: Record<string, unknown>): Promise<unknown> {\n const projectId = validateUuid(args['projectId'], 'projectId');\n const ticketId = validateUuid(args['ticketId'], 'ticketId');\n const body = { ...args };\n delete body['projectId'];\n delete body['ticketId'];\n return apiPost(`/projects/${projectId}/tickets/${ticketId}/complete`, body);\n },\n\n async getTicketGateWaivers(ticketId: string): Promise<string[]> {\n try {\n // Field values require both projectId and ticketId in the path.\n // projectId is injected as an env var (PROJECT_ID) at server startup.\n validateUuid(ticketId, 'ticketId');\n const data = (await apiGet(`/projects/${projectId}/tickets/${ticketId}/field-values`)) as\n Array<{ field_name: string; value: unknown }>;\n const waiver = data.find((fv) => fv.field_name === 'gate_waiver');\n if (!waiver) return [];\n if (Array.isArray(waiver.value)) {\n return waiver.value.filter((v): v is string => typeof v === 'string' && v.length > 0);\n }\n return [];\n } catch (err) {\n process.stderr.write(`gate-proxy-server: waiver fetch failed (running all gates): ${err instanceof Error ? err.message : String(err)}\\n`);\n return [];\n }\n },\n};\n\nconst proxy = new GateProxy(gateConfig, deps);\n\n// ── JSON-RPC types ──────────────────────────────────────────────────────\n\ninterface JsonRpcRequest {\n jsonrpc: '2.0';\n id: number | string;\n method: string;\n params?: Record<string, unknown>;\n}\n\ninterface JsonRpcResponse {\n jsonrpc: '2.0';\n id: number | string | null;\n result?: unknown;\n error?: { code: number; message: string; data?: unknown };\n}\n\n// ── Tool definitions ────────────────────────────────────────────────────\n\nconst TOOLS = [\n {\n name: 'kantban_run_gates',\n description:\n 'Run all configured gates for the current column and report results. ' +\n 'Use this to check gate status before attempting to move a ticket. ' +\n 'Pass ticketId to filter out waived gates for that ticket.',\n inputSchema: {\n type: 'object' as const,\n properties: {\n ticketId: { type: 'string', description: 'Ticket ID (UUID) — filters out waived gates for this ticket' },\n },\n required: [] as string[],\n },\n },\n {\n name: 'kantban_move_ticket',\n description:\n 'Move a ticket to a different column. Gates are automatically enforced — ' +\n 'if any required gate fails, the move is blocked and failure details are returned.',\n inputSchema: {\n type: 'object' as const,\n properties: {\n projectId: { type: 'string', description: 'Project ID (UUID)' },\n ticketId: { type: 'string', description: 'Ticket ID (UUID)' },\n columnId: { type: 'string', description: 'Target column ID (UUID)' },\n currentColumnName: { type: 'string', description: 'Current column name' },\n handoff: {\n type: 'object',\n description: 'Structured handoff data for the next pipeline stage',\n additionalProperties: true,\n },\n },\n required: ['projectId', 'ticketId', 'columnId'],\n },\n },\n {\n name: 'kantban_complete_task',\n description:\n 'Mark a ticket as complete. Gates are automatically enforced — ' +\n 'if any required gate fails, the completion is blocked and failure details are returned.',\n inputSchema: {\n type: 'object' as const,\n properties: {\n projectId: { type: 'string', description: 'Project ID (UUID)' },\n ticketId: { type: 'string', description: 'Ticket ID (UUID)' },\n currentColumnName: { type: 'string', description: 'Current column name' },\n moveToColumn: { type: 'string', description: 'Column name to move the ticket to (e.g. \"Done\")' },\n completionComment: { type: 'string', description: 'Comment to add upon completion' },\n handoff: {\n type: 'object',\n description: 'Structured handoff data for the next pipeline stage',\n additionalProperties: true,\n },\n },\n required: ['projectId', 'ticketId'],\n },\n },\n];\n\n// ── Tool handlers ───────────────────────────────────────────────────────\n\nasync function handleToolCall(\n name: string,\n args: Record<string, unknown>,\n): Promise<{ content: Array<{ type: 'text'; text: string }>; isError?: boolean }> {\n try {\n switch (name) {\n case 'kantban_run_gates': {\n const ticketIdArg = args['ticketId'] as string | undefined;\n if (ticketIdArg) validateUuid(ticketIdArg, 'ticketId');\n const result = await proxy.handleRunGates(columnName, ticketIdArg);\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n };\n }\n\n case 'kantban_move_ticket': {\n const moveProjectId = validateUuid(args['projectId'], 'projectId');\n const moveTicketId = validateUuid(args['ticketId'], 'ticketId');\n const moveColumnId = validateUuid(args['columnId'], 'columnId');\n const result = await proxy.handleMoveTicket({\n projectId: moveProjectId,\n ticketId: moveTicketId,\n columnId: moveColumnId,\n currentColumnName: (args['currentColumnName'] as string | undefined) ?? columnName,\n args: {\n ...(args['handoff'] !== undefined ? { handoff: args['handoff'] } : {}),\n ...(args['column_id'] !== undefined ? { column_id: args['column_id'] } : {}),\n },\n });\n const isError = result.error === 'GATE_FAILURE';\n if (isError && result.results) {\n process.stderr.write(`gate-proxy-server: move blocked\\n${formatGateErrors(result.results)}`);\n }\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n ...(isError ? { isError: true } : {}),\n };\n }\n\n case 'kantban_complete_task': {\n const completeProjectId = validateUuid(args['projectId'], 'projectId');\n const completeTicketId = validateUuid(args['ticketId'], 'ticketId');\n const result = await proxy.handleCompleteTask({\n projectId: completeProjectId,\n ticketId: completeTicketId,\n currentColumnName: (args['currentColumnName'] as string | undefined) ?? columnName,\n args: {\n ...(args['moveToColumn'] !== undefined ? { moveToColumn: args['moveToColumn'] } : {}),\n ...(args['completionComment'] !== undefined ? { completionComment: args['completionComment'] } : {}),\n ...(args['handoff'] !== undefined ? { handoff: args['handoff'] } : {}),\n },\n });\n const isError = result.error === 'GATE_FAILURE';\n if (isError && result.results) {\n process.stderr.write(`gate-proxy-server: complete blocked\\n${formatGateErrors(result.results)}`);\n }\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n ...(isError ? { isError: true } : {}),\n };\n }\n\n default:\n return {\n content: [{ type: 'text', text: `Unknown tool: ${name}` }],\n isError: true,\n };\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n content: [{ type: 'text', text: `Error: ${message}` }],\n isError: true,\n };\n }\n}\n\n// ── JSON-RPC dispatch ───────────────────────────────────────────────────\n\nfunction sendResponse(response: JsonRpcResponse): void {\n const json = JSON.stringify(response);\n process.stdout.write(json + '\\n');\n}\n\nasync function handleMessage(msg: JsonRpcRequest): Promise<void> {\n const { id, method, params } = msg;\n\n switch (method) {\n case 'initialize': {\n sendResponse({\n jsonrpc: '2.0',\n id,\n result: {\n protocolVersion: '2024-11-05',\n capabilities: { tools: {} },\n serverInfo: {\n name: 'kantban-gates',\n version: '0.1.0',\n },\n },\n });\n return;\n }\n\n case 'notifications/initialized': {\n // Client acknowledgement — no response needed for notifications\n return;\n }\n\n case 'tools/list': {\n sendResponse({\n jsonrpc: '2.0',\n id,\n result: { tools: TOOLS },\n });\n return;\n }\n\n case 'tools/call': {\n const toolName = params?.['name'] as string | undefined;\n const toolArgs = (params?.['arguments'] as Record<string, unknown> | undefined) ?? {};\n\n if (!toolName) {\n sendResponse({\n jsonrpc: '2.0',\n id,\n error: { code: -32602, message: 'Missing tool name' },\n });\n return;\n }\n\n const result = await handleToolCall(toolName, toolArgs);\n sendResponse({\n jsonrpc: '2.0',\n id,\n result,\n });\n return;\n }\n\n case 'ping': {\n sendResponse({ jsonrpc: '2.0', id, result: {} });\n return;\n }\n\n default: {\n // Unknown method — return method not found per JSON-RPC spec\n if (method.startsWith('notifications/')) {\n // Notifications don't get responses\n return;\n }\n sendResponse({\n jsonrpc: '2.0',\n id,\n error: { code: -32601, message: `Method not found: ${method}` },\n });\n }\n }\n}\n\n// ── stdin reader ────────────────────────────────────────────────────────\n\nconst rl = createInterface({ input: process.stdin });\n\n// Serialize message processing to prevent concurrent double-moves\nlet messageQueue: Promise<void> = Promise.resolve();\n\nrl.on('line', (line: string) => {\n const trimmed = line.trim();\n if (!trimmed) return;\n\n let msg: JsonRpcRequest;\n try {\n msg = JSON.parse(trimmed) as JsonRpcRequest;\n } catch {\n sendResponse({\n jsonrpc: '2.0',\n id: null as unknown as number,\n error: { code: -32700, message: 'Parse error' },\n });\n return;\n }\n\n messageQueue = messageQueue.then(() => handleMessage(msg)).catch((err) => {\n process.stderr.write(`gate-proxy-server: unhandled error in message handler: ${err instanceof Error ? err.message : String(err)}\\n`);\n });\n});\n\nrl.on('close', () => {\n process.exit(0);\n});\n\n// Suppress unhandled rejection crashes — log to stderr and continue\nprocess.on('unhandledRejection', (err) => {\n process.stderr.write(\n `gate-proxy-server: unhandled rejection: ${err instanceof Error ? err.message : String(err)}\\n`,\n );\n});\n\nprocess.stderr.write(`gate-proxy-server: started (column=\"${columnName}\", gates=${gateConfig.default.length})\\n`);\n","import { resolveGatesForColumn, parseTimeout } from './gate-config.js';\nimport { formatGateErrors } from './gate-runner.js';\nimport type { GateConfig, GateDefinition, GateResult } from '@kantban/types';\n\nexport interface GateProxyDeps {\n runGates: (gates: GateDefinition[], options?: { cwd?: string; env?: Record<string, string>; totalTimeoutMs?: number }) => Promise<GateResult[]>;\n forwardMoveTicket: (args: Record<string, unknown>) => Promise<unknown>;\n forwardCompleteTask: (args: Record<string, unknown>) => Promise<unknown>;\n getTicketGateWaivers: (ticketId: string) => Promise<string[]>;\n}\n\nexport interface RunGatesResult {\n passed: boolean;\n results: GateResult[];\n}\n\nexport interface MoveArgs {\n projectId: string;\n ticketId: string;\n columnId: string;\n currentColumnName: string;\n args: Record<string, unknown>;\n}\n\nexport interface CompleteArgs {\n projectId: string;\n ticketId: string;\n currentColumnName: string;\n args: Record<string, unknown>;\n}\n\nexport interface InterceptResult {\n error?: 'GATE_FAILURE';\n message?: string;\n formatted?: string;\n results?: GateResult[];\n hint?: string;\n forwardResult?: unknown;\n}\n\nexport class GateProxy {\n private config: GateConfig;\n private deps: GateProxyDeps;\n\n constructor(config: GateConfig, deps: GateProxyDeps) {\n this.config = config;\n this.deps = deps;\n }\n\n private buildRunOptions(): { cwd?: string; env?: Record<string, string>; totalTimeoutMs?: number } {\n const opts: { cwd?: string; env?: Record<string, string>; totalTimeoutMs?: number } = {};\n if (this.config.settings?.cwd !== undefined) opts.cwd = this.config.settings.cwd;\n if (this.config.settings?.env !== undefined) opts.env = this.config.settings.env;\n if (this.config.settings?.total_timeout !== undefined) {\n opts.totalTimeoutMs = parseTimeout(this.config.settings.total_timeout);\n }\n return opts;\n }\n\n async handleRunGates(columnName: string, ticketId?: string): Promise<RunGatesResult> {\n const allGates = resolveGatesForColumn(this.config, columnName);\n\n let gates = allGates;\n if (ticketId) {\n const waivers = await this.deps.getTicketGateWaivers(ticketId);\n const waiverSet = new Set(waivers);\n gates = allGates.filter((g) => !waiverSet.has(g.name));\n }\n\n const results = await this.deps.runGates(gates, this.buildRunOptions());\n return {\n passed: results.filter((r) => r.required).every((r) => r.passed),\n results,\n };\n }\n\n async handleMoveTicket(move: MoveArgs): Promise<InterceptResult> {\n const allGates = resolveGatesForColumn(this.config, move.currentColumnName);\n\n // Filter out waived gates\n const waivers = await this.deps.getTicketGateWaivers(move.ticketId);\n const waiverSet = new Set(waivers);\n const gates = allGates.filter((g) => !waiverSet.has(g.name));\n\n let results: GateResult[];\n try {\n results = await this.deps.runGates(gates, this.buildRunOptions());\n } catch (err) {\n return {\n error: 'GATE_FAILURE',\n message: `Gate evaluation error: ${err instanceof Error ? err.message : String(err)}`,\n hint: 'Fix the gate environment and retry',\n };\n }\n\n const requiredFailures = results.filter((r) => r.required && !r.passed);\n if (requiredFailures.length > 0) {\n return {\n error: 'GATE_FAILURE',\n message: `Cannot move ticket — ${requiredFailures.length} required gate(s) failed`,\n formatted: formatGateErrors(results.filter((r) => r.required)),\n results,\n hint: 'Fix the failing gate(s) and try move_ticket again',\n };\n }\n\n const forwardResult = await this.deps.forwardMoveTicket({\n ...move.args,\n projectId: move.projectId,\n ticketId: move.ticketId,\n column_id: move.columnId,\n });\n\n return { forwardResult };\n }\n\n async handleCompleteTask(complete: CompleteArgs): Promise<InterceptResult> {\n const allGates = resolveGatesForColumn(this.config, complete.currentColumnName);\n const waivers = await this.deps.getTicketGateWaivers(complete.ticketId);\n const waiverSet = new Set(waivers);\n const gates = allGates.filter((g) => !waiverSet.has(g.name));\n\n let results: GateResult[];\n try {\n results = await this.deps.runGates(gates, this.buildRunOptions());\n } catch (err) {\n return {\n error: 'GATE_FAILURE',\n message: `Gate evaluation error: ${err instanceof Error ? err.message : String(err)}`,\n hint: 'Fix the gate environment and retry',\n };\n }\n\n const requiredFailures = results.filter((r) => r.required && !r.passed);\n if (requiredFailures.length > 0) {\n return {\n error: 'GATE_FAILURE',\n message: `Cannot complete task — ${requiredFailures.length} required gate(s) failed`,\n formatted: formatGateErrors(results.filter((r) => r.required)),\n results,\n hint: 'Fix the failing gate(s) and try complete_task again',\n };\n }\n\n const forwardResult = await this.deps.forwardCompleteTask({\n ...complete.args,\n projectId: complete.projectId,\n ticketId: complete.ticketId,\n });\n\n return { forwardResult };\n }\n}\n"],"mappings":"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","names":["deps","columnName","projectId"]}
|
|
1
|
+
{"version":3,"sources":["../../src/lib/gate-proxy-server.ts","../../src/lib/gate-proxy.ts"],"sourcesContent":["#!/usr/bin/env node\n\n/**\n * gate-proxy-server.ts — MCP stdio server for gate enforcement.\n *\n * Spawned by the pipeline orchestrator as a child process. Reads gate config\n * from env vars, instantiates GateProxy, and exposes three MCP tools over\n * JSON-RPC on stdin/stdout:\n *\n * - kantban_run_gates — Run column gates and report results\n * - kantban_move_ticket — Run gates then forward move to KantBan API\n * - kantban_complete_task — Run gates then forward complete to KantBan API\n *\n * Uses raw JSON-RPC (no @modelcontextprotocol/sdk dependency).\n */\n\nimport { readFileSync } from 'node:fs';\nimport { createInterface } from 'node:readline';\nimport { parseGateConfig } from './gate-config.js';\nimport { runGates, formatGateErrors } from './gate-runner.js';\nimport { GateProxy } from './gate-proxy.js';\nimport { fetchWithRetry } from '../client.js';\nimport type { GateProxyDeps } from './gate-proxy.js';\n\n// ── UUID validation ──────────────────────────────────────────────────────\n\nconst UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\nfunction validateUuid(value: unknown, name: string): string {\n if (typeof value !== 'string' || !UUID_RE.test(value)) {\n throw new Error(`Invalid ${name}: expected UUID, got \"${String(value)}\"`);\n }\n return value;\n}\n\n// ── env ──────────────────────────────────────────────────────────────────\n\nconst GATE_CONFIG_PATH = process.env['GATE_CONFIG_PATH'];\nconst COLUMN_ID = process.env['COLUMN_ID'];\nconst COLUMN_NAME = process.env['COLUMN_NAME'];\nconst PROJECT_ID = process.env['PROJECT_ID'];\nconst API_TOKEN = process.env['KANTBAN_API_TOKEN'];\nconst API_URL = process.env['KANTBAN_API_URL'];\n\nfunction requireEnv(name: string, value: string | undefined): string {\n if (!value) {\n process.stderr.write(`gate-proxy-server: missing required env var ${name}\\n`);\n process.exit(1);\n }\n return value;\n}\n\nconst gateConfigPath = requireEnv('GATE_CONFIG_PATH', GATE_CONFIG_PATH);\nconst columnId = requireEnv('COLUMN_ID', COLUMN_ID);\nconst columnName = requireEnv('COLUMN_NAME', COLUMN_NAME);\nconst projectId = requireEnv('PROJECT_ID', PROJECT_ID);\nconst apiToken = requireEnv('KANTBAN_API_TOKEN', API_TOKEN);\nconst apiUrl = requireEnv('KANTBAN_API_URL', API_URL);\n\n// ── gate config ──────────────────────────────────────────────────────────\n\nconst yamlContent = readFileSync(gateConfigPath, 'utf-8');\nconst gateConfig = parseGateConfig(yamlContent);\n\n// GATE_CWD overrides the YAML settings.cwd — set by the orchestrator to the\n// agent's worktree path so gates run against the agent's checked-out code,\n// not the root repo.\nconst GATE_CWD = process.env['GATE_CWD'];\nif (GATE_CWD) {\n if (!gateConfig.settings) gateConfig.settings = {};\n gateConfig.settings.cwd = GATE_CWD;\n}\n\n// ── API helpers ──────────────────────────────────────────────────────────\n\nfunction apiHeaders(): Record<string, string> {\n return {\n 'Authorization': `Bearer ${apiToken}`,\n 'Content-Type': 'application/json',\n 'X-KantBan-Via': 'cli-gate-proxy',\n };\n}\n\nasync function apiPost(path: string, body: Record<string, unknown>): Promise<unknown> {\n const url = new URL(path, apiUrl);\n const res = await fetchWithRetry(url.toString(), {\n method: 'POST',\n headers: apiHeaders(),\n body: JSON.stringify(body),\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`API error ${res.status}: ${text}`);\n }\n const json = (await res.json()) as { success: boolean; data: unknown };\n if (!json.success) throw new Error('API responded with success: false');\n return json.data;\n}\n\nasync function apiPatch(path: string, body: Record<string, unknown>): Promise<unknown> {\n const url = new URL(path, apiUrl);\n const res = await fetchWithRetry(url.toString(), {\n method: 'PATCH',\n headers: apiHeaders(),\n body: JSON.stringify(body),\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`API error ${res.status}: ${text}`);\n }\n const json = (await res.json()) as { success: boolean; data: unknown };\n if (!json.success) throw new Error('API responded with success: false');\n return json.data;\n}\n\nasync function apiGet(path: string, params?: Record<string, string>): Promise<unknown> {\n const url = new URL(path, apiUrl);\n if (params) {\n for (const [k, v] of Object.entries(params)) {\n url.searchParams.set(k, v);\n }\n }\n const res = await fetchWithRetry(url.toString(), {\n headers: apiHeaders(),\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`API error ${res.status}: ${text}`);\n }\n const json = (await res.json()) as { success: boolean; data: unknown };\n if (!json.success) throw new Error('API responded with success: false');\n return json.data;\n}\n\n// ── GateProxy deps ──────────────────────────────────────────────────────\n\nconst deps: GateProxyDeps = {\n runGates,\n\n async forwardMoveTicket(args: Record<string, unknown>): Promise<unknown> {\n const ticketProjectId = validateUuid(args['projectId'], 'projectId');\n const ticketId = validateUuid(args['ticketId'], 'ticketId');\n const body = { ...args };\n delete body['projectId'];\n delete body['ticketId'];\n return apiPatch(`/projects/${ticketProjectId}/tickets/${ticketId}/move`, body);\n },\n\n async forwardCompleteTask(args: Record<string, unknown>): Promise<unknown> {\n const projectId = validateUuid(args['projectId'], 'projectId');\n const ticketId = validateUuid(args['ticketId'], 'ticketId');\n const body = { ...args };\n delete body['projectId'];\n delete body['ticketId'];\n return apiPost(`/projects/${projectId}/tickets/${ticketId}/complete`, body);\n },\n\n async getTicketGateWaivers(ticketId: string): Promise<string[]> {\n try {\n // Field values require both projectId and ticketId in the path.\n // projectId is injected as an env var (PROJECT_ID) at server startup.\n validateUuid(ticketId, 'ticketId');\n const data = (await apiGet(`/projects/${projectId}/tickets/${ticketId}/field-values`)) as\n Array<{ field_name: string; value: unknown }>;\n const waiver = data.find((fv) => fv.field_name === 'gate_waiver');\n if (!waiver) return [];\n if (Array.isArray(waiver.value)) {\n return waiver.value.filter((v): v is string => typeof v === 'string' && v.length > 0);\n }\n return [];\n } catch (err) {\n process.stderr.write(`gate-proxy-server: waiver fetch failed (running all gates): ${err instanceof Error ? err.message : String(err)}\\n`);\n return [];\n }\n },\n};\n\nconst proxy = new GateProxy(gateConfig, deps);\n\n// ── JSON-RPC types ──────────────────────────────────────────────────────\n\ninterface JsonRpcRequest {\n jsonrpc: '2.0';\n id: number | string;\n method: string;\n params?: Record<string, unknown>;\n}\n\ninterface JsonRpcResponse {\n jsonrpc: '2.0';\n id: number | string | null;\n result?: unknown;\n error?: { code: number; message: string; data?: unknown };\n}\n\n// ── Tool definitions ────────────────────────────────────────────────────\n\nconst TOOLS = [\n {\n name: 'kantban_run_gates',\n description:\n 'Run all configured gates for the current column and report results. ' +\n 'Use this to check gate status before attempting to move a ticket. ' +\n 'Pass ticketId to filter out waived gates for that ticket.',\n inputSchema: {\n type: 'object' as const,\n properties: {\n ticketId: { type: 'string', description: 'Ticket ID (UUID) — filters out waived gates for this ticket' },\n },\n required: [] as string[],\n },\n },\n {\n name: 'kantban_move_ticket',\n description:\n 'Move a ticket to a different column. Gates are automatically enforced — ' +\n 'if any required gate fails, the move is blocked and failure details are returned.',\n inputSchema: {\n type: 'object' as const,\n properties: {\n projectId: { type: 'string', description: 'Project ID (UUID)' },\n ticketId: { type: 'string', description: 'Ticket ID (UUID)' },\n columnId: { type: 'string', description: 'Target column ID (UUID)' },\n currentColumnName: { type: 'string', description: 'Current column name' },\n handoff: {\n type: 'object',\n description: 'Structured handoff data for the next pipeline stage',\n additionalProperties: true,\n },\n },\n required: ['projectId', 'ticketId', 'columnId'],\n },\n },\n {\n name: 'kantban_complete_task',\n description:\n 'Mark a ticket as complete. Gates are automatically enforced — ' +\n 'if any required gate fails, the completion is blocked and failure details are returned.',\n inputSchema: {\n type: 'object' as const,\n properties: {\n projectId: { type: 'string', description: 'Project ID (UUID)' },\n ticketId: { type: 'string', description: 'Ticket ID (UUID)' },\n currentColumnName: { type: 'string', description: 'Current column name' },\n moveToColumn: { type: 'string', description: 'Column name to move the ticket to (e.g. \"Done\")' },\n completionComment: { type: 'string', description: 'Comment to add upon completion' },\n handoff: {\n type: 'object',\n description: 'Structured handoff data for the next pipeline stage',\n additionalProperties: true,\n },\n },\n required: ['projectId', 'ticketId'],\n },\n },\n];\n\n// ── Tool handlers ───────────────────────────────────────────────────────\n\nasync function handleToolCall(\n name: string,\n args: Record<string, unknown>,\n): Promise<{ content: Array<{ type: 'text'; text: string }>; isError?: boolean }> {\n try {\n switch (name) {\n case 'kantban_run_gates': {\n const ticketIdArg = args['ticketId'] as string | undefined;\n if (ticketIdArg) validateUuid(ticketIdArg, 'ticketId');\n const result = await proxy.handleRunGates(columnName, ticketIdArg);\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n };\n }\n\n case 'kantban_move_ticket': {\n const moveProjectId = validateUuid(args['projectId'], 'projectId');\n const moveTicketId = validateUuid(args['ticketId'], 'ticketId');\n const moveColumnId = validateUuid(args['columnId'], 'columnId');\n const result = await proxy.handleMoveTicket({\n projectId: moveProjectId,\n ticketId: moveTicketId,\n columnId: moveColumnId,\n currentColumnName: (args['currentColumnName'] as string | undefined) ?? columnName,\n args: {\n ...(args['handoff'] !== undefined ? { handoff: args['handoff'] } : {}),\n ...(args['column_id'] !== undefined ? { column_id: args['column_id'] } : {}),\n },\n });\n const isError = result.error === 'GATE_FAILURE';\n if (isError && result.results) {\n process.stderr.write(`gate-proxy-server: move blocked\\n${formatGateErrors(result.results)}`);\n }\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n ...(isError ? { isError: true } : {}),\n };\n }\n\n case 'kantban_complete_task': {\n const completeProjectId = validateUuid(args['projectId'], 'projectId');\n const completeTicketId = validateUuid(args['ticketId'], 'ticketId');\n const result = await proxy.handleCompleteTask({\n projectId: completeProjectId,\n ticketId: completeTicketId,\n currentColumnName: (args['currentColumnName'] as string | undefined) ?? columnName,\n args: {\n ...(args['moveToColumn'] !== undefined ? { moveToColumn: args['moveToColumn'] } : {}),\n ...(args['completionComment'] !== undefined ? { completionComment: args['completionComment'] } : {}),\n ...(args['handoff'] !== undefined ? { handoff: args['handoff'] } : {}),\n },\n });\n const isError = result.error === 'GATE_FAILURE';\n if (isError && result.results) {\n process.stderr.write(`gate-proxy-server: complete blocked\\n${formatGateErrors(result.results)}`);\n }\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n ...(isError ? { isError: true } : {}),\n };\n }\n\n default:\n return {\n content: [{ type: 'text', text: `Unknown tool: ${name}` }],\n isError: true,\n };\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n content: [{ type: 'text', text: `Error: ${message}` }],\n isError: true,\n };\n }\n}\n\n// ── JSON-RPC dispatch ───────────────────────────────────────────────────\n\nfunction sendResponse(response: JsonRpcResponse): void {\n const json = JSON.stringify(response);\n process.stdout.write(json + '\\n');\n}\n\nasync function handleMessage(msg: JsonRpcRequest): Promise<void> {\n const { id, method, params } = msg;\n\n switch (method) {\n case 'initialize': {\n sendResponse({\n jsonrpc: '2.0',\n id,\n result: {\n protocolVersion: '2024-11-05',\n capabilities: { tools: {} },\n serverInfo: {\n name: 'kantban-gates',\n version: '0.1.0',\n },\n },\n });\n return;\n }\n\n case 'notifications/initialized': {\n // Client acknowledgement — no response needed for notifications\n return;\n }\n\n case 'tools/list': {\n sendResponse({\n jsonrpc: '2.0',\n id,\n result: { tools: TOOLS },\n });\n return;\n }\n\n case 'tools/call': {\n const toolName = params?.['name'] as string | undefined;\n const toolArgs = (params?.['arguments'] as Record<string, unknown> | undefined) ?? {};\n\n if (!toolName) {\n sendResponse({\n jsonrpc: '2.0',\n id,\n error: { code: -32602, message: 'Missing tool name' },\n });\n return;\n }\n\n const result = await handleToolCall(toolName, toolArgs);\n sendResponse({\n jsonrpc: '2.0',\n id,\n result,\n });\n return;\n }\n\n case 'ping': {\n sendResponse({ jsonrpc: '2.0', id, result: {} });\n return;\n }\n\n default: {\n // Unknown method — return method not found per JSON-RPC spec\n if (method.startsWith('notifications/')) {\n // Notifications don't get responses\n return;\n }\n sendResponse({\n jsonrpc: '2.0',\n id,\n error: { code: -32601, message: `Method not found: ${method}` },\n });\n }\n }\n}\n\n// ── stdin reader ────────────────────────────────────────────────────────\n\nconst rl = createInterface({ input: process.stdin });\n\n// Serialize message processing to prevent concurrent double-moves\nlet messageQueue: Promise<void> = Promise.resolve();\n\nrl.on('line', (line: string) => {\n const trimmed = line.trim();\n if (!trimmed) return;\n\n let msg: JsonRpcRequest;\n try {\n msg = JSON.parse(trimmed) as JsonRpcRequest;\n } catch {\n sendResponse({\n jsonrpc: '2.0',\n id: null as unknown as number,\n error: { code: -32700, message: 'Parse error' },\n });\n return;\n }\n\n messageQueue = messageQueue.then(() => handleMessage(msg)).catch((err) => {\n process.stderr.write(`gate-proxy-server: unhandled error in message handler: ${err instanceof Error ? err.message : String(err)}\\n`);\n });\n});\n\nrl.on('close', () => {\n process.exit(0);\n});\n\n// Suppress unhandled rejection crashes — log to stderr and continue\nprocess.on('unhandledRejection', (err) => {\n process.stderr.write(\n `gate-proxy-server: unhandled rejection: ${err instanceof Error ? err.message : String(err)}\\n`,\n );\n});\n\nprocess.stderr.write(`gate-proxy-server: started (column=\"${columnName}\", gates=${gateConfig.default.length})\\n`);\n","import { resolveGatesForColumn, parseTimeout } from './gate-config.js';\nimport { formatGateErrors } from './gate-runner.js';\nimport type { GateConfig, GateDefinition, GateResult } from '@kantban/types';\n\nexport interface GateProxyDeps {\n runGates: (gates: GateDefinition[], options?: { cwd?: string; env?: Record<string, string>; totalTimeoutMs?: number }) => Promise<GateResult[]>;\n forwardMoveTicket: (args: Record<string, unknown>) => Promise<unknown>;\n forwardCompleteTask: (args: Record<string, unknown>) => Promise<unknown>;\n getTicketGateWaivers: (ticketId: string) => Promise<string[]>;\n}\n\nexport interface RunGatesResult {\n passed: boolean;\n results: GateResult[];\n}\n\nexport interface MoveArgs {\n projectId: string;\n ticketId: string;\n columnId: string;\n currentColumnName: string;\n args: Record<string, unknown>;\n}\n\nexport interface CompleteArgs {\n projectId: string;\n ticketId: string;\n currentColumnName: string;\n args: Record<string, unknown>;\n}\n\nexport interface InterceptResult {\n error?: 'GATE_FAILURE';\n message?: string;\n formatted?: string;\n results?: GateResult[];\n hint?: string;\n forwardResult?: unknown;\n}\n\nexport class GateProxy {\n private config: GateConfig;\n private deps: GateProxyDeps;\n\n constructor(config: GateConfig, deps: GateProxyDeps) {\n this.config = config;\n this.deps = deps;\n }\n\n private buildRunOptions(): { cwd?: string; env?: Record<string, string>; totalTimeoutMs?: number } {\n const opts: { cwd?: string; env?: Record<string, string>; totalTimeoutMs?: number } = {};\n if (this.config.settings?.cwd !== undefined) opts.cwd = this.config.settings.cwd;\n if (this.config.settings?.env !== undefined) opts.env = this.config.settings.env;\n if (this.config.settings?.total_timeout !== undefined) {\n opts.totalTimeoutMs = parseTimeout(this.config.settings.total_timeout);\n }\n return opts;\n }\n\n async handleRunGates(columnName: string, ticketId?: string): Promise<RunGatesResult> {\n const allGates = resolveGatesForColumn(this.config, columnName);\n\n let gates = allGates;\n if (ticketId) {\n const waivers = await this.deps.getTicketGateWaivers(ticketId);\n const waiverSet = new Set(waivers);\n gates = allGates.filter((g) => !waiverSet.has(g.name));\n }\n\n const results = await this.deps.runGates(gates, this.buildRunOptions());\n return {\n passed: results.filter((r) => r.required).every((r) => r.passed),\n results,\n };\n }\n\n async handleMoveTicket(move: MoveArgs): Promise<InterceptResult> {\n const allGates = resolveGatesForColumn(this.config, move.currentColumnName);\n\n // Filter out waived gates\n const waivers = await this.deps.getTicketGateWaivers(move.ticketId);\n const waiverSet = new Set(waivers);\n const gates = allGates.filter((g) => !waiverSet.has(g.name));\n\n let results: GateResult[];\n try {\n results = await this.deps.runGates(gates, this.buildRunOptions());\n } catch (err) {\n return {\n error: 'GATE_FAILURE',\n message: `Gate evaluation error: ${err instanceof Error ? err.message : String(err)}`,\n hint: 'Fix the gate environment and retry',\n };\n }\n\n const requiredFailures = results.filter((r) => r.required && !r.passed);\n if (requiredFailures.length > 0) {\n return {\n error: 'GATE_FAILURE',\n message: `Cannot move ticket — ${requiredFailures.length} required gate(s) failed`,\n formatted: formatGateErrors(results.filter((r) => r.required)),\n results,\n hint: 'Fix the failing gate(s) and try move_ticket again',\n };\n }\n\n const forwardResult = await this.deps.forwardMoveTicket({\n ...move.args,\n projectId: move.projectId,\n ticketId: move.ticketId,\n column_id: move.columnId,\n });\n\n return { forwardResult };\n }\n\n async handleCompleteTask(complete: CompleteArgs): Promise<InterceptResult> {\n const allGates = resolveGatesForColumn(this.config, complete.currentColumnName);\n const waivers = await this.deps.getTicketGateWaivers(complete.ticketId);\n const waiverSet = new Set(waivers);\n const gates = allGates.filter((g) => !waiverSet.has(g.name));\n\n let results: GateResult[];\n try {\n results = await this.deps.runGates(gates, this.buildRunOptions());\n } catch (err) {\n return {\n error: 'GATE_FAILURE',\n message: `Gate evaluation error: ${err instanceof Error ? err.message : String(err)}`,\n hint: 'Fix the gate environment and retry',\n };\n }\n\n const requiredFailures = results.filter((r) => r.required && !r.passed);\n if (requiredFailures.length > 0) {\n return {\n error: 'GATE_FAILURE',\n message: `Cannot complete task — ${requiredFailures.length} required gate(s) failed`,\n formatted: formatGateErrors(results.filter((r) => r.required)),\n results,\n hint: 'Fix the failing gate(s) and try complete_task again',\n };\n }\n\n const forwardResult = await this.deps.forwardCompleteTask({\n ...complete.args,\n projectId: complete.projectId,\n ticketId: complete.ticketId,\n });\n\n return { forwardResult };\n }\n}\n"],"mappings":"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","names":["deps","columnName","projectId"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
runGates
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-GCDCGOWL.js";
|
|
4
4
|
import {
|
|
5
5
|
ClaudeProvider,
|
|
6
6
|
RalphLoop,
|
|
@@ -12,14 +12,20 @@ import {
|
|
|
12
12
|
generateMcpConfig,
|
|
13
13
|
parseJsonFromLlmOutput,
|
|
14
14
|
parseStuckDetectionResponse
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-YFBFQAFI.js";
|
|
16
16
|
import {
|
|
17
17
|
LoopCheckpointSchema,
|
|
18
18
|
VerdictSchema,
|
|
19
19
|
parseGateConfig,
|
|
20
20
|
parseTimeout,
|
|
21
21
|
resolveGatesForColumn
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-DAFLEMLK.js";
|
|
23
|
+
import {
|
|
24
|
+
IS_WINDOWS,
|
|
25
|
+
crossSpawnOptions,
|
|
26
|
+
killProcessTree,
|
|
27
|
+
normalizeEol
|
|
28
|
+
} from "./chunk-4VT3TGJ5.js";
|
|
23
29
|
|
|
24
30
|
// src/commands/pipeline.ts
|
|
25
31
|
import { mkdirSync as mkdirSync3, writeFileSync as writeFileSync4, readFileSync as readFileSync3, unlinkSync as unlinkSync3, existsSync as existsSync3, appendFileSync as appendFileSync2 } from "fs";
|
|
@@ -51,25 +57,25 @@ function isPlausibleRemoteUrl(url) {
|
|
|
51
57
|
}
|
|
52
58
|
function ensureWorktreeRemote(worktreePath) {
|
|
53
59
|
try {
|
|
54
|
-
const remotes = execFileSync("git", ["-C", worktreePath, "remote"], {
|
|
60
|
+
const remotes = normalizeEol(execFileSync("git", ["-C", worktreePath, "remote"], {
|
|
55
61
|
stdio: "pipe",
|
|
56
62
|
encoding: "utf-8"
|
|
57
|
-
}).trim();
|
|
63
|
+
})).trim();
|
|
58
64
|
if (remotes.split("\n").includes("origin")) {
|
|
59
|
-
const currentUrl = execFileSync("git", ["-C", worktreePath, "remote", "get-url", "origin"], {
|
|
65
|
+
const currentUrl = normalizeEol(execFileSync("git", ["-C", worktreePath, "remote", "get-url", "origin"], {
|
|
60
66
|
stdio: "pipe",
|
|
61
67
|
encoding: "utf-8"
|
|
62
|
-
}).trim();
|
|
68
|
+
})).trim();
|
|
63
69
|
if (isPlausibleRemoteUrl(currentUrl)) return;
|
|
64
70
|
console.error(`[worktree] Invalid origin URL in ${worktreePath}: "${currentUrl}" \u2014 fixing`);
|
|
65
71
|
execFileSync("git", ["-C", worktreePath, "remote", "remove", "origin"], {
|
|
66
72
|
stdio: "pipe"
|
|
67
73
|
});
|
|
68
74
|
}
|
|
69
|
-
const originUrl = execFileSync("git", ["remote", "get-url", "origin"], {
|
|
75
|
+
const originUrl = normalizeEol(execFileSync("git", ["remote", "get-url", "origin"], {
|
|
70
76
|
stdio: "pipe",
|
|
71
77
|
encoding: "utf-8"
|
|
72
|
-
}).trim();
|
|
78
|
+
})).trim();
|
|
73
79
|
if (originUrl && isPlausibleRemoteUrl(originUrl)) {
|
|
74
80
|
execFileSync("git", ["-C", worktreePath, "remote", "add", "origin", originUrl], {
|
|
75
81
|
stdio: "pipe"
|
|
@@ -114,7 +120,7 @@ async function findWorktreeForBranch(exec, branch) {
|
|
|
114
120
|
const { stdout } = await execPromise(exec, "git", ["worktree", "list", "--porcelain"]);
|
|
115
121
|
const targetRef = `refs/heads/${branch}`;
|
|
116
122
|
let currentPath = null;
|
|
117
|
-
for (const line of stdout.split("\n")) {
|
|
123
|
+
for (const line of normalizeEol(stdout).split("\n")) {
|
|
118
124
|
if (line.startsWith("worktree ")) currentPath = line.slice("worktree ".length);
|
|
119
125
|
if (line.startsWith("branch ") && line.slice("branch ".length) === targetRef && currentPath) {
|
|
120
126
|
return currentPath;
|
|
@@ -2116,7 +2122,7 @@ var RunMemory = class {
|
|
|
2116
2122
|
}
|
|
2117
2123
|
try {
|
|
2118
2124
|
const content = await this.deps.getDocument(this._documentId);
|
|
2119
|
-
const lines = content.split("\n");
|
|
2125
|
+
const lines = normalizeEol(content).split("\n");
|
|
2120
2126
|
if (lines.length > DEFAULT_COMPACTION_THRESHOLD) {
|
|
2121
2127
|
const truncated = lines.slice(-DEFAULT_COMPACTION_THRESHOLD);
|
|
2122
2128
|
return "[Run memory truncated \u2014 compaction needed]\n" + truncated.join("\n");
|
|
@@ -2137,7 +2143,7 @@ var RunMemory = class {
|
|
|
2137
2143
|
try {
|
|
2138
2144
|
const content = await this.deps.getDocument(this._documentId);
|
|
2139
2145
|
if (!content) return false;
|
|
2140
|
-
return content.split("\n").length > threshold;
|
|
2146
|
+
return normalizeEol(content).split("\n").length > threshold;
|
|
2141
2147
|
} catch {
|
|
2142
2148
|
return false;
|
|
2143
2149
|
}
|
|
@@ -2768,13 +2774,16 @@ function isAlive(pid) {
|
|
|
2768
2774
|
function readManifest() {
|
|
2769
2775
|
try {
|
|
2770
2776
|
return fs.readFileSync(MANIFEST_PATH, 'utf-8')
|
|
2771
|
-
.split(
|
|
2777
|
+
.split(/\\r?\\n/)
|
|
2772
2778
|
.map(l => parseInt(l.trim(), 10))
|
|
2773
2779
|
.filter(p => !isNaN(p) && p > 0);
|
|
2774
2780
|
} catch { return []; }
|
|
2775
2781
|
}
|
|
2776
2782
|
|
|
2777
2783
|
function killPid(pid, signal) {
|
|
2784
|
+
if (process.platform === 'win32') {
|
|
2785
|
+
try { require('child_process').execFileSync('taskkill', ['/pid', String(pid), '/t', '/f'], { stdio: 'pipe' }); return; } catch { /* fall through */ }
|
|
2786
|
+
}
|
|
2778
2787
|
try { process.kill(pid, signal); } catch { /* already dead */ }
|
|
2779
2788
|
}
|
|
2780
2789
|
|
|
@@ -2782,14 +2791,14 @@ function cleanup() {
|
|
|
2782
2791
|
const pids = readManifest();
|
|
2783
2792
|
for (const pid of pids) {
|
|
2784
2793
|
killPid(pid, 'SIGTERM');
|
|
2785
|
-
try { process.kill(-pid, 'SIGTERM'); } catch { /* ignore */ }
|
|
2794
|
+
if (process.platform !== 'win32') { try { process.kill(-pid, 'SIGTERM'); } catch { /* ignore */ } }
|
|
2786
2795
|
}
|
|
2787
2796
|
|
|
2788
2797
|
setTimeout(() => {
|
|
2789
2798
|
for (const pid of pids) {
|
|
2790
2799
|
if (isAlive(pid)) {
|
|
2791
2800
|
killPid(pid, 'SIGKILL');
|
|
2792
|
-
try { process.kill(-pid, 'SIGKILL'); } catch { /* ignore */ }
|
|
2801
|
+
if (process.platform !== 'win32') { try { process.kill(-pid, 'SIGKILL'); } catch { /* ignore */ } }
|
|
2793
2802
|
}
|
|
2794
2803
|
}
|
|
2795
2804
|
|
|
@@ -2833,7 +2842,8 @@ function spawnReaper(config) {
|
|
|
2833
2842
|
const script = buildReaperScript(config);
|
|
2834
2843
|
const child = spawn(process.execPath, ["-e", script], {
|
|
2835
2844
|
detached: true,
|
|
2836
|
-
stdio: "ignore"
|
|
2845
|
+
stdio: "ignore",
|
|
2846
|
+
windowsHide: true
|
|
2837
2847
|
});
|
|
2838
2848
|
child.unref();
|
|
2839
2849
|
if (child.pid) {
|
|
@@ -2844,7 +2854,7 @@ function spawnReaper(config) {
|
|
|
2844
2854
|
function killReaper(reaperPidPath) {
|
|
2845
2855
|
try {
|
|
2846
2856
|
const pid = parseInt(
|
|
2847
|
-
readFileSync(reaperPidPath, "utf-8").trim(),
|
|
2857
|
+
readFileSync(reaperPidPath, "utf-8").replace(/\r\n/g, "\n").trim(),
|
|
2848
2858
|
10
|
|
2849
2859
|
);
|
|
2850
2860
|
if (pid && !isNaN(pid)) {
|
|
@@ -3153,7 +3163,7 @@ var ProviderRegistry = class {
|
|
|
3153
3163
|
|
|
3154
3164
|
// src/providers/codex-provider.ts
|
|
3155
3165
|
import { spawn as spawn2, execFileSync as execFileSync2 } from "child_process";
|
|
3156
|
-
import { existsSync } from "fs";
|
|
3166
|
+
import { existsSync, rmSync as rmSync2 } from "fs";
|
|
3157
3167
|
|
|
3158
3168
|
// src/providers/codex-jsonl-parser.ts
|
|
3159
3169
|
var CodexJsonlParser = class {
|
|
@@ -3311,7 +3321,7 @@ var CodexProvider = class {
|
|
|
3311
3321
|
});
|
|
3312
3322
|
} catch {
|
|
3313
3323
|
try {
|
|
3314
|
-
|
|
3324
|
+
rmSync2(request.workingDirectory, { recursive: true, force: true });
|
|
3315
3325
|
execFileSync2("git", ["worktree", "add", "-b", request.workingDirectory, request.workingDirectory, "HEAD"], {
|
|
3316
3326
|
stdio: "pipe"
|
|
3317
3327
|
});
|
|
@@ -3333,7 +3343,8 @@ var CodexProvider = class {
|
|
|
3333
3343
|
return new Promise((resolve) => {
|
|
3334
3344
|
const child = spawn2("codex", args, {
|
|
3335
3345
|
stdio: ["ignore", "pipe", "pipe"],
|
|
3336
|
-
env: { ...process.env, ...env }
|
|
3346
|
+
env: { ...process.env, ...env },
|
|
3347
|
+
...crossSpawnOptions()
|
|
3337
3348
|
});
|
|
3338
3349
|
const parser = new CodexJsonlParser();
|
|
3339
3350
|
parser.onEvent = (event) => request.onStreamEvent?.(event);
|
|
@@ -3359,10 +3370,7 @@ var CodexProvider = class {
|
|
|
3359
3370
|
} catch {
|
|
3360
3371
|
}
|
|
3361
3372
|
killTimer = setTimeout(() => {
|
|
3362
|
-
|
|
3363
|
-
child.kill("SIGKILL");
|
|
3364
|
-
} catch {
|
|
3365
|
-
}
|
|
3373
|
+
if (child.pid) killProcessTree(child.pid, "SIGKILL");
|
|
3366
3374
|
}, 5e3);
|
|
3367
3375
|
}, CODEX_TIMEOUT_MS);
|
|
3368
3376
|
let resolved = false;
|
|
@@ -3451,7 +3459,7 @@ var CodexProvider = class {
|
|
|
3451
3459
|
|
|
3452
3460
|
// src/providers/gemini-provider.ts
|
|
3453
3461
|
import { spawn as spawn3, execFileSync as execFileSync3 } from "child_process";
|
|
3454
|
-
import { existsSync as existsSync2, writeFileSync as writeFileSync3, mkdirSync as mkdirSync2 } from "fs";
|
|
3462
|
+
import { existsSync as existsSync2, writeFileSync as writeFileSync3, mkdirSync as mkdirSync2, rmSync as rmSync3 } from "fs";
|
|
3455
3463
|
import { join as join2, dirname } from "path";
|
|
3456
3464
|
import { homedir } from "os";
|
|
3457
3465
|
import { fileURLToPath } from "url";
|
|
@@ -3681,7 +3689,7 @@ var GeminiProvider = class _GeminiProvider {
|
|
|
3681
3689
|
});
|
|
3682
3690
|
} catch {
|
|
3683
3691
|
try {
|
|
3684
|
-
|
|
3692
|
+
rmSync3(request.workingDirectory, { recursive: true, force: true });
|
|
3685
3693
|
execFileSync3("git", ["worktree", "add", "-b", request.workingDirectory, request.workingDirectory, "HEAD"], {
|
|
3686
3694
|
stdio: "pipe"
|
|
3687
3695
|
});
|
|
@@ -3708,7 +3716,8 @@ var GeminiProvider = class _GeminiProvider {
|
|
|
3708
3716
|
return new Promise((resolve) => {
|
|
3709
3717
|
const child = spawn3("gemini", args, {
|
|
3710
3718
|
stdio: ["pipe", "pipe", "pipe"],
|
|
3711
|
-
cwd: cwd || void 0
|
|
3719
|
+
cwd: cwd || void 0,
|
|
3720
|
+
...crossSpawnOptions()
|
|
3712
3721
|
});
|
|
3713
3722
|
const parser = new GeminiJsonlParser();
|
|
3714
3723
|
parser.onEvent = (event) => request.onStreamEvent?.(event);
|
|
@@ -3724,7 +3733,7 @@ var GeminiProvider = class _GeminiProvider {
|
|
|
3724
3733
|
child.stderr?.on("data", (chunk) => {
|
|
3725
3734
|
const text = chunk.toString();
|
|
3726
3735
|
stderr += text;
|
|
3727
|
-
const lines = text.split("\n").filter((l) => l.trim());
|
|
3736
|
+
const lines = normalizeEol(text).split("\n").filter((l) => l.trim());
|
|
3728
3737
|
if (lines.length) lastStderrLine = lines[lines.length - 1];
|
|
3729
3738
|
});
|
|
3730
3739
|
child.stdin?.end();
|
|
@@ -3754,10 +3763,7 @@ var GeminiProvider = class _GeminiProvider {
|
|
|
3754
3763
|
} catch {
|
|
3755
3764
|
}
|
|
3756
3765
|
killTimer = setTimeout(() => {
|
|
3757
|
-
|
|
3758
|
-
child.kill("SIGKILL");
|
|
3759
|
-
} catch {
|
|
3760
|
-
}
|
|
3766
|
+
if (child.pid) killProcessTree(child.pid, "SIGKILL");
|
|
3761
3767
|
}, 5e3);
|
|
3762
3768
|
}, GEMINI_TIMEOUT_MS);
|
|
3763
3769
|
let resolved = false;
|
|
@@ -3841,14 +3847,16 @@ var GeminiProvider = class _GeminiProvider {
|
|
|
3841
3847
|
hookConfig.allowedTools = tr.allowedTools ? translateToolNames(tr.allowedTools) : null;
|
|
3842
3848
|
hookConfig.disallowedTools = tr.disallowedTools ? translateToolNames(tr.disallowedTools) : null;
|
|
3843
3849
|
if (tr.tools !== void 0) hookConfig.builtinToolsMode = tr.tools;
|
|
3844
|
-
const
|
|
3850
|
+
const ext = IS_WINDOWS ? ".cmd" : ".sh";
|
|
3851
|
+
const wrapperPath = join2(dir, `.kantban-hook-before-tool${ext}`);
|
|
3845
3852
|
writeFileSync3(wrapperPath, this.generateHookWrapper(hookPath, "BeforeToolSelection", join2(dir, ".kantban-hook-config.json")), { mode: 493 });
|
|
3846
3853
|
hooks.BeforeToolSelection = [{ matcher: "*", hooks: [{ type: "command", command: wrapperPath, timeout: 3e4 }] }];
|
|
3847
3854
|
}
|
|
3848
3855
|
if (request.maxTurns && request.mcpConfig) {
|
|
3849
3856
|
hookConfig.maxTurns = request.maxTurns;
|
|
3850
3857
|
hookConfig.turnFile = join2(dir, ".kantban-turn-counter");
|
|
3851
|
-
const
|
|
3858
|
+
const ext = IS_WINDOWS ? ".cmd" : ".sh";
|
|
3859
|
+
const wrapperPath = join2(dir, `.kantban-hook-after-agent${ext}`);
|
|
3852
3860
|
writeFileSync3(wrapperPath, this.generateHookWrapper(hookPath, "AfterAgent", join2(dir, ".kantban-hook-config.json")), { mode: 493 });
|
|
3853
3861
|
hooks.AfterAgent = [{ matcher: "*", hooks: [{ type: "command", command: wrapperPath, timeout: 3e4 }] }];
|
|
3854
3862
|
}
|
|
@@ -3881,6 +3889,18 @@ var GeminiProvider = class _GeminiProvider {
|
|
|
3881
3889
|
/** Generate a per-session bash wrapper that invokes the Node hook script.
|
|
3882
3890
|
* Gemini CLI ignores `args` in hook definitions, so we embed all arguments. */
|
|
3883
3891
|
generateHookWrapper(hookScript, event, configFile) {
|
|
3892
|
+
if (IS_WINDOWS) {
|
|
3893
|
+
return [
|
|
3894
|
+
"@echo off",
|
|
3895
|
+
'set "STDIN_FILE=%TEMP%\\kantban-hook-%RANDOM%%RANDOM%.tmp"',
|
|
3896
|
+
'findstr "^" > "%STDIN_FILE%"',
|
|
3897
|
+
`node "${hookScript}" "${event}" "${configFile}" < "%STDIN_FILE%"`,
|
|
3898
|
+
'set "EXIT_CODE=%ERRORLEVEL%"',
|
|
3899
|
+
'del /f /q "%STDIN_FILE%" >nul 2>&1',
|
|
3900
|
+
"exit /b %EXIT_CODE%",
|
|
3901
|
+
""
|
|
3902
|
+
].join("\r\n");
|
|
3903
|
+
}
|
|
3884
3904
|
return `#!/bin/bash
|
|
3885
3905
|
# KantBan pipeline hook wrapper \u2014 Gemini CLI does not pass args, so we embed them.
|
|
3886
3906
|
STDIN_FILE=$(mktemp)
|
|
@@ -3894,7 +3914,7 @@ node "${hookScript}" "${event}" "${configFile}" < "$STDIN_FILE"
|
|
|
3894
3914
|
* which contains lines like "YOLO mode is enabled..." and "Loaded cached credentials."
|
|
3895
3915
|
* that corrupt JSON parsing in downstream consumers (advisor, light-call). */
|
|
3896
3916
|
static stripCliPreamble(text) {
|
|
3897
|
-
const lines = text.split("\n");
|
|
3917
|
+
const lines = normalizeEol(text).split("\n");
|
|
3898
3918
|
const jsonStart = lines.findIndex((line) => {
|
|
3899
3919
|
const trimmed = line.trim();
|
|
3900
3920
|
return trimmed.startsWith("{") || trimmed.startsWith("[");
|
|
@@ -4057,7 +4077,7 @@ function childManifestPath(boardId) {
|
|
|
4057
4077
|
}
|
|
4058
4078
|
function readChildManifest(boardId) {
|
|
4059
4079
|
try {
|
|
4060
|
-
const contents = readFileSync3(childManifestPath(boardId), "utf-8");
|
|
4080
|
+
const contents = normalizeEol(readFileSync3(childManifestPath(boardId), "utf-8"));
|
|
4061
4081
|
return contents.split("\n").map((l) => l.trim()).filter((l) => l !== "").map(Number).filter((n) => !isNaN(n) && n > 0);
|
|
4062
4082
|
} catch {
|
|
4063
4083
|
return [];
|
|
@@ -4077,7 +4097,7 @@ function cleanupOrphanedProcesses(boardId) {
|
|
|
4077
4097
|
if (stalePid && stalePid !== process.pid) {
|
|
4078
4098
|
try {
|
|
4079
4099
|
process.kill(stalePid, 0);
|
|
4080
|
-
|
|
4100
|
+
killProcessTree(stalePid, "SIGTERM");
|
|
4081
4101
|
console.log(`Killed stale orchestrator (PID ${String(stalePid)})`);
|
|
4082
4102
|
} catch {
|
|
4083
4103
|
}
|
|
@@ -4091,7 +4111,7 @@ function cleanupOrphanedProcesses(boardId) {
|
|
|
4091
4111
|
for (const pid of manifestPids) {
|
|
4092
4112
|
try {
|
|
4093
4113
|
process.kill(pid, 0);
|
|
4094
|
-
|
|
4114
|
+
killProcessTree(pid, "SIGTERM");
|
|
4095
4115
|
} catch {
|
|
4096
4116
|
}
|
|
4097
4117
|
}
|
|
@@ -4105,7 +4125,7 @@ function cleanupOrphanedProcesses(boardId) {
|
|
|
4105
4125
|
if (reaperPid && !isNaN(reaperPid)) {
|
|
4106
4126
|
try {
|
|
4107
4127
|
process.kill(reaperPid, 0);
|
|
4108
|
-
|
|
4128
|
+
killProcessTree(reaperPid, "SIGTERM");
|
|
4109
4129
|
console.log(`Killed stale reaper (PID ${String(reaperPid)})`);
|
|
4110
4130
|
} catch {
|
|
4111
4131
|
}
|
|
@@ -4257,7 +4277,7 @@ async function runPipeline(client, args) {
|
|
|
4257
4277
|
// Run memory enrichment — inject accumulated discoveries into each iteration prompt
|
|
4258
4278
|
fetchRunMemoryContent: mem ? async () => {
|
|
4259
4279
|
const content = await mem.getContent();
|
|
4260
|
-
const lines = content.split("\n");
|
|
4280
|
+
const lines = normalizeEol(content).split("\n");
|
|
4261
4281
|
if (lines.length > 500) {
|
|
4262
4282
|
return lines.slice(-500).join("\n");
|
|
4263
4283
|
}
|
|
@@ -4671,12 +4691,14 @@ Received ${signal}. Shutting down gracefully...`);
|
|
|
4671
4691
|
process.exit(1);
|
|
4672
4692
|
});
|
|
4673
4693
|
});
|
|
4674
|
-
|
|
4675
|
-
|
|
4676
|
-
|
|
4677
|
-
|
|
4694
|
+
if (!IS_WINDOWS) {
|
|
4695
|
+
process.on("SIGHUP", () => {
|
|
4696
|
+
shutdown("SIGHUP").catch((err) => {
|
|
4697
|
+
console.error("Error during shutdown:", err);
|
|
4698
|
+
process.exit(1);
|
|
4699
|
+
});
|
|
4678
4700
|
});
|
|
4679
|
-
}
|
|
4701
|
+
}
|
|
4680
4702
|
cleanupOrphanedProcesses(opts.boardId);
|
|
4681
4703
|
writePidFile(opts.boardId);
|
|
4682
4704
|
logger.orchestrator(`PID file written: ${String(process.pid)}`);
|
|
@@ -4855,13 +4877,8 @@ async function stopPipeline(args) {
|
|
|
4855
4877
|
return;
|
|
4856
4878
|
}
|
|
4857
4879
|
try {
|
|
4858
|
-
|
|
4859
|
-
|
|
4860
|
-
console.log(`Sent SIGTERM to pipeline process group (pgid ${String(pid)}) for board ${boardId}.`);
|
|
4861
|
-
} catch {
|
|
4862
|
-
process.kill(pid, "SIGTERM");
|
|
4863
|
-
console.log(`Sent SIGTERM to pipeline process ${String(pid)} for board ${boardId}.`);
|
|
4864
|
-
}
|
|
4880
|
+
killProcessTree(pid, "SIGTERM");
|
|
4881
|
+
console.log(`Sent SIGTERM to pipeline process ${String(pid)} for board ${boardId}.`);
|
|
4865
4882
|
} catch (err) {
|
|
4866
4883
|
const message = err instanceof Error ? err.message : String(err);
|
|
4867
4884
|
console.error(`Failed to stop pipeline (PID ${String(pid)}): ${message}`);
|
|
@@ -4874,4 +4891,4 @@ export {
|
|
|
4874
4891
|
runPipeline,
|
|
4875
4892
|
stopPipeline
|
|
4876
4893
|
};
|
|
4877
|
-
//# sourceMappingURL=pipeline-
|
|
4894
|
+
//# sourceMappingURL=pipeline-N7Z43P6P.js.map
|