edsger 0.2.1 → 0.2.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 (178) hide show
  1. package/dist/api/features/feature-utils.d.ts +13 -0
  2. package/dist/api/features/feature-utils.js +46 -0
  3. package/dist/api/features/get-feature.d.ts +5 -0
  4. package/dist/api/features/get-feature.js +19 -0
  5. package/dist/api/features/index.d.ts +7 -0
  6. package/dist/api/features/index.js +9 -0
  7. package/dist/api/features/status-updater.d.ts +27 -0
  8. package/dist/api/features/status-updater.js +64 -0
  9. package/dist/api/features/test-cases.d.ts +21 -0
  10. package/dist/api/features/test-cases.js +63 -0
  11. package/dist/api/features/update-feature.d.ts +13 -0
  12. package/dist/api/features/update-feature.js +31 -0
  13. package/dist/api/features/user-stories.d.ts +21 -0
  14. package/dist/api/features/user-stories.js +63 -0
  15. package/dist/api/features.d.ts +100 -0
  16. package/dist/api/features.js +219 -0
  17. package/dist/api/mcp-client.d.ts +18 -0
  18. package/dist/api/mcp-client.js +58 -0
  19. package/dist/api/products.d.ts +10 -0
  20. package/dist/api/products.js +22 -0
  21. package/dist/api/test-reports.d.ts +9 -0
  22. package/dist/api/test-reports.js +25 -0
  23. package/dist/cli/commands/code-implementation-command.d.ts +2 -0
  24. package/dist/cli/commands/code-implementation-command.js +36 -0
  25. package/dist/cli/commands/code-review-command.d.ts +2 -0
  26. package/dist/cli/commands/code-review-command.js +39 -0
  27. package/dist/cli/commands/feature-analysis-command.d.ts +2 -0
  28. package/dist/cli/commands/feature-analysis-command.js +36 -0
  29. package/dist/cli/commands/functional-testing-command.d.ts +2 -0
  30. package/dist/cli/commands/functional-testing-command.js +36 -0
  31. package/dist/cli/commands/technical-design-command.d.ts +2 -0
  32. package/dist/cli/commands/technical-design-command.js +36 -0
  33. package/dist/cli/commands/workflow-command.d.ts +2 -0
  34. package/dist/cli/commands/workflow-command.js +34 -0
  35. package/dist/cli/formatters/code-implementation-formatter.d.ts +9 -0
  36. package/dist/cli/formatters/code-implementation-formatter.js +27 -0
  37. package/dist/cli/formatters/feature-analysis-formatter.d.ts +2 -0
  38. package/dist/cli/formatters/feature-analysis-formatter.js +27 -0
  39. package/dist/cli/formatters/functional-testing-formatter.d.ts +15 -0
  40. package/dist/cli/formatters/functional-testing-formatter.js +37 -0
  41. package/dist/cli/formatters/technical-design-formatter.d.ts +7 -0
  42. package/dist/cli/formatters/technical-design-formatter.js +30 -0
  43. package/dist/cli/index.d.ts +3 -0
  44. package/dist/cli/index.js +99 -0
  45. package/dist/cli/utils/validation.d.ts +25 -0
  46. package/dist/cli/utils/validation.js +58 -0
  47. package/dist/cli/utils/workflow-utils.d.ts +21 -0
  48. package/dist/cli/utils/workflow-utils.js +47 -0
  49. package/dist/cli.d.ts +1 -1
  50. package/dist/cli.js +11 -466
  51. package/dist/config.d.ts +1 -1
  52. package/dist/index.d.ts +3 -3
  53. package/dist/index.js +2 -2
  54. package/dist/{bug-fixing → phases/bug-fixing}/analyzer.d.ts +1 -1
  55. package/dist/{bug-fixing → phases/bug-fixing}/analyzer.js +1 -1
  56. package/dist/{bug-fixing → phases/bug-fixing}/context-fetcher.d.ts +4 -22
  57. package/dist/{bug-fixing → phases/bug-fixing}/context-fetcher.js +14 -58
  58. package/dist/{bug-fixing → phases/bug-fixing}/mcp-server.js +1 -30
  59. package/dist/phases/code-implementation/analyzer.d.ts +33 -0
  60. package/dist/{code-implementation → phases/code-implementation}/analyzer.js +174 -15
  61. package/dist/phases/code-implementation/context-fetcher.d.ts +17 -0
  62. package/dist/phases/code-implementation/context-fetcher.js +86 -0
  63. package/dist/{code-implementation → phases/code-implementation}/mcp-server.js +1 -30
  64. package/dist/{code-review → phases/code-review}/reviewer.d.ts +1 -1
  65. package/dist/{feature-analysis → phases/feature-analysis}/analyzer.d.ts +3 -2
  66. package/dist/{feature-analysis → phases/feature-analysis}/analyzer.js +29 -127
  67. package/dist/phases/feature-analysis/context-fetcher.d.ts +18 -0
  68. package/dist/phases/feature-analysis/context-fetcher.js +86 -0
  69. package/dist/{feature-analysis → phases/feature-analysis}/http-fallback.js +1 -1
  70. package/dist/{feature-analysis → phases/feature-analysis}/mcp-server.js +1 -24
  71. package/dist/{functional-testing → phases/functional-testing}/analyzer.d.ts +17 -2
  72. package/dist/{functional-testing → phases/functional-testing}/analyzer.js +225 -31
  73. package/dist/phases/functional-testing/context-fetcher.d.ts +16 -0
  74. package/dist/phases/functional-testing/context-fetcher.js +81 -0
  75. package/dist/{functional-testing → phases/functional-testing}/http-fallback.js +1 -1
  76. package/dist/{functional-testing → phases/functional-testing}/index.d.ts +1 -1
  77. package/dist/{functional-testing → phases/functional-testing}/index.js +1 -1
  78. package/dist/{functional-testing → phases/functional-testing}/mcp-server.js +1 -30
  79. package/dist/{functional-testing → phases/functional-testing}/test-report-creator.js +1 -1
  80. package/dist/phases/functional-testing/test-retry-handler.d.ts +16 -0
  81. package/dist/phases/functional-testing/test-retry-handler.js +75 -0
  82. package/dist/{pull-request → phases/pull-request}/creator.js +47 -6
  83. package/dist/phases/pull-request/handler.d.ts +16 -0
  84. package/dist/phases/pull-request/handler.js +60 -0
  85. package/dist/{technical-design → phases/technical-design}/analyzer.d.ts +7 -2
  86. package/dist/phases/technical-design/analyzer.js +418 -0
  87. package/dist/phases/technical-design/context-fetcher.d.ts +12 -0
  88. package/dist/phases/technical-design/context-fetcher.js +39 -0
  89. package/dist/{technical-design → phases/technical-design}/http-fallback.js +1 -1
  90. package/dist/{technical-design → phases/technical-design}/mcp-server.js +1 -30
  91. package/dist/prompts/bug-fixing.d.ts +2 -0
  92. package/dist/prompts/bug-fixing.js +63 -0
  93. package/dist/prompts/code-implementation.d.ts +3 -0
  94. package/dist/prompts/code-implementation.js +132 -0
  95. package/dist/prompts/feature-analysis.d.ts +3 -0
  96. package/dist/prompts/feature-analysis.js +149 -0
  97. package/dist/prompts/formatters.d.ts +29 -0
  98. package/dist/prompts/formatters.js +139 -0
  99. package/dist/prompts/functional-testing.d.ts +3 -0
  100. package/dist/prompts/functional-testing.js +126 -0
  101. package/dist/prompts/index.d.ts +6 -0
  102. package/dist/prompts/index.js +7 -0
  103. package/dist/prompts/technical-design.d.ts +3 -0
  104. package/dist/prompts/technical-design.js +130 -0
  105. package/dist/services/checklist.d.ts +99 -0
  106. package/dist/services/checklist.js +337 -0
  107. package/dist/types/features.d.ts +29 -0
  108. package/dist/types/features.js +1 -0
  109. package/dist/types/index.d.ts +112 -0
  110. package/dist/types/index.js +1 -0
  111. package/dist/types/pipeline.d.ts +25 -0
  112. package/dist/types/pipeline.js +4 -0
  113. package/dist/utils/logger.d.ts +19 -0
  114. package/dist/utils/logger.js +52 -0
  115. package/dist/utils/pipeline-logger.d.ts +8 -0
  116. package/dist/utils/pipeline-logger.js +35 -0
  117. package/dist/workflow-runner/config/phase-configs.d.ts +5 -0
  118. package/dist/workflow-runner/config/phase-configs.js +34 -0
  119. package/dist/workflow-runner/config/stage-configs.d.ts +5 -0
  120. package/dist/workflow-runner/config/stage-configs.js +34 -0
  121. package/dist/workflow-runner/core/feature-filter.d.ts +16 -0
  122. package/dist/workflow-runner/core/feature-filter.js +46 -0
  123. package/dist/workflow-runner/core/feature-filter.test.d.ts +4 -0
  124. package/dist/workflow-runner/core/feature-filter.test.js +127 -0
  125. package/dist/workflow-runner/core/index.d.ts +8 -0
  126. package/dist/workflow-runner/core/index.js +12 -0
  127. package/dist/workflow-runner/core/pipeline-evaluator.d.ts +24 -0
  128. package/dist/workflow-runner/core/pipeline-evaluator.js +32 -0
  129. package/dist/workflow-runner/core/state-manager.d.ts +24 -0
  130. package/dist/workflow-runner/core/state-manager.js +42 -0
  131. package/dist/workflow-runner/core/workflow-logger.d.ts +20 -0
  132. package/dist/workflow-runner/core/workflow-logger.js +65 -0
  133. package/dist/workflow-runner/executors/phase-executor.d.ts +8 -0
  134. package/dist/workflow-runner/executors/phase-executor.js +183 -0
  135. package/dist/workflow-runner/executors/stage-executor.d.ts +8 -0
  136. package/dist/workflow-runner/executors/stage-executor.js +49 -0
  137. package/dist/workflow-runner/feature-service.d.ts +17 -0
  138. package/dist/workflow-runner/feature-service.js +60 -0
  139. package/dist/workflow-runner/feature-workflow-runner.d.ts +26 -0
  140. package/dist/workflow-runner/feature-workflow-runner.js +113 -0
  141. package/dist/workflow-runner/index.d.ts +0 -1
  142. package/dist/workflow-runner/index.js +0 -1
  143. package/dist/workflow-runner/pipeline-runner.d.ts +9 -19
  144. package/dist/workflow-runner/pipeline-runner.js +247 -256
  145. package/dist/workflow-runner/pipeline.d.ts +18 -0
  146. package/dist/workflow-runner/pipeline.js +197 -0
  147. package/dist/workflow-runner/processor.d.ts +40 -0
  148. package/dist/workflow-runner/processor.js +191 -0
  149. package/dist/workflow-runner/types.d.ts +48 -0
  150. package/dist/workflow-runner/types.js +4 -0
  151. package/dist/workflow-runner/workflow-processor.d.ts +6 -23
  152. package/dist/workflow-runner/workflow-processor.js +38 -100
  153. package/package.json +1 -1
  154. package/dist/code-implementation/analyzer.d.ts +0 -19
  155. package/dist/code-implementation/context-fetcher.d.ts +0 -38
  156. package/dist/code-implementation/context-fetcher.js +0 -147
  157. package/dist/feature-analysis/context-fetcher.d.ts +0 -54
  158. package/dist/feature-analysis/context-fetcher.js +0 -193
  159. package/dist/functional-testing/context-fetcher.d.ts +0 -47
  160. package/dist/functional-testing/context-fetcher.js +0 -192
  161. package/dist/technical-design/analyzer.js +0 -338
  162. package/dist/technical-design/context-fetcher.d.ts +0 -42
  163. package/dist/technical-design/context-fetcher.js +0 -170
  164. /package/dist/{bug-fixing → phases/bug-fixing}/index.d.ts +0 -0
  165. /package/dist/{bug-fixing → phases/bug-fixing}/index.js +0 -0
  166. /package/dist/{bug-fixing → phases/bug-fixing}/mcp-server.d.ts +0 -0
  167. /package/dist/{code-implementation → phases/code-implementation}/mcp-server.d.ts +0 -0
  168. /package/dist/{code-review → phases/code-review}/reviewer.js +0 -0
  169. /package/dist/{feature-analysis → phases/feature-analysis}/http-fallback.d.ts +0 -0
  170. /package/dist/{feature-analysis → phases/feature-analysis}/index.d.ts +0 -0
  171. /package/dist/{feature-analysis → phases/feature-analysis}/index.js +0 -0
  172. /package/dist/{feature-analysis → phases/feature-analysis}/mcp-server.d.ts +0 -0
  173. /package/dist/{functional-testing → phases/functional-testing}/http-fallback.d.ts +0 -0
  174. /package/dist/{functional-testing → phases/functional-testing}/mcp-server.d.ts +0 -0
  175. /package/dist/{functional-testing → phases/functional-testing}/test-report-creator.d.ts +0 -0
  176. /package/dist/{pull-request → phases/pull-request}/creator.d.ts +0 -0
  177. /package/dist/{technical-design → phases/technical-design}/http-fallback.d.ts +0 -0
  178. /package/dist/{technical-design → phases/technical-design}/mcp-server.d.ts +0 -0
@@ -0,0 +1,197 @@
1
+ /**
2
+ * Pipeline execution logic for feature development workflow
3
+ */
4
+ import { updateFeatureStatusForStage } from './feature-service.js';
5
+ // Import phase analyzers
6
+ import { analyzeFeatureWithMCP, checkFeatureAnalysisRequirements, } from '../phases/feature-analysis/analyzer.js';
7
+ import { generateTechnicalDesign, checkTechnicalDesignRequirements, } from '../phases/technical-design/analyzer.js';
8
+ import { implementFeatureCode, checkCodeImplementationRequirements, } from '../phases/code-implementation/analyzer.js';
9
+ import { runFunctionalTesting, checkFunctionalTestingRequirements, } from '../phases/functional-testing/analyzer.js';
10
+ import { fixTestFailures, checkBugFixingRequirements, } from '../phases/bug-fixing/analyzer.js';
11
+ import { createPullRequest, updateFeatureWithPullRequest, } from '../phases/pull-request/creator.js';
12
+ import { getFeature } from '../api/features.js';
13
+ // Common requirements error message
14
+ const COMMON_REQUIREMENTS_ERROR = 'Requirements not met. Install with: npm install @anthropic-ai/claude-code zod';
15
+ // Pipeline stage configurations
16
+ const stageConfigs = [
17
+ {
18
+ name: 'feature-analysis',
19
+ checkRequirements: checkFeatureAnalysisRequirements,
20
+ execute: analyzeFeatureWithMCP,
21
+ requirementsError: `Feature analysis ${COMMON_REQUIREMENTS_ERROR}`,
22
+ },
23
+ {
24
+ name: 'technical-design',
25
+ checkRequirements: checkTechnicalDesignRequirements,
26
+ execute: generateTechnicalDesign,
27
+ requirementsError: `Technical design ${COMMON_REQUIREMENTS_ERROR}`,
28
+ },
29
+ {
30
+ name: 'code-implementation',
31
+ checkRequirements: checkCodeImplementationRequirements,
32
+ execute: implementFeatureCode,
33
+ requirementsError: `Code implementation ${COMMON_REQUIREMENTS_ERROR}`,
34
+ },
35
+ {
36
+ name: 'functional-testing',
37
+ checkRequirements: checkFunctionalTestingRequirements,
38
+ execute: runFunctionalTesting,
39
+ requirementsError: `Functional testing ${COMMON_REQUIREMENTS_ERROR}`,
40
+ },
41
+ ];
42
+ /**
43
+ * Execute a single pipeline stage
44
+ */
45
+ async function executeStage(stageConfig, options, config) {
46
+ const { featureId } = options;
47
+ try {
48
+ // Check requirements
49
+ if (!(await stageConfig.checkRequirements())) {
50
+ return {
51
+ featureId,
52
+ stage: stageConfig.name,
53
+ status: 'error',
54
+ message: stageConfig.requirementsError,
55
+ };
56
+ }
57
+ // Update status to indicate stage is starting
58
+ await updateFeatureStatusForStage(options.mcpServerUrl, options.mcpToken, featureId, stageConfig.name, options.verbose);
59
+ // Execute stage
60
+ const result = await stageConfig.execute(options, config);
61
+ return {
62
+ featureId,
63
+ stage: stageConfig.name,
64
+ status: 'success',
65
+ message: `${stageConfig.name} completed successfully`,
66
+ data: result,
67
+ };
68
+ }
69
+ catch (error) {
70
+ return {
71
+ featureId,
72
+ stage: stageConfig.name,
73
+ status: 'error',
74
+ message: `${stageConfig.name} failed: ${error instanceof Error ? error.message : String(error)}`,
75
+ };
76
+ }
77
+ }
78
+ /**
79
+ * Run the complete pipeline for a feature
80
+ */
81
+ export async function runCompletePipeline(options, config, githubConfig) {
82
+ const results = [];
83
+ for (const stageConfig of stageConfigs) {
84
+ const result = await executeStage(stageConfig, options, config);
85
+ results.push(result);
86
+ // Stop pipeline if stage failed
87
+ if (result.status === 'error') {
88
+ break;
89
+ }
90
+ }
91
+ // Handle testing failures with bug fixing
92
+ const lastResult = results[results.length - 1];
93
+ if (lastResult?.stage === 'functional-testing' &&
94
+ lastResult?.status === 'error') {
95
+ // Try bug fixing
96
+ try {
97
+ if (await checkBugFixingRequirements()) {
98
+ await updateFeatureStatusForStage(options.mcpServerUrl, options.mcpToken, options.featureId, 'bug-fixing', options.verbose);
99
+ const bugFixResult = await fixTestFailures({
100
+ ...options,
101
+ testErrors: 'Functional testing failed',
102
+ }, config);
103
+ results.push({
104
+ featureId: options.featureId,
105
+ stage: 'bug-fixing',
106
+ status: 'success',
107
+ message: 'Bug fixing completed',
108
+ data: bugFixResult,
109
+ });
110
+ // Retry functional testing
111
+ const functionalTestingStage = stageConfigs.find(stage => stage.name === 'functional-testing');
112
+ if (!functionalTestingStage) {
113
+ throw new Error('Functional testing stage configuration not found');
114
+ }
115
+ const retestResult = await executeStage(functionalTestingStage, options, config);
116
+ results.push(retestResult);
117
+ }
118
+ }
119
+ catch (error) {
120
+ results.push({
121
+ featureId: options.featureId,
122
+ stage: 'bug-fixing',
123
+ status: 'error',
124
+ message: `Bug fixing failed: ${error instanceof Error ? error.message : String(error)}`,
125
+ });
126
+ }
127
+ }
128
+ // Create pull request if GitHub configuration is provided and all stages succeeded
129
+ const allSuccessful = results.every((r) => r.status === 'success');
130
+ if (githubConfig && allSuccessful) {
131
+ try {
132
+ // Get feature details for PR creation
133
+ const feature = await getFeature(options.mcpServerUrl, options.mcpToken, options.featureId, options.verbose);
134
+ if (feature) {
135
+ const prConfig = {
136
+ githubToken: githubConfig.githubToken,
137
+ owner: githubConfig.githubOwner,
138
+ repo: githubConfig.githubRepo,
139
+ baseBranch: githubConfig.githubBaseBranch || 'main',
140
+ verbose: options.verbose,
141
+ };
142
+ // Convert API FeatureInfo to PR FeatureInfo format
143
+ const prFeature = {
144
+ id: feature.id,
145
+ name: feature.name,
146
+ description: feature.description || 'No description provided',
147
+ productId: feature.product_id,
148
+ technicalDesign: feature.technical_design,
149
+ testResult: undefined,
150
+ testReportUrl: undefined,
151
+ };
152
+ const prResult = await createPullRequest(prConfig, prFeature);
153
+ if (prResult.success && prResult.pullRequestUrl) {
154
+ // Update feature with PR URL
155
+ await updateFeatureWithPullRequest(options.mcpServerUrl, options.mcpToken, options.featureId, prResult.pullRequestUrl, options.verbose);
156
+ results.push({
157
+ featureId: options.featureId,
158
+ stage: 'pull-request',
159
+ status: 'success',
160
+ message: `Pull request created: ${prResult.pullRequestUrl}`,
161
+ data: prResult,
162
+ });
163
+ }
164
+ else {
165
+ results.push({
166
+ featureId: options.featureId,
167
+ stage: 'pull-request',
168
+ status: 'error',
169
+ message: `Pull request creation failed: ${prResult.error || 'Unknown error'}`,
170
+ });
171
+ }
172
+ }
173
+ }
174
+ catch (error) {
175
+ results.push({
176
+ featureId: options.featureId,
177
+ stage: 'pull-request',
178
+ status: 'error',
179
+ message: `Pull request creation failed: ${error instanceof Error ? error.message : String(error)}`,
180
+ });
181
+ }
182
+ }
183
+ return results;
184
+ }
185
+ /**
186
+ * Log pipeline results summary
187
+ */
188
+ export function logPipelineResults(results) {
189
+ console.log('\n' + '='.repeat(60));
190
+ console.log('📊 Pipeline Results Summary');
191
+ console.log('='.repeat(60));
192
+ results.forEach((result, index) => {
193
+ const statusIcon = result.status === 'success' ? '✅' : '❌';
194
+ console.log(`${index + 1}. ${statusIcon} ${result.stage}: ${result.message}`);
195
+ });
196
+ console.log('='.repeat(60) + '\n');
197
+ }
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Main workflow processor for continuous feature development
3
+ */
4
+ import { EdsgerConfig } from '../types.js';
5
+ import { WorkflowOptions, WorkflowStats } from './types.js';
6
+ /**
7
+ * Main workflow processor class
8
+ */
9
+ export declare class WorkflowProcessor {
10
+ private readonly options;
11
+ private readonly config;
12
+ private isRunning;
13
+ private processedFeatures;
14
+ private pollTimer?;
15
+ constructor(options: WorkflowOptions, config: EdsgerConfig);
16
+ /**
17
+ * Start the workflow processor
18
+ */
19
+ start(): Promise<void>;
20
+ /**
21
+ * Stop the workflow processor
22
+ */
23
+ stop(): void;
24
+ /**
25
+ * Process the next available feature
26
+ */
27
+ private processNextFeature;
28
+ /**
29
+ * Process a single feature through the complete pipeline
30
+ */
31
+ private processFeature;
32
+ /**
33
+ * Get current processing statistics
34
+ */
35
+ getStats(): WorkflowStats;
36
+ }
37
+ /**
38
+ * Create and start a workflow processor
39
+ */
40
+ export declare function startWorkflowProcessor(options: WorkflowOptions, config: EdsgerConfig): Promise<WorkflowProcessor>;
@@ -0,0 +1,191 @@
1
+ /**
2
+ * Main workflow processor for continuous feature development
3
+ */
4
+ import { logInfo, logError, logSuccess } from '../logger.js';
5
+ import { fetchReadyForDevFeatures } from './feature-service.js';
6
+ import { runCompletePipeline, logPipelineResults } from './pipeline.js';
7
+ /**
8
+ * Main workflow processor class
9
+ */
10
+ export class WorkflowProcessor {
11
+ options;
12
+ config;
13
+ isRunning = false;
14
+ processedFeatures = new Map();
15
+ pollTimer;
16
+ constructor(options, config) {
17
+ this.options = {
18
+ pollInterval: 30000, // 30 seconds default
19
+ maxRetries: 3,
20
+ verbose: false,
21
+ ...options,
22
+ };
23
+ this.config = config;
24
+ }
25
+ /**
26
+ * Start the workflow processor
27
+ */
28
+ async start() {
29
+ if (this.isRunning) {
30
+ logInfo('Workflow processor is already running');
31
+ return;
32
+ }
33
+ this.isRunning = true;
34
+ logInfo('🚀 Starting workflow processor...');
35
+ logInfo(`📋 Product ID: ${this.options.productId}`);
36
+ logInfo(`🔄 Poll interval: ${this.options.pollInterval}ms`);
37
+ // Initial check
38
+ await this.processNextFeature();
39
+ // Set up polling for new features
40
+ this.pollTimer = setInterval(() => {
41
+ this.processNextFeature().catch((error) => {
42
+ logError(`Error in polling cycle: ${error instanceof Error ? error.message : String(error)}`);
43
+ });
44
+ }, this.options.pollInterval);
45
+ logInfo('✅ Workflow processor started and monitoring for new features');
46
+ }
47
+ /**
48
+ * Stop the workflow processor
49
+ */
50
+ stop() {
51
+ if (!this.isRunning) {
52
+ return;
53
+ }
54
+ this.isRunning = false;
55
+ if (this.pollTimer) {
56
+ clearInterval(this.pollTimer);
57
+ this.pollTimer = undefined;
58
+ }
59
+ logInfo('⏹️ Workflow processor stopped');
60
+ }
61
+ /**
62
+ * Process the next available feature
63
+ */
64
+ async processNextFeature() {
65
+ try {
66
+ // Skip if features are being processed
67
+ const processing = Array.from(this.processedFeatures.values()).filter((s) => s.status === 'processing').length;
68
+ if (processing > 0) {
69
+ if (this.options.verbose) {
70
+ logInfo(`⏳ Skipping - ${processing} feature(s) being processed`);
71
+ }
72
+ return;
73
+ }
74
+ // Fetch ready features
75
+ const features = await fetchReadyForDevFeatures(this.options.mcpServerUrl, this.options.mcpToken, this.options.productId, this.options.verbose);
76
+ if (features.length === 0) {
77
+ if (this.options.verbose) {
78
+ logInfo('🔍 No ready_for_dev features found, continuing to monitor...');
79
+ }
80
+ return;
81
+ }
82
+ // Find next feature to process
83
+ const nextFeature = features.find((feature) => {
84
+ const state = this.processedFeatures.get(feature.id);
85
+ return (!state ||
86
+ (state.status === 'failed' &&
87
+ state.retryCount < this.options.maxRetries));
88
+ });
89
+ if (!nextFeature) {
90
+ if (this.options.verbose) {
91
+ logInfo('🔄 All features processed or being processed, continuing to monitor...');
92
+ }
93
+ return;
94
+ }
95
+ // Process the feature
96
+ await this.processFeature(nextFeature);
97
+ }
98
+ catch (error) {
99
+ logError(`Error in processNextFeature: ${error instanceof Error ? error.message : String(error)}`);
100
+ }
101
+ }
102
+ /**
103
+ * Process a single feature through the complete pipeline
104
+ */
105
+ async processFeature(feature) {
106
+ const featureId = feature.id;
107
+ const currentState = this.processedFeatures.get(featureId);
108
+ // Update state to processing
109
+ this.processedFeatures.set(featureId, {
110
+ featureId,
111
+ retryCount: currentState ? currentState.retryCount + 1 : 1,
112
+ lastAttempt: new Date(),
113
+ status: 'processing',
114
+ });
115
+ logInfo(`🎯 Processing feature: ${feature.name} (${feature.id})`);
116
+ if (this.options.verbose) {
117
+ logInfo(` Description: ${feature.description}`);
118
+ logInfo(` Status: ${feature.status}`);
119
+ }
120
+ try {
121
+ // Prepare GitHub configuration if provided
122
+ const githubConfig = this.options.githubToken && this.options.githubOwner && this.options.githubRepo
123
+ ? {
124
+ githubToken: this.options.githubToken,
125
+ githubOwner: this.options.githubOwner,
126
+ githubRepo: this.options.githubRepo,
127
+ githubBaseBranch: this.options.githubBaseBranch,
128
+ }
129
+ : undefined;
130
+ // Run complete pipeline
131
+ const results = await runCompletePipeline({
132
+ featureId,
133
+ mcpServerUrl: this.options.mcpServerUrl,
134
+ mcpToken: this.options.mcpToken,
135
+ verbose: this.options.verbose,
136
+ }, this.config, githubConfig);
137
+ // Check if all stages succeeded
138
+ const allSuccessful = results.every((r) => r.status === 'success');
139
+ if (allSuccessful) {
140
+ this.processedFeatures.set(featureId, {
141
+ featureId,
142
+ retryCount: this.processedFeatures.get(featureId).retryCount,
143
+ lastAttempt: new Date(),
144
+ status: 'completed',
145
+ });
146
+ logSuccess(`✅ Feature ${feature.name} completed successfully!`);
147
+ }
148
+ else {
149
+ this.processedFeatures.set(featureId, {
150
+ featureId,
151
+ retryCount: this.processedFeatures.get(featureId).retryCount,
152
+ lastAttempt: new Date(),
153
+ status: 'failed',
154
+ });
155
+ logError(`❌ Feature ${feature.name} failed in pipeline`);
156
+ }
157
+ // Log pipeline results
158
+ logPipelineResults(results);
159
+ }
160
+ catch (error) {
161
+ this.processedFeatures.set(featureId, {
162
+ featureId,
163
+ retryCount: this.processedFeatures.get(featureId).retryCount,
164
+ lastAttempt: new Date(),
165
+ status: 'failed',
166
+ });
167
+ logError(`❌ Error processing feature ${feature.name}: ${error instanceof Error ? error.message : String(error)}`);
168
+ }
169
+ }
170
+ /**
171
+ * Get current processing statistics
172
+ */
173
+ getStats() {
174
+ const states = Array.from(this.processedFeatures.values());
175
+ return {
176
+ totalProcessed: states.length,
177
+ completed: states.filter((s) => s.status === 'completed').length,
178
+ failed: states.filter((s) => s.status === 'failed').length,
179
+ processing: states.filter((s) => s.status === 'processing').length,
180
+ isRunning: this.isRunning,
181
+ };
182
+ }
183
+ }
184
+ /**
185
+ * Create and start a workflow processor
186
+ */
187
+ export async function startWorkflowProcessor(options, config) {
188
+ const processor = new WorkflowProcessor(options, config);
189
+ await processor.start();
190
+ return processor;
191
+ }
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Types and interfaces for workflow processor
3
+ */
4
+ import { EdsgerConfig } from '../types.js';
5
+ export interface WorkflowOptions {
6
+ readonly productId: string;
7
+ readonly mcpServerUrl: string;
8
+ readonly mcpToken: string;
9
+ readonly pollInterval?: number;
10
+ readonly maxRetries?: number;
11
+ readonly verbose?: boolean;
12
+ readonly githubToken?: string;
13
+ readonly githubOwner?: string;
14
+ readonly githubRepo?: string;
15
+ readonly githubBaseBranch?: string;
16
+ }
17
+ export interface PipelineStageOptions {
18
+ readonly featureId: string;
19
+ readonly mcpServerUrl: string;
20
+ readonly mcpToken: string;
21
+ readonly verbose?: boolean;
22
+ }
23
+ export interface PipelineResult {
24
+ readonly featureId: string;
25
+ readonly stage: string;
26
+ readonly status: 'success' | 'error';
27
+ readonly message: string;
28
+ readonly data?: unknown;
29
+ }
30
+ export interface FeatureProcessingState {
31
+ readonly featureId: string;
32
+ readonly retryCount: number;
33
+ readonly lastAttempt: Date;
34
+ readonly status: 'processing' | 'completed' | 'failed';
35
+ }
36
+ export interface WorkflowStats {
37
+ readonly totalProcessed: number;
38
+ readonly completed: number;
39
+ readonly failed: number;
40
+ readonly processing: number;
41
+ readonly isRunning: boolean;
42
+ }
43
+ export interface StageConfig {
44
+ readonly name: string;
45
+ readonly checkRequirements: () => Promise<boolean>;
46
+ readonly execute: (options: PipelineStageOptions, config: EdsgerConfig) => Promise<any>;
47
+ readonly requirementsError: string;
48
+ }
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Types and interfaces for workflow processor
3
+ */
4
+ export {};
@@ -3,9 +3,8 @@
3
3
  * Monitors for ready_for_dev features and processes them through the complete pipeline
4
4
  * Uses functional programming principles
5
5
  */
6
- import { EdsgerConfig } from '../types.js';
7
- import { FeatureInfo } from './feature-fetcher.js';
8
- import { PipelineResult } from './pipeline-runner.js';
6
+ import { EdsgerConfig } from '../types/index.js';
7
+ import { type WorkflowStats } from './core/state-manager.js';
9
8
  export interface WorkflowOptions {
10
9
  readonly productId: string;
11
10
  readonly mcpServerUrl: string;
@@ -14,25 +13,7 @@ export interface WorkflowOptions {
14
13
  readonly maxRetries?: number;
15
14
  readonly verbose?: boolean;
16
15
  }
17
- export interface FeatureProcessingState {
18
- readonly featureId: string;
19
- readonly retryCount: number;
20
- readonly lastAttempt: Date;
21
- readonly status: 'processing' | 'completed' | 'failed';
22
- }
23
- export interface WorkflowStats {
24
- readonly totalProcessed: number;
25
- readonly completed: number;
26
- readonly failed: number;
27
- readonly processing: number;
28
- readonly isRunning: boolean;
29
- }
30
- declare const createInitialState: () => Map<string, FeatureProcessingState>;
31
- declare const updateFeatureState: (states: Map<string, FeatureProcessingState>, featureId: string, updateFn: (currentState?: FeatureProcessingState) => FeatureProcessingState) => Map<string, FeatureProcessingState>;
32
- declare const shouldProcessFeature: (maxRetries: number) => (feature: FeatureInfo, states: Map<string, FeatureProcessingState>) => boolean;
33
- declare const findNextFeature: (features: readonly FeatureInfo[], states: Map<string, FeatureProcessingState>, maxRetries: number) => FeatureInfo | undefined;
34
- declare const evaluatePipelineResults: (results: readonly PipelineResult[]) => boolean;
35
- declare const calculateStats: (states: Map<string, FeatureProcessingState>, isRunning: boolean) => WorkflowStats;
16
+ export type { FeatureProcessingState, WorkflowStats, } from './core/state-manager.js';
36
17
  /**
37
18
  * Workflow processor using functional programming principles
38
19
  */
@@ -68,4 +49,6 @@ export declare class WorkflowProcessor {
68
49
  * Create and start a workflow processor using functional composition
69
50
  */
70
51
  export declare const startWorkflowProcessor: (options: WorkflowOptions, config: EdsgerConfig) => () => Promise<WorkflowProcessor>;
71
- export { createInitialState, updateFeatureState, shouldProcessFeature, findNextFeature, evaluatePipelineResults, calculateStats, };
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';