edsger 0.2.0 → 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.
- package/dist/api/features/feature-utils.d.ts +13 -0
- package/dist/api/features/feature-utils.js +46 -0
- package/dist/api/features/get-feature.d.ts +5 -0
- package/dist/api/features/get-feature.js +19 -0
- package/dist/api/features/index.d.ts +7 -0
- package/dist/api/features/index.js +9 -0
- package/dist/api/features/status-updater.d.ts +27 -0
- package/dist/api/features/status-updater.js +64 -0
- package/dist/api/features/test-cases.d.ts +21 -0
- package/dist/api/features/test-cases.js +63 -0
- package/dist/api/features/update-feature.d.ts +13 -0
- package/dist/api/features/update-feature.js +31 -0
- package/dist/api/features/user-stories.d.ts +21 -0
- package/dist/api/features/user-stories.js +63 -0
- package/dist/api/features.d.ts +100 -0
- package/dist/api/features.js +219 -0
- package/dist/api/mcp-client.d.ts +18 -0
- package/dist/api/mcp-client.js +58 -0
- package/dist/api/products.d.ts +10 -0
- package/dist/api/products.js +22 -0
- package/dist/api/test-reports.d.ts +9 -0
- package/dist/api/test-reports.js +25 -0
- package/dist/cli/commands/code-implementation-command.d.ts +2 -0
- package/dist/cli/commands/code-implementation-command.js +36 -0
- package/dist/cli/commands/code-review-command.d.ts +2 -0
- package/dist/cli/commands/code-review-command.js +39 -0
- package/dist/cli/commands/feature-analysis-command.d.ts +2 -0
- package/dist/cli/commands/feature-analysis-command.js +36 -0
- package/dist/cli/commands/functional-testing-command.d.ts +2 -0
- package/dist/cli/commands/functional-testing-command.js +36 -0
- package/dist/cli/commands/technical-design-command.d.ts +2 -0
- package/dist/cli/commands/technical-design-command.js +36 -0
- package/dist/cli/commands/workflow-command.d.ts +2 -0
- package/dist/cli/commands/workflow-command.js +34 -0
- package/dist/cli/formatters/code-implementation-formatter.d.ts +9 -0
- package/dist/cli/formatters/code-implementation-formatter.js +27 -0
- package/dist/cli/formatters/feature-analysis-formatter.d.ts +2 -0
- package/dist/cli/formatters/feature-analysis-formatter.js +27 -0
- package/dist/cli/formatters/functional-testing-formatter.d.ts +15 -0
- package/dist/cli/formatters/functional-testing-formatter.js +37 -0
- package/dist/cli/formatters/technical-design-formatter.d.ts +7 -0
- package/dist/cli/formatters/technical-design-formatter.js +30 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.js +99 -0
- package/dist/cli/utils/validation.d.ts +25 -0
- package/dist/cli/utils/validation.js +58 -0
- package/dist/cli/utils/workflow-utils.d.ts +21 -0
- package/dist/cli/utils/workflow-utils.js +47 -0
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +11 -466
- package/dist/config.d.ts +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +2 -2
- package/dist/{bug-fixing → phases/bug-fixing}/analyzer.d.ts +1 -1
- package/dist/{bug-fixing → phases/bug-fixing}/analyzer.js +1 -1
- package/dist/{bug-fixing → phases/bug-fixing}/context-fetcher.d.ts +4 -22
- package/dist/{bug-fixing → phases/bug-fixing}/context-fetcher.js +14 -58
- package/dist/{bug-fixing → phases/bug-fixing}/mcp-server.js +1 -30
- package/dist/phases/code-implementation/analyzer.d.ts +33 -0
- package/dist/{code-implementation → phases/code-implementation}/analyzer.js +174 -15
- package/dist/phases/code-implementation/context-fetcher.d.ts +17 -0
- package/dist/phases/code-implementation/context-fetcher.js +86 -0
- package/dist/{code-implementation → phases/code-implementation}/mcp-server.js +1 -30
- package/dist/{code-review → phases/code-review}/reviewer.d.ts +1 -1
- package/dist/{feature-analysis → phases/feature-analysis}/analyzer.d.ts +3 -2
- package/dist/{feature-analysis → phases/feature-analysis}/analyzer.js +29 -127
- package/dist/phases/feature-analysis/context-fetcher.d.ts +18 -0
- package/dist/phases/feature-analysis/context-fetcher.js +86 -0
- package/dist/{feature-analysis → phases/feature-analysis}/http-fallback.js +1 -1
- package/dist/{feature-analysis → phases/feature-analysis}/mcp-server.js +1 -24
- package/dist/{functional-testing → phases/functional-testing}/analyzer.d.ts +17 -2
- package/dist/{functional-testing → phases/functional-testing}/analyzer.js +225 -31
- package/dist/phases/functional-testing/context-fetcher.d.ts +16 -0
- package/dist/phases/functional-testing/context-fetcher.js +81 -0
- package/dist/{functional-testing → phases/functional-testing}/http-fallback.js +1 -1
- package/dist/{functional-testing → phases/functional-testing}/index.d.ts +1 -1
- package/dist/{functional-testing → phases/functional-testing}/index.js +1 -1
- package/dist/{functional-testing → phases/functional-testing}/mcp-server.js +1 -30
- package/dist/{functional-testing → phases/functional-testing}/test-report-creator.d.ts +26 -0
- package/dist/{functional-testing → phases/functional-testing}/test-report-creator.js +87 -5
- package/dist/phases/functional-testing/test-retry-handler.d.ts +16 -0
- package/dist/phases/functional-testing/test-retry-handler.js +75 -0
- package/dist/{pull-request → phases/pull-request}/creator.js +47 -6
- package/dist/phases/pull-request/handler.d.ts +16 -0
- package/dist/phases/pull-request/handler.js +60 -0
- package/dist/{technical-design → phases/technical-design}/analyzer.d.ts +7 -2
- package/dist/phases/technical-design/analyzer.js +418 -0
- package/dist/phases/technical-design/context-fetcher.d.ts +12 -0
- package/dist/phases/technical-design/context-fetcher.js +39 -0
- package/dist/{technical-design → phases/technical-design}/http-fallback.js +1 -1
- package/dist/{technical-design → phases/technical-design}/mcp-server.js +1 -30
- package/dist/prompts/bug-fixing.d.ts +2 -0
- package/dist/prompts/bug-fixing.js +63 -0
- package/dist/prompts/code-implementation.d.ts +3 -0
- package/dist/prompts/code-implementation.js +132 -0
- package/dist/prompts/feature-analysis.d.ts +3 -0
- package/dist/prompts/feature-analysis.js +149 -0
- package/dist/prompts/formatters.d.ts +29 -0
- package/dist/prompts/formatters.js +139 -0
- package/dist/prompts/functional-testing.d.ts +3 -0
- package/dist/prompts/functional-testing.js +126 -0
- package/dist/prompts/index.d.ts +6 -0
- package/dist/prompts/index.js +7 -0
- package/dist/prompts/technical-design.d.ts +3 -0
- package/dist/prompts/technical-design.js +130 -0
- package/dist/services/checklist.d.ts +99 -0
- package/dist/services/checklist.js +337 -0
- package/dist/types/features.d.ts +29 -0
- package/dist/types/features.js +1 -0
- package/dist/types/index.d.ts +112 -0
- package/dist/types/index.js +1 -0
- package/dist/types/pipeline.d.ts +25 -0
- package/dist/types/pipeline.js +4 -0
- package/dist/utils/logger.d.ts +19 -0
- package/dist/utils/logger.js +52 -0
- package/dist/utils/pipeline-logger.d.ts +8 -0
- package/dist/utils/pipeline-logger.js +35 -0
- package/dist/workflow-runner/config/phase-configs.d.ts +5 -0
- package/dist/workflow-runner/config/phase-configs.js +34 -0
- package/dist/workflow-runner/config/stage-configs.d.ts +5 -0
- package/dist/workflow-runner/config/stage-configs.js +34 -0
- package/dist/workflow-runner/core/feature-filter.d.ts +16 -0
- package/dist/workflow-runner/core/feature-filter.js +46 -0
- package/dist/workflow-runner/core/feature-filter.test.d.ts +4 -0
- package/dist/workflow-runner/core/feature-filter.test.js +127 -0
- package/dist/workflow-runner/core/index.d.ts +8 -0
- package/dist/workflow-runner/core/index.js +12 -0
- package/dist/workflow-runner/core/pipeline-evaluator.d.ts +24 -0
- package/dist/workflow-runner/core/pipeline-evaluator.js +32 -0
- package/dist/workflow-runner/core/state-manager.d.ts +24 -0
- package/dist/workflow-runner/core/state-manager.js +42 -0
- package/dist/workflow-runner/core/workflow-logger.d.ts +20 -0
- package/dist/workflow-runner/core/workflow-logger.js +65 -0
- package/dist/workflow-runner/executors/phase-executor.d.ts +8 -0
- package/dist/workflow-runner/executors/phase-executor.js +183 -0
- package/dist/workflow-runner/executors/stage-executor.d.ts +8 -0
- package/dist/workflow-runner/executors/stage-executor.js +49 -0
- package/dist/workflow-runner/feature-service.d.ts +17 -0
- package/dist/workflow-runner/feature-service.js +60 -0
- package/dist/workflow-runner/feature-workflow-runner.d.ts +26 -0
- package/dist/workflow-runner/feature-workflow-runner.js +113 -0
- package/dist/workflow-runner/index.d.ts +0 -1
- package/dist/workflow-runner/index.js +0 -1
- package/dist/workflow-runner/pipeline-runner.d.ts +9 -19
- package/dist/workflow-runner/pipeline-runner.js +247 -256
- package/dist/workflow-runner/pipeline.d.ts +18 -0
- package/dist/workflow-runner/pipeline.js +197 -0
- package/dist/workflow-runner/processor.d.ts +40 -0
- package/dist/workflow-runner/processor.js +191 -0
- package/dist/workflow-runner/types.d.ts +48 -0
- package/dist/workflow-runner/types.js +4 -0
- package/dist/workflow-runner/workflow-processor.d.ts +6 -23
- package/dist/workflow-runner/workflow-processor.js +38 -100
- package/package.json +2 -2
- package/dist/code-implementation/analyzer.d.ts +0 -19
- package/dist/code-implementation/context-fetcher.d.ts +0 -38
- package/dist/code-implementation/context-fetcher.js +0 -147
- package/dist/feature-analysis/context-fetcher.d.ts +0 -54
- package/dist/feature-analysis/context-fetcher.js +0 -193
- package/dist/functional-testing/context-fetcher.d.ts +0 -47
- package/dist/functional-testing/context-fetcher.js +0 -192
- package/dist/technical-design/analyzer.js +0 -338
- package/dist/technical-design/context-fetcher.d.ts +0 -42
- package/dist/technical-design/context-fetcher.js +0 -170
- /package/dist/{bug-fixing → phases/bug-fixing}/index.d.ts +0 -0
- /package/dist/{bug-fixing → phases/bug-fixing}/index.js +0 -0
- /package/dist/{bug-fixing → phases/bug-fixing}/mcp-server.d.ts +0 -0
- /package/dist/{code-implementation → phases/code-implementation}/mcp-server.d.ts +0 -0
- /package/dist/{code-review → phases/code-review}/reviewer.js +0 -0
- /package/dist/{feature-analysis → phases/feature-analysis}/http-fallback.d.ts +0 -0
- /package/dist/{feature-analysis → phases/feature-analysis}/index.d.ts +0 -0
- /package/dist/{feature-analysis → phases/feature-analysis}/index.js +0 -0
- /package/dist/{feature-analysis → phases/feature-analysis}/mcp-server.d.ts +0 -0
- /package/dist/{functional-testing → phases/functional-testing}/http-fallback.d.ts +0 -0
- /package/dist/{functional-testing → phases/functional-testing}/mcp-server.d.ts +0 -0
- /package/dist/{pull-request → phases/pull-request}/creator.d.ts +0 -0
- /package/dist/{technical-design → phases/technical-design}/http-fallback.d.ts +0 -0
- /package/dist/{technical-design → phases/technical-design}/mcp-server.d.ts +0 -0
|
@@ -3,80 +3,14 @@
|
|
|
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 {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
//
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
newStates.set(featureId, updateFn(currentState));
|
|
15
|
-
return newStates;
|
|
16
|
-
};
|
|
17
|
-
const createProcessingState = (featureId, currentState) => ({
|
|
18
|
-
featureId,
|
|
19
|
-
retryCount: currentState ? currentState.retryCount + 1 : 1,
|
|
20
|
-
lastAttempt: new Date(),
|
|
21
|
-
status: 'processing',
|
|
22
|
-
});
|
|
23
|
-
const createCompletedState = (featureId, currentState) => ({
|
|
24
|
-
featureId,
|
|
25
|
-
retryCount: currentState ? currentState.retryCount : 1,
|
|
26
|
-
lastAttempt: new Date(),
|
|
27
|
-
status: 'completed',
|
|
28
|
-
});
|
|
29
|
-
const createFailedState = (featureId, currentState) => ({
|
|
30
|
-
featureId,
|
|
31
|
-
retryCount: currentState ? currentState.retryCount : 1,
|
|
32
|
-
lastAttempt: new Date(),
|
|
33
|
-
status: 'failed',
|
|
34
|
-
});
|
|
35
|
-
// Feature filtering functions (pure)
|
|
36
|
-
const shouldProcessFeature = (maxRetries) => (feature, states) => {
|
|
37
|
-
const state = states.get(feature.id);
|
|
38
|
-
return (!state || (state.status === 'failed' && state.retryCount < maxRetries));
|
|
39
|
-
};
|
|
40
|
-
const findNextFeature = (features, states, maxRetries) => features.find((feature) => shouldProcessFeature(maxRetries)(feature, states));
|
|
41
|
-
// Pipeline result evaluation (pure)
|
|
42
|
-
const evaluatePipelineResults = (results) => results.every((result) => result.status === 'success');
|
|
43
|
-
// Logging functions (side effects contained)
|
|
44
|
-
const logPipelineResults = (results) => {
|
|
45
|
-
console.log('\\n' + '='.repeat(60));
|
|
46
|
-
console.log('📊 Pipeline Results Summary');
|
|
47
|
-
console.log('='.repeat(60));
|
|
48
|
-
results.forEach((result, index) => {
|
|
49
|
-
const statusIcon = result.status === 'success' ? '✅' : '❌';
|
|
50
|
-
console.log(`${index + 1}. ${statusIcon} ${result.stage}: ${result.message}`);
|
|
51
|
-
});
|
|
52
|
-
console.log('='.repeat(60) + '\\n');
|
|
53
|
-
};
|
|
54
|
-
const logProcessingStart = (feature, verbose) => {
|
|
55
|
-
logInfo(`🎯 Processing feature: ${feature.name} (${feature.id})`);
|
|
56
|
-
if (verbose) {
|
|
57
|
-
logInfo(` Description: ${feature.description}`);
|
|
58
|
-
logInfo(` Last updated: ${feature.updated_at}`);
|
|
59
|
-
}
|
|
60
|
-
};
|
|
61
|
-
const logRetryInfo = (featureName, retryCount, maxRetries) => {
|
|
62
|
-
if (retryCount < maxRetries) {
|
|
63
|
-
logInfo(`🔄 Will retry feature ${featureName} (attempt ${retryCount + 1}/${maxRetries})`);
|
|
64
|
-
}
|
|
65
|
-
else {
|
|
66
|
-
logError(`⛔ Max retries reached for feature ${featureName}, marking as permanently failed`);
|
|
67
|
-
}
|
|
68
|
-
};
|
|
69
|
-
// Statistics calculation (pure)
|
|
70
|
-
const calculateStats = (states, isRunning) => {
|
|
71
|
-
const stateArray = Array.from(states.values());
|
|
72
|
-
return {
|
|
73
|
-
totalProcessed: stateArray.length,
|
|
74
|
-
completed: stateArray.filter((s) => s.status === 'completed').length,
|
|
75
|
-
failed: stateArray.filter((s) => s.status === 'failed').length,
|
|
76
|
-
processing: stateArray.filter((s) => s.status === 'processing').length,
|
|
77
|
-
isRunning,
|
|
78
|
-
};
|
|
79
|
-
};
|
|
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';
|
|
80
14
|
/**
|
|
81
15
|
* Workflow processor using functional programming principles
|
|
82
16
|
*/
|
|
@@ -104,18 +38,16 @@ export class WorkflowProcessor {
|
|
|
104
38
|
return;
|
|
105
39
|
}
|
|
106
40
|
this.isRunning = true;
|
|
107
|
-
|
|
108
|
-
logInfo(`📋 Product ID: ${this.options.productId}`);
|
|
109
|
-
logInfo(`🔄 Poll interval: ${this.options.pollInterval}ms`);
|
|
41
|
+
logProcessorStart(this.options.productId, this.options.pollInterval);
|
|
110
42
|
// Initial check
|
|
111
43
|
await this.processNextFeature();
|
|
112
44
|
// Set up polling for new features
|
|
113
45
|
this.pollTimer = setInterval(() => {
|
|
114
46
|
this.processNextFeature().catch((error) => {
|
|
115
|
-
|
|
47
|
+
logPollingError(error);
|
|
116
48
|
});
|
|
117
49
|
}, this.options.pollInterval);
|
|
118
|
-
|
|
50
|
+
logProcessorReady();
|
|
119
51
|
}
|
|
120
52
|
/**
|
|
121
53
|
* Stop the workflow processor
|
|
@@ -129,7 +61,7 @@ export class WorkflowProcessor {
|
|
|
129
61
|
clearInterval(this.pollTimer);
|
|
130
62
|
this.pollTimer = undefined;
|
|
131
63
|
}
|
|
132
|
-
|
|
64
|
+
logProcessorStop();
|
|
133
65
|
}
|
|
134
66
|
/**
|
|
135
67
|
* Process the next available feature using functional composition
|
|
@@ -140,21 +72,15 @@ export class WorkflowProcessor {
|
|
|
140
72
|
const stats = calculateStats(this.processedFeatures, this.isRunning);
|
|
141
73
|
if (stats.processing > 0) {
|
|
142
74
|
if (this.options.verbose) {
|
|
143
|
-
|
|
75
|
+
logSkippingProcessing(stats.processing);
|
|
144
76
|
}
|
|
145
77
|
return;
|
|
146
78
|
}
|
|
147
|
-
// Fetch features using
|
|
148
|
-
const
|
|
149
|
-
mcpServerUrl: this.options.mcpServerUrl,
|
|
150
|
-
mcpToken: this.options.mcpToken,
|
|
151
|
-
productId: this.options.productId,
|
|
152
|
-
verbose: this.options.verbose,
|
|
153
|
-
});
|
|
154
|
-
const features = await fetchFeatures();
|
|
79
|
+
// Fetch features using unified API
|
|
80
|
+
const features = await getReadyForDevFeatures(this.options.mcpServerUrl, this.options.mcpToken, this.options.productId, this.options.verbose);
|
|
155
81
|
if (features.length === 0) {
|
|
156
82
|
if (this.options.verbose) {
|
|
157
|
-
|
|
83
|
+
logNoFeaturesFound();
|
|
158
84
|
}
|
|
159
85
|
return;
|
|
160
86
|
}
|
|
@@ -162,7 +88,7 @@ export class WorkflowProcessor {
|
|
|
162
88
|
const nextFeature = findNextFeature(features, this.processedFeatures, this.options.maxRetries);
|
|
163
89
|
if (!nextFeature) {
|
|
164
90
|
if (this.options.verbose) {
|
|
165
|
-
|
|
91
|
+
logAllFeaturesProcessed();
|
|
166
92
|
}
|
|
167
93
|
return;
|
|
168
94
|
}
|
|
@@ -170,7 +96,7 @@ export class WorkflowProcessor {
|
|
|
170
96
|
await this.processFeature(nextFeature);
|
|
171
97
|
}
|
|
172
98
|
catch (error) {
|
|
173
|
-
|
|
99
|
+
logProcessNextFeatureError(error);
|
|
174
100
|
}
|
|
175
101
|
}
|
|
176
102
|
/**
|
|
@@ -178,30 +104,40 @@ export class WorkflowProcessor {
|
|
|
178
104
|
*/
|
|
179
105
|
async processFeature(feature) {
|
|
180
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
|
+
}
|
|
181
118
|
// Update state to processing using pure function
|
|
182
119
|
this.processedFeatures = updateFeatureState(this.processedFeatures, featureId, (currentState) => createProcessingState(featureId, currentState));
|
|
183
120
|
logProcessingStart(feature, this.options.verbose);
|
|
184
121
|
try {
|
|
185
|
-
// Run pipeline using
|
|
186
|
-
const
|
|
122
|
+
// Run pipeline using feature workflow with execution mode support
|
|
123
|
+
const results = await runFeatureWorkflow({
|
|
187
124
|
featureId,
|
|
188
125
|
mcpServerUrl: this.options.mcpServerUrl,
|
|
189
126
|
mcpToken: this.options.mcpToken,
|
|
190
127
|
verbose: this.options.verbose,
|
|
191
128
|
}, this.config);
|
|
192
|
-
const results = await runPipeline();
|
|
193
129
|
// Evaluate results using pure function
|
|
194
130
|
const allSuccessful = evaluatePipelineResults(results);
|
|
195
131
|
if (allSuccessful) {
|
|
196
132
|
// Mark as completed using pure function
|
|
197
133
|
this.processedFeatures = updateFeatureState(this.processedFeatures, featureId, (currentState) => createCompletedState(featureId, currentState));
|
|
198
|
-
|
|
134
|
+
logFeatureSuccess(feature.name);
|
|
199
135
|
logPipelineResults(results);
|
|
200
136
|
}
|
|
201
137
|
else {
|
|
202
138
|
// Mark as failed using pure function
|
|
203
139
|
this.processedFeatures = updateFeatureState(this.processedFeatures, featureId, (currentState) => createFailedState(featureId, currentState));
|
|
204
|
-
|
|
140
|
+
logFeatureFailed(feature.name);
|
|
205
141
|
logPipelineResults(results);
|
|
206
142
|
const currentState = this.processedFeatures.get(featureId);
|
|
207
143
|
logRetryInfo(feature.name, currentState.retryCount, this.options.maxRetries);
|
|
@@ -210,7 +146,7 @@ export class WorkflowProcessor {
|
|
|
210
146
|
catch (error) {
|
|
211
147
|
// Mark as failed using pure function
|
|
212
148
|
this.processedFeatures = updateFeatureState(this.processedFeatures, featureId, (currentState) => createFailedState(featureId, currentState));
|
|
213
|
-
|
|
149
|
+
logFeatureError(feature.name, error);
|
|
214
150
|
}
|
|
215
151
|
}
|
|
216
152
|
/**
|
|
@@ -228,5 +164,7 @@ export const startWorkflowProcessor = (options, config) => async () => {
|
|
|
228
164
|
await processor.start();
|
|
229
165
|
return processor;
|
|
230
166
|
};
|
|
231
|
-
//
|
|
232
|
-
export { createInitialState, updateFeatureState,
|
|
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.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"description": "AI-powered software development CLI tool with comprehensive feature management, code review, technical design, implementation, and testing capabilities using Claude Code SDK and MCP integration",
|
|
33
33
|
"repository": {
|
|
34
34
|
"type": "git",
|
|
35
|
-
"url": "https://github.com/
|
|
35
|
+
"url": "git+https://github.com/stevenzg/edsger.git"
|
|
36
36
|
},
|
|
37
37
|
"engines": {
|
|
38
38
|
"node": ">=18.0.0"
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { EdsgerConfig } from '../types.js';
|
|
2
|
-
export interface CodeImplementationOptions {
|
|
3
|
-
featureId: string;
|
|
4
|
-
mcpServerUrl: string;
|
|
5
|
-
mcpToken: string;
|
|
6
|
-
verbose?: boolean;
|
|
7
|
-
baseBranch?: string;
|
|
8
|
-
}
|
|
9
|
-
export interface CodeImplementationResult {
|
|
10
|
-
featureId: string;
|
|
11
|
-
branchName: string;
|
|
12
|
-
implementationSummary: string | null;
|
|
13
|
-
status: 'success' | 'error';
|
|
14
|
-
message: string;
|
|
15
|
-
filesModified?: string[];
|
|
16
|
-
commitHash?: string;
|
|
17
|
-
}
|
|
18
|
-
export declare const implementFeatureCode: (options: CodeImplementationOptions, config: EdsgerConfig) => Promise<CodeImplementationResult>;
|
|
19
|
-
export declare const checkCodeImplementationRequirements: () => Promise<boolean>;
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
export interface CodeImplementationContext {
|
|
2
|
-
feature: {
|
|
3
|
-
id: string;
|
|
4
|
-
name: string;
|
|
5
|
-
description?: string;
|
|
6
|
-
technical_design?: string;
|
|
7
|
-
status: string;
|
|
8
|
-
product_id: string;
|
|
9
|
-
};
|
|
10
|
-
product: {
|
|
11
|
-
id: string;
|
|
12
|
-
name: string;
|
|
13
|
-
description?: string;
|
|
14
|
-
[key: string]: any;
|
|
15
|
-
};
|
|
16
|
-
user_stories: Array<{
|
|
17
|
-
id: string;
|
|
18
|
-
title: string;
|
|
19
|
-
description: string;
|
|
20
|
-
status: string;
|
|
21
|
-
[key: string]: any;
|
|
22
|
-
}>;
|
|
23
|
-
test_cases: Array<{
|
|
24
|
-
id: string;
|
|
25
|
-
name: string;
|
|
26
|
-
description: string;
|
|
27
|
-
is_critical: boolean;
|
|
28
|
-
[key: string]: any;
|
|
29
|
-
}>;
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* Fetch all code implementation context information via MCP endpoints
|
|
33
|
-
*/
|
|
34
|
-
export declare function fetchCodeImplementationContext(mcpServerUrl: string, mcpToken: string, featureId: string, verbose?: boolean): Promise<CodeImplementationContext>;
|
|
35
|
-
/**
|
|
36
|
-
* Format the context into a readable string for Claude Code
|
|
37
|
-
*/
|
|
38
|
-
export declare function formatContextForPrompt(context: CodeImplementationContext): string;
|
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
import { logInfo, logError } from '../logger.js';
|
|
2
|
-
// Helper function to make HTTP requests to the MCP server
|
|
3
|
-
async function callMcpEndpoint(mcpServerUrl, mcpToken, method, params) {
|
|
4
|
-
try {
|
|
5
|
-
const response = await fetch(`${mcpServerUrl}/mcp`, {
|
|
6
|
-
method: 'POST',
|
|
7
|
-
headers: {
|
|
8
|
-
'Content-Type': 'application/json',
|
|
9
|
-
Authorization: `Bearer ${mcpToken}`,
|
|
10
|
-
},
|
|
11
|
-
body: JSON.stringify({
|
|
12
|
-
jsonrpc: '2.0',
|
|
13
|
-
method,
|
|
14
|
-
params,
|
|
15
|
-
id: Math.random().toString(36).substring(7),
|
|
16
|
-
}),
|
|
17
|
-
});
|
|
18
|
-
if (!response.ok) {
|
|
19
|
-
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
20
|
-
}
|
|
21
|
-
const data = await response.json();
|
|
22
|
-
if (data.error) {
|
|
23
|
-
throw new Error(data.error.message || 'MCP call failed');
|
|
24
|
-
}
|
|
25
|
-
return data.result;
|
|
26
|
-
}
|
|
27
|
-
catch (error) {
|
|
28
|
-
console.error(`MCP call failed for ${method}:`, error instanceof Error ? error.message : String(error));
|
|
29
|
-
throw error;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Fetch all code implementation context information via MCP endpoints
|
|
34
|
-
*/
|
|
35
|
-
export async function fetchCodeImplementationContext(mcpServerUrl, mcpToken, featureId, verbose) {
|
|
36
|
-
try {
|
|
37
|
-
if (verbose) {
|
|
38
|
-
logInfo(`Fetching complete implementation context for feature: ${featureId}`);
|
|
39
|
-
}
|
|
40
|
-
// Step 1: Get feature details
|
|
41
|
-
if (verbose) {
|
|
42
|
-
logInfo('1/4 Fetching feature details...');
|
|
43
|
-
}
|
|
44
|
-
const featureResult = (await callMcpEndpoint(mcpServerUrl, mcpToken, 'features/get', { feature_id: featureId }));
|
|
45
|
-
if (!featureResult.features || featureResult.features.length === 0) {
|
|
46
|
-
throw new Error(`Feature not found: ${featureId}`);
|
|
47
|
-
}
|
|
48
|
-
const feature = featureResult.features[0];
|
|
49
|
-
// Step 2: Get product details
|
|
50
|
-
if (verbose) {
|
|
51
|
-
logInfo('2/4 Fetching product details...');
|
|
52
|
-
}
|
|
53
|
-
const productResult = (await callMcpEndpoint(mcpServerUrl, mcpToken, 'resources/read', {
|
|
54
|
-
uri: `product://${feature.product_id}`,
|
|
55
|
-
}));
|
|
56
|
-
const productText = productResult.contents?.[0]?.text || '{}';
|
|
57
|
-
let product;
|
|
58
|
-
try {
|
|
59
|
-
product = JSON.parse(productText);
|
|
60
|
-
}
|
|
61
|
-
catch {
|
|
62
|
-
product = {
|
|
63
|
-
id: feature.product_id,
|
|
64
|
-
name: 'Unknown Product',
|
|
65
|
-
description: 'Product information could not be loaded',
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
// Step 3: Get user stories
|
|
69
|
-
if (verbose) {
|
|
70
|
-
logInfo('3/4 Fetching user stories...');
|
|
71
|
-
}
|
|
72
|
-
const userStoriesResult = (await callMcpEndpoint(mcpServerUrl, mcpToken, 'user_stories/list', { feature_id: featureId }));
|
|
73
|
-
const user_stories = (userStoriesResult.user_stories || []);
|
|
74
|
-
// Step 4: Get test cases
|
|
75
|
-
if (verbose) {
|
|
76
|
-
logInfo('4/4 Fetching test cases...');
|
|
77
|
-
}
|
|
78
|
-
const testCasesResult = (await callMcpEndpoint(mcpServerUrl, mcpToken, 'test_cases/list', { feature_id: featureId }));
|
|
79
|
-
const test_cases = (testCasesResult.test_cases || []);
|
|
80
|
-
// Log summary if verbose
|
|
81
|
-
if (verbose) {
|
|
82
|
-
logInfo(`✅ Context fetched successfully:`);
|
|
83
|
-
logInfo(` Feature: ${feature.name}`);
|
|
84
|
-
logInfo(` Product: ${product.name}`);
|
|
85
|
-
logInfo(` User Stories: ${user_stories.length}`);
|
|
86
|
-
logInfo(` Test Cases: ${test_cases.length} (${test_cases.filter((tc) => tc.is_critical).length} critical)`);
|
|
87
|
-
logInfo(` Technical Design: ${feature.technical_design ? 'Available' : 'Not available'}`);
|
|
88
|
-
}
|
|
89
|
-
return {
|
|
90
|
-
feature,
|
|
91
|
-
product,
|
|
92
|
-
user_stories,
|
|
93
|
-
test_cases,
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
catch (error) {
|
|
97
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
98
|
-
logError(`Failed to fetch code implementation context: ${errorMessage}`);
|
|
99
|
-
throw new Error(`Context fetch failed: ${errorMessage}`);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
/**
|
|
103
|
-
* Format the context into a readable string for Claude Code
|
|
104
|
-
*/
|
|
105
|
-
export function formatContextForPrompt(context) {
|
|
106
|
-
const formatUserStories = (stories) => {
|
|
107
|
-
if (stories.length === 0)
|
|
108
|
-
return 'No user stories defined.';
|
|
109
|
-
return stories
|
|
110
|
-
.map((story, index) => `${index + 1}. **${story.title}** (Status: ${story.status})
|
|
111
|
-
${story.description}`)
|
|
112
|
-
.join('\n\n');
|
|
113
|
-
};
|
|
114
|
-
const formatTestCases = (cases) => {
|
|
115
|
-
if (cases.length === 0)
|
|
116
|
-
return 'No test cases defined.';
|
|
117
|
-
return cases
|
|
118
|
-
.map((testCase, index) => `${index + 1}. **${testCase.name}** ${testCase.is_critical ? '[CRITICAL]' : '[OPTIONAL]'}
|
|
119
|
-
${testCase.description}`)
|
|
120
|
-
.join('\n\n');
|
|
121
|
-
};
|
|
122
|
-
return `# Code Implementation Context
|
|
123
|
-
|
|
124
|
-
## Feature Information
|
|
125
|
-
- **ID**: ${context.feature.id}
|
|
126
|
-
- **Name**: ${context.feature.name}
|
|
127
|
-
- **Description**: ${context.feature.description || 'No description provided'}
|
|
128
|
-
- **Current Status**: ${context.feature.status}
|
|
129
|
-
|
|
130
|
-
## Product Information
|
|
131
|
-
- **Product**: ${context.product.name}
|
|
132
|
-
- **Product ID**: ${context.product.id}
|
|
133
|
-
- **Description**: ${context.product.description || 'No product description'}
|
|
134
|
-
|
|
135
|
-
## User Stories (${context.user_stories.length})
|
|
136
|
-
${formatUserStories(context.user_stories)}
|
|
137
|
-
|
|
138
|
-
## Test Cases (${context.test_cases.length})
|
|
139
|
-
${formatTestCases(context.test_cases)}
|
|
140
|
-
|
|
141
|
-
## Technical Design
|
|
142
|
-
${context.feature.technical_design || 'No technical design available - you will need to implement based on user stories and test cases'}
|
|
143
|
-
|
|
144
|
-
---
|
|
145
|
-
|
|
146
|
-
**Implementation Instructions**: Implement the above feature based on the user stories, test cases, and technical design. Follow existing code patterns, create necessary components, APIs, and database changes, and ensure all functionality works as specified.`;
|
|
147
|
-
}
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
export interface FeatureAnalysisContext {
|
|
2
|
-
feature: {
|
|
3
|
-
id: string;
|
|
4
|
-
name: string;
|
|
5
|
-
description?: string;
|
|
6
|
-
technical_design?: string;
|
|
7
|
-
status: string;
|
|
8
|
-
product_id: string;
|
|
9
|
-
};
|
|
10
|
-
product: {
|
|
11
|
-
id: string;
|
|
12
|
-
name: string;
|
|
13
|
-
description?: string;
|
|
14
|
-
[key: string]: any;
|
|
15
|
-
};
|
|
16
|
-
existing_user_stories: Array<{
|
|
17
|
-
id: string;
|
|
18
|
-
title: string;
|
|
19
|
-
description: string;
|
|
20
|
-
status: string;
|
|
21
|
-
[key: string]: any;
|
|
22
|
-
}>;
|
|
23
|
-
existing_test_cases: Array<{
|
|
24
|
-
id: string;
|
|
25
|
-
name: string;
|
|
26
|
-
description: string;
|
|
27
|
-
is_critical: boolean;
|
|
28
|
-
[key: string]: any;
|
|
29
|
-
}>;
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* Fetch all feature analysis context information via MCP endpoints
|
|
33
|
-
*/
|
|
34
|
-
export declare function fetchFeatureAnalysisContext(mcpServerUrl: string, mcpToken: string, featureId: string, verbose?: boolean): Promise<FeatureAnalysisContext>;
|
|
35
|
-
/**
|
|
36
|
-
* Create new user stories via MCP endpoint
|
|
37
|
-
*/
|
|
38
|
-
export declare function createUserStories(mcpServerUrl: string, mcpToken: string, featureId: string, userStories: Array<{
|
|
39
|
-
title: string;
|
|
40
|
-
description: string;
|
|
41
|
-
status?: string;
|
|
42
|
-
}>, verbose?: boolean): Promise<boolean>;
|
|
43
|
-
/**
|
|
44
|
-
* Create new test cases via MCP endpoint
|
|
45
|
-
*/
|
|
46
|
-
export declare function createTestCases(mcpServerUrl: string, mcpToken: string, featureId: string, testCases: Array<{
|
|
47
|
-
name: string;
|
|
48
|
-
description: string;
|
|
49
|
-
is_critical?: boolean;
|
|
50
|
-
}>, verbose?: boolean): Promise<boolean>;
|
|
51
|
-
/**
|
|
52
|
-
* Format the context into a readable string for Claude Code
|
|
53
|
-
*/
|
|
54
|
-
export declare function formatContextForPrompt(context: FeatureAnalysisContext): string;
|