edsger 0.41.1 → 0.41.2

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 (103) hide show
  1. package/.claude/settings.local.json +23 -3
  2. package/.env.local +12 -0
  3. package/dist/api/features/__tests__/regression-prevention.test.d.ts +5 -0
  4. package/dist/api/features/__tests__/regression-prevention.test.js +338 -0
  5. package/dist/api/features/__tests__/status-updater.integration.test.d.ts +5 -0
  6. package/dist/api/features/__tests__/status-updater.integration.test.js +497 -0
  7. package/dist/commands/workflow/pipeline-runner.d.ts +17 -0
  8. package/dist/commands/workflow/pipeline-runner.js +393 -0
  9. package/dist/commands/workflow/runner.d.ts +26 -0
  10. package/dist/commands/workflow/runner.js +119 -0
  11. package/dist/commands/workflow/workflow-runner.d.ts +26 -0
  12. package/dist/commands/workflow/workflow-runner.js +119 -0
  13. package/dist/index.js +0 -0
  14. package/dist/phases/code-implementation/analyzer-helpers.d.ts +28 -0
  15. package/dist/phases/code-implementation/analyzer-helpers.js +177 -0
  16. package/dist/phases/code-implementation/analyzer.d.ts +32 -0
  17. package/dist/phases/code-implementation/analyzer.js +629 -0
  18. package/dist/phases/code-implementation/context-fetcher.d.ts +17 -0
  19. package/dist/phases/code-implementation/context-fetcher.js +86 -0
  20. package/dist/phases/code-implementation/mcp-server.d.ts +1 -0
  21. package/dist/phases/code-implementation/mcp-server.js +93 -0
  22. package/dist/phases/code-implementation/prompts-improvement.d.ts +5 -0
  23. package/dist/phases/code-implementation/prompts-improvement.js +108 -0
  24. package/dist/phases/code-implementation-verification/verifier.d.ts +31 -0
  25. package/dist/phases/code-implementation-verification/verifier.js +196 -0
  26. package/dist/phases/code-refine/analyzer.d.ts +41 -0
  27. package/dist/phases/code-refine/analyzer.js +561 -0
  28. package/dist/phases/code-refine/context-fetcher.d.ts +94 -0
  29. package/dist/phases/code-refine/context-fetcher.js +423 -0
  30. package/dist/phases/code-refine-verification/analysis/llm-analyzer.d.ts +22 -0
  31. package/dist/phases/code-refine-verification/analysis/llm-analyzer.js +134 -0
  32. package/dist/phases/code-refine-verification/verifier.d.ts +47 -0
  33. package/dist/phases/code-refine-verification/verifier.js +597 -0
  34. package/dist/phases/code-review/analyzer.d.ts +29 -0
  35. package/dist/phases/code-review/analyzer.js +363 -0
  36. package/dist/phases/code-review/context-fetcher.d.ts +92 -0
  37. package/dist/phases/code-review/context-fetcher.js +296 -0
  38. package/dist/phases/feature-analysis/analyzer-helpers.d.ts +10 -0
  39. package/dist/phases/feature-analysis/analyzer-helpers.js +47 -0
  40. package/dist/phases/feature-analysis/analyzer.d.ts +11 -0
  41. package/dist/phases/feature-analysis/analyzer.js +208 -0
  42. package/dist/phases/feature-analysis/context-fetcher.d.ts +26 -0
  43. package/dist/phases/feature-analysis/context-fetcher.js +134 -0
  44. package/dist/phases/feature-analysis/http-fallback.d.ts +20 -0
  45. package/dist/phases/feature-analysis/http-fallback.js +95 -0
  46. package/dist/phases/feature-analysis/mcp-server.d.ts +1 -0
  47. package/dist/phases/feature-analysis/mcp-server.js +144 -0
  48. package/dist/phases/feature-analysis/prompts-improvement.d.ts +8 -0
  49. package/dist/phases/feature-analysis/prompts-improvement.js +109 -0
  50. package/dist/phases/feature-analysis-verification/verifier.d.ts +37 -0
  51. package/dist/phases/feature-analysis-verification/verifier.js +147 -0
  52. package/dist/phases/pr-execution/file-assigner.js +20 -12
  53. package/dist/phases/technical-design/analyzer-helpers.d.ts +25 -0
  54. package/dist/phases/technical-design/analyzer-helpers.js +39 -0
  55. package/dist/phases/technical-design/analyzer.d.ts +21 -0
  56. package/dist/phases/technical-design/analyzer.js +461 -0
  57. package/dist/phases/technical-design/context-fetcher.d.ts +12 -0
  58. package/dist/phases/technical-design/context-fetcher.js +39 -0
  59. package/dist/phases/technical-design/http-fallback.d.ts +17 -0
  60. package/dist/phases/technical-design/http-fallback.js +151 -0
  61. package/dist/phases/technical-design/mcp-server.d.ts +1 -0
  62. package/dist/phases/technical-design/mcp-server.js +157 -0
  63. package/dist/phases/technical-design/prompts-improvement.d.ts +5 -0
  64. package/dist/phases/technical-design/prompts-improvement.js +93 -0
  65. package/dist/phases/technical-design-verification/verifier.d.ts +53 -0
  66. package/dist/phases/technical-design-verification/verifier.js +170 -0
  67. package/dist/services/feature-branches.d.ts +77 -0
  68. package/dist/services/feature-branches.js +205 -0
  69. package/dist/workflow-runner/config/phase-configs.d.ts +5 -0
  70. package/dist/workflow-runner/config/phase-configs.js +120 -0
  71. package/dist/workflow-runner/core/feature-filter.d.ts +16 -0
  72. package/dist/workflow-runner/core/feature-filter.js +46 -0
  73. package/dist/workflow-runner/core/index.d.ts +8 -0
  74. package/dist/workflow-runner/core/index.js +12 -0
  75. package/dist/workflow-runner/core/pipeline-evaluator.d.ts +24 -0
  76. package/dist/workflow-runner/core/pipeline-evaluator.js +32 -0
  77. package/dist/workflow-runner/core/state-manager.d.ts +24 -0
  78. package/dist/workflow-runner/core/state-manager.js +42 -0
  79. package/dist/workflow-runner/core/workflow-logger.d.ts +20 -0
  80. package/dist/workflow-runner/core/workflow-logger.js +65 -0
  81. package/dist/workflow-runner/executors/phase-executor.d.ts +8 -0
  82. package/dist/workflow-runner/executors/phase-executor.js +248 -0
  83. package/dist/workflow-runner/feature-workflow-runner.d.ts +26 -0
  84. package/dist/workflow-runner/feature-workflow-runner.js +119 -0
  85. package/dist/workflow-runner/index.d.ts +2 -0
  86. package/dist/workflow-runner/index.js +2 -0
  87. package/dist/workflow-runner/pipeline-runner.d.ts +17 -0
  88. package/dist/workflow-runner/pipeline-runner.js +393 -0
  89. package/dist/workflow-runner/workflow-processor.d.ts +54 -0
  90. package/dist/workflow-runner/workflow-processor.js +170 -0
  91. package/package.json +1 -1
  92. package/dist/services/lifecycle-agent/__tests__/phase-criteria.test.d.ts +0 -4
  93. package/dist/services/lifecycle-agent/__tests__/phase-criteria.test.js +0 -133
  94. package/dist/services/lifecycle-agent/__tests__/transition-rules.test.d.ts +0 -4
  95. package/dist/services/lifecycle-agent/__tests__/transition-rules.test.js +0 -336
  96. package/dist/services/lifecycle-agent/index.d.ts +0 -24
  97. package/dist/services/lifecycle-agent/index.js +0 -25
  98. package/dist/services/lifecycle-agent/phase-criteria.d.ts +0 -57
  99. package/dist/services/lifecycle-agent/phase-criteria.js +0 -335
  100. package/dist/services/lifecycle-agent/transition-rules.d.ts +0 -60
  101. package/dist/services/lifecycle-agent/transition-rules.js +0 -184
  102. package/dist/services/lifecycle-agent/types.d.ts +0 -190
  103. package/dist/services/lifecycle-agent/types.js +0 -12
@@ -0,0 +1,393 @@
1
+ /**
2
+ * Pipeline runner for executing development workflow phases
3
+ * Complete pipeline flow:
4
+ * feature-analysis → technical-design → code-implementation →
5
+ * functional-testing → pull-request → code-review → code-refine → code-refine-verification
6
+ * Uses functional programming principles
7
+ */
8
+ import { updateFeatureStatusForPhase } from '../api/features/index.js';
9
+ import { runFeatureAnalysisPhase, runTechnicalDesignPhase, runCodeImplementationPhase, runFunctionalTestingPhase, runCodeTestingPhase, runCodeReviewPhase, } from './executors/phase-executor.js';
10
+ import { logPipelineStart, logPhaseResult, logPipelineComplete, shouldContinuePipeline, } from '../utils/pipeline-logger.js';
11
+ import { handleTestFailuresWithRetry } from '../phases/functional-testing/test-retry-handler.js';
12
+ import { handleCodeRefineWithRetry } from '../phases/code-refine/retry-handler.js';
13
+ import { handlePullRequestCreation } from '../phases/pull-request/handler.js';
14
+ /**
15
+ * Run pipeline based on execution mode
16
+ */
17
+ export const runPipelineByMode = async (options, config, executionMode) => {
18
+ const { featureId, verbose } = options;
19
+ if (verbose) {
20
+ console.log(`🚀 Starting pipeline with mode: ${executionMode} for feature: ${featureId}`);
21
+ console.log(`📋 Execution mode details:`);
22
+ console.log(` - Mode value: "${executionMode}"`);
23
+ console.log(` - Mode type: ${typeof executionMode}`);
24
+ console.log(` - Mode === 'only_feature_analysis': ${executionMode === 'only_feature_analysis'}`);
25
+ }
26
+ switch (executionMode) {
27
+ // Complete pipeline
28
+ case 'full_pipeline':
29
+ case 'from_feature_analysis':
30
+ if (verbose) {
31
+ console.log(` ➡️ Matched: full_pipeline or from_feature_analysis - running complete pipeline`);
32
+ }
33
+ return await runFromFeatureAnalysis(options, config);
34
+ // Feature Analysis
35
+ case 'only_feature_analysis':
36
+ if (verbose) {
37
+ console.log(` ➡️ Matched: only_feature_analysis - running analysis only`);
38
+ }
39
+ return await runOnlyFeatureAnalysis(options, config);
40
+ // Technical Design
41
+ case 'only_technical_design':
42
+ return await runOnlyTechnicalDesign(options, config);
43
+ case 'from_technical_design':
44
+ return await runFromTechnicalDesign(options, config);
45
+ // Code Implementation
46
+ case 'only_code_implementation':
47
+ return await runOnlyCodeImplementation(options, config);
48
+ case 'from_code_implementation':
49
+ return await runFromCodeImplementation(options, config);
50
+ // Functional Testing
51
+ case 'only_functional_testing':
52
+ return await runOnlyFunctionalTesting(options, config);
53
+ case 'from_functional_testing':
54
+ return await runFromFunctionalTesting(options, config);
55
+ // Code Refine
56
+ case 'only_code_refine':
57
+ return await runOnlyCodeRefine(options, config);
58
+ // Code Review
59
+ case 'only_code_review':
60
+ return await runOnlyCodeReview(options, config);
61
+ case 'from_code_review':
62
+ return await runFromCodeReview(options, config);
63
+ default:
64
+ throw new Error(`Unsupported execution mode: ${executionMode}`);
65
+ }
66
+ };
67
+ /**
68
+ * Run complete pipeline for a feature using functional composition (legacy)
69
+ */
70
+ export const runCompletePipeline = (options, config) => {
71
+ return async () => {
72
+ return await runFromFeatureAnalysis(options, config);
73
+ };
74
+ };
75
+ // Helper functions for different execution patterns
76
+ /**
77
+ * Run only feature analysis phase
78
+ */
79
+ const runOnlyFeatureAnalysis = async (options, config) => {
80
+ const { featureId, verbose } = options;
81
+ logPipelineStart(featureId, verbose);
82
+ const results = [];
83
+ const analysisResult = await runFeatureAnalysisPhase(options, config);
84
+ results.push(logPhaseResult(analysisResult, verbose));
85
+ return logPipelineComplete(results, verbose);
86
+ };
87
+ /**
88
+ * Run only technical design phase
89
+ */
90
+ const runOnlyTechnicalDesign = async (options, config) => {
91
+ const { featureId, verbose } = options;
92
+ logPipelineStart(featureId, verbose);
93
+ const results = [];
94
+ const designResult = await runTechnicalDesignPhase(options, config);
95
+ results.push(logPhaseResult(designResult, verbose));
96
+ return logPipelineComplete(results, verbose);
97
+ };
98
+ /**
99
+ * Run only code implementation phase
100
+ */
101
+ const runOnlyCodeImplementation = async (options, config) => {
102
+ const { featureId, verbose } = options;
103
+ logPipelineStart(featureId, verbose);
104
+ const results = [];
105
+ const implementationResult = await runCodeImplementationPhase(options, config);
106
+ results.push(logPhaseResult(implementationResult, verbose));
107
+ return logPipelineComplete(results, verbose);
108
+ };
109
+ /**
110
+ * Run only functional testing phase
111
+ */
112
+ const runOnlyFunctionalTesting = async (options, config) => {
113
+ const { featureId, verbose } = options;
114
+ logPipelineStart(featureId, verbose);
115
+ const results = [];
116
+ const testingResult = await runFunctionalTestingPhase(options, config);
117
+ results.push(logPhaseResult(testingResult, verbose));
118
+ return logPipelineComplete(results, verbose);
119
+ };
120
+ /**
121
+ * Run from feature analysis to end
122
+ */
123
+ const runFromFeatureAnalysis = async (options, config) => {
124
+ const { featureId, mcpServerUrl, mcpToken, verbose } = options;
125
+ logPipelineStart(featureId, verbose);
126
+ const results = [];
127
+ // 1. Feature Analysis
128
+ const analysisResult = await runFeatureAnalysisPhase(options, config);
129
+ results.push(logPhaseResult(analysisResult, verbose));
130
+ if (!shouldContinuePipeline(results)) {
131
+ return logPipelineComplete(results, verbose);
132
+ }
133
+ // 2. Technical Design
134
+ const designResult = await runTechnicalDesignPhase(options, config);
135
+ results.push(logPhaseResult(designResult, verbose));
136
+ if (!shouldContinuePipeline(results)) {
137
+ return logPipelineComplete(results, verbose);
138
+ }
139
+ // 3. Code Implementation
140
+ const implementationResult = await runCodeImplementationPhase(options, config);
141
+ results.push(logPhaseResult(implementationResult, verbose));
142
+ if (!shouldContinuePipeline(results)) {
143
+ return logPipelineComplete(results, verbose);
144
+ }
145
+ // 4. Functional Testing with retry loop for bug fixes
146
+ const testingResult = await handleTestFailuresWithRetry({
147
+ options,
148
+ config,
149
+ results,
150
+ verbose,
151
+ });
152
+ // Update final status based on functional testing result
153
+ const finalStatus = testingResult.status === 'success' ? 'testing_passed' : 'testing_failed';
154
+ await updateFeatureStatusForPhase({ mcpServerUrl, mcpToken }, featureId, finalStatus === 'testing_passed' ? 'testing-passed' : 'testing-failed', verbose);
155
+ // Create pull request if tests passed
156
+ if (testingResult.status === 'success') {
157
+ const prCreated = await handlePullRequestCreation({
158
+ featureId,
159
+ mcpServerUrl,
160
+ mcpToken,
161
+ results,
162
+ testingResult,
163
+ verbose,
164
+ });
165
+ // Continue with code review and refine workflow only if PR was created
166
+ if (prCreated) {
167
+ await continueWithCodeReviewAndRefine(options, config, results, verbose);
168
+ }
169
+ else {
170
+ if (verbose) {
171
+ console.log('⚠️ Skipping code review and refine workflow: pull request creation failed');
172
+ }
173
+ }
174
+ }
175
+ return logPipelineComplete(results, verbose);
176
+ };
177
+ /**
178
+ * Run from technical design to end
179
+ */
180
+ const runFromTechnicalDesign = async (options, config) => {
181
+ const { featureId, mcpServerUrl, mcpToken, verbose } = options;
182
+ logPipelineStart(featureId, verbose);
183
+ const results = [];
184
+ // 1. Technical Design
185
+ const designResult = await runTechnicalDesignPhase(options, config);
186
+ results.push(logPhaseResult(designResult, verbose));
187
+ if (!shouldContinuePipeline(results)) {
188
+ return logPipelineComplete(results, verbose);
189
+ }
190
+ // 2. Code Implementation
191
+ const implementationResult = await runCodeImplementationPhase(options, config);
192
+ results.push(logPhaseResult(implementationResult, verbose));
193
+ if (!shouldContinuePipeline(results)) {
194
+ return logPipelineComplete(results, verbose);
195
+ }
196
+ // 3. Functional Testing with retry loop for bug fixes
197
+ const testingResult = await handleTestFailuresWithRetry({
198
+ options,
199
+ config,
200
+ results,
201
+ verbose,
202
+ });
203
+ // Update final status based on functional testing result
204
+ const finalStatus = testingResult.status === 'success' ? 'testing_passed' : 'testing_failed';
205
+ await updateFeatureStatusForPhase({ mcpServerUrl, mcpToken }, featureId, finalStatus === 'testing_passed' ? 'testing-passed' : 'testing-failed', verbose);
206
+ // Create pull request if tests passed
207
+ if (testingResult.status === 'success') {
208
+ const prCreated = await handlePullRequestCreation({
209
+ featureId,
210
+ mcpServerUrl,
211
+ mcpToken,
212
+ results,
213
+ testingResult,
214
+ verbose,
215
+ });
216
+ // Continue with code review and refine workflow only if PR was created
217
+ if (prCreated) {
218
+ await continueWithCodeReviewAndRefine(options, config, results, verbose);
219
+ }
220
+ else {
221
+ if (verbose) {
222
+ console.log('⚠️ Skipping code review and refine workflow: pull request creation failed');
223
+ }
224
+ }
225
+ }
226
+ return logPipelineComplete(results, verbose);
227
+ };
228
+ /**
229
+ * Run from code implementation to end
230
+ */
231
+ const runFromCodeImplementation = async (options, config) => {
232
+ const { featureId, mcpServerUrl, mcpToken, verbose } = options;
233
+ logPipelineStart(featureId, verbose);
234
+ const results = [];
235
+ // 1. Code Implementation
236
+ const implementationResult = await runCodeImplementationPhase(options, config);
237
+ results.push(logPhaseResult(implementationResult, verbose));
238
+ if (!shouldContinuePipeline(results)) {
239
+ return logPipelineComplete(results, verbose);
240
+ }
241
+ // 2. Functional Testing with retry loop for bug fixes
242
+ const testingResult = await handleTestFailuresWithRetry({
243
+ options,
244
+ config,
245
+ results,
246
+ verbose,
247
+ });
248
+ // Update final status based on functional testing result
249
+ const finalStatus = testingResult.status === 'success' ? 'testing_passed' : 'testing_failed';
250
+ await updateFeatureStatusForPhase({ mcpServerUrl, mcpToken }, featureId, finalStatus === 'testing_passed' ? 'testing-passed' : 'testing-failed', verbose);
251
+ // Create pull request if tests passed
252
+ if (testingResult.status === 'success') {
253
+ const prCreated = await handlePullRequestCreation({
254
+ featureId,
255
+ mcpServerUrl,
256
+ mcpToken,
257
+ results,
258
+ testingResult,
259
+ verbose,
260
+ });
261
+ // Continue with code review and refine workflow only if PR was created
262
+ if (prCreated) {
263
+ await continueWithCodeReviewAndRefine(options, config, results, verbose);
264
+ }
265
+ else {
266
+ if (verbose) {
267
+ console.log('⚠️ Skipping code review and refine workflow: pull request creation failed');
268
+ }
269
+ }
270
+ }
271
+ return logPipelineComplete(results, verbose);
272
+ };
273
+ /**
274
+ * Run from functional testing to end
275
+ */
276
+ const runFromFunctionalTesting = async (options, config) => {
277
+ const { featureId, mcpServerUrl, mcpToken, verbose } = options;
278
+ logPipelineStart(featureId, verbose);
279
+ const results = [];
280
+ // 1. Functional Testing with retry loop for bug fixes
281
+ const testingResult = await handleTestFailuresWithRetry({
282
+ options,
283
+ config,
284
+ results,
285
+ verbose,
286
+ });
287
+ // Update final status based on functional testing result
288
+ const finalStatus = testingResult.status === 'success' ? 'testing_passed' : 'testing_failed';
289
+ await updateFeatureStatusForPhase({ mcpServerUrl, mcpToken }, featureId, finalStatus === 'testing_passed' ? 'testing-passed' : 'testing-failed', verbose);
290
+ // Create pull request if tests passed
291
+ if (testingResult.status === 'success') {
292
+ const prCreated = await handlePullRequestCreation({
293
+ featureId,
294
+ mcpServerUrl,
295
+ mcpToken,
296
+ results,
297
+ testingResult,
298
+ verbose,
299
+ });
300
+ // Continue with code review and refine workflow only if PR was created
301
+ if (prCreated) {
302
+ await continueWithCodeReviewAndRefine(options, config, results, verbose);
303
+ }
304
+ else {
305
+ if (verbose) {
306
+ console.log('⚠️ Skipping code review and refine workflow: pull request creation failed');
307
+ }
308
+ }
309
+ }
310
+ return logPipelineComplete(results, verbose);
311
+ };
312
+ /**
313
+ * Run only code refine phase (refine code based on PR feedback)
314
+ * Includes automatic retry loop for verification failures
315
+ */
316
+ const runOnlyCodeRefine = async (options, config) => {
317
+ const { featureId, verbose } = options;
318
+ logPipelineStart(featureId, verbose);
319
+ const results = [];
320
+ // Code Refine with automatic retry for verification failures
321
+ await handleCodeRefineWithRetry({
322
+ options,
323
+ config,
324
+ results,
325
+ verbose,
326
+ });
327
+ return logPipelineComplete(results, verbose);
328
+ };
329
+ /**
330
+ * Run only code review phase (review PR and create review comments)
331
+ */
332
+ const runOnlyCodeReview = async (options, config) => {
333
+ const { featureId, verbose } = options;
334
+ logPipelineStart(featureId, verbose);
335
+ const results = [];
336
+ // Code Review - analyze PR and create review comments
337
+ const reviewResult = await runCodeReviewPhase(options, config);
338
+ results.push(logPhaseResult(reviewResult, verbose));
339
+ return logPipelineComplete(results, verbose);
340
+ };
341
+ /**
342
+ * Run from code review to end (code-review → code-refine → code-refine-verification)
343
+ */
344
+ const runFromCodeReview = async (options, config) => {
345
+ const { featureId, verbose } = options;
346
+ logPipelineStart(featureId, verbose);
347
+ const results = [];
348
+ // 1. Code Review - analyze PR and create review comments
349
+ const reviewResult = await runCodeReviewPhase(options, config);
350
+ results.push(logPhaseResult(reviewResult, verbose));
351
+ if (!shouldContinuePipeline(results)) {
352
+ return logPipelineComplete(results, verbose);
353
+ }
354
+ // 2. Code Refine with automatic retry for verification failures
355
+ await handleCodeRefineWithRetry({
356
+ options,
357
+ config,
358
+ results,
359
+ verbose,
360
+ });
361
+ return logPipelineComplete(results, verbose);
362
+ };
363
+ /**
364
+ * Continue with code review and refine after PR creation
365
+ * This is the post-PR workflow: code-review → code-refine → code-refine-verification → code-testing
366
+ */
367
+ const continueWithCodeReviewAndRefine = async (options, config, results, verbose) => {
368
+ if (verbose) {
369
+ console.log('\n🔄 Continuing with code review and refine workflow...');
370
+ }
371
+ // 1. Code Review - analyze PR and create review comments
372
+ const reviewResult = await runCodeReviewPhase(options, config);
373
+ results.push(logPhaseResult(reviewResult, verbose));
374
+ if (!shouldContinuePipeline(results)) {
375
+ return;
376
+ }
377
+ // 2. Code Refine with automatic retry for verification failures
378
+ await handleCodeRefineWithRetry({
379
+ options,
380
+ config,
381
+ results,
382
+ verbose,
383
+ });
384
+ if (!shouldContinuePipeline(results)) {
385
+ return;
386
+ }
387
+ // 3. Code Testing - write automated tests for the implemented code
388
+ if (verbose) {
389
+ console.log('\n📝 Starting code testing phase...');
390
+ }
391
+ const testingResult = await runCodeTestingPhase(options, config);
392
+ results.push(logPhaseResult(testingResult, verbose));
393
+ };
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Main workflow processor for continuous feature development
3
+ * Monitors for ready_for_dev features and processes them through the complete pipeline
4
+ * Uses functional programming principles
5
+ */
6
+ import { EdsgerConfig } from '../types/index.js';
7
+ import { type WorkflowStats } from './core/state-manager.js';
8
+ export interface WorkflowOptions {
9
+ readonly productId: string;
10
+ readonly mcpServerUrl: string;
11
+ readonly mcpToken: string;
12
+ readonly pollInterval?: number;
13
+ readonly maxRetries?: number;
14
+ readonly verbose?: boolean;
15
+ }
16
+ export type { FeatureProcessingState, WorkflowStats, } from './core/state-manager.js';
17
+ /**
18
+ * Workflow processor using functional programming principles
19
+ */
20
+ export declare class WorkflowProcessor {
21
+ private readonly options;
22
+ private readonly config;
23
+ private isRunning;
24
+ private processedFeatures;
25
+ private pollTimer?;
26
+ constructor(options: WorkflowOptions, config: EdsgerConfig);
27
+ /**
28
+ * Start the workflow processor
29
+ */
30
+ start(): Promise<void>;
31
+ /**
32
+ * Stop the workflow processor
33
+ */
34
+ stop(): void;
35
+ /**
36
+ * Process the next available feature using functional composition
37
+ */
38
+ private processNextFeature;
39
+ /**
40
+ * Process a single feature through the complete pipeline using functional composition
41
+ */
42
+ private processFeature;
43
+ /**
44
+ * Get current processing statistics using pure function
45
+ */
46
+ getStats(): WorkflowStats;
47
+ }
48
+ /**
49
+ * Create and start a workflow processor using functional composition
50
+ */
51
+ export declare const startWorkflowProcessor: (options: WorkflowOptions, config: EdsgerConfig) => () => Promise<WorkflowProcessor>;
52
+ export { createInitialState, updateFeatureState, createProcessingState, createCompletedState, createFailedState, calculateStats, } from './core/state-manager.js';
53
+ export { shouldProcessFeature, findNextFeature } from './core/feature-filter.js';
54
+ export { evaluatePipelineResults } from './core/pipeline-evaluator.js';
@@ -0,0 +1,170 @@
1
+ /**
2
+ * Main workflow processor for continuous feature development
3
+ * Monitors for ready_for_dev features and processes them through the complete pipeline
4
+ * Uses functional programming principles
5
+ */
6
+ import { getReadyForDevFeatures } from '../api/features/index.js';
7
+ import { runFeatureWorkflow } from './feature-workflow-runner.js';
8
+ import { logInfo } from '../utils/logger.js';
9
+ // Import core modules
10
+ import { createInitialState, updateFeatureState, createProcessingState, createCompletedState, createFailedState, calculateStats, } from './core/state-manager.js';
11
+ import { findNextFeature } from './core/feature-filter.js';
12
+ import { evaluatePipelineResults } from './core/pipeline-evaluator.js';
13
+ import { logProcessingStart, logRetryInfo, logPipelineResults, logProcessorStart, logProcessorReady, logProcessorStop, logFeatureSuccess, logFeatureFailed, logFeatureError, logNoFeaturesFound, logAllFeaturesProcessed, logSkippingProcessing, logPollingError, logProcessNextFeatureError, } from './core/workflow-logger.js';
14
+ /**
15
+ * Workflow processor using functional programming principles
16
+ */
17
+ export class WorkflowProcessor {
18
+ options;
19
+ config;
20
+ isRunning = false;
21
+ processedFeatures = createInitialState();
22
+ pollTimer;
23
+ constructor(options, config) {
24
+ this.options = {
25
+ pollInterval: 30000, // 30 seconds default
26
+ maxRetries: 3,
27
+ verbose: false, // default value
28
+ ...options,
29
+ };
30
+ this.config = config;
31
+ }
32
+ /**
33
+ * Start the workflow processor
34
+ */
35
+ async start() {
36
+ if (this.isRunning) {
37
+ logInfo('Workflow processor is already running');
38
+ return;
39
+ }
40
+ this.isRunning = true;
41
+ logProcessorStart(this.options.productId, this.options.pollInterval);
42
+ // Initial check
43
+ await this.processNextFeature();
44
+ // Set up polling for new features
45
+ this.pollTimer = setInterval(() => {
46
+ this.processNextFeature().catch((error) => {
47
+ logPollingError(error);
48
+ });
49
+ }, this.options.pollInterval);
50
+ logProcessorReady();
51
+ }
52
+ /**
53
+ * Stop the workflow processor
54
+ */
55
+ stop() {
56
+ if (!this.isRunning) {
57
+ return;
58
+ }
59
+ this.isRunning = false;
60
+ if (this.pollTimer) {
61
+ clearInterval(this.pollTimer);
62
+ this.pollTimer = undefined;
63
+ }
64
+ logProcessorStop();
65
+ }
66
+ /**
67
+ * Process the next available feature using functional composition
68
+ */
69
+ async processNextFeature() {
70
+ try {
71
+ // Skip feature fetching if there are any features currently being processed
72
+ const stats = calculateStats(this.processedFeatures, this.isRunning);
73
+ if (stats.processing > 0) {
74
+ if (this.options.verbose) {
75
+ logSkippingProcessing(stats.processing);
76
+ }
77
+ return;
78
+ }
79
+ // Fetch features using unified API
80
+ const features = await getReadyForDevFeatures(this.options.mcpServerUrl, this.options.mcpToken, this.options.productId, this.options.verbose);
81
+ if (features.length === 0) {
82
+ if (this.options.verbose) {
83
+ logNoFeaturesFound();
84
+ }
85
+ return;
86
+ }
87
+ // Find next feature to process using pure functions
88
+ const nextFeature = findNextFeature(features, this.processedFeatures, this.options.maxRetries);
89
+ if (!nextFeature) {
90
+ if (this.options.verbose) {
91
+ logAllFeaturesProcessed();
92
+ }
93
+ return;
94
+ }
95
+ // Process the feature
96
+ await this.processFeature(nextFeature);
97
+ }
98
+ catch (error) {
99
+ logProcessNextFeatureError(error);
100
+ }
101
+ }
102
+ /**
103
+ * Process a single feature through the complete pipeline using functional composition
104
+ */
105
+ async processFeature(feature) {
106
+ const featureId = feature.id;
107
+ // Check if this is a reprocess due to feature update
108
+ const existingState = this.processedFeatures.get(featureId);
109
+ if (existingState &&
110
+ existingState.status === 'completed' &&
111
+ this.options.verbose) {
112
+ logInfo(`🔄 Reprocessing feature "${feature.name}" - detected status change`);
113
+ if (feature.updated_at) {
114
+ logInfo(` Previous process: ${existingState.lastAttempt.toISOString()}`);
115
+ logInfo(` Feature updated: ${feature.updated_at}`);
116
+ }
117
+ }
118
+ // Update state to processing using pure function
119
+ this.processedFeatures = updateFeatureState(this.processedFeatures, featureId, (currentState) => createProcessingState(featureId, currentState));
120
+ logProcessingStart(feature, this.options.verbose);
121
+ try {
122
+ // Run pipeline using feature workflow with execution mode support
123
+ const results = await runFeatureWorkflow({
124
+ featureId,
125
+ mcpServerUrl: this.options.mcpServerUrl,
126
+ mcpToken: this.options.mcpToken,
127
+ verbose: this.options.verbose,
128
+ }, this.config);
129
+ // Evaluate results using pure function
130
+ const allSuccessful = evaluatePipelineResults(results);
131
+ if (allSuccessful) {
132
+ // Mark as completed using pure function
133
+ this.processedFeatures = updateFeatureState(this.processedFeatures, featureId, (currentState) => createCompletedState(featureId, currentState));
134
+ logFeatureSuccess(feature.name);
135
+ logPipelineResults(results);
136
+ }
137
+ else {
138
+ // Mark as failed using pure function
139
+ this.processedFeatures = updateFeatureState(this.processedFeatures, featureId, (currentState) => createFailedState(featureId, currentState));
140
+ logFeatureFailed(feature.name);
141
+ logPipelineResults(results);
142
+ const currentState = this.processedFeatures.get(featureId);
143
+ logRetryInfo(feature.name, currentState.retryCount, this.options.maxRetries);
144
+ }
145
+ }
146
+ catch (error) {
147
+ // Mark as failed using pure function
148
+ this.processedFeatures = updateFeatureState(this.processedFeatures, featureId, (currentState) => createFailedState(featureId, currentState));
149
+ logFeatureError(feature.name, error);
150
+ }
151
+ }
152
+ /**
153
+ * Get current processing statistics using pure function
154
+ */
155
+ getStats() {
156
+ return calculateStats(this.processedFeatures, this.isRunning);
157
+ }
158
+ }
159
+ /**
160
+ * Create and start a workflow processor using functional composition
161
+ */
162
+ export const startWorkflowProcessor = (options, config) => async () => {
163
+ const processor = new WorkflowProcessor(options, config);
164
+ await processor.start();
165
+ return processor;
166
+ };
167
+ // Re-export core functions for testing and external use
168
+ export { createInitialState, updateFeatureState, createProcessingState, createCompletedState, createFailedState, calculateStats, } from './core/state-manager.js';
169
+ export { shouldProcessFeature, findNextFeature } from './core/feature-filter.js';
170
+ export { evaluatePipelineResults } from './core/pipeline-evaluator.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "edsger",
3
- "version": "0.41.1",
3
+ "version": "0.41.2",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "edsger": "dist/index.js"
@@ -1,4 +0,0 @@
1
- /**
2
- * Unit tests for phase quality criteria definitions
3
- */
4
- export {};