edsger 0.2.1 → 0.2.3

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 (182) 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 +178 -19
  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 +35 -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 +424 -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 +42 -0
  98. package/dist/prompts/formatters.js +168 -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/image-downloader.d.ts +32 -0
  114. package/dist/utils/image-downloader.js +144 -0
  115. package/dist/utils/image-processor.d.ts +5 -0
  116. package/dist/utils/image-processor.js +55 -0
  117. package/dist/utils/logger.d.ts +19 -0
  118. package/dist/utils/logger.js +52 -0
  119. package/dist/utils/pipeline-logger.d.ts +8 -0
  120. package/dist/utils/pipeline-logger.js +35 -0
  121. package/dist/workflow-runner/config/phase-configs.d.ts +5 -0
  122. package/dist/workflow-runner/config/phase-configs.js +34 -0
  123. package/dist/workflow-runner/config/stage-configs.d.ts +5 -0
  124. package/dist/workflow-runner/config/stage-configs.js +34 -0
  125. package/dist/workflow-runner/core/feature-filter.d.ts +16 -0
  126. package/dist/workflow-runner/core/feature-filter.js +46 -0
  127. package/dist/workflow-runner/core/feature-filter.test.d.ts +4 -0
  128. package/dist/workflow-runner/core/feature-filter.test.js +127 -0
  129. package/dist/workflow-runner/core/index.d.ts +8 -0
  130. package/dist/workflow-runner/core/index.js +12 -0
  131. package/dist/workflow-runner/core/pipeline-evaluator.d.ts +24 -0
  132. package/dist/workflow-runner/core/pipeline-evaluator.js +32 -0
  133. package/dist/workflow-runner/core/state-manager.d.ts +24 -0
  134. package/dist/workflow-runner/core/state-manager.js +42 -0
  135. package/dist/workflow-runner/core/workflow-logger.d.ts +20 -0
  136. package/dist/workflow-runner/core/workflow-logger.js +65 -0
  137. package/dist/workflow-runner/executors/phase-executor.d.ts +8 -0
  138. package/dist/workflow-runner/executors/phase-executor.js +183 -0
  139. package/dist/workflow-runner/executors/stage-executor.d.ts +8 -0
  140. package/dist/workflow-runner/executors/stage-executor.js +49 -0
  141. package/dist/workflow-runner/feature-service.d.ts +17 -0
  142. package/dist/workflow-runner/feature-service.js +60 -0
  143. package/dist/workflow-runner/feature-workflow-runner.d.ts +26 -0
  144. package/dist/workflow-runner/feature-workflow-runner.js +113 -0
  145. package/dist/workflow-runner/index.d.ts +0 -1
  146. package/dist/workflow-runner/index.js +0 -1
  147. package/dist/workflow-runner/pipeline-runner.d.ts +9 -19
  148. package/dist/workflow-runner/pipeline-runner.js +247 -256
  149. package/dist/workflow-runner/pipeline.d.ts +18 -0
  150. package/dist/workflow-runner/pipeline.js +197 -0
  151. package/dist/workflow-runner/processor.d.ts +40 -0
  152. package/dist/workflow-runner/processor.js +191 -0
  153. package/dist/workflow-runner/types.d.ts +48 -0
  154. package/dist/workflow-runner/types.js +4 -0
  155. package/dist/workflow-runner/workflow-processor.d.ts +6 -23
  156. package/dist/workflow-runner/workflow-processor.js +38 -100
  157. package/package.json +1 -1
  158. package/dist/code-implementation/analyzer.d.ts +0 -19
  159. package/dist/code-implementation/context-fetcher.d.ts +0 -38
  160. package/dist/code-implementation/context-fetcher.js +0 -147
  161. package/dist/feature-analysis/context-fetcher.d.ts +0 -54
  162. package/dist/feature-analysis/context-fetcher.js +0 -193
  163. package/dist/functional-testing/context-fetcher.d.ts +0 -47
  164. package/dist/functional-testing/context-fetcher.js +0 -192
  165. package/dist/technical-design/analyzer.js +0 -338
  166. package/dist/technical-design/context-fetcher.d.ts +0 -42
  167. package/dist/technical-design/context-fetcher.js +0 -170
  168. /package/dist/{bug-fixing → phases/bug-fixing}/index.d.ts +0 -0
  169. /package/dist/{bug-fixing → phases/bug-fixing}/index.js +0 -0
  170. /package/dist/{bug-fixing → phases/bug-fixing}/mcp-server.d.ts +0 -0
  171. /package/dist/{code-implementation → phases/code-implementation}/mcp-server.d.ts +0 -0
  172. /package/dist/{code-review → phases/code-review}/reviewer.js +0 -0
  173. /package/dist/{feature-analysis → phases/feature-analysis}/http-fallback.d.ts +0 -0
  174. /package/dist/{feature-analysis → phases/feature-analysis}/index.d.ts +0 -0
  175. /package/dist/{feature-analysis → phases/feature-analysis}/index.js +0 -0
  176. /package/dist/{feature-analysis → phases/feature-analysis}/mcp-server.d.ts +0 -0
  177. /package/dist/{functional-testing → phases/functional-testing}/http-fallback.d.ts +0 -0
  178. /package/dist/{functional-testing → phases/functional-testing}/mcp-server.d.ts +0 -0
  179. /package/dist/{functional-testing → phases/functional-testing}/test-report-creator.d.ts +0 -0
  180. /package/dist/{pull-request → phases/pull-request}/creator.d.ts +0 -0
  181. /package/dist/{technical-design → phases/technical-design}/http-fallback.d.ts +0 -0
  182. /package/dist/{technical-design → phases/technical-design}/mcp-server.d.ts +0 -0
@@ -1,273 +1,264 @@
1
1
  /**
2
- * Pipeline runner for executing development workflow stages
2
+ * Pipeline runner for executing development workflow phases
3
3
  * Coordinates feature-analysis -> technical-design -> code-implementation -> functional-testing
4
4
  * Uses functional programming principles
5
5
  */
6
- import { analyzeFeatureWithMCP, checkFeatureAnalysisRequirements, } from '../feature-analysis/analyzer.js';
7
- import { generateTechnicalDesign, checkTechnicalDesignRequirements, } from '../technical-design/analyzer.js';
8
- import { implementFeatureCode, checkCodeImplementationRequirements, } from '../code-implementation/analyzer.js';
9
- import { runFunctionalTesting, checkFunctionalTestingRequirements, } from '../functional-testing/analyzer.js';
10
- import { updateFeatureStatusForStage } from './status-updater.js';
11
- import { createPullRequest, updateFeatureWithPullRequest, } from '../pull-request/creator.js';
12
- import { getFeatureDetails } from './feature-fetcher.js';
13
- import { fixTestFailures, checkBugFixingRequirements, } from '../bug-fixing/analyzer.js';
14
- // Pipeline stage configurations
15
- const stageConfigs = [
16
- {
17
- name: 'feature-analysis',
18
- checkRequirements: checkFeatureAnalysisRequirements,
19
- execute: analyzeFeatureWithMCP,
20
- requirementsError: 'Feature analysis requirements not met. Install with: npm install @anthropic-ai/claude-code zod',
21
- },
22
- {
23
- name: 'technical-design',
24
- checkRequirements: checkTechnicalDesignRequirements,
25
- execute: generateTechnicalDesign,
26
- requirementsError: 'Technical design requirements not met. Install with: npm install @anthropic-ai/claude-code zod',
27
- },
28
- {
29
- name: 'code-implementation',
30
- checkRequirements: checkCodeImplementationRequirements,
31
- execute: implementFeatureCode,
32
- requirementsError: 'Code implementation requirements not met. Install with: npm install @anthropic-ai/claude-code zod',
33
- },
34
- {
35
- name: 'functional-testing',
36
- checkRequirements: checkFunctionalTestingRequirements,
37
- execute: runFunctionalTesting,
38
- requirementsError: 'Functional testing requirements not met. Install with: npm install @anthropic-ai/claude-code zod',
39
- },
40
- ];
41
- // Higher-order function for stage execution
42
- const createStageRunner = (stageConfig) => async (options, config) => {
6
+ import { updateFeatureStatusForPhase } from '../api/features/index.js';
7
+ import { runFeatureAnalysisPhase, runTechnicalDesignPhase, runCodeImplementationPhase, runFunctionalTestingPhase, } from './executors/phase-executor.js';
8
+ import { logPipelineStart, logPhaseResult, logPipelineComplete, shouldContinuePipeline, } from '../utils/pipeline-logger.js';
9
+ import { handleTestFailuresWithRetry } from '../phases/functional-testing/test-retry-handler.js';
10
+ import { handlePullRequestCreation } from '../phases/pull-request/handler.js';
11
+ /**
12
+ * Run pipeline based on execution mode
13
+ */
14
+ export const runPipelineByMode = async (options, config, executionMode) => {
15
+ const { featureId, verbose } = options;
16
+ if (verbose) {
17
+ console.log(`🚀 Starting pipeline with mode: ${executionMode} for feature: ${featureId}`);
18
+ console.log(`📋 Execution mode details:`);
19
+ console.log(` - Mode value: "${executionMode}"`);
20
+ console.log(` - Mode type: ${typeof executionMode}`);
21
+ console.log(` - Mode === 'only_feature_analysis': ${executionMode === 'only_feature_analysis'}`);
22
+ }
23
+ switch (executionMode) {
24
+ // Complete pipeline
25
+ case 'full_pipeline':
26
+ case 'from_feature_analysis':
27
+ if (verbose) {
28
+ console.log(` ➡️ Matched: full_pipeline or from_feature_analysis - running complete pipeline`);
29
+ }
30
+ return await runFromFeatureAnalysis(options, config);
31
+ // Feature Analysis
32
+ case 'only_feature_analysis':
33
+ if (verbose) {
34
+ console.log(` ➡️ Matched: only_feature_analysis - running analysis only`);
35
+ }
36
+ return await runOnlyFeatureAnalysis(options, config);
37
+ // Technical Design
38
+ case 'only_technical_design':
39
+ return await runOnlyTechnicalDesign(options, config);
40
+ case 'from_technical_design':
41
+ return await runFromTechnicalDesign(options, config);
42
+ // Code Implementation
43
+ case 'only_code_implementation':
44
+ return await runOnlyCodeImplementation(options, config);
45
+ case 'from_code_implementation':
46
+ return await runFromCodeImplementation(options, config);
47
+ // Functional Testing
48
+ case 'only_functional_testing':
49
+ return await runOnlyFunctionalTesting(options, config);
50
+ case 'from_functional_testing':
51
+ return await runFromFunctionalTesting(options, config);
52
+ default:
53
+ throw new Error(`Unsupported execution mode: ${executionMode}`);
54
+ }
55
+ };
56
+ /**
57
+ * Run complete pipeline for a feature using functional composition (legacy)
58
+ */
59
+ export const runCompletePipeline = (options, config) => {
60
+ return async () => {
61
+ return await runFromFeatureAnalysis(options, config);
62
+ };
63
+ };
64
+ // Helper functions for different execution patterns
65
+ /**
66
+ * Run only feature analysis phase
67
+ */
68
+ const runOnlyFeatureAnalysis = async (options, config) => {
69
+ const { featureId, verbose } = options;
70
+ logPipelineStart(featureId, verbose);
71
+ const results = [];
72
+ const analysisResult = await runFeatureAnalysisPhase(options, config);
73
+ results.push(logPhaseResult(analysisResult, verbose));
74
+ return logPipelineComplete(results, verbose);
75
+ };
76
+ /**
77
+ * Run only technical design phase
78
+ */
79
+ const runOnlyTechnicalDesign = async (options, config) => {
80
+ const { featureId, verbose } = options;
81
+ logPipelineStart(featureId, verbose);
82
+ const results = [];
83
+ const designResult = await runTechnicalDesignPhase(options, config);
84
+ results.push(logPhaseResult(designResult, verbose));
85
+ return logPipelineComplete(results, verbose);
86
+ };
87
+ /**
88
+ * Run only code implementation phase
89
+ */
90
+ const runOnlyCodeImplementation = async (options, config) => {
91
+ const { featureId, verbose } = options;
92
+ logPipelineStart(featureId, verbose);
93
+ const results = [];
94
+ const implementationResult = await runCodeImplementationPhase(options, config);
95
+ results.push(logPhaseResult(implementationResult, verbose));
96
+ return logPipelineComplete(results, verbose);
97
+ };
98
+ /**
99
+ * Run only functional testing phase
100
+ */
101
+ const runOnlyFunctionalTesting = async (options, config) => {
102
+ const { featureId, verbose } = options;
103
+ logPipelineStart(featureId, verbose);
104
+ const results = [];
105
+ const testingResult = await runFunctionalTestingPhase(options, config);
106
+ results.push(logPhaseResult(testingResult, verbose));
107
+ return logPipelineComplete(results, verbose);
108
+ };
109
+ /**
110
+ * Run from feature analysis to end
111
+ */
112
+ const runFromFeatureAnalysis = async (options, config) => {
43
113
  const { featureId, mcpServerUrl, mcpToken, verbose } = options;
44
- const { name, checkRequirements, execute, requirementsError } = stageConfig;
45
- try {
46
- // Check requirements
47
- const hasRequirements = await checkRequirements();
48
- if (!hasRequirements) {
49
- return {
50
- featureId,
51
- stage: name,
52
- status: 'error',
53
- message: requirementsError,
54
- };
55
- }
56
- // Update feature status to reflect current stage
57
- await updateFeatureStatusForStage({ mcpServerUrl, mcpToken }, featureId, name, verbose);
58
- if (verbose) {
59
- console.log(`🎯 Starting ${name} for: ${featureId}`);
60
- }
61
- const result = await execute(options, config);
62
- return {
63
- featureId,
64
- stage: name,
65
- status: result.status === 'success' ? 'success' : 'error',
66
- message: result.status === 'success'
67
- ? `${name.replace('-', ' ')} completed successfully`
68
- : `${name.replace('-', ' ')} failed`,
69
- data: result,
70
- };
114
+ logPipelineStart(featureId, verbose);
115
+ const results = [];
116
+ // 1. Feature Analysis
117
+ const analysisResult = await runFeatureAnalysisPhase(options, config);
118
+ results.push(logPhaseResult(analysisResult, verbose));
119
+ if (!shouldContinuePipeline(results)) {
120
+ return logPipelineComplete(results, verbose);
71
121
  }
72
- catch (error) {
73
- return {
122
+ // 2. Technical Design
123
+ const designResult = await runTechnicalDesignPhase(options, config);
124
+ results.push(logPhaseResult(designResult, verbose));
125
+ if (!shouldContinuePipeline(results)) {
126
+ return logPipelineComplete(results, verbose);
127
+ }
128
+ // 3. Code Implementation
129
+ const implementationResult = await runCodeImplementationPhase(options, config);
130
+ results.push(logPhaseResult(implementationResult, verbose));
131
+ if (!shouldContinuePipeline(results)) {
132
+ return logPipelineComplete(results, verbose);
133
+ }
134
+ // 4. Functional Testing with retry loop for bug fixes
135
+ const testingResult = await handleTestFailuresWithRetry({
136
+ options,
137
+ config,
138
+ results,
139
+ verbose,
140
+ });
141
+ // Update final status based on functional testing result
142
+ const finalStatus = testingResult.status === 'success' ? 'testing_passed' : 'testing_failed';
143
+ await updateFeatureStatusForPhase({ mcpServerUrl, mcpToken }, featureId, finalStatus === 'testing_passed' ? 'testing-passed' : 'testing-failed', verbose);
144
+ // Create pull request if tests passed
145
+ if (testingResult.status === 'success') {
146
+ await handlePullRequestCreation({
74
147
  featureId,
75
- stage: name,
76
- status: 'error',
77
- message: `${name.replace('-', ' ')} failed: ${error instanceof Error ? error.message : String(error)}`,
78
- };
148
+ mcpServerUrl,
149
+ mcpToken,
150
+ results,
151
+ testingResult,
152
+ verbose,
153
+ });
79
154
  }
155
+ return logPipelineComplete(results, verbose);
80
156
  };
81
- // Create stage runners using the configuration
82
- const [runFeatureAnalysisStage, runTechnicalDesignStage, runCodeImplementationStage, runFunctionalTestingStage,] = stageConfigs.map(createStageRunner);
83
- // Pipeline execution utilities
84
- const logPipelineStart = (featureId, verbose) => {
85
- if (verbose) {
86
- console.log(`🚀 Starting complete pipeline for feature: ${featureId}`);
87
- console.log('📋 Pipeline stages: feature-analysis → technical-design → code-implementation → functional-testing');
157
+ /**
158
+ * Run from technical design to end
159
+ */
160
+ const runFromTechnicalDesign = async (options, config) => {
161
+ const { featureId, mcpServerUrl, mcpToken, verbose } = options;
162
+ logPipelineStart(featureId, verbose);
163
+ const results = [];
164
+ // 1. Technical Design
165
+ const designResult = await runTechnicalDesignPhase(options, config);
166
+ results.push(logPhaseResult(designResult, verbose));
167
+ if (!shouldContinuePipeline(results)) {
168
+ return logPipelineComplete(results, verbose);
88
169
  }
89
- };
90
- const logStageResult = (result, verbose) => {
91
- if (verbose) {
92
- const statusIcon = result.status === 'success' ? '✅' : '❌';
93
- console.log(`${statusIcon} ${result.stage}: ${result.message}`);
170
+ // 2. Code Implementation
171
+ const implementationResult = await runCodeImplementationPhase(options, config);
172
+ results.push(logPhaseResult(implementationResult, verbose));
173
+ if (!shouldContinuePipeline(results)) {
174
+ return logPipelineComplete(results, verbose);
94
175
  }
95
- return result;
96
- };
97
- const logPipelineComplete = (results, verbose) => {
98
- if (verbose) {
99
- const lastResult = results[results.length - 1];
100
- const featureId = lastResult?.featureId;
101
- if (lastResult?.status === 'success') {
102
- console.log(`✅ Complete pipeline finished successfully for feature: ${featureId}`);
103
- }
104
- else {
105
- console.log(`❌ Pipeline failed at ${lastResult?.stage}: ${lastResult?.message}`);
106
- }
176
+ // 3. Functional Testing with retry loop for bug fixes
177
+ const testingResult = await handleTestFailuresWithRetry({
178
+ options,
179
+ config,
180
+ results,
181
+ verbose,
182
+ });
183
+ // Update final status based on functional testing result
184
+ const finalStatus = testingResult.status === 'success' ? 'testing_passed' : 'testing_failed';
185
+ await updateFeatureStatusForPhase({ mcpServerUrl, mcpToken }, featureId, finalStatus === 'testing_passed' ? 'testing-passed' : 'testing-failed', verbose);
186
+ // Create pull request if tests passed
187
+ if (testingResult.status === 'success') {
188
+ await handlePullRequestCreation({
189
+ featureId,
190
+ mcpServerUrl,
191
+ mcpToken,
192
+ results,
193
+ testingResult,
194
+ verbose,
195
+ });
107
196
  }
108
- return results;
109
- };
110
- // Pure function to check if pipeline should continue
111
- const shouldContinuePipeline = (results) => {
112
- const lastResult = results[results.length - 1];
113
- return lastResult?.status === 'success';
197
+ return logPipelineComplete(results, verbose);
114
198
  };
115
199
  /**
116
- * Run complete pipeline for a feature using functional composition
200
+ * Run from code implementation to end
117
201
  */
118
- export const runCompletePipeline = (options, config) => {
119
- const { featureId, verbose } = options;
120
- return async () => {
121
- logPipelineStart(featureId, verbose);
122
- const results = [];
123
- // Feature Analysis
124
- const analysisResult = await runFeatureAnalysisStage(options, config);
125
- results.push(logStageResult(analysisResult, verbose));
126
- if (!shouldContinuePipeline(results)) {
127
- return logPipelineComplete(results, verbose);
128
- }
129
- // Technical Design
130
- const designResult = await runTechnicalDesignStage(options, config);
131
- results.push(logStageResult(designResult, verbose));
132
- if (!shouldContinuePipeline(results)) {
133
- return logPipelineComplete(results, verbose);
134
- }
135
- // Code Implementation
136
- const implementationResult = await runCodeImplementationStage(options, config);
137
- results.push(logStageResult(implementationResult, verbose));
138
- if (!shouldContinuePipeline(results)) {
139
- return logPipelineComplete(results, verbose);
140
- }
141
- // Functional Testing with retry loop for bug fixes
142
- const MAX_FIX_ATTEMPTS = 3;
143
- let testingResult;
144
- let fixAttempt = 0;
145
- do {
146
- // Run functional testing
147
- testingResult = await runFunctionalTestingStage(options, config);
148
- results.push(logStageResult(testingResult, verbose));
149
- // If tests failed and we haven't exceeded max attempts, try to fix
150
- if (testingResult.status === 'error' && fixAttempt < MAX_FIX_ATTEMPTS) {
151
- fixAttempt++;
152
- if (verbose) {
153
- console.log(`🔧 Tests failed. Attempting to fix bugs (Attempt ${fixAttempt}/${MAX_FIX_ATTEMPTS})...`);
154
- }
155
- // Check if bug fixing requirements are met
156
- const hasBugFixingReqs = await checkBugFixingRequirements();
157
- if (!hasBugFixingReqs) {
158
- if (verbose) {
159
- console.log('⚠️ Bug fixing requirements not met. Skipping automatic fixes.');
160
- }
161
- break;
162
- }
163
- // Extract test errors from the testing result
164
- const testErrors = testingResult.data?.testResult || testingResult.message;
165
- // Run bug fixing
166
- const fixResult = await fixTestFailures({
167
- featureId,
168
- mcpServerUrl: options.mcpServerUrl,
169
- mcpToken: options.mcpToken,
170
- testErrors,
171
- attemptNumber: fixAttempt,
172
- verbose,
173
- }, config);
174
- if (fixResult.status === 'success') {
175
- if (verbose) {
176
- console.log(`✅ Bug fixes applied. Re-running tests...`);
177
- if (fixResult.filesFixed && fixResult.filesFixed.length > 0) {
178
- console.log(` Files fixed: ${fixResult.filesFixed.join(', ')}`);
179
- }
180
- }
181
- // Remove the previous failed test result from results
182
- results.pop();
183
- // Update status to indicate we're retrying tests
184
- await updateFeatureStatusForStage({ mcpServerUrl: options.mcpServerUrl, mcpToken: options.mcpToken }, featureId, 'functional-testing', verbose);
185
- }
186
- else {
187
- if (verbose) {
188
- console.log(`❌ Bug fixing failed: ${fixResult.message}`);
189
- }
190
- break;
191
- }
192
- }
193
- else {
194
- // Tests passed or max attempts reached
195
- break;
196
- }
197
- } while (fixAttempt <= MAX_FIX_ATTEMPTS);
198
- // Log if max attempts reached
199
- if (testingResult.status === 'error' &&
200
- fixAttempt >= MAX_FIX_ATTEMPTS &&
201
- verbose) {
202
- console.log(`⚠️ Maximum fix attempts (${MAX_FIX_ATTEMPTS}) reached. Tests still failing.`);
203
- }
204
- // Update final status based on functional testing result
205
- const { mcpServerUrl, mcpToken } = options;
206
- const finalStatus = testingResult.status === 'success' ? 'testing_passed' : 'testing_failed';
207
- await updateFeatureStatusForStage({ mcpServerUrl, mcpToken }, featureId, finalStatus === 'testing_passed' ? 'testing-passed' : 'testing-failed', verbose);
208
- // Create pull request if tests passed
209
- if (testingResult.status === 'success') {
210
- if (verbose) {
211
- console.log('🔄 Creating pull request for successful feature...');
212
- }
213
- // Get feature details for PR creation
214
- const getFeature = getFeatureDetails(featureId, {
215
- mcpServerUrl,
216
- mcpToken,
217
- verbose,
218
- });
219
- const feature = await getFeature();
220
- if (feature) {
221
- // Get GitHub configuration from environment
222
- const githubToken = process.env.GITHUB_TOKEN || process.env.GITHUB_ACCESS_TOKEN;
223
- const githubOwner = process.env.GITHUB_OWNER;
224
- const githubRepo = process.env.GITHUB_REPO;
225
- if (githubToken && githubOwner && githubRepo) {
226
- const prResult = await createPullRequest({
227
- githubToken,
228
- owner: githubOwner,
229
- repo: githubRepo,
230
- baseBranch: 'main',
231
- verbose,
232
- }, {
233
- id: feature.id,
234
- name: feature.name,
235
- description: feature.description,
236
- productId: feature.product_id,
237
- // Get technical design and test result from previous stages
238
- technicalDesign: results.find((r) => r.stage === 'technical-design')?.data?.technicalDesign,
239
- testResult: testingResult.data?.testResult,
240
- testReportUrl: testingResult.data?.testReport
241
- ?.testReportUrl,
242
- });
243
- if (prResult.success && prResult.pullRequestUrl) {
244
- // Update feature with PR URL and status
245
- await updateFeatureWithPullRequest(mcpServerUrl, mcpToken, featureId, prResult.pullRequestUrl, verbose);
246
- if (verbose) {
247
- console.log(`✅ Pull request created and feature updated to ready_for_review`);
248
- }
249
- }
250
- else {
251
- if (verbose) {
252
- console.log(`⚠️ Pull request creation failed: ${prResult.error}`);
253
- }
254
- }
255
- }
256
- else {
257
- if (verbose) {
258
- console.log('⚠️ GitHub configuration not found. Skipping pull request creation.');
259
- console.log(' Set GITHUB_TOKEN, GITHUB_OWNER, and GITHUB_REPO environment variables.');
260
- }
261
- }
262
- }
263
- else {
264
- if (verbose) {
265
- console.log('⚠️ Could not fetch feature details for pull request creation');
266
- }
267
- }
268
- }
202
+ const runFromCodeImplementation = async (options, config) => {
203
+ const { featureId, mcpServerUrl, mcpToken, verbose } = options;
204
+ logPipelineStart(featureId, verbose);
205
+ const results = [];
206
+ // 1. Code Implementation
207
+ const implementationResult = await runCodeImplementationPhase(options, config);
208
+ results.push(logPhaseResult(implementationResult, verbose));
209
+ if (!shouldContinuePipeline(results)) {
269
210
  return logPipelineComplete(results, verbose);
270
- };
211
+ }
212
+ // 2. Functional Testing with retry loop for bug fixes
213
+ const testingResult = await handleTestFailuresWithRetry({
214
+ options,
215
+ config,
216
+ results,
217
+ verbose,
218
+ });
219
+ // Update final status based on functional testing result
220
+ const finalStatus = testingResult.status === 'success' ? 'testing_passed' : 'testing_failed';
221
+ await updateFeatureStatusForPhase({ mcpServerUrl, mcpToken }, featureId, finalStatus === 'testing_passed' ? 'testing-passed' : 'testing-failed', verbose);
222
+ // Create pull request if tests passed
223
+ if (testingResult.status === 'success') {
224
+ await handlePullRequestCreation({
225
+ featureId,
226
+ mcpServerUrl,
227
+ mcpToken,
228
+ results,
229
+ testingResult,
230
+ verbose,
231
+ });
232
+ }
233
+ return logPipelineComplete(results, verbose);
234
+ };
235
+ /**
236
+ * Run from functional testing to end
237
+ */
238
+ const runFromFunctionalTesting = async (options, config) => {
239
+ const { featureId, mcpServerUrl, mcpToken, verbose } = options;
240
+ logPipelineStart(featureId, verbose);
241
+ const results = [];
242
+ // 1. Functional Testing with retry loop for bug fixes
243
+ const testingResult = await handleTestFailuresWithRetry({
244
+ options,
245
+ config,
246
+ results,
247
+ verbose,
248
+ });
249
+ // Update final status based on functional testing result
250
+ const finalStatus = testingResult.status === 'success' ? 'testing_passed' : 'testing_failed';
251
+ await updateFeatureStatusForPhase({ mcpServerUrl, mcpToken }, featureId, finalStatus === 'testing_passed' ? 'testing-passed' : 'testing-failed', verbose);
252
+ // Create pull request if tests passed
253
+ if (testingResult.status === 'success') {
254
+ await handlePullRequestCreation({
255
+ featureId,
256
+ mcpServerUrl,
257
+ mcpToken,
258
+ results,
259
+ testingResult,
260
+ verbose,
261
+ });
262
+ }
263
+ return logPipelineComplete(results, verbose);
271
264
  };
272
- // Export individual stage runners for granular control
273
- export { runFeatureAnalysisStage, runTechnicalDesignStage, runCodeImplementationStage, runFunctionalTestingStage, };
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Pipeline execution logic for feature development workflow
3
+ */
4
+ import { EdsgerConfig } from '../types.js';
5
+ import { PipelineStageOptions, PipelineResult } from './types.js';
6
+ /**
7
+ * Run the complete pipeline for a feature
8
+ */
9
+ export declare function runCompletePipeline(options: PipelineStageOptions, config: EdsgerConfig, githubConfig?: {
10
+ githubToken: string;
11
+ githubOwner: string;
12
+ githubRepo: string;
13
+ githubBaseBranch?: string;
14
+ }): Promise<PipelineResult[]>;
15
+ /**
16
+ * Log pipeline results summary
17
+ */
18
+ export declare function logPipelineResults(results: readonly PipelineResult[]): void;