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.
- 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 +178 -19
- 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 +35 -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.js +1 -1
- 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 +424 -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 +42 -0
- package/dist/prompts/formatters.js +168 -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/image-downloader.d.ts +32 -0
- package/dist/utils/image-downloader.js +144 -0
- package/dist/utils/image-processor.d.ts +5 -0
- package/dist/utils/image-processor.js +55 -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 +1 -1
- 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/{functional-testing → phases/functional-testing}/test-report-creator.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
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logging utilities for workflow processor
|
|
3
|
+
* Centralized logging functions for workflow operations
|
|
4
|
+
*/
|
|
5
|
+
import { logInfo, logError, logSuccess } from '../../utils/logger.js';
|
|
6
|
+
export const logProcessingStart = (feature, verbose) => {
|
|
7
|
+
logInfo(`🎯 Processing feature: ${feature.name} (${feature.id})`);
|
|
8
|
+
if (verbose) {
|
|
9
|
+
logInfo(` Description: ${feature.description}`);
|
|
10
|
+
logInfo(` Last updated: ${feature.updated_at}`);
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
export const logRetryInfo = (featureName, retryCount, maxRetries) => {
|
|
14
|
+
if (retryCount < maxRetries) {
|
|
15
|
+
logInfo(`🔄 Will retry feature ${featureName} (attempt ${retryCount + 1}/${maxRetries})`);
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
logError(`⛔ Max retries reached for feature ${featureName}, marking as permanently failed`);
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
export const logPipelineResults = (results) => {
|
|
22
|
+
console.log('\n' + '='.repeat(60));
|
|
23
|
+
console.log('📊 Pipeline Results Summary');
|
|
24
|
+
console.log('='.repeat(60));
|
|
25
|
+
results.forEach((result, index) => {
|
|
26
|
+
const statusIcon = result.status === 'success' ? '✅' : '❌';
|
|
27
|
+
console.log(`${index + 1}. ${statusIcon} ${result.phase}: ${result.message}`);
|
|
28
|
+
});
|
|
29
|
+
console.log('='.repeat(60) + '\n');
|
|
30
|
+
};
|
|
31
|
+
export const logProcessorStart = (productId, pollInterval) => {
|
|
32
|
+
logInfo('🚀 Starting workflow processor...');
|
|
33
|
+
logInfo(`📋 Product ID: ${productId}`);
|
|
34
|
+
logInfo(`🔄 Poll interval: ${pollInterval}ms`);
|
|
35
|
+
};
|
|
36
|
+
export const logProcessorReady = () => {
|
|
37
|
+
logInfo('✅ Workflow processor started and monitoring for new features');
|
|
38
|
+
};
|
|
39
|
+
export const logProcessorStop = () => {
|
|
40
|
+
logInfo('⏹️ Workflow processor stopped');
|
|
41
|
+
};
|
|
42
|
+
export const logFeatureSuccess = (featureName) => {
|
|
43
|
+
logSuccess(`✅ Feature ${featureName} completed successfully!`);
|
|
44
|
+
};
|
|
45
|
+
export const logFeatureFailed = (featureName) => {
|
|
46
|
+
logError(`❌ Feature ${featureName} failed in pipeline`);
|
|
47
|
+
};
|
|
48
|
+
export const logFeatureError = (featureName, error) => {
|
|
49
|
+
logError(`❌ Error processing feature ${featureName}: ${error instanceof Error ? error.message : String(error)}`);
|
|
50
|
+
};
|
|
51
|
+
export const logNoFeaturesFound = () => {
|
|
52
|
+
logInfo('🔍 No ready_for_dev features found, continuing to monitor...');
|
|
53
|
+
};
|
|
54
|
+
export const logAllFeaturesProcessed = () => {
|
|
55
|
+
logInfo('🔄 All current features are processed or being processed, continuing to monitor...');
|
|
56
|
+
};
|
|
57
|
+
export const logSkippingProcessing = (processingCount) => {
|
|
58
|
+
logInfo(`⏳ Skipping feature fetching as ${processingCount} feature(s) are currently being processed`);
|
|
59
|
+
};
|
|
60
|
+
export const logPollingError = (error) => {
|
|
61
|
+
logError(`Error in polling cycle: ${error instanceof Error ? error.message : String(error)}`);
|
|
62
|
+
};
|
|
63
|
+
export const logProcessNextFeatureError = (error) => {
|
|
64
|
+
logError(`Error in processNextFeature: ${error instanceof Error ? error.message : String(error)}`);
|
|
65
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phase execution logic for pipeline runner
|
|
3
|
+
*/
|
|
4
|
+
import { EdsgerConfig } from '../../types/index.js';
|
|
5
|
+
import { PipelinePhaseOptions, PipelineResult, PhaseConfig } from '../../types/pipeline.js';
|
|
6
|
+
export declare const createPhaseRunner: (phaseConfig: PhaseConfig) => (options: PipelinePhaseOptions, config: EdsgerConfig) => Promise<PipelineResult>;
|
|
7
|
+
declare const runFeatureAnalysisPhase: (options: PipelinePhaseOptions, config: EdsgerConfig) => Promise<PipelineResult>, runTechnicalDesignPhase: (options: PipelinePhaseOptions, config: EdsgerConfig) => Promise<PipelineResult>, runCodeImplementationPhase: (options: PipelinePhaseOptions, config: EdsgerConfig) => Promise<PipelineResult>, runFunctionalTestingPhase: (options: PipelinePhaseOptions, config: EdsgerConfig) => Promise<PipelineResult>;
|
|
8
|
+
export { runFeatureAnalysisPhase, runTechnicalDesignPhase, runCodeImplementationPhase, runFunctionalTestingPhase, };
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phase execution logic for pipeline runner
|
|
3
|
+
*/
|
|
4
|
+
import { updateFeatureStatusForPhase } from '../../api/features/index.js';
|
|
5
|
+
import { phaseConfigs } from '../config/phase-configs.js';
|
|
6
|
+
import { getChecklistsForPhase, validateChecklistsForPhase, validateRequiredChecklistResults, processChecklistResultsFromResponse, processChecklistItemResultsFromResponse, } from '../../services/checklist.js';
|
|
7
|
+
// Higher-order function for phase execution
|
|
8
|
+
export const createPhaseRunner = (phaseConfig) => async (options, config) => {
|
|
9
|
+
const { featureId, mcpServerUrl, mcpToken, verbose } = options;
|
|
10
|
+
const { name, checkRequirements, execute, requirementsError } = phaseConfig;
|
|
11
|
+
try {
|
|
12
|
+
// Check requirements
|
|
13
|
+
const hasRequirements = await checkRequirements();
|
|
14
|
+
if (!hasRequirements) {
|
|
15
|
+
return {
|
|
16
|
+
featureId,
|
|
17
|
+
phase: name,
|
|
18
|
+
status: 'error',
|
|
19
|
+
message: requirementsError,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
// Update feature status to reflect current phase
|
|
23
|
+
await updateFeatureStatusForPhase({ mcpServerUrl, mcpToken }, featureId, name, verbose);
|
|
24
|
+
if (verbose) {
|
|
25
|
+
console.log(`🎯 Starting ${name} for: ${featureId}`);
|
|
26
|
+
}
|
|
27
|
+
// Fetch checklists for this phase as context
|
|
28
|
+
let checklistContext = null;
|
|
29
|
+
try {
|
|
30
|
+
checklistContext = await getChecklistsForPhase(options, name);
|
|
31
|
+
if (verbose && checklistContext.checklists.length > 0) {
|
|
32
|
+
console.log(`📋 Found ${checklistContext.checklists.length} checklists for ${name} phase`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
catch (checklistError) {
|
|
36
|
+
// Always log checklist fetch errors, not just in verbose mode
|
|
37
|
+
console.log(`⚠️ Failed to fetch checklists for ${name} phase: ${checklistError instanceof Error ? checklistError.message : String(checklistError)}`);
|
|
38
|
+
// Log more details in verbose mode
|
|
39
|
+
if (verbose && checklistError instanceof Error) {
|
|
40
|
+
console.log(` Details: ${checklistError.stack}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
// Execute the phase with checklist context
|
|
44
|
+
const result = await execute(options, config, checklistContext);
|
|
45
|
+
console.log({
|
|
46
|
+
result,
|
|
47
|
+
});
|
|
48
|
+
console.log({
|
|
49
|
+
status: result.status,
|
|
50
|
+
});
|
|
51
|
+
console.log({
|
|
52
|
+
data: result.data,
|
|
53
|
+
});
|
|
54
|
+
console.log({
|
|
55
|
+
checklist_item_results: result.data?.checklist_item_results,
|
|
56
|
+
});
|
|
57
|
+
// Process checklist results from phase response if phase was successful
|
|
58
|
+
if (result.status === 'success') {
|
|
59
|
+
try {
|
|
60
|
+
// Extract checklist_item_results from result data if available (new format)
|
|
61
|
+
const checklistItemResults = result.data?.checklist_item_results;
|
|
62
|
+
if (checklistItemResults && Array.isArray(checklistItemResults)) {
|
|
63
|
+
const processResult = await processChecklistItemResultsFromResponse(options, name, checklistItemResults, verbose);
|
|
64
|
+
if (verbose) {
|
|
65
|
+
if (processResult.created > 0) {
|
|
66
|
+
console.log(`📋 Processed ${processResult.created} checklist item results from ${name} phase`);
|
|
67
|
+
}
|
|
68
|
+
if (processResult.errors.length > 0) {
|
|
69
|
+
console.log(`⚠️ ${processResult.errors.length} errors processing checklist item results`);
|
|
70
|
+
processResult.errors.forEach((error) => console.log(` - ${error}`));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
// Fallback to old format for backward compatibility
|
|
76
|
+
const checklistResults = result.data?.checklist_results;
|
|
77
|
+
if (checklistResults && Array.isArray(checklistResults)) {
|
|
78
|
+
const processResult = await processChecklistResultsFromResponse(options, checklistResults, verbose);
|
|
79
|
+
if (verbose) {
|
|
80
|
+
if (processResult.created > 0) {
|
|
81
|
+
console.log(`📋 Processed ${processResult.created} checklist results from ${name} phase (legacy format)`);
|
|
82
|
+
}
|
|
83
|
+
if (processResult.errors.length > 0) {
|
|
84
|
+
console.log(`⚠️ ${processResult.errors.length} errors processing checklist results`);
|
|
85
|
+
processResult.errors.forEach((error) => console.log(` - ${error}`));
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
catch (processError) {
|
|
92
|
+
if (verbose) {
|
|
93
|
+
console.log(`⚠️ Failed to process checklist results from ${name} phase: ${processError instanceof Error ? processError.message : String(processError)}`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// Strictly validate checklist results after phase execution
|
|
98
|
+
let checklistValidation = null;
|
|
99
|
+
if (result.status === 'success') {
|
|
100
|
+
try {
|
|
101
|
+
// First perform strict validation - this will fail if checklists exist but have no results
|
|
102
|
+
const strictValidation = await validateRequiredChecklistResults(options, name, verbose);
|
|
103
|
+
if (!strictValidation.success) {
|
|
104
|
+
// If validation fails, return error immediately - don't continue pipeline
|
|
105
|
+
return {
|
|
106
|
+
featureId,
|
|
107
|
+
phase: name,
|
|
108
|
+
status: 'error',
|
|
109
|
+
message: `Checklist validation failed: ${strictValidation.error}`,
|
|
110
|
+
data: {
|
|
111
|
+
...result,
|
|
112
|
+
checklist_context: checklistContext,
|
|
113
|
+
checklist_validation_error: strictValidation.error,
|
|
114
|
+
missing_checklists: strictValidation.missingChecklists,
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
// If strict validation passes, get detailed validation info for logging
|
|
119
|
+
checklistValidation = await validateChecklistsForPhase(options, name);
|
|
120
|
+
if (verbose) {
|
|
121
|
+
console.log(`📋 Checklist validation: ${checklistValidation.summary}`);
|
|
122
|
+
}
|
|
123
|
+
// Log completion status
|
|
124
|
+
if (checklistValidation.checklists_validation.length > 0) {
|
|
125
|
+
const completedCount = checklistValidation.checklists_validation.filter((v) => v.is_completed).length;
|
|
126
|
+
const totalCount = checklistValidation.checklists_validation.length;
|
|
127
|
+
if (verbose) {
|
|
128
|
+
console.log(`📋 Checklist results status: ${completedCount}/${totalCount} checklists have results`);
|
|
129
|
+
}
|
|
130
|
+
// Log any incomplete checklists
|
|
131
|
+
if (!checklistValidation.all_completed) {
|
|
132
|
+
checklistValidation.checklists_validation.forEach((validation) => {
|
|
133
|
+
if (!validation.is_completed) {
|
|
134
|
+
console.log(` - ${validation.checklist_name} (${validation.role}): ${validation.status}`);
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
catch (validationError) {
|
|
141
|
+
// If validation itself fails, treat as error and stop pipeline
|
|
142
|
+
return {
|
|
143
|
+
featureId,
|
|
144
|
+
phase: name,
|
|
145
|
+
status: 'error',
|
|
146
|
+
message: `Checklist validation error: ${validationError instanceof Error ? validationError.message : String(validationError)}`,
|
|
147
|
+
data: {
|
|
148
|
+
...result,
|
|
149
|
+
checklist_context: checklistContext,
|
|
150
|
+
checklist_validation_error: validationError instanceof Error
|
|
151
|
+
? validationError.message
|
|
152
|
+
: String(validationError),
|
|
153
|
+
},
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return {
|
|
158
|
+
featureId,
|
|
159
|
+
phase: name,
|
|
160
|
+
status: result.status === 'success' ? 'success' : 'error',
|
|
161
|
+
message: result.status === 'success'
|
|
162
|
+
? `${name.replace('-', ' ')} completed successfully`
|
|
163
|
+
: `${name.replace('-', ' ')} failed`,
|
|
164
|
+
data: {
|
|
165
|
+
...result,
|
|
166
|
+
checklist_context: checklistContext,
|
|
167
|
+
checklist_validation: checklistValidation,
|
|
168
|
+
},
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
catch (error) {
|
|
172
|
+
return {
|
|
173
|
+
featureId,
|
|
174
|
+
phase: name,
|
|
175
|
+
status: 'error',
|
|
176
|
+
message: `${name.replace('-', ' ')} failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
// Create phase runners using the configuration
|
|
181
|
+
const [runFeatureAnalysisPhase, runTechnicalDesignPhase, runCodeImplementationPhase, runFunctionalTestingPhase,] = phaseConfigs.map(createPhaseRunner);
|
|
182
|
+
// Export individual phase runners for granular control
|
|
183
|
+
export { runFeatureAnalysisPhase, runTechnicalDesignPhase, runCodeImplementationPhase, runFunctionalTestingPhase, };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stage execution logic for pipeline runner
|
|
3
|
+
*/
|
|
4
|
+
import { EdsgerConfig } from '../../types/index.js';
|
|
5
|
+
import { PipelineStageOptions, PipelineResult, StageConfig } from '../../types/pipeline.js';
|
|
6
|
+
export declare const createStageRunner: (stageConfig: StageConfig) => (options: PipelineStageOptions, config: EdsgerConfig) => Promise<PipelineResult>;
|
|
7
|
+
declare const runFeatureAnalysisStage: (options: PipelineStageOptions, config: EdsgerConfig) => Promise<PipelineResult>, runTechnicalDesignStage: (options: PipelineStageOptions, config: EdsgerConfig) => Promise<PipelineResult>, runCodeImplementationStage: (options: PipelineStageOptions, config: EdsgerConfig) => Promise<PipelineResult>, runFunctionalTestingStage: (options: PipelineStageOptions, config: EdsgerConfig) => Promise<PipelineResult>;
|
|
8
|
+
export { runFeatureAnalysisStage, runTechnicalDesignStage, runCodeImplementationStage, runFunctionalTestingStage, };
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stage execution logic for pipeline runner
|
|
3
|
+
*/
|
|
4
|
+
import { updateFeatureStatusForStage } from '../../api/features/index.js';
|
|
5
|
+
import { stageConfigs } from '../config/stage-configs.js';
|
|
6
|
+
// Higher-order function for stage execution
|
|
7
|
+
export const createStageRunner = (stageConfig) => async (options, config) => {
|
|
8
|
+
const { featureId, mcpServerUrl, mcpToken, verbose } = options;
|
|
9
|
+
const { name, checkRequirements, execute, requirementsError } = stageConfig;
|
|
10
|
+
try {
|
|
11
|
+
// Check requirements
|
|
12
|
+
const hasRequirements = await checkRequirements();
|
|
13
|
+
if (!hasRequirements) {
|
|
14
|
+
return {
|
|
15
|
+
featureId,
|
|
16
|
+
stage: name,
|
|
17
|
+
status: 'error',
|
|
18
|
+
message: requirementsError,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
// Update feature status to reflect current stage
|
|
22
|
+
await updateFeatureStatusForStage({ mcpServerUrl, mcpToken }, featureId, name, verbose);
|
|
23
|
+
if (verbose) {
|
|
24
|
+
console.log(`🎯 Starting ${name} for: ${featureId}`);
|
|
25
|
+
}
|
|
26
|
+
const result = await execute(options, config);
|
|
27
|
+
return {
|
|
28
|
+
featureId,
|
|
29
|
+
stage: name,
|
|
30
|
+
status: result.status === 'success' ? 'success' : 'error',
|
|
31
|
+
message: result.status === 'success'
|
|
32
|
+
? `${name.replace('-', ' ')} completed successfully`
|
|
33
|
+
: `${name.replace('-', ' ')} failed`,
|
|
34
|
+
data: result,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
return {
|
|
39
|
+
featureId,
|
|
40
|
+
stage: name,
|
|
41
|
+
status: 'error',
|
|
42
|
+
message: `${name.replace('-', ' ')} failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
// Create stage runners using the configuration
|
|
47
|
+
const [runFeatureAnalysisStage, runTechnicalDesignStage, runCodeImplementationStage, runFunctionalTestingStage,] = stageConfigs.map(createStageRunner);
|
|
48
|
+
// Export individual stage runners for granular control
|
|
49
|
+
export { runFeatureAnalysisStage, runTechnicalDesignStage, runCodeImplementationStage, runFunctionalTestingStage, };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Feature fetching and status management service
|
|
3
|
+
*/
|
|
4
|
+
import { FeatureStatus } from '../types.js';
|
|
5
|
+
import { type FeatureInfo } from '../api/features.js';
|
|
6
|
+
/**
|
|
7
|
+
* Fetch features with ready_for_dev status for a product
|
|
8
|
+
*/
|
|
9
|
+
export declare function fetchReadyForDevFeatures(mcpServerUrl: string, mcpToken: string, productId: string, verbose?: boolean): Promise<FeatureInfo[]>;
|
|
10
|
+
/**
|
|
11
|
+
* Map pipeline stage to feature status
|
|
12
|
+
*/
|
|
13
|
+
export declare function getStatusForStage(stage: string): FeatureStatus;
|
|
14
|
+
/**
|
|
15
|
+
* Update feature status based on pipeline stage
|
|
16
|
+
*/
|
|
17
|
+
export declare function updateFeatureStatusForStage(mcpServerUrl: string, mcpToken: string, featureId: string, stage: string, verbose?: boolean): Promise<boolean>;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Feature fetching and status management service
|
|
3
|
+
*/
|
|
4
|
+
import { logInfo, logError } from '../logger.js';
|
|
5
|
+
import { updateFeatureStatus, } from '../api/features.js';
|
|
6
|
+
import { callMcpEndpoint } from '../api/mcp-client.js';
|
|
7
|
+
/**
|
|
8
|
+
* Fetch features with ready_for_dev status for a product
|
|
9
|
+
*/
|
|
10
|
+
export async function fetchReadyForDevFeatures(mcpServerUrl, mcpToken, productId, verbose) {
|
|
11
|
+
try {
|
|
12
|
+
if (verbose) {
|
|
13
|
+
logInfo(`📋 Fetching ready_for_dev features for product: ${productId}`);
|
|
14
|
+
}
|
|
15
|
+
const result = (await callMcpEndpoint(mcpServerUrl, mcpToken, 'features/list', {
|
|
16
|
+
product_id: productId,
|
|
17
|
+
status: 'ready_for_dev',
|
|
18
|
+
}));
|
|
19
|
+
const features = result?.features || [];
|
|
20
|
+
if (verbose) {
|
|
21
|
+
logInfo(`✅ Found ${features.length} ready_for_dev features`);
|
|
22
|
+
features.forEach((feature, index) => {
|
|
23
|
+
logInfo(` ${index + 1}. ${feature.name} (${feature.id})`);
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
return features;
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
logError(`❌ Error fetching features: ${error}`);
|
|
30
|
+
throw error;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Map pipeline stage to feature status
|
|
35
|
+
*/
|
|
36
|
+
export function getStatusForStage(stage) {
|
|
37
|
+
switch (stage) {
|
|
38
|
+
case 'feature-analysis':
|
|
39
|
+
return 'feature_analysis';
|
|
40
|
+
case 'technical-design':
|
|
41
|
+
return 'technical_design';
|
|
42
|
+
case 'code-implementation':
|
|
43
|
+
return 'code_implementation';
|
|
44
|
+
case 'functional-testing':
|
|
45
|
+
return 'testing_in_progress';
|
|
46
|
+
case 'testing-passed':
|
|
47
|
+
return 'testing_passed';
|
|
48
|
+
case 'testing-failed':
|
|
49
|
+
return 'testing_failed';
|
|
50
|
+
default:
|
|
51
|
+
return 'backlog';
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Update feature status based on pipeline stage
|
|
56
|
+
*/
|
|
57
|
+
export async function updateFeatureStatusForStage(mcpServerUrl, mcpToken, featureId, stage, verbose) {
|
|
58
|
+
const status = getStatusForStage(stage);
|
|
59
|
+
return await updateFeatureStatus(mcpServerUrl, mcpToken, featureId, status, verbose);
|
|
60
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Feature workflow runner with execution mode support
|
|
3
|
+
* Main entry point for running workflow pipelines with different execution modes
|
|
4
|
+
*/
|
|
5
|
+
import { EdsgerConfig } from '../types/index.js';
|
|
6
|
+
import { PipelinePhaseOptions, PipelineResult, ExecutionMode } from '../types/pipeline.js';
|
|
7
|
+
/**
|
|
8
|
+
* Run workflow for a feature based on its execution_mode configuration
|
|
9
|
+
*/
|
|
10
|
+
export declare function runFeatureWorkflow(options: PipelinePhaseOptions, config: EdsgerConfig): Promise<readonly PipelineResult[]>;
|
|
11
|
+
/**
|
|
12
|
+
* Run workflow for a feature with explicit execution mode override
|
|
13
|
+
*/
|
|
14
|
+
export declare function runFeatureWorkflowWithMode(options: PipelinePhaseOptions, config: EdsgerConfig, executionMode: ExecutionMode): Promise<readonly PipelineResult[]>;
|
|
15
|
+
/**
|
|
16
|
+
* Get available execution modes
|
|
17
|
+
*/
|
|
18
|
+
export declare function getAvailableExecutionModes(): ExecutionMode[];
|
|
19
|
+
/**
|
|
20
|
+
* Validate execution mode
|
|
21
|
+
*/
|
|
22
|
+
export declare function isValidExecutionMode(mode: string): mode is ExecutionMode;
|
|
23
|
+
/**
|
|
24
|
+
* Get execution mode description
|
|
25
|
+
*/
|
|
26
|
+
export declare function getExecutionModeDescription(mode: ExecutionMode): string;
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Feature workflow runner with execution mode support
|
|
3
|
+
* Main entry point for running workflow pipelines with different execution modes
|
|
4
|
+
*/
|
|
5
|
+
import { runPipelineByMode } from './pipeline-runner.js';
|
|
6
|
+
import { getFeature } from '../api/features/get-feature.js';
|
|
7
|
+
import { logError, logInfo } from '../utils/logger.js';
|
|
8
|
+
/**
|
|
9
|
+
* Run workflow for a feature based on its execution_mode configuration
|
|
10
|
+
*/
|
|
11
|
+
export async function runFeatureWorkflow(options, config) {
|
|
12
|
+
const { featureId, mcpServerUrl, mcpToken, verbose } = options;
|
|
13
|
+
try {
|
|
14
|
+
// 1. Get feature details to check execution_mode
|
|
15
|
+
if (verbose) {
|
|
16
|
+
logInfo(`🔍 Fetching feature configuration for: ${featureId}`);
|
|
17
|
+
}
|
|
18
|
+
const feature = await getFeature(mcpServerUrl, mcpToken, featureId, verbose);
|
|
19
|
+
// Debug log raw feature data
|
|
20
|
+
if (verbose) {
|
|
21
|
+
logInfo(`🔍 Feature data from API:`);
|
|
22
|
+
logInfo(` - execution_mode (raw): ${feature.execution_mode}`);
|
|
23
|
+
logInfo(` - execution_mode (type): ${typeof feature.execution_mode}`);
|
|
24
|
+
logInfo(` - is valid: ${isValidExecutionMode(feature.execution_mode || '')}`);
|
|
25
|
+
}
|
|
26
|
+
// 2. Determine execution mode (default to full_pipeline if not set)
|
|
27
|
+
const executionMode = isValidExecutionMode(feature.execution_mode || '')
|
|
28
|
+
? feature.execution_mode
|
|
29
|
+
: 'full_pipeline';
|
|
30
|
+
if (verbose) {
|
|
31
|
+
logInfo(`📋 Selected execution mode: ${executionMode}`);
|
|
32
|
+
logInfo(`📋 Mode description: ${getExecutionModeDescription(executionMode)}`);
|
|
33
|
+
}
|
|
34
|
+
// 3. Run pipeline based on execution mode
|
|
35
|
+
return await runPipelineByMode(options, config, executionMode);
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
39
|
+
logError(`Failed to run feature workflow: ${errorMessage}`);
|
|
40
|
+
// Return error result
|
|
41
|
+
return [
|
|
42
|
+
{
|
|
43
|
+
featureId,
|
|
44
|
+
phase: 'workflow-initialization',
|
|
45
|
+
status: 'error',
|
|
46
|
+
message: `Workflow initialization failed: ${errorMessage}`,
|
|
47
|
+
},
|
|
48
|
+
];
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Run workflow for a feature with explicit execution mode override
|
|
53
|
+
*/
|
|
54
|
+
export async function runFeatureWorkflowWithMode(options, config, executionMode) {
|
|
55
|
+
const { featureId, verbose } = options;
|
|
56
|
+
if (verbose) {
|
|
57
|
+
logInfo(`🚀 Running workflow with explicit mode: ${executionMode} for feature: ${featureId}`);
|
|
58
|
+
}
|
|
59
|
+
try {
|
|
60
|
+
return await runPipelineByMode(options, config, executionMode);
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
64
|
+
logError(`Failed to run feature workflow with mode ${executionMode}: ${errorMessage}`);
|
|
65
|
+
return [
|
|
66
|
+
{
|
|
67
|
+
featureId,
|
|
68
|
+
phase: 'workflow-execution',
|
|
69
|
+
status: 'error',
|
|
70
|
+
message: `Workflow execution failed: ${errorMessage}`,
|
|
71
|
+
},
|
|
72
|
+
];
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Get available execution modes
|
|
77
|
+
*/
|
|
78
|
+
export function getAvailableExecutionModes() {
|
|
79
|
+
return [
|
|
80
|
+
'full_pipeline',
|
|
81
|
+
'only_feature_analysis',
|
|
82
|
+
'only_technical_design',
|
|
83
|
+
'only_code_implementation',
|
|
84
|
+
'only_functional_testing',
|
|
85
|
+
'from_feature_analysis',
|
|
86
|
+
'from_technical_design',
|
|
87
|
+
'from_code_implementation',
|
|
88
|
+
'from_functional_testing',
|
|
89
|
+
];
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Validate execution mode
|
|
93
|
+
*/
|
|
94
|
+
export function isValidExecutionMode(mode) {
|
|
95
|
+
return getAvailableExecutionModes().includes(mode);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Get execution mode description
|
|
99
|
+
*/
|
|
100
|
+
export function getExecutionModeDescription(mode) {
|
|
101
|
+
const descriptions = {
|
|
102
|
+
full_pipeline: 'Execute complete workflow: analysis → design → implementation → testing',
|
|
103
|
+
only_feature_analysis: 'Execute only: feature analysis',
|
|
104
|
+
only_technical_design: 'Execute only: technical design',
|
|
105
|
+
only_code_implementation: 'Execute only: code implementation',
|
|
106
|
+
only_functional_testing: 'Execute only: functional testing',
|
|
107
|
+
from_feature_analysis: 'Execute from feature analysis to end: analysis → design → implementation → testing',
|
|
108
|
+
from_technical_design: 'Execute from technical design to end: design → implementation → testing',
|
|
109
|
+
from_code_implementation: 'Execute from code implementation to end: implementation → testing',
|
|
110
|
+
from_functional_testing: 'Execute from functional testing to end: testing',
|
|
111
|
+
};
|
|
112
|
+
return descriptions[mode] || 'Unknown execution mode';
|
|
113
|
+
}
|
|
@@ -1,25 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Pipeline runner for executing development workflow
|
|
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 { EdsgerConfig } from '../types.js';
|
|
7
|
-
|
|
8
|
-
readonly featureId: string;
|
|
9
|
-
readonly mcpServerUrl: string;
|
|
10
|
-
readonly mcpToken: string;
|
|
11
|
-
readonly verbose?: boolean;
|
|
12
|
-
}
|
|
13
|
-
export interface PipelineResult {
|
|
14
|
-
readonly featureId: string;
|
|
15
|
-
readonly stage: string;
|
|
16
|
-
readonly status: 'success' | 'error';
|
|
17
|
-
readonly message: string;
|
|
18
|
-
readonly data?: unknown;
|
|
19
|
-
}
|
|
20
|
-
declare const runFeatureAnalysisStage: (options: PipelineStageOptions, config: EdsgerConfig) => Promise<PipelineResult>, runTechnicalDesignStage: (options: PipelineStageOptions, config: EdsgerConfig) => Promise<PipelineResult>, runCodeImplementationStage: (options: PipelineStageOptions, config: EdsgerConfig) => Promise<PipelineResult>, runFunctionalTestingStage: (options: PipelineStageOptions, config: EdsgerConfig) => Promise<PipelineResult>;
|
|
6
|
+
import { EdsgerConfig } from '../types/index.js';
|
|
7
|
+
import { PipelinePhaseOptions, PipelineResult, ExecutionMode } from '../types/pipeline.js';
|
|
21
8
|
/**
|
|
22
|
-
* Run
|
|
9
|
+
* Run pipeline based on execution mode
|
|
23
10
|
*/
|
|
24
|
-
export declare const
|
|
25
|
-
|
|
11
|
+
export declare const runPipelineByMode: (options: PipelinePhaseOptions, config: EdsgerConfig, executionMode: ExecutionMode) => Promise<readonly PipelineResult[]>;
|
|
12
|
+
/**
|
|
13
|
+
* Run complete pipeline for a feature using functional composition (legacy)
|
|
14
|
+
*/
|
|
15
|
+
export declare const runCompletePipeline: (options: PipelinePhaseOptions, config: EdsgerConfig) => () => Promise<readonly PipelineResult[]>;
|