edsger 0.11.0 → 0.12.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.
- package/dist/api/features/__tests__/feature-utils.test.js +38 -38
- package/dist/api/features/__tests__/status-updater.test.js +6 -6
- package/dist/api/features/feature-utils.d.ts +2 -2
- package/dist/api/features/feature-utils.js +6 -6
- package/dist/commands/workflow/core/feature-filter.js +1 -1
- package/dist/commands/workflow/core/workflow-logger.js +1 -1
- package/dist/commands/workflow/processor.d.ts +1 -1
- package/dist/commands/workflow/processor.js +3 -3
- package/dist/config/__tests__/feature-status.test.js +1 -1
- package/dist/config/feature-status.js +1 -1
- package/dist/types/index.d.ts +1 -1
- package/package.json +1 -1
|
@@ -11,21 +11,21 @@ describe('Feature Utils', () => {
|
|
|
11
11
|
{
|
|
12
12
|
id: '1',
|
|
13
13
|
name: 'Feature 1',
|
|
14
|
-
status: '
|
|
14
|
+
status: 'ready_for_ai',
|
|
15
15
|
product_id: 'test-product',
|
|
16
16
|
updated_at: '2024-01-15T10:00:00Z',
|
|
17
17
|
},
|
|
18
18
|
{
|
|
19
19
|
id: '2',
|
|
20
20
|
name: 'Feature 2',
|
|
21
|
-
status: '
|
|
21
|
+
status: 'ready_for_ai',
|
|
22
22
|
product_id: 'test-product',
|
|
23
23
|
updated_at: '2024-01-10T10:00:00Z',
|
|
24
24
|
},
|
|
25
25
|
{
|
|
26
26
|
id: '3',
|
|
27
27
|
name: 'Feature 3',
|
|
28
|
-
status: '
|
|
28
|
+
status: 'ready_for_ai',
|
|
29
29
|
product_id: 'test-product',
|
|
30
30
|
updated_at: '2024-01-20T10:00:00Z',
|
|
31
31
|
},
|
|
@@ -41,21 +41,21 @@ describe('Feature Utils', () => {
|
|
|
41
41
|
{
|
|
42
42
|
id: '1',
|
|
43
43
|
name: 'Feature 1',
|
|
44
|
-
status: '
|
|
44
|
+
status: 'ready_for_ai',
|
|
45
45
|
product_id: 'test-product',
|
|
46
46
|
updated_at: '2024-01-15T10:00:00Z',
|
|
47
47
|
},
|
|
48
48
|
{
|
|
49
49
|
id: '2',
|
|
50
50
|
name: 'Feature 2',
|
|
51
|
-
status: '
|
|
51
|
+
status: 'ready_for_ai',
|
|
52
52
|
product_id: 'test-product',
|
|
53
53
|
// Missing updated_at
|
|
54
54
|
},
|
|
55
55
|
{
|
|
56
56
|
id: '3',
|
|
57
57
|
name: 'Feature 3',
|
|
58
|
-
status: '
|
|
58
|
+
status: 'ready_for_ai',
|
|
59
59
|
product_id: 'test-product',
|
|
60
60
|
updated_at: '2024-01-10T10:00:00Z',
|
|
61
61
|
},
|
|
@@ -77,7 +77,7 @@ describe('Feature Utils', () => {
|
|
|
77
77
|
{
|
|
78
78
|
id: '1',
|
|
79
79
|
name: 'Feature 1',
|
|
80
|
-
status: '
|
|
80
|
+
status: 'ready_for_ai',
|
|
81
81
|
product_id: 'test-product',
|
|
82
82
|
updated_at: '2024-01-15T10:00:00Z',
|
|
83
83
|
},
|
|
@@ -91,14 +91,14 @@ describe('Feature Utils', () => {
|
|
|
91
91
|
{
|
|
92
92
|
id: '1',
|
|
93
93
|
name: 'Feature 1',
|
|
94
|
-
status: '
|
|
94
|
+
status: 'ready_for_ai',
|
|
95
95
|
product_id: 'test-product',
|
|
96
96
|
updated_at: '2024-01-15T10:00:00Z',
|
|
97
97
|
},
|
|
98
98
|
{
|
|
99
99
|
id: '2',
|
|
100
100
|
name: 'Feature 2',
|
|
101
|
-
status: '
|
|
101
|
+
status: 'ready_for_ai',
|
|
102
102
|
product_id: 'test-product',
|
|
103
103
|
updated_at: '2024-01-10T10:00:00Z',
|
|
104
104
|
},
|
|
@@ -117,21 +117,21 @@ describe('Feature Utils', () => {
|
|
|
117
117
|
{
|
|
118
118
|
id: '1',
|
|
119
119
|
name: 'Feature 1',
|
|
120
|
-
status: '
|
|
120
|
+
status: 'ready_for_ai',
|
|
121
121
|
product_id: 'test-product',
|
|
122
122
|
updated_at: sameTimestamp,
|
|
123
123
|
},
|
|
124
124
|
{
|
|
125
125
|
id: '2',
|
|
126
126
|
name: 'Feature 2',
|
|
127
|
-
status: '
|
|
127
|
+
status: 'ready_for_ai',
|
|
128
128
|
product_id: 'test-product',
|
|
129
129
|
updated_at: sameTimestamp,
|
|
130
130
|
},
|
|
131
131
|
{
|
|
132
132
|
id: '3',
|
|
133
133
|
name: 'Feature 3',
|
|
134
|
-
status: '
|
|
134
|
+
status: 'ready_for_ai',
|
|
135
135
|
product_id: 'test-product',
|
|
136
136
|
updated_at: sameTimestamp,
|
|
137
137
|
},
|
|
@@ -146,21 +146,21 @@ describe('Feature Utils', () => {
|
|
|
146
146
|
{
|
|
147
147
|
id: '1',
|
|
148
148
|
name: 'Feature 1',
|
|
149
|
-
status: '
|
|
149
|
+
status: 'ready_for_ai',
|
|
150
150
|
product_id: 'test-product',
|
|
151
151
|
updated_at: '2024-01-15', // Date only
|
|
152
152
|
},
|
|
153
153
|
{
|
|
154
154
|
id: '2',
|
|
155
155
|
name: 'Feature 2',
|
|
156
|
-
status: '
|
|
156
|
+
status: 'ready_for_ai',
|
|
157
157
|
product_id: 'test-product',
|
|
158
158
|
updated_at: '2024-01-10T10:00:00.000Z', // Full ISO format
|
|
159
159
|
},
|
|
160
160
|
{
|
|
161
161
|
id: '3',
|
|
162
162
|
name: 'Feature 3',
|
|
163
|
-
status: '
|
|
163
|
+
status: 'ready_for_ai',
|
|
164
164
|
product_id: 'test-product',
|
|
165
165
|
updated_at: '2024-01-20T15:30:00Z', // ISO with time
|
|
166
166
|
},
|
|
@@ -178,7 +178,7 @@ describe('Feature Utils', () => {
|
|
|
178
178
|
{
|
|
179
179
|
id: '1',
|
|
180
180
|
name: 'Feature 1',
|
|
181
|
-
status: '
|
|
181
|
+
status: 'ready_for_ai',
|
|
182
182
|
product_id: 'test-product',
|
|
183
183
|
},
|
|
184
184
|
{
|
|
@@ -190,12 +190,12 @@ describe('Feature Utils', () => {
|
|
|
190
190
|
{
|
|
191
191
|
id: '3',
|
|
192
192
|
name: 'Feature 3',
|
|
193
|
-
status: '
|
|
193
|
+
status: 'ready_for_ai',
|
|
194
194
|
product_id: 'test-product',
|
|
195
195
|
},
|
|
196
196
|
];
|
|
197
|
-
const filtered = filterFeaturesByStatus(features, '
|
|
198
|
-
assert.strictEqual(filtered.length, 2, 'Should return 2
|
|
197
|
+
const filtered = filterFeaturesByStatus(features, 'ready_for_ai');
|
|
198
|
+
assert.strictEqual(filtered.length, 2, 'Should return 2 ready_for_ai features');
|
|
199
199
|
assert.strictEqual(filtered[0].id, '1', 'Should include Feature 1');
|
|
200
200
|
assert.strictEqual(filtered[1].id, '3', 'Should include Feature 3');
|
|
201
201
|
});
|
|
@@ -214,12 +214,12 @@ describe('Feature Utils', () => {
|
|
|
214
214
|
product_id: 'test-product',
|
|
215
215
|
},
|
|
216
216
|
];
|
|
217
|
-
const filtered = filterFeaturesByStatus(features, '
|
|
217
|
+
const filtered = filterFeaturesByStatus(features, 'ready_for_ai');
|
|
218
218
|
assert.strictEqual(filtered.length, 0, 'Should return empty array');
|
|
219
219
|
});
|
|
220
220
|
it('should handle empty input array', () => {
|
|
221
221
|
const features = [];
|
|
222
|
-
const filtered = filterFeaturesByStatus(features, '
|
|
222
|
+
const filtered = filterFeaturesByStatus(features, 'ready_for_ai');
|
|
223
223
|
assert.strictEqual(filtered.length, 0, 'Should return empty array');
|
|
224
224
|
});
|
|
225
225
|
});
|
|
@@ -230,21 +230,21 @@ describe('Feature Utils', () => {
|
|
|
230
230
|
{
|
|
231
231
|
id: 'urgent-feature',
|
|
232
232
|
name: 'Urgent Feature',
|
|
233
|
-
status: '
|
|
233
|
+
status: 'ready_for_ai',
|
|
234
234
|
product_id: 'test-product',
|
|
235
235
|
updated_at: '2024-01-01T08:00:00Z', // Very old - should be processed first
|
|
236
236
|
},
|
|
237
237
|
{
|
|
238
238
|
id: 'recent-feature',
|
|
239
239
|
name: 'Recent Feature',
|
|
240
|
-
status: '
|
|
240
|
+
status: 'ready_for_ai',
|
|
241
241
|
product_id: 'test-product',
|
|
242
242
|
updated_at: '2024-01-20T10:00:00Z', // Recent - should be processed last
|
|
243
243
|
},
|
|
244
244
|
{
|
|
245
245
|
id: 'medium-feature',
|
|
246
246
|
name: 'Medium Feature',
|
|
247
|
-
status: '
|
|
247
|
+
status: 'ready_for_ai',
|
|
248
248
|
product_id: 'test-product',
|
|
249
249
|
updated_at: '2024-01-10T12:00:00Z', // Medium age - should be processed second
|
|
250
250
|
},
|
|
@@ -265,21 +265,21 @@ describe('Feature Utils', () => {
|
|
|
265
265
|
{
|
|
266
266
|
id: '1',
|
|
267
267
|
name: 'Feature 1',
|
|
268
|
-
status: '
|
|
268
|
+
status: 'ready_for_ai',
|
|
269
269
|
product_id: 'test-product',
|
|
270
270
|
updated_at: '2024-01-15T10:00:00Z',
|
|
271
271
|
},
|
|
272
272
|
{
|
|
273
273
|
id: '2',
|
|
274
274
|
name: 'Feature 2',
|
|
275
|
-
status: '
|
|
275
|
+
status: 'ready_for_ai',
|
|
276
276
|
product_id: 'test-product',
|
|
277
277
|
updated_at: '2024-01-10T10:00:00Z',
|
|
278
278
|
},
|
|
279
279
|
{
|
|
280
280
|
id: '3',
|
|
281
281
|
name: 'Feature 3',
|
|
282
|
-
status: '
|
|
282
|
+
status: 'ready_for_ai',
|
|
283
283
|
product_id: 'test-product',
|
|
284
284
|
updated_at: '2024-01-20T10:00:00Z',
|
|
285
285
|
},
|
|
@@ -298,21 +298,21 @@ describe('Feature Utils', () => {
|
|
|
298
298
|
{
|
|
299
299
|
id: 'very-old-bug',
|
|
300
300
|
name: 'Critical Bug Fix',
|
|
301
|
-
status: '
|
|
301
|
+
status: 'ready_for_ai',
|
|
302
302
|
product_id: 'test-product',
|
|
303
303
|
updated_at: '2024-01-01T00:00:00Z', // Very old, should be highest priority
|
|
304
304
|
},
|
|
305
305
|
{
|
|
306
306
|
id: 'new-enhancement',
|
|
307
307
|
name: 'Nice to Have Feature',
|
|
308
|
-
status: '
|
|
308
|
+
status: 'ready_for_ai',
|
|
309
309
|
product_id: 'test-product',
|
|
310
310
|
updated_at: '2024-01-25T00:00:00Z', // Recent, should be lowest priority
|
|
311
311
|
},
|
|
312
312
|
{
|
|
313
313
|
id: 'medium-priority',
|
|
314
314
|
name: 'Important Feature',
|
|
315
|
-
status: '
|
|
315
|
+
status: 'ready_for_ai',
|
|
316
316
|
product_id: 'test-product',
|
|
317
317
|
updated_at: '2024-01-15T00:00:00Z', // Medium age, should be middle priority
|
|
318
318
|
},
|
|
@@ -328,36 +328,36 @@ describe('Feature Utils', () => {
|
|
|
328
328
|
assert.ok(ages[0] <= ages[1] && ages[1] <= ages[2], 'Features should be processed in age order (oldest first)');
|
|
329
329
|
});
|
|
330
330
|
});
|
|
331
|
-
describe('
|
|
331
|
+
describe('getReadyForAIFeatures integration behavior', () => {
|
|
332
332
|
it('should use sortFeaturesByUpdatedAt to ensure oldest-first processing', () => {
|
|
333
|
-
// This test verifies the integration between
|
|
334
|
-
// We can test this indirectly by testing the sorting function that
|
|
333
|
+
// This test verifies the integration between getReadyForAIFeatures and sortFeaturesByUpdatedAt
|
|
334
|
+
// We can test this indirectly by testing the sorting function that getReadyForAIFeatures uses
|
|
335
335
|
const mockApiResponse = [
|
|
336
336
|
{
|
|
337
337
|
id: 'feat-1',
|
|
338
338
|
name: 'Feature Added Last Week',
|
|
339
|
-
status: '
|
|
339
|
+
status: 'ready_for_ai',
|
|
340
340
|
product_id: 'product-123',
|
|
341
341
|
updated_at: '2024-01-18T10:00:00Z',
|
|
342
342
|
},
|
|
343
343
|
{
|
|
344
344
|
id: 'feat-2',
|
|
345
345
|
name: 'Feature Added Yesterday',
|
|
346
|
-
status: '
|
|
346
|
+
status: 'ready_for_ai',
|
|
347
347
|
product_id: 'product-123',
|
|
348
348
|
updated_at: '2024-01-24T15:30:00Z',
|
|
349
349
|
},
|
|
350
350
|
{
|
|
351
351
|
id: 'feat-3',
|
|
352
352
|
name: 'Feature Added Last Month',
|
|
353
|
-
status: '
|
|
353
|
+
status: 'ready_for_ai',
|
|
354
354
|
product_id: 'product-123',
|
|
355
355
|
updated_at: '2024-01-05T08:00:00Z',
|
|
356
356
|
},
|
|
357
357
|
];
|
|
358
|
-
// This simulates what
|
|
358
|
+
// This simulates what getReadyForAIFeatures does internally
|
|
359
359
|
const sortedForWorkflow = sortFeaturesByUpdatedAt(mockApiResponse);
|
|
360
|
-
// Verify oldest-first ordering that
|
|
360
|
+
// Verify oldest-first ordering that getReadyForAIFeatures should provide
|
|
361
361
|
assert.strictEqual(sortedForWorkflow[0].id, 'feat-3', 'Oldest feature should be first');
|
|
362
362
|
assert.strictEqual(sortedForWorkflow[1].id, 'feat-1', 'Second oldest should be second');
|
|
363
363
|
assert.strictEqual(sortedForWorkflow[2].id, 'feat-2', 'Newest feature should be last');
|
|
@@ -8,7 +8,7 @@ import { isForwardProgression } from '../status-updater.js';
|
|
|
8
8
|
describe('Status Progression Logic', () => {
|
|
9
9
|
describe('isForwardProgression', () => {
|
|
10
10
|
it('should allow forward progression', () => {
|
|
11
|
-
assert.strictEqual(isForwardProgression('backlog', '
|
|
11
|
+
assert.strictEqual(isForwardProgression('backlog', 'ready_for_ai'), true, 'Should allow progression from backlog to ready_for_ai');
|
|
12
12
|
assert.strictEqual(isForwardProgression('feature_analysis', 'technical_design'), true, 'Should allow progression from feature_analysis to technical_design');
|
|
13
13
|
assert.strictEqual(isForwardProgression('code_implementation', 'shipped'), true, 'Should allow progression from code_implementation to shipped');
|
|
14
14
|
});
|
|
@@ -18,7 +18,7 @@ describe('Status Progression Logic', () => {
|
|
|
18
18
|
assert.strictEqual(isForwardProgression('shipped', 'shipped'), true, 'Should allow staying at shipped status');
|
|
19
19
|
});
|
|
20
20
|
it('should prevent backward progression', () => {
|
|
21
|
-
assert.strictEqual(isForwardProgression('
|
|
21
|
+
assert.strictEqual(isForwardProgression('ready_for_ai', 'backlog'), false, 'Should prevent regression from ready_for_ai to backlog');
|
|
22
22
|
assert.strictEqual(isForwardProgression('technical_design', 'feature_analysis'), false, 'Should prevent regression from technical_design to feature_analysis');
|
|
23
23
|
assert.strictEqual(isForwardProgression('shipped', 'code_implementation'), false, 'Should prevent regression from shipped to code_implementation');
|
|
24
24
|
});
|
|
@@ -42,7 +42,7 @@ describe('Status Progression Logic', () => {
|
|
|
42
42
|
it('should contain all expected statuses', () => {
|
|
43
43
|
const expectedStatuses = [
|
|
44
44
|
'backlog',
|
|
45
|
-
'
|
|
45
|
+
'ready_for_ai',
|
|
46
46
|
'feature_analysis',
|
|
47
47
|
'feature_analysis_verification',
|
|
48
48
|
'technical_design',
|
|
@@ -68,13 +68,13 @@ describe('Status Progression Logic', () => {
|
|
|
68
68
|
});
|
|
69
69
|
it('should have correct ordering for key workflow phases', () => {
|
|
70
70
|
const backlogIndex = STATUS_PROGRESSION_ORDER.indexOf('backlog');
|
|
71
|
-
const readyForDevIndex = STATUS_PROGRESSION_ORDER.indexOf('
|
|
71
|
+
const readyForDevIndex = STATUS_PROGRESSION_ORDER.indexOf('ready_for_ai');
|
|
72
72
|
const featureAnalysisIndex = STATUS_PROGRESSION_ORDER.indexOf('feature_analysis');
|
|
73
73
|
const technicalDesignIndex = STATUS_PROGRESSION_ORDER.indexOf('technical_design');
|
|
74
74
|
const codeImplementationIndex = STATUS_PROGRESSION_ORDER.indexOf('code_implementation');
|
|
75
75
|
const shippedIndex = STATUS_PROGRESSION_ORDER.indexOf('shipped');
|
|
76
|
-
assert.ok(backlogIndex < readyForDevIndex, 'backlog should come before
|
|
77
|
-
assert.ok(readyForDevIndex < featureAnalysisIndex, '
|
|
76
|
+
assert.ok(backlogIndex < readyForDevIndex, 'backlog should come before ready_for_ai');
|
|
77
|
+
assert.ok(readyForDevIndex < featureAnalysisIndex, 'ready_for_ai should come before feature_analysis');
|
|
78
78
|
assert.ok(featureAnalysisIndex < technicalDesignIndex, 'feature_analysis should come before technical_design');
|
|
79
79
|
assert.ok(technicalDesignIndex < codeImplementationIndex, 'technical_design should come before code_implementation');
|
|
80
80
|
assert.ok(codeImplementationIndex < shippedIndex, 'code_implementation should come before shipped');
|
|
@@ -8,6 +8,6 @@ export declare function filterFeaturesByStatus(features: FeatureInfo[], status:
|
|
|
8
8
|
*/
|
|
9
9
|
export declare function sortFeaturesByUpdatedAt(features: FeatureInfo[]): FeatureInfo[];
|
|
10
10
|
/**
|
|
11
|
-
* Get features with
|
|
11
|
+
* Get features with ready_for_ai status for a product
|
|
12
12
|
*/
|
|
13
|
-
export declare function
|
|
13
|
+
export declare function getReadyForAIFeatures(productId: string, verbose?: boolean): Promise<FeatureInfo[]>;
|
|
@@ -17,21 +17,21 @@ export function sortFeaturesByUpdatedAt(features) {
|
|
|
17
17
|
});
|
|
18
18
|
}
|
|
19
19
|
/**
|
|
20
|
-
* Get features with
|
|
20
|
+
* Get features with ready_for_ai status for a product
|
|
21
21
|
*/
|
|
22
|
-
export async function
|
|
22
|
+
export async function getReadyForAIFeatures(productId, verbose) {
|
|
23
23
|
if (verbose) {
|
|
24
|
-
logInfo(`Fetching
|
|
24
|
+
logInfo(`Fetching ready_for_ai features for product: ${productId}`);
|
|
25
25
|
}
|
|
26
26
|
try {
|
|
27
27
|
const result = (await callMcpEndpoint('features/list', {
|
|
28
28
|
product_id: productId,
|
|
29
|
-
status: '
|
|
29
|
+
status: 'ready_for_ai',
|
|
30
30
|
}));
|
|
31
31
|
const features = result.features || [];
|
|
32
32
|
const sortedFeatures = sortFeaturesByUpdatedAt(features);
|
|
33
33
|
if (verbose) {
|
|
34
|
-
logInfo(`✅ Found ${sortedFeatures.length}
|
|
34
|
+
logInfo(`✅ Found ${sortedFeatures.length} ready_for_ai features (oldest first)`);
|
|
35
35
|
sortedFeatures.forEach((feature, index) => {
|
|
36
36
|
logInfo(` ${index + 1}. ${feature.name} (updated: ${feature.updated_at})`);
|
|
37
37
|
});
|
|
@@ -40,7 +40,7 @@ export async function getReadyForDevFeatures(productId, verbose) {
|
|
|
40
40
|
}
|
|
41
41
|
catch (error) {
|
|
42
42
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
43
|
-
logError(`Failed to fetch
|
|
43
|
+
logError(`Failed to fetch ready_for_ai features: ${errorMessage}`);
|
|
44
44
|
throw error;
|
|
45
45
|
}
|
|
46
46
|
}
|
|
@@ -9,7 +9,7 @@ export const shouldProcessFeature = (maxRetries) => (feature, states) => {
|
|
|
9
9
|
if (!state)
|
|
10
10
|
return true;
|
|
11
11
|
// If feature was updated after last processing attempt, should reprocess
|
|
12
|
-
// This handles cases where user manually changes status back to
|
|
12
|
+
// This handles cases where user manually changes status back to ready_for_ai
|
|
13
13
|
if (feature.updated_at) {
|
|
14
14
|
const featureUpdatedTime = new Date(feature.updated_at).getTime();
|
|
15
15
|
const lastAttemptTime = state.lastAttempt.getTime();
|
|
@@ -49,7 +49,7 @@ export const logFeatureError = (featureName, error) => {
|
|
|
49
49
|
logError(`❌ Error processing feature ${featureName}: ${error instanceof Error ? error.message : String(error)}`);
|
|
50
50
|
};
|
|
51
51
|
export const logNoFeaturesFound = () => {
|
|
52
|
-
logInfo('🔍 No
|
|
52
|
+
logInfo('🔍 No ready_for_ai features found, continuing to monitor...');
|
|
53
53
|
};
|
|
54
54
|
export const logAllFeaturesProcessed = () => {
|
|
55
55
|
logInfo('🔄 All current features are processed or being processed, continuing to monitor...');
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Main workflow processor for continuous feature development
|
|
3
|
-
* Monitors for
|
|
3
|
+
* Monitors for ready_for_ai features and processes them through the complete pipeline
|
|
4
4
|
* Uses functional programming principles
|
|
5
5
|
*/
|
|
6
6
|
import { EdsgerConfig } from '../../types/index.js';
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Main workflow processor for continuous feature development
|
|
3
|
-
* Monitors for
|
|
3
|
+
* Monitors for ready_for_ai features and processes them through the complete pipeline
|
|
4
4
|
* Uses functional programming principles
|
|
5
5
|
*/
|
|
6
|
-
import {
|
|
6
|
+
import { getReadyForAIFeatures } from '../../api/features/index.js';
|
|
7
7
|
import { runFeatureWorkflow } from './feature-coordinator.js';
|
|
8
8
|
import { logInfo } from '../../utils/logger.js';
|
|
9
9
|
// Import core modules
|
|
@@ -77,7 +77,7 @@ export class WorkflowProcessor {
|
|
|
77
77
|
return;
|
|
78
78
|
}
|
|
79
79
|
// Fetch features using unified API
|
|
80
|
-
const features = await
|
|
80
|
+
const features = await getReadyForAIFeatures(this.options.productId, this.options.verbose);
|
|
81
81
|
if (features.length === 0) {
|
|
82
82
|
if (this.options.verbose) {
|
|
83
83
|
logNoFeaturesFound();
|
package/dist/types/index.d.ts
CHANGED
|
@@ -130,4 +130,4 @@ export interface FeatureAnalysisDisplayResult {
|
|
|
130
130
|
createdUserStories?: DisplayUserStory[];
|
|
131
131
|
createdTestCases?: DisplayTestCase[];
|
|
132
132
|
}
|
|
133
|
-
export type FeatureStatus = 'backlog' | '
|
|
133
|
+
export type FeatureStatus = 'backlog' | 'ready_for_ai' | 'feature_analysis' | 'feature_analysis_verification' | 'technical_design' | 'technical_design_verification' | 'code_implementation' | 'code_implementation_verification' | 'code_refine' | 'code_refine_verification' | 'bug_fixing' | 'code_review' | 'pull_request' | 'functional_testing' | 'ready_for_review' | 'shipped' | 'testing_in_progress' | 'testing_passed' | 'testing_failed';
|