kantban-cli 0.1.1

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 (58) hide show
  1. package/README.md +37 -0
  2. package/dist/client.d.ts +35 -0
  3. package/dist/client.d.ts.map +1 -0
  4. package/dist/client.js +109 -0
  5. package/dist/client.js.map +1 -0
  6. package/dist/commands/context.d.ts +3 -0
  7. package/dist/commands/context.d.ts.map +1 -0
  8. package/dist/commands/context.js +27 -0
  9. package/dist/commands/context.js.map +1 -0
  10. package/dist/commands/cron.d.ts +3 -0
  11. package/dist/commands/cron.d.ts.map +1 -0
  12. package/dist/commands/cron.js +106 -0
  13. package/dist/commands/cron.js.map +1 -0
  14. package/dist/commands/pipeline.d.ts +4 -0
  15. package/dist/commands/pipeline.d.ts.map +1 -0
  16. package/dist/commands/pipeline.js +543 -0
  17. package/dist/commands/pipeline.js.map +1 -0
  18. package/dist/commands/status.d.ts +3 -0
  19. package/dist/commands/status.d.ts.map +1 -0
  20. package/dist/commands/status.js +135 -0
  21. package/dist/commands/status.js.map +1 -0
  22. package/dist/commands/work.d.ts +3 -0
  23. package/dist/commands/work.d.ts.map +1 -0
  24. package/dist/commands/work.js +76 -0
  25. package/dist/commands/work.js.map +1 -0
  26. package/dist/index.d.ts +3 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +65 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/lib/event-queue.d.ts +28 -0
  31. package/dist/lib/event-queue.d.ts.map +1 -0
  32. package/dist/lib/event-queue.js +65 -0
  33. package/dist/lib/event-queue.js.map +1 -0
  34. package/dist/lib/logger.d.ts +20 -0
  35. package/dist/lib/logger.d.ts.map +1 -0
  36. package/dist/lib/logger.js +52 -0
  37. package/dist/lib/logger.js.map +1 -0
  38. package/dist/lib/mcp-config.d.ts +3 -0
  39. package/dist/lib/mcp-config.d.ts.map +1 -0
  40. package/dist/lib/mcp-config.js +49 -0
  41. package/dist/lib/mcp-config.js.map +1 -0
  42. package/dist/lib/orchestrator.d.ts +172 -0
  43. package/dist/lib/orchestrator.d.ts.map +1 -0
  44. package/dist/lib/orchestrator.js +315 -0
  45. package/dist/lib/orchestrator.js.map +1 -0
  46. package/dist/lib/prompt-composer.d.ts +102 -0
  47. package/dist/lib/prompt-composer.d.ts.map +1 -0
  48. package/dist/lib/prompt-composer.js +178 -0
  49. package/dist/lib/prompt-composer.js.map +1 -0
  50. package/dist/lib/ralph-loop.d.ts +47 -0
  51. package/dist/lib/ralph-loop.d.ts.map +1 -0
  52. package/dist/lib/ralph-loop.js +114 -0
  53. package/dist/lib/ralph-loop.js.map +1 -0
  54. package/dist/lib/ws-client.d.ts +28 -0
  55. package/dist/lib/ws-client.d.ts.map +1 -0
  56. package/dist/lib/ws-client.js +113 -0
  57. package/dist/lib/ws-client.js.map +1 -0
  58. package/package.json +49 -0
@@ -0,0 +1,543 @@
1
+ import { execFile, execSync } from 'node:child_process';
2
+ import { mkdirSync, writeFileSync, readFileSync, unlinkSync, existsSync } from 'node:fs';
3
+ import { homedir } from 'node:os';
4
+ import { join } from 'node:path';
5
+ import { PipelineOrchestrator } from '../lib/orchestrator.js';
6
+ import { RalphLoop } from '../lib/ralph-loop.js';
7
+ import { EventQueue } from '../lib/event-queue.js';
8
+ import { PipelineWsClient } from '../lib/ws-client.js';
9
+ import { generateMcpConfig, cleanupMcpConfig } from '../lib/mcp-config.js';
10
+ import { PipelineLogger } from '../lib/logger.js';
11
+ function parseArgs(args) {
12
+ const positional = [];
13
+ let once = false;
14
+ let dryRun = false;
15
+ let columnFilter = null;
16
+ let maxIterations = null;
17
+ let maxBudget = null;
18
+ let model = null;
19
+ let concurrency = null;
20
+ let logRetention = 7;
21
+ let yes = false;
22
+ for (let i = 0; i < args.length; i++) {
23
+ const arg = args[i];
24
+ switch (arg) {
25
+ case '--once':
26
+ once = true;
27
+ break;
28
+ case '--dry-run':
29
+ dryRun = true;
30
+ break;
31
+ case '--yes':
32
+ case '-y':
33
+ yes = true;
34
+ break;
35
+ case '--column':
36
+ columnFilter = args[++i] ?? null;
37
+ break;
38
+ case '--max-iterations':
39
+ maxIterations = Number(args[++i]);
40
+ break;
41
+ case '--max-budget':
42
+ maxBudget = Number(args[++i]);
43
+ break;
44
+ case '--model':
45
+ model = args[++i] ?? null;
46
+ break;
47
+ case '--concurrency':
48
+ concurrency = Number(args[++i]);
49
+ break;
50
+ case '--log-retention':
51
+ logRetention = Number(args[++i]) || 7;
52
+ break;
53
+ default:
54
+ if (!arg.startsWith('--'))
55
+ positional.push(arg);
56
+ break;
57
+ }
58
+ }
59
+ const boardId = positional[0] ?? '';
60
+ if (!boardId) {
61
+ console.error(`Usage: kantban pipeline <board-id> [flags]
62
+
63
+ Flags:
64
+ --once Run one scan, wait for loops, then exit
65
+ --dry-run Show config without starting
66
+ --column <id> Filter to a single column
67
+ --max-iterations <n> Override max iterations per ticket
68
+ --max-budget <usd> Per-ticket budget cap (USD)
69
+ --model <model> Override model preference
70
+ --concurrency <n> Override concurrency per column
71
+ --log-retention <d> Log retention in days (default: 7)
72
+ --yes, -y Skip safety confirmation`);
73
+ process.exit(1);
74
+ }
75
+ return { boardId, once, dryRun, columnFilter, maxIterations, maxBudget, model, concurrency, logRetention, yes };
76
+ }
77
+ // ---------------------------------------------------------------------------
78
+ // PID file helpers
79
+ // ---------------------------------------------------------------------------
80
+ function pidDir(boardId) {
81
+ return join(homedir(), '.kantban', 'pipelines', boardId);
82
+ }
83
+ function pidFilePath(boardId) {
84
+ return join(pidDir(boardId), 'orchestrator.pid');
85
+ }
86
+ function writePidFile(boardId) {
87
+ const dir = pidDir(boardId);
88
+ mkdirSync(dir, { recursive: true });
89
+ writeFileSync(pidFilePath(boardId), String(process.pid));
90
+ }
91
+ function removePidFile(boardId) {
92
+ try {
93
+ unlinkSync(pidFilePath(boardId));
94
+ }
95
+ catch {
96
+ /* already removed */
97
+ }
98
+ }
99
+ /**
100
+ * Kill any orphaned pipeline processes from a previous run.
101
+ * Reads the stale PID file, kills that process tree, then removes the file.
102
+ * Also kills any lingering `claude -p` processes that reference our MCP config dir.
103
+ */
104
+ function cleanupOrphanedProcesses(boardId) {
105
+ // 1. Kill stale orchestrator from PID file
106
+ const pidPath = pidFilePath(boardId);
107
+ if (existsSync(pidPath)) {
108
+ try {
109
+ const stalePid = parseInt(readFileSync(pidPath, 'utf-8').trim(), 10);
110
+ if (stalePid && stalePid !== process.pid) {
111
+ try {
112
+ process.kill(stalePid, 0); // test if alive
113
+ process.kill(stalePid, 'SIGTERM');
114
+ console.log(`Killed stale orchestrator (PID ${String(stalePid)})`);
115
+ }
116
+ catch {
117
+ // already dead
118
+ }
119
+ }
120
+ }
121
+ catch {
122
+ // can't read PID file
123
+ }
124
+ removePidFile(boardId);
125
+ }
126
+ // 2. Kill orphaned claude -p processes with kantban-pipeline MCP configs
127
+ try {
128
+ const out = execSync(`ps aux | grep 'claude.*-p.*kantban-pipeline' | grep -v grep | awk '{print $2}'`, { encoding: 'utf-8', timeout: 5000 }).trim();
129
+ if (out) {
130
+ const pids = out.split('\n').filter(Boolean);
131
+ for (const pid of pids) {
132
+ try {
133
+ process.kill(parseInt(pid, 10), 'SIGTERM');
134
+ }
135
+ catch {
136
+ // already dead
137
+ }
138
+ }
139
+ if (pids.length > 0) {
140
+ console.log(`Killed ${String(pids.length)} orphaned claude agent(s)`);
141
+ }
142
+ }
143
+ }
144
+ catch {
145
+ // ps/grep failed — not critical
146
+ }
147
+ }
148
+ // ---------------------------------------------------------------------------
149
+ // invokeClaudeP — spawns a Claude Code process with -p flag
150
+ // Children are spawned in the orchestrator's process group so that killing
151
+ // the group (e.g. on crash) takes all children down with it.
152
+ // ---------------------------------------------------------------------------
153
+ const activeChildProcesses = new Set();
154
+ const CLAUDE_TIMEOUT_MS = 60 * 60 * 1000; // 1 hour max per invocation
155
+ async function invokeClaudeP(prompt, options) {
156
+ const args = ['-p', prompt, '--mcp-config', options.mcpConfigPath, '--dangerously-skip-permissions'];
157
+ if (options.model)
158
+ args.push('--model', options.model);
159
+ if (options.maxBudgetUsd)
160
+ args.push('--max-turns', String(Math.ceil(options.maxBudgetUsd * 10)));
161
+ if (options.worktree)
162
+ args.push('--worktree', options.worktree);
163
+ return new Promise((resolve) => {
164
+ const child = execFile('claude', args, {
165
+ maxBuffer: 50 * 1024 * 1024, // 50MB
166
+ timeout: CLAUDE_TIMEOUT_MS,
167
+ }, (err, stdout) => {
168
+ activeChildProcesses.delete(child);
169
+ if (err) {
170
+ const execErr = err;
171
+ const exitCode = execErr.code ?? (execErr.killed ? 137 : 1);
172
+ resolve({ exitCode, output: stdout || err.message || '' });
173
+ }
174
+ else {
175
+ resolve({ exitCode: 0, output: stdout });
176
+ }
177
+ });
178
+ activeChildProcesses.add(child);
179
+ });
180
+ }
181
+ function killAllChildProcesses() {
182
+ for (const child of activeChildProcesses) {
183
+ if (child.pid) {
184
+ // Kill the child's entire process tree (claude spawns sub-processes)
185
+ try {
186
+ process.kill(-child.pid, 'SIGTERM');
187
+ }
188
+ catch {
189
+ // Process group kill failed — try direct kill
190
+ child.kill('SIGTERM');
191
+ }
192
+ }
193
+ else {
194
+ child.kill('SIGTERM');
195
+ }
196
+ }
197
+ }
198
+ // ---------------------------------------------------------------------------
199
+ // Safety confirmation
200
+ // ---------------------------------------------------------------------------
201
+ function printSafetyWarning() {
202
+ console.log(`
203
+ === SAFETY WARNING ===
204
+
205
+ This pipeline will run Claude Code agents with --dangerously-skip-permissions.
206
+ Agents will have unrestricted access to tools, file system, and MCP servers.
207
+
208
+ Before proceeding:
209
+ 1. Review all prompt documents linked to pipeline columns
210
+ 2. Ensure your project signals/guardrails are configured correctly
211
+ 3. Verify your MCP server configuration is appropriate
212
+
213
+ Press Ctrl+C to cancel, or re-run with --yes to skip this warning.
214
+ `);
215
+ }
216
+ async function waitForConfirmation() {
217
+ return new Promise((resolve) => {
218
+ process.stdout.write('Continue? [y/N] ');
219
+ process.stdin.setEncoding('utf8');
220
+ process.stdin.once('data', (data) => {
221
+ const answer = data.trim().toLowerCase();
222
+ resolve(answer === 'y' || answer === 'yes');
223
+ });
224
+ // If stdin is not a TTY (piped), reject
225
+ if (!process.stdin.isTTY) {
226
+ resolve(false);
227
+ }
228
+ });
229
+ }
230
+ // ---------------------------------------------------------------------------
231
+ // runPipeline — main entry point
232
+ // ---------------------------------------------------------------------------
233
+ export async function runPipeline(client, args) {
234
+ const opts = parseArgs(args);
235
+ // Safety confirmation
236
+ if (!opts.yes && !opts.dryRun) {
237
+ printSafetyWarning();
238
+ const confirmed = await waitForConfirmation();
239
+ if (!confirmed) {
240
+ console.log('Aborted.');
241
+ return;
242
+ }
243
+ }
244
+ // Resolve project ID
245
+ let projectId = process.env['KANTBAN_PROJECT_ID'] ?? '';
246
+ if (!projectId) {
247
+ try {
248
+ const result = await client.getBoardProject(opts.boardId);
249
+ projectId = result.project_id;
250
+ }
251
+ catch (err) {
252
+ const message = err instanceof Error ? err.message : String(err);
253
+ console.error(`Error: Could not resolve project ID for board ${opts.boardId}: ${message}`);
254
+ console.error('Set KANTBAN_PROJECT_ID environment variable or ensure the board exists.');
255
+ process.exit(1);
256
+ }
257
+ }
258
+ // Generate MCP config
259
+ const mcpConfigPath = generateMcpConfig(client.baseUrl, client.token);
260
+ // Initialize logger
261
+ const logBaseDir = join(homedir(), '.kantban', 'pipelines');
262
+ const logger = new PipelineLogger(logBaseDir, opts.boardId);
263
+ logger.pruneOldLogs(opts.logRetention);
264
+ // Wire up OrchestratorDeps
265
+ const deps = {
266
+ fetchBoardScope: (boardId) => client.get(`/projects/${projectId}/pipeline-context`, { boardId }),
267
+ fetchColumnScope: (columnId) => client.get(`/projects/${projectId}/pipeline-context`, { columnId }),
268
+ startLoop: (ticketId, columnId, config) => {
269
+ // Apply CLI overrides
270
+ const effectiveConfig = {
271
+ ...config,
272
+ ...(opts.maxIterations !== null && { maxIterations: opts.maxIterations }),
273
+ ...(opts.maxBudget !== null && { maxBudgetUsd: opts.maxBudget }),
274
+ ...(opts.model !== null && { modelPreference: opts.model }),
275
+ };
276
+ const loopDeps = {
277
+ fetchTicketContext: (tid) => client.get(`/projects/${projectId}/pipeline-context`, { ticketId: tid }),
278
+ fetchColumnContext: (cid) => client.get(`/projects/${projectId}/pipeline-context`, { columnId: cid }),
279
+ fetchFingerprint: (tid) => client.getFingerprint(projectId, tid),
280
+ invokeClaudeP,
281
+ mcpConfigPath,
282
+ projectId,
283
+ };
284
+ const loop = new RalphLoop(ticketId, columnId, effectiveConfig, loopDeps);
285
+ // Track active loops for graceful shutdown
286
+ activeRalphLoops.add(loop);
287
+ return loop.run().finally(() => {
288
+ activeRalphLoops.delete(loop);
289
+ });
290
+ },
291
+ createComment: (ticketId, body) => client.post(`/projects/${projectId}/tickets/${ticketId}/comments`, { body }),
292
+ createSignal: (ticketId, body) => client.post(`/projects/${projectId}/tickets/${ticketId}/signals`, { body }),
293
+ claimTicket: (ticketId) => client.claimTicket(projectId, ticketId),
294
+ fetchBlockedTickets: (ticketId) => client.get(`/projects/${projectId}/tickets/${ticketId}/blocked-tickets`),
295
+ hasUnresolvedBlockers: async (ticketId) => {
296
+ const blockers = await client.get(`/projects/${projectId}/tickets/${ticketId}/unresolved-blockers`);
297
+ return blockers.length > 0;
298
+ },
299
+ };
300
+ // Create orchestrator
301
+ const orchestrator = new PipelineOrchestrator(opts.boardId, projectId, deps);
302
+ // Initialize — discovers pipeline columns
303
+ console.log(`Initializing pipeline for board ${opts.boardId}...`);
304
+ logger.orchestrator('Initializing pipeline');
305
+ await orchestrator.initialize();
306
+ const columnIds = orchestrator.pipelineColumnIds;
307
+ if (columnIds.length === 0) {
308
+ console.log('No pipeline columns found (columns need has_prompt=true and type !== "done").');
309
+ cleanupMcpConfig(mcpConfigPath);
310
+ return;
311
+ }
312
+ console.log(`Discovered ${String(columnIds.length)} pipeline column(s).`);
313
+ logger.orchestrator(`Discovered ${String(columnIds.length)} pipeline columns: ${columnIds.join(', ')}`);
314
+ // Dry-run: print config summary and exit
315
+ if (opts.dryRun) {
316
+ console.log('\n--- Dry Run Configuration ---');
317
+ console.log(`Board ID: ${opts.boardId}`);
318
+ console.log(`Project ID: ${projectId}`);
319
+ console.log(`Pipeline cols: ${String(columnIds.length)}`);
320
+ console.log(`Column filter: ${opts.columnFilter ?? '(none)'}`);
321
+ console.log(`Max iterations: ${opts.maxIterations !== null ? String(opts.maxIterations) : '(per-column default)'}`);
322
+ console.log(`Max budget: ${opts.maxBudget !== null ? `$${String(opts.maxBudget)}` : '(per-column default)'}`);
323
+ console.log(`Model: ${opts.model ?? '(per-column default)'}`);
324
+ console.log(`Concurrency: ${opts.concurrency !== null ? String(opts.concurrency) : '(per-column default)'}`);
325
+ console.log(`Mode: ${opts.once ? 'once' : 'persistent'}`);
326
+ console.log(`Log retention: ${String(opts.logRetention)} days`);
327
+ console.log(`MCP config: ${mcpConfigPath}`);
328
+ console.log('\n[Dry run -- no agents started]');
329
+ cleanupMcpConfig(mcpConfigPath);
330
+ return;
331
+ }
332
+ // --- Live mode ---
333
+ // Set up graceful shutdown
334
+ let shutdownInProgress = false;
335
+ const shutdown = async (signal) => {
336
+ if (shutdownInProgress)
337
+ return;
338
+ shutdownInProgress = true;
339
+ console.log(`\nReceived ${signal}. Shutting down gracefully...`);
340
+ logger.orchestrator(`Shutdown initiated (${signal})`);
341
+ // Stop WS client
342
+ wsClient?.stop();
343
+ // Stop polling fallback
344
+ if (pollFallbackTimer)
345
+ clearInterval(pollFallbackTimer);
346
+ // Stop event queue
347
+ eventQueue?.stop();
348
+ // Stop all active Ralph Loops
349
+ for (const loop of activeRalphLoops) {
350
+ loop.stop();
351
+ }
352
+ // Kill any running claude -p child processes
353
+ killAllChildProcesses();
354
+ // Cleanup
355
+ cleanupMcpConfig(mcpConfigPath);
356
+ removePidFile(opts.boardId);
357
+ logger.orchestrator('Shutdown complete');
358
+ console.log('Pipeline stopped.');
359
+ process.exit(0);
360
+ };
361
+ process.on('SIGTERM', () => void shutdown('SIGTERM'));
362
+ process.on('SIGINT', () => void shutdown('SIGINT'));
363
+ // Clean up orphaned processes from a previous run before starting
364
+ cleanupOrphanedProcesses(opts.boardId);
365
+ // Write PID file
366
+ writePidFile(opts.boardId);
367
+ logger.orchestrator(`PID file written: ${String(process.pid)}`);
368
+ // Set up event queue and WS client
369
+ let eventQueue = null;
370
+ let wsClient = null;
371
+ let pollFallbackTimer = null;
372
+ const onEventError = (event, err) => {
373
+ const msg = err instanceof Error ? err.message : String(err);
374
+ logger.orchestrator(`Event handler error for ${event.type} ticket=${event.ticketId}: ${msg}`);
375
+ console.error(`Event handler error: ${msg}`);
376
+ };
377
+ eventQueue = new EventQueue((event) => orchestrator.handleEvent(event), {
378
+ drainRateMs: 100,
379
+ onError: onEventError,
380
+ });
381
+ wsClient = new PipelineWsClient(client, {
382
+ boardId: opts.boardId,
383
+ projectId,
384
+ onEvent: (wsEvent) => {
385
+ // Log ALL WS events for debugging
386
+ logger.orchestrator(`WS raw event: ${wsEvent.type} payload=${JSON.stringify(wsEvent.payload)}`);
387
+ // Map WS events to pipeline events
388
+ const payload = wsEvent.payload;
389
+ // ticket:moved and ticket:created nest the id inside payload.ticket
390
+ // ticket:deleted and ticket:archived have payload.ticketId directly
391
+ const ticket = payload['ticket'];
392
+ const ticketId = (typeof payload['ticketId'] === 'string' ? payload['ticketId'] : null) ??
393
+ (ticket && typeof ticket['id'] === 'string' ? ticket['id'] : null);
394
+ // ticket:created has payload.columnId; ticket:moved has the new column in ticket.column_id
395
+ const columnId = (typeof payload['columnId'] === 'string' ? payload['columnId'] : null) ??
396
+ (ticket && typeof ticket['column_id'] === 'string' ? ticket['column_id'] : null);
397
+ if (!ticketId)
398
+ return;
399
+ const eventType = wsEvent.type;
400
+ if (eventType === 'ticket:created' ||
401
+ eventType === 'ticket:moved' ||
402
+ eventType === 'ticket:archived' ||
403
+ eventType === 'ticket:deleted') {
404
+ const pipelineEvent = { type: eventType, ticketId, columnId };
405
+ eventQueue.push(pipelineEvent);
406
+ logger.orchestrator(`WS event: ${eventType} ticket=${ticketId} column=${columnId ?? 'null'}`);
407
+ }
408
+ },
409
+ onConnect: () => {
410
+ console.log('WebSocket connected. Listening for board events...');
411
+ logger.orchestrator('WebSocket connected');
412
+ // Stop polling fallback if running
413
+ if (pollFallbackTimer) {
414
+ clearInterval(pollFallbackTimer);
415
+ pollFallbackTimer = null;
416
+ logger.orchestrator('Polling fallback stopped (WS reconnected)');
417
+ }
418
+ },
419
+ onDisconnect: () => {
420
+ console.log('WebSocket disconnected. Attempting reconnect...');
421
+ logger.orchestrator('WebSocket disconnected');
422
+ // Start polling fallback if not already running
423
+ if (!pollFallbackTimer) {
424
+ logger.orchestrator('Starting polling fallback (every 15s)');
425
+ pollFallbackTimer = setInterval(() => {
426
+ void orchestrator.scanAndSpawn().catch((err) => {
427
+ const msg = err instanceof Error ? err.message : String(err);
428
+ logger.orchestrator(`Poll fallback scan error: ${msg}`);
429
+ });
430
+ }, 15000);
431
+ }
432
+ },
433
+ });
434
+ // Connect WS
435
+ try {
436
+ await wsClient.connect();
437
+ }
438
+ catch (err) {
439
+ const message = err instanceof Error ? err.message : String(err);
440
+ console.error(`Warning: WebSocket connection failed: ${message}`);
441
+ console.error('Pipeline will use polling fallback for event detection.');
442
+ logger.orchestrator(`WebSocket connection failed: ${message}`);
443
+ // Start polling fallback since WS is unavailable
444
+ if (!pollFallbackTimer) {
445
+ logger.orchestrator('Starting polling fallback (every 15s) — WS unavailable');
446
+ pollFallbackTimer = setInterval(() => {
447
+ void orchestrator.scanAndSpawn().catch((pollErr) => {
448
+ const msg = pollErr instanceof Error ? pollErr.message : String(pollErr);
449
+ logger.orchestrator(`Poll fallback scan error: ${msg}`);
450
+ });
451
+ }, 15000);
452
+ }
453
+ }
454
+ // Start event queue
455
+ eventQueue.start();
456
+ // Initial scan and spawn
457
+ console.log('Scanning pipeline columns for tickets...');
458
+ logger.orchestrator('Starting scan and spawn');
459
+ try {
460
+ await orchestrator.scanAndSpawn();
461
+ logger.orchestrator(`Scan complete. Active loops: ${String(orchestrator.activeLoopCount)}`);
462
+ console.log(`Scan complete. Active loops: ${String(orchestrator.activeLoopCount)}`);
463
+ }
464
+ catch (scanErr) {
465
+ const scanMsg = scanErr instanceof Error ? scanErr.message : String(scanErr);
466
+ logger.orchestrator(`Scan error: ${scanMsg}`);
467
+ console.error(`Scan error: ${scanMsg}`);
468
+ }
469
+ if (opts.once) {
470
+ // Wait for all active loops to complete, then exit
471
+ console.log('Running in --once mode. Waiting for all loops to complete...');
472
+ logger.orchestrator('Once mode: waiting for loops to complete');
473
+ // Poll until no active loops remain
474
+ await waitForAllLoops();
475
+ // Cleanup
476
+ wsClient.stop();
477
+ eventQueue.stop();
478
+ cleanupMcpConfig(mcpConfigPath);
479
+ removePidFile(opts.boardId);
480
+ logger.orchestrator('Once mode complete. Exiting.');
481
+ console.log('All loops complete. Pipeline exiting.');
482
+ }
483
+ else {
484
+ // Persistent mode — process stays alive via WS connection and event queue interval
485
+ console.log(`Pipeline running (PID ${String(process.pid)}). Use 'kantban pipeline stop ${opts.boardId}' to stop.`);
486
+ logger.orchestrator('Pipeline running in persistent mode');
487
+ }
488
+ }
489
+ // ---------------------------------------------------------------------------
490
+ // Active loop tracking for graceful shutdown
491
+ // ---------------------------------------------------------------------------
492
+ const activeRalphLoops = new Set();
493
+ async function waitForAllLoops() {
494
+ // Check every second if all loops have completed
495
+ while (activeRalphLoops.size > 0) {
496
+ await new Promise((resolve) => setTimeout(resolve, 1000));
497
+ }
498
+ }
499
+ // ---------------------------------------------------------------------------
500
+ // stopPipeline — sends SIGTERM to a running pipeline
501
+ // ---------------------------------------------------------------------------
502
+ export async function stopPipeline(args) {
503
+ const boardId = args[0];
504
+ if (!boardId) {
505
+ console.error('Usage: kantban pipeline stop <board-id>');
506
+ process.exit(1);
507
+ }
508
+ const pidFile = pidFilePath(boardId);
509
+ let pid;
510
+ try {
511
+ const content = readFileSync(pidFile, 'utf8').trim();
512
+ pid = Number(content);
513
+ if (isNaN(pid) || pid <= 0) {
514
+ throw new Error('Invalid PID');
515
+ }
516
+ }
517
+ catch {
518
+ console.error(`No running pipeline found for board ${boardId}.`);
519
+ console.error(`Expected PID file at: ${pidFile}`);
520
+ process.exit(1);
521
+ return; // unreachable, but helps TS
522
+ }
523
+ try {
524
+ // Kill the entire process group to take down child claude -p processes too
525
+ try {
526
+ process.kill(-pid, 'SIGTERM');
527
+ console.log(`Sent SIGTERM to pipeline process group (pgid ${String(pid)}) for board ${boardId}.`);
528
+ }
529
+ catch {
530
+ // Process group kill failed (not a group leader) — fall back to direct kill
531
+ process.kill(pid, 'SIGTERM');
532
+ console.log(`Sent SIGTERM to pipeline process ${String(pid)} for board ${boardId}.`);
533
+ }
534
+ }
535
+ catch (err) {
536
+ const message = err instanceof Error ? err.message : String(err);
537
+ console.error(`Failed to stop pipeline (PID ${String(pid)}): ${message}`);
538
+ console.error('The process may have already exited. Removing stale PID file.');
539
+ removePidFile(boardId);
540
+ process.exit(1);
541
+ }
542
+ }
543
+ //# sourceMappingURL=pipeline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline.js","sourceRoot":"","sources":["../../src/commands/pipeline.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { KantBanCLIClient } from '../client.js';
2
+ export declare function runStatus(client: KantBanCLIClient, args: string[]): Promise<void>;
3
+ //# sourceMappingURL=status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAgGrD,wBAAsB,SAAS,CAAC,MAAM,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA0DvF"}