@supaku/agentfactory-linear 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,43 @@
1
+ import type { RetryConfig } from './types';
2
+ /**
3
+ * Default retry configuration
4
+ */
5
+ export declare const DEFAULT_RETRY_CONFIG: Required<RetryConfig>;
6
+ /**
7
+ * Sleep utility for async delays
8
+ */
9
+ export declare function sleep(ms: number): Promise<void>;
10
+ /**
11
+ * Calculate delay for a given retry attempt with exponential backoff
12
+ */
13
+ export declare function calculateDelay(attempt: number, config: Required<RetryConfig>): number;
14
+ /**
15
+ * Retry context passed to callbacks
16
+ */
17
+ export interface RetryContext {
18
+ attempt: number;
19
+ maxRetries: number;
20
+ lastError?: Error;
21
+ delay: number;
22
+ }
23
+ /**
24
+ * Callback for retry events
25
+ */
26
+ export type RetryCallback = (context: RetryContext) => void;
27
+ /**
28
+ * Options for withRetry function
29
+ */
30
+ export interface WithRetryOptions {
31
+ config?: RetryConfig;
32
+ onRetry?: RetryCallback;
33
+ shouldRetry?: (error: unknown) => boolean;
34
+ }
35
+ /**
36
+ * Execute an async function with exponential backoff retry logic
37
+ */
38
+ export declare function withRetry<T>(fn: () => Promise<T>, options?: WithRetryOptions): Promise<T>;
39
+ /**
40
+ * Create a retry wrapper with pre-configured options
41
+ */
42
+ export declare function createRetryWrapper(defaultOptions?: WithRetryOptions): <T>(fn: () => Promise<T>, options?: WithRetryOptions) => Promise<T>;
43
+ //# sourceMappingURL=retry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../../src/retry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAG1C;;GAEG;AACH,eAAO,MAAM,oBAAoB,EAAE,QAAQ,CAAC,WAAW,CAMtD,CAAA;AAED;;GAEG;AACH,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/C;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,QAAQ,CAAC,WAAW,CAAC,GAC5B,MAAM,CAIR;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,KAAK,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;CACd;AAED;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,EAAE,YAAY,KAAK,IAAI,CAAA;AAE3D;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,OAAO,CAAC,EAAE,aAAa,CAAA;IACvB,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAA;CAC1C;AAED;;GAEG;AACH,wBAAsB,SAAS,CAAC,CAAC,EAC/B,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,CAAC,CAAC,CAsCZ;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,cAAc,GAAE,gBAAqB,IACrD,CAAC,EAChB,IAAI,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,UAAU,gBAAgB,KACzB,OAAO,CAAC,CAAC,CAAC,CAUd"}
@@ -0,0 +1,73 @@
1
+ import { isRetryableError } from './errors';
2
+ /**
3
+ * Default retry configuration
4
+ */
5
+ export const DEFAULT_RETRY_CONFIG = {
6
+ maxRetries: 3,
7
+ initialDelayMs: 1000,
8
+ backoffMultiplier: 2,
9
+ maxDelayMs: 10000,
10
+ retryableStatusCodes: [429, 500, 502, 503, 504],
11
+ };
12
+ /**
13
+ * Sleep utility for async delays
14
+ */
15
+ export function sleep(ms) {
16
+ return new Promise((resolve) => setTimeout(resolve, ms));
17
+ }
18
+ /**
19
+ * Calculate delay for a given retry attempt with exponential backoff
20
+ */
21
+ export function calculateDelay(attempt, config) {
22
+ const delay = config.initialDelayMs * Math.pow(config.backoffMultiplier, attempt);
23
+ return Math.min(delay, config.maxDelayMs);
24
+ }
25
+ /**
26
+ * Execute an async function with exponential backoff retry logic
27
+ */
28
+ export async function withRetry(fn, options = {}) {
29
+ const config = {
30
+ ...DEFAULT_RETRY_CONFIG,
31
+ ...options.config,
32
+ };
33
+ const shouldRetry = options.shouldRetry ??
34
+ ((error) => isRetryableError(error, config.retryableStatusCodes));
35
+ let lastError = new Error('Unknown error');
36
+ for (let attempt = 0; attempt <= config.maxRetries; attempt++) {
37
+ try {
38
+ return await fn();
39
+ }
40
+ catch (error) {
41
+ lastError = error instanceof Error ? error : new Error(String(error));
42
+ if (attempt === config.maxRetries || !shouldRetry(error)) {
43
+ throw lastError;
44
+ }
45
+ const delay = calculateDelay(attempt, config);
46
+ if (options.onRetry) {
47
+ options.onRetry({
48
+ attempt,
49
+ maxRetries: config.maxRetries,
50
+ lastError,
51
+ delay,
52
+ });
53
+ }
54
+ await sleep(delay);
55
+ }
56
+ }
57
+ throw lastError;
58
+ }
59
+ /**
60
+ * Create a retry wrapper with pre-configured options
61
+ */
62
+ export function createRetryWrapper(defaultOptions = {}) {
63
+ return function (fn, options) {
64
+ return withRetry(fn, {
65
+ ...defaultOptions,
66
+ ...options,
67
+ config: {
68
+ ...defaultOptions.config,
69
+ ...options?.config,
70
+ },
71
+ });
72
+ };
73
+ }
@@ -0,0 +1,412 @@
1
+ import type { LinearClient } from '@linear/sdk';
2
+ /**
3
+ * AgentSession states as defined by Linear Agent SDK
4
+ */
5
+ export type AgentSessionState = 'pending' | 'active' | 'error' | 'awaitingInput' | 'complete';
6
+ /**
7
+ * AgentActivity types as defined by Linear Agent API
8
+ */
9
+ export type AgentActivityType = 'thought' | 'action' | 'response' | 'elicitation' | 'error' | 'prompt';
10
+ /**
11
+ * AgentActivity signals - modifiers that provide additional instructions
12
+ * on how the activity should be interpreted
13
+ */
14
+ export type AgentActivitySignal = 'auth' | 'continue' | 'select' | 'stop';
15
+ /**
16
+ * Content for a thought activity - reasoning steps
17
+ */
18
+ export interface ThoughtActivityContent {
19
+ type: 'thought';
20
+ body: string;
21
+ }
22
+ /**
23
+ * Content for an action activity - tool calls
24
+ */
25
+ export interface ActionActivityContent {
26
+ type: 'action';
27
+ action: string;
28
+ parameter: string;
29
+ result?: string;
30
+ }
31
+ /**
32
+ * Content for a response activity - final responses
33
+ */
34
+ export interface ResponseActivityContent {
35
+ type: 'response';
36
+ body: string;
37
+ }
38
+ /**
39
+ * Content for an elicitation activity - asking for clarification
40
+ */
41
+ export interface ElicitationActivityContent {
42
+ type: 'elicitation';
43
+ body: string;
44
+ }
45
+ /**
46
+ * Content for an error activity - error reporting
47
+ */
48
+ export interface ErrorActivityContent {
49
+ type: 'error';
50
+ body: string;
51
+ }
52
+ /**
53
+ * Content for a prompt activity - prompts/instructions
54
+ */
55
+ export interface PromptActivityContent {
56
+ type: 'prompt';
57
+ body: string;
58
+ }
59
+ /**
60
+ * Union type for all activity content types
61
+ */
62
+ export type AgentActivityContentPayload = ThoughtActivityContent | ActionActivityContent | ResponseActivityContent | ElicitationActivityContent | ErrorActivityContent | PromptActivityContent;
63
+ /**
64
+ * Input for creating an agent activity via the native Linear API
65
+ */
66
+ export interface AgentActivityCreateInput {
67
+ agentSessionId: string;
68
+ content: AgentActivityContentPayload;
69
+ ephemeral?: boolean;
70
+ id?: string;
71
+ signal?: AgentActivitySignal;
72
+ }
73
+ /**
74
+ * Result of creating an agent activity
75
+ */
76
+ export interface AgentActivityResult {
77
+ success: boolean;
78
+ activityId?: string;
79
+ }
80
+ /**
81
+ * Legacy activity content for backward compatibility
82
+ * @deprecated Use AgentActivityContentPayload instead
83
+ */
84
+ export interface AgentActivityContent {
85
+ text: string;
86
+ metadata?: Record<string, unknown>;
87
+ }
88
+ /**
89
+ * Configuration for creating an agent activity (internal use)
90
+ */
91
+ export interface CreateActivityOptions {
92
+ type: AgentActivityType;
93
+ content: AgentActivityContent;
94
+ ephemeral?: boolean;
95
+ signals?: AgentSignals;
96
+ }
97
+ /**
98
+ * AgentPlan item states
99
+ */
100
+ export type AgentPlanItemState = 'pending' | 'inProgress' | 'completed' | 'canceled';
101
+ /**
102
+ * Linear's native plan item status values
103
+ * @see https://linear.app/developers/agents
104
+ */
105
+ export type LinearPlanStatus = 'pending' | 'inProgress' | 'completed' | 'canceled';
106
+ /**
107
+ * Linear's native plan item structure for agentSessionUpdate mutation
108
+ * @see https://linear.app/developers/agents
109
+ */
110
+ export interface LinearPlanItem {
111
+ /** The task description */
112
+ content: string;
113
+ /** Current status of the task */
114
+ status: LinearPlanStatus;
115
+ }
116
+ /**
117
+ * A single item in the agent's plan (internal representation)
118
+ * Supports nested children for more detailed task tracking
119
+ */
120
+ export interface AgentPlanItem {
121
+ id: string;
122
+ title: string;
123
+ state: AgentPlanItemState;
124
+ details?: string;
125
+ children?: AgentPlanItem[];
126
+ }
127
+ /**
128
+ * Full agent plan structure (internal representation)
129
+ */
130
+ export interface AgentPlan {
131
+ items: AgentPlanItem[];
132
+ }
133
+ /**
134
+ * Optional metadata for activity interpretation
135
+ */
136
+ export interface AgentSignals {
137
+ toolName?: string;
138
+ toolInput?: Record<string, unknown>;
139
+ toolOutput?: unknown;
140
+ error?: {
141
+ message: string;
142
+ code?: string;
143
+ stack?: string;
144
+ };
145
+ progress?: number;
146
+ [key: string]: unknown;
147
+ }
148
+ /**
149
+ * Configuration for the Linear Agent Client
150
+ */
151
+ export interface LinearAgentClientConfig {
152
+ apiKey: string;
153
+ baseUrl?: string;
154
+ retry?: RetryConfig;
155
+ }
156
+ /**
157
+ * Retry configuration with exponential backoff
158
+ */
159
+ export interface RetryConfig {
160
+ maxRetries?: number;
161
+ initialDelayMs?: number;
162
+ backoffMultiplier?: number;
163
+ maxDelayMs?: number;
164
+ retryableStatusCodes?: number[];
165
+ }
166
+ /**
167
+ * Standard Linear workflow states
168
+ */
169
+ export type LinearWorkflowStatus = 'Backlog' | 'Started' | 'Finished' | 'Delivered' | 'Accepted' | 'Rejected' | 'Canceled';
170
+ /**
171
+ * Type of agent work being performed based on issue status
172
+ *
173
+ * | Issue Status | Work Type | Agent Role |
174
+ * |--------------|------------------------|-----------------------------------------------|
175
+ * | Icebox | research | Research/story-writer |
176
+ * | Icebox | backlog-creation | Create backlog issues from research |
177
+ * | Backlog | development | Developer agents |
178
+ * | Backlog | coordination | Coordinate sub-issue execution |
179
+ * | Started | inflight | Developer (resume/continue) |
180
+ * | Finished | qa | QA agents |
181
+ * | Finished | qa-coordination | Coordinate QA across sub-issues |
182
+ * | Delivered | acceptance | Acceptance testing |
183
+ * | Delivered | acceptance-coordination| Coordinate acceptance across sub-issues |
184
+ * | Rejected | refinement | Refine and return to Backlog |
185
+ */
186
+ export type AgentWorkType = 'research' | 'backlog-creation' | 'development' | 'inflight' | 'qa' | 'acceptance' | 'refinement' | 'coordination' | 'qa-coordination' | 'acceptance-coordination';
187
+ /**
188
+ * Mapping from Linear issue status to agent work type
189
+ */
190
+ export declare const STATUS_WORK_TYPE_MAP: Record<string, AgentWorkType>;
191
+ /**
192
+ * Terminal statuses where no agent work is needed
193
+ * Issues in these states are considered complete and should not be processed
194
+ */
195
+ export declare const TERMINAL_STATUSES: readonly ["Accepted", "Canceled", "Duplicate"];
196
+ export type TerminalStatus = typeof TERMINAL_STATUSES[number];
197
+ /**
198
+ * Status to transition to when agent session STARTS
199
+ * null means no transition on start
200
+ */
201
+ export declare const WORK_TYPE_START_STATUS: Record<AgentWorkType, LinearWorkflowStatus | null>;
202
+ /**
203
+ * Status to transition to when agent session COMPLETES successfully
204
+ * null means no auto-transition on completion
205
+ */
206
+ export declare const WORK_TYPE_COMPLETE_STATUS: Record<AgentWorkType, LinearWorkflowStatus | null>;
207
+ /**
208
+ * Status to transition to when agent work FAILS (e.g., QA rejected)
209
+ * null means no auto-transition on failure (stays in current status)
210
+ */
211
+ export declare const WORK_TYPE_FAIL_STATUS: Record<AgentWorkType, LinearWorkflowStatus | null>;
212
+ /**
213
+ * Allowed statuses for each work type
214
+ * Used to validate that an agent isn't assigned to an issue in the wrong status
215
+ */
216
+ export declare const WORK_TYPE_ALLOWED_STATUSES: Record<AgentWorkType, string[]>;
217
+ /**
218
+ * Valid work types for each status (reverse of WORK_TYPE_ALLOWED_STATUSES)
219
+ * Used to constrain keyword detection to only valid options for the current status
220
+ *
221
+ * For example:
222
+ * - Icebox issues can use keywords to choose between 'research' and 'backlog-creation'
223
+ * - Backlog issues only have 'development' as valid, so keywords won't change work type
224
+ * but could still provide agent specialization hints
225
+ */
226
+ export declare const STATUS_VALID_WORK_TYPES: Record<string, AgentWorkType[]>;
227
+ /**
228
+ * Get valid work types for a given status
229
+ * Returns empty array if status is unknown
230
+ */
231
+ export declare function getValidWorkTypesForStatus(status: string): AgentWorkType[];
232
+ /**
233
+ * Result of work type validation
234
+ */
235
+ export interface WorkTypeValidationResult {
236
+ valid: boolean;
237
+ error?: string;
238
+ }
239
+ /**
240
+ * Validate that a work type is appropriate for an issue's current status
241
+ *
242
+ * @param workType - The work type being assigned
243
+ * @param issueStatus - The current status of the issue
244
+ * @returns Validation result with error message if invalid
245
+ */
246
+ export declare function validateWorkTypeForStatus(workType: AgentWorkType, issueStatus: string): WorkTypeValidationResult;
247
+ /**
248
+ * Mapping of status names to their Linear state IDs
249
+ */
250
+ export interface StatusMapping {
251
+ [statusName: string]: string;
252
+ }
253
+ /**
254
+ * Configuration for creating/managing an agent session
255
+ */
256
+ export interface AgentSessionConfig {
257
+ client: LinearClient;
258
+ issueId: string;
259
+ sessionId?: string;
260
+ autoTransition?: boolean;
261
+ /**
262
+ * Type of work being performed.
263
+ * - 'development': Normal development work (transitions to Started on start)
264
+ * - 'qa': QA validation work (stays at Finished until QA passes, then Delivered)
265
+ * Defaults to 'development'.
266
+ */
267
+ workType?: AgentWorkType;
268
+ }
269
+ /**
270
+ * Result of session operations
271
+ */
272
+ export interface SessionOperationResult {
273
+ success: boolean;
274
+ sessionId?: string;
275
+ error?: Error;
276
+ }
277
+ /**
278
+ * External URL associated with an agent session
279
+ */
280
+ export interface AgentSessionExternalUrl {
281
+ /** Label for the URL (e.g., "Dashboard", "Logs") */
282
+ label: string;
283
+ /** The URL of the external resource */
284
+ url: string;
285
+ }
286
+ /**
287
+ * Input for updating an agent session via the Linear API
288
+ */
289
+ export interface AgentSessionUpdateInput {
290
+ /** The agent session ID to update */
291
+ sessionId: string;
292
+ /** External URLs linking to agent dashboard/logs */
293
+ externalUrls?: AgentSessionExternalUrl[];
294
+ /** External link URL (single, for backward compatibility) */
295
+ externalLink?: string;
296
+ /** Plan array showing agent execution strategy (Linear's native format) */
297
+ plan?: LinearPlanItem[];
298
+ }
299
+ /**
300
+ * Result of updating an agent session
301
+ */
302
+ export interface AgentSessionUpdateResult {
303
+ success: boolean;
304
+ sessionId?: string;
305
+ }
306
+ /**
307
+ * Input for creating an agent session on an issue via the Linear API
308
+ * @see https://linear.app/developers/agents
309
+ */
310
+ export interface AgentSessionCreateOnIssueInput {
311
+ /** The issue ID (UUID) or identifier (e.g., 'SUP-123') to create the session on */
312
+ issueId: string;
313
+ /** External URLs linking to agent dashboard/logs */
314
+ externalUrls?: AgentSessionExternalUrl[];
315
+ /** External link URL (single, for backward compatibility) */
316
+ externalLink?: string;
317
+ }
318
+ /**
319
+ * Result of creating an agent session on an issue
320
+ */
321
+ export interface AgentSessionCreateResult {
322
+ success: boolean;
323
+ /** The ID of the created agent session */
324
+ sessionId?: string;
325
+ }
326
+ /**
327
+ * Linear issue relationship types
328
+ * @see https://linear.app/developers/sdk
329
+ */
330
+ export type IssueRelationType = 'related' | 'blocks' | 'duplicate';
331
+ /**
332
+ * Input for creating an issue relation
333
+ */
334
+ export interface IssueRelationCreateInput {
335
+ issueId: string;
336
+ relatedIssueId: string;
337
+ type: IssueRelationType;
338
+ }
339
+ /**
340
+ * Result of creating/deleting an issue relation
341
+ */
342
+ export interface IssueRelationResult {
343
+ success: boolean;
344
+ relationId?: string;
345
+ }
346
+ /**
347
+ * Batch result for creating multiple relations
348
+ */
349
+ export interface IssueRelationBatchResult {
350
+ success: boolean;
351
+ relationIds: string[];
352
+ errors: Array<{
353
+ targetIssueId: string;
354
+ error: string;
355
+ }>;
356
+ }
357
+ /**
358
+ * Sub-issue with its blocking relations for dependency graph building
359
+ */
360
+ export interface SubIssueGraphNode {
361
+ issue: {
362
+ id: string;
363
+ identifier: string;
364
+ title: string;
365
+ description?: string;
366
+ status?: string;
367
+ priority: number;
368
+ labels: string[];
369
+ url: string;
370
+ };
371
+ /** Identifiers of issues that block this sub-issue */
372
+ blockedBy: string[];
373
+ /** Identifiers of issues that this sub-issue blocks */
374
+ blocks: string[];
375
+ }
376
+ /**
377
+ * Result of getSubIssueGraph - the complete dependency graph for a parent issue
378
+ */
379
+ export interface SubIssueGraph {
380
+ parentId: string;
381
+ parentIdentifier: string;
382
+ subIssues: SubIssueGraphNode[];
383
+ }
384
+ /**
385
+ * Lightweight sub-issue status info (no blocking relations)
386
+ * Used by QA and acceptance agents to validate sub-issue completion
387
+ */
388
+ export interface SubIssueStatus {
389
+ identifier: string;
390
+ title: string;
391
+ status: string;
392
+ }
393
+ /**
394
+ * Representation of an issue relation
395
+ */
396
+ export interface IssueRelationInfo {
397
+ id: string;
398
+ type: string;
399
+ issueId: string;
400
+ issueIdentifier?: string;
401
+ relatedIssueId: string;
402
+ relatedIssueIdentifier?: string;
403
+ createdAt: Date;
404
+ }
405
+ /**
406
+ * Result of querying issue relations
407
+ */
408
+ export interface IssueRelationsResult {
409
+ relations: IssueRelationInfo[];
410
+ inverseRelations: IssueRelationInfo[];
411
+ }
412
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,121 @@
1
+ /**
2
+ * Mapping from Linear issue status to agent work type
3
+ */
4
+ export const STATUS_WORK_TYPE_MAP = {
5
+ 'Icebox': 'research',
6
+ 'Backlog': 'development',
7
+ 'Started': 'inflight',
8
+ 'Finished': 'qa',
9
+ 'Delivered': 'acceptance',
10
+ 'Rejected': 'refinement',
11
+ };
12
+ /**
13
+ * Terminal statuses where no agent work is needed
14
+ * Issues in these states are considered complete and should not be processed
15
+ */
16
+ export const TERMINAL_STATUSES = ['Accepted', 'Canceled', 'Duplicate'];
17
+ /**
18
+ * Status to transition to when agent session STARTS
19
+ * null means no transition on start
20
+ */
21
+ export const WORK_TYPE_START_STATUS = {
22
+ 'research': null, // No transition from Icebox on start
23
+ 'backlog-creation': null, // No transition from Icebox on start
24
+ 'development': 'Started', // Backlog -> Started when agent begins
25
+ 'inflight': null, // Already Started, no change
26
+ 'qa': null, // Already Finished
27
+ 'acceptance': null, // Already Delivered
28
+ 'refinement': null, // Already Rejected
29
+ 'coordination': 'Started', // Backlog -> Started when coordinator begins
30
+ 'qa-coordination': null, // Already Finished
31
+ 'acceptance-coordination': null, // Already Delivered
32
+ };
33
+ /**
34
+ * Status to transition to when agent session COMPLETES successfully
35
+ * null means no auto-transition on completion
36
+ */
37
+ export const WORK_TYPE_COMPLETE_STATUS = {
38
+ 'research': null, // No auto-transition, user moves to Backlog
39
+ 'backlog-creation': null, // Issues created in Backlog, source stays in Icebox
40
+ 'development': 'Finished', // Started -> Finished when work done
41
+ 'inflight': 'Finished', // Started -> Finished when work done
42
+ 'qa': 'Delivered', // Finished -> Delivered on QA pass
43
+ 'acceptance': 'Accepted', // Delivered -> Accepted on acceptance pass
44
+ 'refinement': 'Backlog', // Rejected -> Backlog after refinement
45
+ 'coordination': 'Finished', // Started -> Finished when all sub-issues done
46
+ 'qa-coordination': 'Delivered', // Finished -> Delivered when QA coordination passes
47
+ 'acceptance-coordination': 'Accepted', // Delivered -> Accepted when acceptance coordination passes
48
+ };
49
+ /**
50
+ * Status to transition to when agent work FAILS (e.g., QA rejected)
51
+ * null means no auto-transition on failure (stays in current status)
52
+ */
53
+ export const WORK_TYPE_FAIL_STATUS = {
54
+ 'research': null,
55
+ 'backlog-creation': null,
56
+ 'development': null,
57
+ 'inflight': null,
58
+ 'qa': 'Rejected', // QA failure -> Rejected (rejection handler diagnoses next steps)
59
+ 'acceptance': 'Rejected', // Acceptance failure -> Rejected (rejection handler diagnoses next steps)
60
+ 'refinement': null,
61
+ 'coordination': null,
62
+ 'qa-coordination': 'Rejected', // QA coordination failure -> Rejected
63
+ 'acceptance-coordination': 'Rejected', // Acceptance coordination failure -> Rejected
64
+ };
65
+ /**
66
+ * Allowed statuses for each work type
67
+ * Used to validate that an agent isn't assigned to an issue in the wrong status
68
+ */
69
+ export const WORK_TYPE_ALLOWED_STATUSES = {
70
+ 'research': ['Icebox'],
71
+ 'backlog-creation': ['Icebox'],
72
+ 'development': ['Backlog'],
73
+ 'inflight': ['Started'],
74
+ 'qa': ['Finished'],
75
+ 'acceptance': ['Delivered'],
76
+ 'refinement': ['Rejected'],
77
+ 'coordination': ['Backlog', 'Started'],
78
+ 'qa-coordination': ['Finished'],
79
+ 'acceptance-coordination': ['Delivered'],
80
+ };
81
+ /**
82
+ * Valid work types for each status (reverse of WORK_TYPE_ALLOWED_STATUSES)
83
+ * Used to constrain keyword detection to only valid options for the current status
84
+ *
85
+ * For example:
86
+ * - Icebox issues can use keywords to choose between 'research' and 'backlog-creation'
87
+ * - Backlog issues only have 'development' as valid, so keywords won't change work type
88
+ * but could still provide agent specialization hints
89
+ */
90
+ export const STATUS_VALID_WORK_TYPES = {
91
+ 'Icebox': ['research', 'backlog-creation'],
92
+ 'Backlog': ['development', 'coordination'],
93
+ 'Started': ['inflight'],
94
+ 'Finished': ['qa', 'qa-coordination'],
95
+ 'Delivered': ['acceptance', 'acceptance-coordination'],
96
+ 'Rejected': ['refinement'],
97
+ };
98
+ /**
99
+ * Get valid work types for a given status
100
+ * Returns empty array if status is unknown
101
+ */
102
+ export function getValidWorkTypesForStatus(status) {
103
+ return STATUS_VALID_WORK_TYPES[status] ?? [];
104
+ }
105
+ /**
106
+ * Validate that a work type is appropriate for an issue's current status
107
+ *
108
+ * @param workType - The work type being assigned
109
+ * @param issueStatus - The current status of the issue
110
+ * @returns Validation result with error message if invalid
111
+ */
112
+ export function validateWorkTypeForStatus(workType, issueStatus) {
113
+ const allowedStatuses = WORK_TYPE_ALLOWED_STATUSES[workType];
114
+ if (!allowedStatuses.includes(issueStatus)) {
115
+ return {
116
+ valid: false,
117
+ error: `Cannot assign ${workType} work to issue in ${issueStatus} status. Expected: ${allowedStatuses.join(', ')}`,
118
+ };
119
+ }
120
+ return { valid: true };
121
+ }