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.
- package/README.md +37 -0
- package/dist/client.d.ts +35 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +109 -0
- package/dist/client.js.map +1 -0
- package/dist/commands/context.d.ts +3 -0
- package/dist/commands/context.d.ts.map +1 -0
- package/dist/commands/context.js +27 -0
- package/dist/commands/context.js.map +1 -0
- package/dist/commands/cron.d.ts +3 -0
- package/dist/commands/cron.d.ts.map +1 -0
- package/dist/commands/cron.js +106 -0
- package/dist/commands/cron.js.map +1 -0
- package/dist/commands/pipeline.d.ts +4 -0
- package/dist/commands/pipeline.d.ts.map +1 -0
- package/dist/commands/pipeline.js +543 -0
- package/dist/commands/pipeline.js.map +1 -0
- package/dist/commands/status.d.ts +3 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +135 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/work.d.ts +3 -0
- package/dist/commands/work.d.ts.map +1 -0
- package/dist/commands/work.js +76 -0
- package/dist/commands/work.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +65 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/event-queue.d.ts +28 -0
- package/dist/lib/event-queue.d.ts.map +1 -0
- package/dist/lib/event-queue.js +65 -0
- package/dist/lib/event-queue.js.map +1 -0
- package/dist/lib/logger.d.ts +20 -0
- package/dist/lib/logger.d.ts.map +1 -0
- package/dist/lib/logger.js +52 -0
- package/dist/lib/logger.js.map +1 -0
- package/dist/lib/mcp-config.d.ts +3 -0
- package/dist/lib/mcp-config.d.ts.map +1 -0
- package/dist/lib/mcp-config.js +49 -0
- package/dist/lib/mcp-config.js.map +1 -0
- package/dist/lib/orchestrator.d.ts +172 -0
- package/dist/lib/orchestrator.d.ts.map +1 -0
- package/dist/lib/orchestrator.js +315 -0
- package/dist/lib/orchestrator.js.map +1 -0
- package/dist/lib/prompt-composer.d.ts +102 -0
- package/dist/lib/prompt-composer.d.ts.map +1 -0
- package/dist/lib/prompt-composer.js +178 -0
- package/dist/lib/prompt-composer.js.map +1 -0
- package/dist/lib/ralph-loop.d.ts +47 -0
- package/dist/lib/ralph-loop.d.ts.map +1 -0
- package/dist/lib/ralph-loop.js +114 -0
- package/dist/lib/ralph-loop.js.map +1 -0
- package/dist/lib/ws-client.d.ts +28 -0
- package/dist/lib/ws-client.d.ts.map +1 -0
- package/dist/lib/ws-client.js +113 -0
- package/dist/lib/ws-client.js.map +1 -0
- package/package.json +49 -0
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import type { LoopConfig, LoopResult } from './ralph-loop.js';
|
|
2
|
+
import type { PipelineEvent } from './event-queue.js';
|
|
3
|
+
/**
|
|
4
|
+
* Shape of a board-scope column as returned by fetchBoardScope.
|
|
5
|
+
*/
|
|
6
|
+
interface BoardColumn {
|
|
7
|
+
id: string;
|
|
8
|
+
name: string;
|
|
9
|
+
type: string;
|
|
10
|
+
goal: string;
|
|
11
|
+
ticket_count: number;
|
|
12
|
+
has_prompt: boolean;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Shape of the board-scope response.
|
|
16
|
+
*/
|
|
17
|
+
interface BoardScope {
|
|
18
|
+
scope: string;
|
|
19
|
+
board: {
|
|
20
|
+
id: string;
|
|
21
|
+
name: string;
|
|
22
|
+
};
|
|
23
|
+
columns: BoardColumn[];
|
|
24
|
+
circuit_breaker: {
|
|
25
|
+
threshold: number;
|
|
26
|
+
target_column_id: string | null;
|
|
27
|
+
};
|
|
28
|
+
tool_prefix: string;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Shape of a ticket summary in column scope.
|
|
32
|
+
*/
|
|
33
|
+
interface ColumnTicket {
|
|
34
|
+
id: string;
|
|
35
|
+
ticket_number: number;
|
|
36
|
+
title: string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Agent config from column scope.
|
|
40
|
+
*/
|
|
41
|
+
interface ColumnAgentConfig {
|
|
42
|
+
execution_mode?: string | undefined;
|
|
43
|
+
model_preference?: string | undefined;
|
|
44
|
+
max_iterations?: number | undefined;
|
|
45
|
+
max_budget_usd?: number | null | undefined;
|
|
46
|
+
concurrency?: number | undefined;
|
|
47
|
+
gutter_threshold?: number | undefined;
|
|
48
|
+
poll_interval_seconds?: number | undefined;
|
|
49
|
+
worktree?: {
|
|
50
|
+
enabled: boolean;
|
|
51
|
+
path_pattern?: string | undefined;
|
|
52
|
+
} | undefined;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Shape of the column-scope response.
|
|
56
|
+
*/
|
|
57
|
+
interface ColumnScope {
|
|
58
|
+
scope: string;
|
|
59
|
+
column: {
|
|
60
|
+
id: string;
|
|
61
|
+
name: string;
|
|
62
|
+
goal: string;
|
|
63
|
+
};
|
|
64
|
+
prompt_document: {
|
|
65
|
+
id: string;
|
|
66
|
+
title: string;
|
|
67
|
+
content: string;
|
|
68
|
+
} | null;
|
|
69
|
+
agent_config: ColumnAgentConfig | null;
|
|
70
|
+
tickets: ColumnTicket[];
|
|
71
|
+
transition_rules: string;
|
|
72
|
+
signals: unknown[];
|
|
73
|
+
field_definitions: unknown[];
|
|
74
|
+
tool_prefix: string;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Injectable dependencies for the PipelineOrchestrator.
|
|
78
|
+
* Allows full testability via dependency injection.
|
|
79
|
+
*/
|
|
80
|
+
/**
|
|
81
|
+
* A ticket that is blocked by another ticket, with its current column.
|
|
82
|
+
*/
|
|
83
|
+
interface BlockedTicket {
|
|
84
|
+
id: string;
|
|
85
|
+
column_id: string | null;
|
|
86
|
+
}
|
|
87
|
+
export interface OrchestratorDeps {
|
|
88
|
+
fetchBoardScope: (boardId: string) => Promise<BoardScope>;
|
|
89
|
+
fetchColumnScope: (columnId: string) => Promise<ColumnScope>;
|
|
90
|
+
startLoop: (ticketId: string, columnId: string, config: LoopConfig) => Promise<LoopResult>;
|
|
91
|
+
createComment: (ticketId: string, body: string) => Promise<void>;
|
|
92
|
+
createSignal: (ticketId: string, body: string) => Promise<void>;
|
|
93
|
+
claimTicket: (ticketId: string) => Promise<void>;
|
|
94
|
+
fetchBlockedTickets: (ticketId: string) => Promise<BlockedTicket[]>;
|
|
95
|
+
hasUnresolvedBlockers: (ticketId: string) => Promise<boolean>;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* PipelineOrchestrator — coordination layer for Ralph Loops.
|
|
99
|
+
*
|
|
100
|
+
* Discovers pipeline columns (has_prompt=true, type !== 'done'),
|
|
101
|
+
* spawns loops for tickets with concurrency limits per column,
|
|
102
|
+
* and handles WebSocket events for dynamic ticket arrivals.
|
|
103
|
+
*/
|
|
104
|
+
export declare class PipelineOrchestrator {
|
|
105
|
+
private boardId;
|
|
106
|
+
private projectId;
|
|
107
|
+
private deps;
|
|
108
|
+
/** Column ID -> column configuration */
|
|
109
|
+
private pipelineColumns;
|
|
110
|
+
/** Column ID -> cached column scope (from initialize) */
|
|
111
|
+
private columnScopes;
|
|
112
|
+
/** Ticket ID -> active loop tracking */
|
|
113
|
+
private activeLoops;
|
|
114
|
+
/** Column ID -> queued ticket IDs (FIFO) */
|
|
115
|
+
private loopQueues;
|
|
116
|
+
/** Ticket IDs that have been spawned or queued (prevents re-processing) */
|
|
117
|
+
private knownTickets;
|
|
118
|
+
/** Tickets deferred because they have unresolved blockers. Re-queued when a blocker reaches Done. */
|
|
119
|
+
private deferredTickets;
|
|
120
|
+
/** Ticket IDs currently in the spawning process (prevents double-spawn race) */
|
|
121
|
+
private spawning;
|
|
122
|
+
constructor(boardId: string, projectId: string, deps: OrchestratorDeps);
|
|
123
|
+
/** Returns the IDs of all discovered pipeline columns. */
|
|
124
|
+
get pipelineColumnIds(): string[];
|
|
125
|
+
/** Returns the total number of active loops. */
|
|
126
|
+
get activeLoopCount(): number;
|
|
127
|
+
/** Returns the number of queued (waiting) tickets for a column. */
|
|
128
|
+
queuedCount(columnId: string): number;
|
|
129
|
+
/**
|
|
130
|
+
* Initialize the orchestrator: fetch board scope, identify pipeline columns,
|
|
131
|
+
* and fetch column-level agent configs.
|
|
132
|
+
*/
|
|
133
|
+
initialize(): Promise<void>;
|
|
134
|
+
/**
|
|
135
|
+
* Refresh the cached column scope for a single column.
|
|
136
|
+
* Keeps stale scope on error rather than crashing.
|
|
137
|
+
*/
|
|
138
|
+
refreshColumnScope(columnId: string): Promise<void>;
|
|
139
|
+
/**
|
|
140
|
+
* Scan all pipeline columns for existing tickets and spawn loops.
|
|
141
|
+
* Refreshes column scopes before scanning to avoid stale ticket lists.
|
|
142
|
+
* Respects per-column concurrency limits — excess tickets are queued.
|
|
143
|
+
*/
|
|
144
|
+
scanAndSpawn(): Promise<void>;
|
|
145
|
+
/**
|
|
146
|
+
* Handle a pipeline event (typically from WebSocket via EventQueue).
|
|
147
|
+
*/
|
|
148
|
+
handleEvent(event: PipelineEvent): Promise<void>;
|
|
149
|
+
/**
|
|
150
|
+
* Spawn a loop for a ticket if under concurrency limit, otherwise queue it.
|
|
151
|
+
* @param skipKnownCheck - true for event-driven spawns (bypass scan dedup)
|
|
152
|
+
*/
|
|
153
|
+
private spawnOrQueue;
|
|
154
|
+
/**
|
|
155
|
+
* Start a loop and track it. Attach completion handler for cleanup + queue drain.
|
|
156
|
+
*/
|
|
157
|
+
private startTrackedLoop;
|
|
158
|
+
/**
|
|
159
|
+
* Called when a loop finishes. Cleans up tracking and drains the queue.
|
|
160
|
+
*/
|
|
161
|
+
private onLoopComplete;
|
|
162
|
+
/**
|
|
163
|
+
* Start the next queued ticket for a column if under concurrency limit.
|
|
164
|
+
*/
|
|
165
|
+
private drainQueue;
|
|
166
|
+
/**
|
|
167
|
+
* Count active loops for a specific column.
|
|
168
|
+
*/
|
|
169
|
+
private activeCountForColumn;
|
|
170
|
+
}
|
|
171
|
+
export {};
|
|
172
|
+
//# sourceMappingURL=orchestrator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orchestrator.d.ts","sourceRoot":"","sources":["../../src/lib/orchestrator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PipelineOrchestrator — coordination layer for Ralph Loops.
|
|
3
|
+
*
|
|
4
|
+
* Discovers pipeline columns (has_prompt=true, type !== 'done'),
|
|
5
|
+
* spawns loops for tickets with concurrency limits per column,
|
|
6
|
+
* and handles WebSocket events for dynamic ticket arrivals.
|
|
7
|
+
*/
|
|
8
|
+
export class PipelineOrchestrator {
|
|
9
|
+
boardId;
|
|
10
|
+
projectId;
|
|
11
|
+
deps;
|
|
12
|
+
/** Column ID -> column configuration */
|
|
13
|
+
pipelineColumns = new Map();
|
|
14
|
+
/** Column ID -> cached column scope (from initialize) */
|
|
15
|
+
columnScopes = new Map();
|
|
16
|
+
/** Ticket ID -> active loop tracking */
|
|
17
|
+
activeLoops = new Map();
|
|
18
|
+
/** Column ID -> queued ticket IDs (FIFO) */
|
|
19
|
+
loopQueues = new Map();
|
|
20
|
+
/** Ticket IDs that have been spawned or queued (prevents re-processing) */
|
|
21
|
+
knownTickets = new Set();
|
|
22
|
+
/** Tickets deferred because they have unresolved blockers. Re-queued when a blocker reaches Done. */
|
|
23
|
+
deferredTickets = new Map(); // ticketId → columnId
|
|
24
|
+
/** Ticket IDs currently in the spawning process (prevents double-spawn race) */
|
|
25
|
+
spawning = new Set();
|
|
26
|
+
constructor(boardId, projectId, deps) {
|
|
27
|
+
this.boardId = boardId;
|
|
28
|
+
this.projectId = projectId;
|
|
29
|
+
this.deps = deps;
|
|
30
|
+
}
|
|
31
|
+
/** Returns the IDs of all discovered pipeline columns. */
|
|
32
|
+
get pipelineColumnIds() {
|
|
33
|
+
return Array.from(this.pipelineColumns.keys());
|
|
34
|
+
}
|
|
35
|
+
/** Returns the total number of active loops. */
|
|
36
|
+
get activeLoopCount() {
|
|
37
|
+
return this.activeLoops.size;
|
|
38
|
+
}
|
|
39
|
+
/** Returns the number of queued (waiting) tickets for a column. */
|
|
40
|
+
queuedCount(columnId) {
|
|
41
|
+
return this.loopQueues.get(columnId)?.length ?? 0;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Initialize the orchestrator: fetch board scope, identify pipeline columns,
|
|
45
|
+
* and fetch column-level agent configs.
|
|
46
|
+
*/
|
|
47
|
+
async initialize() {
|
|
48
|
+
const boardScope = await this.deps.fetchBoardScope(this.boardId);
|
|
49
|
+
// Identify pipeline columns: has_prompt=true AND type !== 'done'
|
|
50
|
+
const pipelineCols = boardScope.columns.filter((col) => col.has_prompt && col.type !== 'done');
|
|
51
|
+
// Fetch column scope for each pipeline column to get agent_config and tickets
|
|
52
|
+
await Promise.all(pipelineCols.map(async (col) => {
|
|
53
|
+
const colScope = await this.deps.fetchColumnScope(col.id);
|
|
54
|
+
const cfg = colScope.agent_config;
|
|
55
|
+
this.pipelineColumns.set(col.id, {
|
|
56
|
+
columnId: col.id,
|
|
57
|
+
name: col.name,
|
|
58
|
+
concurrency: cfg?.concurrency ?? 1,
|
|
59
|
+
maxIterations: cfg?.max_iterations ?? 10,
|
|
60
|
+
gutterThreshold: cfg?.gutter_threshold ?? 3,
|
|
61
|
+
modelPreference: cfg?.model_preference,
|
|
62
|
+
maxBudgetUsd: cfg?.max_budget_usd,
|
|
63
|
+
worktreeEnabled: cfg?.worktree?.enabled,
|
|
64
|
+
worktreePattern: cfg?.worktree?.path_pattern,
|
|
65
|
+
});
|
|
66
|
+
// Cache column scope for scanAndSpawn
|
|
67
|
+
this.columnScopes.set(col.id, colScope);
|
|
68
|
+
// Initialize the queue for this column
|
|
69
|
+
this.loopQueues.set(col.id, []);
|
|
70
|
+
}));
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Refresh the cached column scope for a single column.
|
|
74
|
+
* Keeps stale scope on error rather than crashing.
|
|
75
|
+
*/
|
|
76
|
+
async refreshColumnScope(columnId) {
|
|
77
|
+
try {
|
|
78
|
+
const colScope = await this.deps.fetchColumnScope(columnId);
|
|
79
|
+
this.columnScopes.set(columnId, colScope);
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
// Keep stale scope rather than crash
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Scan all pipeline columns for existing tickets and spawn loops.
|
|
87
|
+
* Refreshes column scopes before scanning to avoid stale ticket lists.
|
|
88
|
+
* Respects per-column concurrency limits — excess tickets are queued.
|
|
89
|
+
*/
|
|
90
|
+
async scanAndSpawn() {
|
|
91
|
+
for (const [columnId] of this.pipelineColumns) {
|
|
92
|
+
await this.refreshColumnScope(columnId);
|
|
93
|
+
const colScope = this.columnScopes.get(columnId);
|
|
94
|
+
if (!colScope) {
|
|
95
|
+
console.error(` [scan] Column ${columnId}: no cached scope`);
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
console.error(` [scan] Column ${columnId} (${colScope.column.name}): ${String(colScope.tickets.length)} ticket(s)`);
|
|
99
|
+
for (const ticket of colScope.tickets) {
|
|
100
|
+
await this.spawnOrQueue(ticket.id, columnId);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Handle a pipeline event (typically from WebSocket via EventQueue).
|
|
106
|
+
*/
|
|
107
|
+
async handleEvent(event) {
|
|
108
|
+
switch (event.type) {
|
|
109
|
+
case 'ticket:moved':
|
|
110
|
+
case 'ticket:created': {
|
|
111
|
+
if (event.columnId && this.pipelineColumns.has(event.columnId)) {
|
|
112
|
+
await this.spawnOrQueue(event.ticketId, event.columnId, true);
|
|
113
|
+
}
|
|
114
|
+
// On any move, check if the moved ticket unblocks dependents
|
|
115
|
+
if (event.type === 'ticket:moved') {
|
|
116
|
+
try {
|
|
117
|
+
const blocked = await this.deps.fetchBlockedTickets(event.ticketId);
|
|
118
|
+
for (const dep of blocked) {
|
|
119
|
+
if (dep.id === event.ticketId)
|
|
120
|
+
continue; // skip self
|
|
121
|
+
if (dep.column_id && this.pipelineColumns.has(dep.column_id)) {
|
|
122
|
+
this.knownTickets.delete(dep.id);
|
|
123
|
+
this.deferredTickets.delete(dep.id);
|
|
124
|
+
await this.spawnOrQueue(dep.id, dep.column_id, true);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
// Best-effort
|
|
130
|
+
}
|
|
131
|
+
// Re-evaluate all deferred tickets — resolution is server-side now
|
|
132
|
+
for (const [deferredId, deferredCol] of Array.from(this.deferredTickets)) {
|
|
133
|
+
if (deferredId === event.ticketId)
|
|
134
|
+
continue; // already handled above
|
|
135
|
+
this.knownTickets.delete(deferredId);
|
|
136
|
+
this.deferredTickets.delete(deferredId);
|
|
137
|
+
await this.spawnOrQueue(deferredId, deferredCol, true);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
142
|
+
case 'ticket:deleted':
|
|
143
|
+
case 'ticket:archived': {
|
|
144
|
+
// If there's an active loop for this ticket, it will detect the
|
|
145
|
+
// change via fingerprint/404. We just clean up our tracking.
|
|
146
|
+
this.activeLoops.delete(event.ticketId);
|
|
147
|
+
this.knownTickets.delete(event.ticketId);
|
|
148
|
+
// Also remove from any queue
|
|
149
|
+
for (const [, queue] of this.loopQueues) {
|
|
150
|
+
const idx = queue.indexOf(event.ticketId);
|
|
151
|
+
if (idx !== -1) {
|
|
152
|
+
queue.splice(idx, 1);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
break;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Spawn a loop for a ticket if under concurrency limit, otherwise queue it.
|
|
161
|
+
* @param skipKnownCheck - true for event-driven spawns (bypass scan dedup)
|
|
162
|
+
*/
|
|
163
|
+
async spawnOrQueue(ticketId, columnId, skipKnownCheck = false) {
|
|
164
|
+
// Don't double-spawn
|
|
165
|
+
if (this.activeLoops.has(ticketId))
|
|
166
|
+
return;
|
|
167
|
+
// Prevent double-spawn race: two rapid events passing the activeLoops check
|
|
168
|
+
if (this.spawning.has(ticketId))
|
|
169
|
+
return;
|
|
170
|
+
// During scanAndSpawn, prevent re-processing tickets seen in other columns
|
|
171
|
+
if (!skipKnownCheck && this.knownTickets.has(ticketId))
|
|
172
|
+
return;
|
|
173
|
+
const colConfig = this.pipelineColumns.get(columnId);
|
|
174
|
+
if (!colConfig)
|
|
175
|
+
return;
|
|
176
|
+
// Count active loops for this column
|
|
177
|
+
const activeInColumn = this.activeCountForColumn(columnId);
|
|
178
|
+
// Mark as known to prevent re-processing
|
|
179
|
+
this.knownTickets.add(ticketId);
|
|
180
|
+
if (activeInColumn >= colConfig.concurrency) {
|
|
181
|
+
// Queue it
|
|
182
|
+
const queue = this.loopQueues.get(columnId);
|
|
183
|
+
if (queue && !queue.includes(ticketId)) {
|
|
184
|
+
queue.push(ticketId);
|
|
185
|
+
}
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
// Mark as in-progress spawning to prevent double-spawn race
|
|
189
|
+
this.spawning.add(ticketId);
|
|
190
|
+
// Check for unresolved blockers before spawning — skip blocked tickets
|
|
191
|
+
// entirely instead of burning agent iterations on them.
|
|
192
|
+
try {
|
|
193
|
+
const blocked = await this.deps.hasUnresolvedBlockers(ticketId);
|
|
194
|
+
if (blocked) {
|
|
195
|
+
this.spawning.delete(ticketId);
|
|
196
|
+
this.deferredTickets.set(ticketId, columnId);
|
|
197
|
+
console.error(` [skip] ${ticketId} has unresolved blockers — deferred`);
|
|
198
|
+
// Try next in queue instead
|
|
199
|
+
void this.drainQueue(columnId).catch(() => { });
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
catch {
|
|
204
|
+
// If the check fails, proceed anyway — the agent will handle it
|
|
205
|
+
}
|
|
206
|
+
// Spawn the loop
|
|
207
|
+
await this.deps.claimTicket(ticketId);
|
|
208
|
+
this.startTrackedLoop(ticketId, columnId, colConfig);
|
|
209
|
+
this.spawning.delete(ticketId);
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Start a loop and track it. Attach completion handler for cleanup + queue drain.
|
|
213
|
+
*/
|
|
214
|
+
startTrackedLoop(ticketId, columnId, config) {
|
|
215
|
+
const loopConfig = {
|
|
216
|
+
maxIterations: config.maxIterations,
|
|
217
|
+
gutterThreshold: config.gutterThreshold,
|
|
218
|
+
...(config.modelPreference !== undefined && { modelPreference: config.modelPreference }),
|
|
219
|
+
...(config.maxBudgetUsd !== undefined && { maxBudgetUsd: config.maxBudgetUsd }),
|
|
220
|
+
...(config.worktreeEnabled !== undefined && { worktreeEnabled: config.worktreeEnabled }),
|
|
221
|
+
...(config.worktreePattern !== undefined && { worktreePattern: config.worktreePattern }),
|
|
222
|
+
};
|
|
223
|
+
const promise = this.deps.startLoop(ticketId, columnId, loopConfig);
|
|
224
|
+
this.activeLoops.set(ticketId, { columnId, promise });
|
|
225
|
+
// Attach completion handler — do NOT await
|
|
226
|
+
void promise.then((result) => this.onLoopComplete(ticketId, columnId, result).catch((err) => {
|
|
227
|
+
console.error(`onLoopComplete error for ${ticketId}:`, err);
|
|
228
|
+
}), (err) => this.onLoopComplete(ticketId, columnId, {
|
|
229
|
+
reason: 'error',
|
|
230
|
+
iterations: 0,
|
|
231
|
+
gutterCount: 0,
|
|
232
|
+
lastError: err instanceof Error ? err.message : String(err),
|
|
233
|
+
}).catch((completionErr) => {
|
|
234
|
+
console.error(`onLoopComplete error for ${ticketId}:`, completionErr);
|
|
235
|
+
}));
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Called when a loop finishes. Cleans up tracking and drains the queue.
|
|
239
|
+
*/
|
|
240
|
+
async onLoopComplete(ticketId, columnId, result) {
|
|
241
|
+
this.activeLoops.delete(ticketId);
|
|
242
|
+
// Write reason-specific comment
|
|
243
|
+
let comment;
|
|
244
|
+
switch (result.reason) {
|
|
245
|
+
case 'moved':
|
|
246
|
+
comment = `✓ Pipeline agent advanced ticket after ${result.iterations} iteration(s).`;
|
|
247
|
+
break;
|
|
248
|
+
case 'max_iterations':
|
|
249
|
+
comment = `Pipeline agent reached iteration limit (${result.iterations}) without advancing. Manual review needed.`;
|
|
250
|
+
break;
|
|
251
|
+
case 'stalled':
|
|
252
|
+
comment = `Pipeline agent stalled — no progress for ${result.gutterCount} consecutive iterations (of ${result.iterations} total). Manual review needed.`;
|
|
253
|
+
break;
|
|
254
|
+
case 'error':
|
|
255
|
+
comment = `Pipeline agent encountered an error after ${result.iterations} iteration(s): ${result.lastError ?? 'unknown error'}`;
|
|
256
|
+
break;
|
|
257
|
+
case 'stopped':
|
|
258
|
+
comment = `Pipeline agent was stopped externally after ${result.iterations} iteration(s).`;
|
|
259
|
+
break;
|
|
260
|
+
}
|
|
261
|
+
await this.deps.createComment(ticketId, comment).catch(() => { });
|
|
262
|
+
// Create signal for failure exits so future agents inherit the context
|
|
263
|
+
if (result.reason === 'stalled') {
|
|
264
|
+
await this.deps.createSignal(ticketId, `Previous pipeline run stalled after ${result.iterations} iterations with no progress. Review comments for details before retrying.`).catch(() => { });
|
|
265
|
+
}
|
|
266
|
+
else if (result.reason === 'error') {
|
|
267
|
+
await this.deps.createSignal(ticketId, `Previous pipeline run failed after ${result.iterations} iteration(s): ${result.lastError ?? 'unknown error'}. Review comments for details before retrying.`).catch(() => { });
|
|
268
|
+
}
|
|
269
|
+
// Drain queue: start next ticket for this column
|
|
270
|
+
await this.drainQueue(columnId);
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Start the next queued ticket for a column if under concurrency limit.
|
|
274
|
+
*/
|
|
275
|
+
async drainQueue(columnId) {
|
|
276
|
+
const colConfig = this.pipelineColumns.get(columnId);
|
|
277
|
+
if (!colConfig)
|
|
278
|
+
return;
|
|
279
|
+
const queue = this.loopQueues.get(columnId);
|
|
280
|
+
if (!queue || queue.length === 0)
|
|
281
|
+
return;
|
|
282
|
+
const activeInColumn = this.activeCountForColumn(columnId);
|
|
283
|
+
if (activeInColumn >= colConfig.concurrency)
|
|
284
|
+
return;
|
|
285
|
+
// Find the first unblocked ticket in the queue
|
|
286
|
+
while (queue.length > 0) {
|
|
287
|
+
const nextTicketId = queue.shift();
|
|
288
|
+
try {
|
|
289
|
+
const blocked = await this.deps.hasUnresolvedBlockers(nextTicketId);
|
|
290
|
+
if (blocked) {
|
|
291
|
+
this.deferredTickets.set(nextTicketId, columnId);
|
|
292
|
+
continue; // skip, try next
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
catch {
|
|
296
|
+
// If check fails, proceed anyway
|
|
297
|
+
}
|
|
298
|
+
await this.deps.claimTicket(nextTicketId);
|
|
299
|
+
this.startTrackedLoop(nextTicketId, columnId, colConfig);
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Count active loops for a specific column.
|
|
305
|
+
*/
|
|
306
|
+
activeCountForColumn(columnId) {
|
|
307
|
+
let count = 0;
|
|
308
|
+
for (const [, loop] of this.activeLoops) {
|
|
309
|
+
if (loop.columnId === columnId)
|
|
310
|
+
count++;
|
|
311
|
+
}
|
|
312
|
+
return count;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
//# sourceMappingURL=orchestrator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orchestrator.js","sourceRoot":"","sources":["../../src/lib/orchestrator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import type { AgentConfig } from '@kantban/types';
|
|
2
|
+
interface ColumnContext {
|
|
3
|
+
scope: 'column';
|
|
4
|
+
column: {
|
|
5
|
+
id: string;
|
|
6
|
+
name: string;
|
|
7
|
+
goal: string | null;
|
|
8
|
+
};
|
|
9
|
+
prompt_document: {
|
|
10
|
+
id: string;
|
|
11
|
+
title: string;
|
|
12
|
+
content: string;
|
|
13
|
+
} | null;
|
|
14
|
+
agent_config: AgentConfig | null;
|
|
15
|
+
tickets: Array<{
|
|
16
|
+
id: string;
|
|
17
|
+
ticket_number: number;
|
|
18
|
+
title: string;
|
|
19
|
+
}>;
|
|
20
|
+
transition_rules: string;
|
|
21
|
+
signals: string[];
|
|
22
|
+
field_definitions: Array<{
|
|
23
|
+
id: string;
|
|
24
|
+
name: string;
|
|
25
|
+
type: string;
|
|
26
|
+
}>;
|
|
27
|
+
tool_prefix: string;
|
|
28
|
+
}
|
|
29
|
+
interface TicketContext {
|
|
30
|
+
scope: 'ticket';
|
|
31
|
+
ticket: {
|
|
32
|
+
id: string;
|
|
33
|
+
ticket_number: number;
|
|
34
|
+
title: string;
|
|
35
|
+
description: string;
|
|
36
|
+
backward_transitions: number;
|
|
37
|
+
assignee: {
|
|
38
|
+
id: string;
|
|
39
|
+
name: string;
|
|
40
|
+
} | null;
|
|
41
|
+
column: {
|
|
42
|
+
id: string;
|
|
43
|
+
name: string;
|
|
44
|
+
type: string;
|
|
45
|
+
} | null;
|
|
46
|
+
};
|
|
47
|
+
field_values: Array<{
|
|
48
|
+
field_name: string;
|
|
49
|
+
value: unknown;
|
|
50
|
+
}>;
|
|
51
|
+
transitions: Array<{
|
|
52
|
+
from: string | null;
|
|
53
|
+
to: string;
|
|
54
|
+
handoff: unknown;
|
|
55
|
+
timestamp: string;
|
|
56
|
+
}>;
|
|
57
|
+
comments: Array<{
|
|
58
|
+
author: string;
|
|
59
|
+
body: string;
|
|
60
|
+
created_at: string;
|
|
61
|
+
}>;
|
|
62
|
+
ticket_links: Array<{
|
|
63
|
+
direction: 'outward' | 'inward';
|
|
64
|
+
link_type: 'blocks' | 'relates_to' | 'duplicates';
|
|
65
|
+
ticket_id: string;
|
|
66
|
+
ticket_number: number;
|
|
67
|
+
title: string;
|
|
68
|
+
column_name: string | null;
|
|
69
|
+
resolved: boolean;
|
|
70
|
+
}>;
|
|
71
|
+
parent: {
|
|
72
|
+
id: string;
|
|
73
|
+
ticket_number: number;
|
|
74
|
+
title: string;
|
|
75
|
+
} | null;
|
|
76
|
+
children: Array<{
|
|
77
|
+
id: string;
|
|
78
|
+
ticket_number: number;
|
|
79
|
+
title: string;
|
|
80
|
+
column_name: string | null;
|
|
81
|
+
}>;
|
|
82
|
+
signals: string[];
|
|
83
|
+
linked_documents: Array<{
|
|
84
|
+
id: string;
|
|
85
|
+
title: string;
|
|
86
|
+
content?: string;
|
|
87
|
+
truncated?: boolean;
|
|
88
|
+
}>;
|
|
89
|
+
transition_rules: string;
|
|
90
|
+
dependency_requirements: string;
|
|
91
|
+
tool_prefix: string;
|
|
92
|
+
}
|
|
93
|
+
interface IterationMeta {
|
|
94
|
+
iteration: number;
|
|
95
|
+
maxIterations: number;
|
|
96
|
+
projectId: string;
|
|
97
|
+
gutterCount: number;
|
|
98
|
+
gutterThreshold: number;
|
|
99
|
+
}
|
|
100
|
+
export type { ColumnContext, TicketContext };
|
|
101
|
+
export declare function composePrompt(columnContext: ColumnContext, ticketContext: TicketContext, meta: IterationMeta): string;
|
|
102
|
+
//# sourceMappingURL=prompt-composer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt-composer.d.ts","sourceRoot":"","sources":["../../src/lib/prompt-composer.ts"],"names":[],"mappings":"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"}
|