edsger 0.30.0 → 0.30.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/.claude/settings.local.json +28 -0
- package/.env.local +12 -0
- package/dist/api/features/__tests__/regression-prevention.test.d.ts +5 -0
- package/dist/api/features/__tests__/regression-prevention.test.js +338 -0
- package/dist/api/features/__tests__/status-updater.integration.test.d.ts +5 -0
- package/dist/api/features/__tests__/status-updater.integration.test.js +497 -0
- package/dist/commands/workflow/pipeline-runner.d.ts +17 -0
- package/dist/commands/workflow/pipeline-runner.js +393 -0
- package/dist/commands/workflow/runner.d.ts +26 -0
- package/dist/commands/workflow/runner.js +119 -0
- package/dist/commands/workflow/workflow-runner.d.ts +26 -0
- package/dist/commands/workflow/workflow-runner.js +119 -0
- package/dist/index.js +0 -0
- package/dist/phases/autonomous/index.js +9 -56
- package/dist/phases/code-implementation/analyzer-helpers.d.ts +28 -0
- package/dist/phases/code-implementation/analyzer-helpers.js +177 -0
- package/dist/phases/code-implementation/analyzer.d.ts +32 -0
- package/dist/phases/code-implementation/analyzer.js +629 -0
- package/dist/phases/code-implementation/branch-pr-creator.js +2 -58
- package/dist/phases/code-implementation/context-fetcher.d.ts +17 -0
- package/dist/phases/code-implementation/context-fetcher.js +86 -0
- package/dist/phases/code-implementation/index.js +9 -67
- package/dist/phases/code-implementation/mcp-server.d.ts +1 -0
- package/dist/phases/code-implementation/mcp-server.js +93 -0
- package/dist/phases/code-implementation/prompts-improvement.d.ts +5 -0
- package/dist/phases/code-implementation/prompts-improvement.js +108 -0
- package/dist/phases/code-implementation-verification/verifier.d.ts +31 -0
- package/dist/phases/code-implementation-verification/verifier.js +196 -0
- package/dist/phases/code-refine/analyzer.d.ts +41 -0
- package/dist/phases/code-refine/analyzer.js +561 -0
- package/dist/phases/code-refine/context-fetcher.d.ts +94 -0
- package/dist/phases/code-refine/context-fetcher.js +423 -0
- package/dist/phases/code-refine/index.js +6 -37
- package/dist/phases/code-refine-verification/analysis/llm-analyzer.d.ts +22 -0
- package/dist/phases/code-refine-verification/analysis/llm-analyzer.js +134 -0
- package/dist/phases/code-refine-verification/verifier.d.ts +47 -0
- package/dist/phases/code-refine-verification/verifier.js +597 -0
- package/dist/phases/code-review/analyzer.d.ts +29 -0
- package/dist/phases/code-review/analyzer.js +363 -0
- package/dist/phases/code-review/context-fetcher.d.ts +92 -0
- package/dist/phases/code-review/context-fetcher.js +296 -0
- package/dist/phases/code-review/index.js +1 -0
- package/dist/phases/feature-analysis/analyzer-helpers.d.ts +10 -0
- package/dist/phases/feature-analysis/analyzer-helpers.js +47 -0
- package/dist/phases/feature-analysis/analyzer.d.ts +11 -0
- package/dist/phases/feature-analysis/analyzer.js +208 -0
- package/dist/phases/feature-analysis/context-fetcher.d.ts +26 -0
- package/dist/phases/feature-analysis/context-fetcher.js +134 -0
- package/dist/phases/feature-analysis/http-fallback.d.ts +20 -0
- package/dist/phases/feature-analysis/http-fallback.js +95 -0
- package/dist/phases/feature-analysis/mcp-server.d.ts +1 -0
- package/dist/phases/feature-analysis/mcp-server.js +144 -0
- package/dist/phases/feature-analysis/prompts-improvement.d.ts +8 -0
- package/dist/phases/feature-analysis/prompts-improvement.js +109 -0
- package/dist/phases/feature-analysis-verification/verifier.d.ts +37 -0
- package/dist/phases/feature-analysis-verification/verifier.js +147 -0
- package/dist/phases/pr-execution/index.js +1 -0
- package/dist/phases/pr-execution/pr-executor.d.ts +2 -1
- package/dist/phases/pr-execution/pr-executor.js +9 -38
- package/dist/phases/pull-request/creator.js +9 -35
- package/dist/phases/technical-design/analyzer-helpers.d.ts +25 -0
- package/dist/phases/technical-design/analyzer-helpers.js +39 -0
- package/dist/phases/technical-design/analyzer.d.ts +21 -0
- package/dist/phases/technical-design/analyzer.js +461 -0
- package/dist/phases/technical-design/context-fetcher.d.ts +12 -0
- package/dist/phases/technical-design/context-fetcher.js +39 -0
- package/dist/phases/technical-design/http-fallback.d.ts +17 -0
- package/dist/phases/technical-design/http-fallback.js +151 -0
- package/dist/phases/technical-design/mcp-server.d.ts +1 -0
- package/dist/phases/technical-design/mcp-server.js +157 -0
- package/dist/phases/technical-design/prompts-improvement.d.ts +5 -0
- package/dist/phases/technical-design/prompts-improvement.js +93 -0
- package/dist/phases/technical-design-verification/verifier.d.ts +53 -0
- package/dist/phases/technical-design-verification/verifier.js +170 -0
- package/dist/services/feature-branches.d.ts +77 -0
- package/dist/services/feature-branches.js +205 -0
- package/dist/utils/git-branch-manager.d.ts +2 -0
- package/dist/utils/git-branch-manager.js +8 -35
- package/dist/utils/git-push.d.ts +43 -0
- package/dist/utils/git-push.js +127 -0
- package/dist/workflow-runner/config/phase-configs.d.ts +5 -0
- package/dist/workflow-runner/config/phase-configs.js +120 -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/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 +248 -0
- package/dist/workflow-runner/feature-workflow-runner.d.ts +26 -0
- package/dist/workflow-runner/feature-workflow-runner.js +119 -0
- package/dist/workflow-runner/index.d.ts +2 -0
- package/dist/workflow-runner/index.js +2 -0
- package/dist/workflow-runner/pipeline-runner.d.ts +17 -0
- package/dist/workflow-runner/pipeline-runner.js +393 -0
- package/dist/workflow-runner/workflow-processor.d.ts +54 -0
- package/dist/workflow-runner/workflow-processor.js +170 -0
- package/dist/workspace/workspace-manager.js +5 -3
- package/package.json +1 -1
- package/dist/services/lifecycle-agent/__tests__/phase-criteria.test.d.ts +0 -4
- package/dist/services/lifecycle-agent/__tests__/phase-criteria.test.js +0 -133
- package/dist/services/lifecycle-agent/__tests__/transition-rules.test.d.ts +0 -4
- package/dist/services/lifecycle-agent/__tests__/transition-rules.test.js +0 -336
- package/dist/services/lifecycle-agent/index.d.ts +0 -24
- package/dist/services/lifecycle-agent/index.js +0 -25
- package/dist/services/lifecycle-agent/phase-criteria.d.ts +0 -57
- package/dist/services/lifecycle-agent/phase-criteria.js +0 -335
- package/dist/services/lifecycle-agent/transition-rules.d.ts +0 -60
- package/dist/services/lifecycle-agent/transition-rules.js +0 -184
- package/dist/services/lifecycle-agent/types.d.ts +0 -190
- package/dist/services/lifecycle-agent/types.js +0 -12
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
* Creates pull requests from dev/ branches to feat/ branches
|
|
4
4
|
*/
|
|
5
5
|
import { Octokit } from '@octokit/rest';
|
|
6
|
-
import { execSync } from 'child_process';
|
|
7
6
|
import { logInfo, logError } from '../../utils/logger.js';
|
|
7
|
+
import { gitPush } from '../../utils/git-push.js';
|
|
8
8
|
// GitHub PR title best practice: keep under 72 characters
|
|
9
9
|
const MAX_PR_TITLE_LENGTH = 72;
|
|
10
10
|
const PR_TITLE_PREFIX = 'feat: ';
|
|
@@ -40,62 +40,6 @@ export function devBranchToFeatBranch(devBranchName) {
|
|
|
40
40
|
// If already feat/ or other format, return as-is
|
|
41
41
|
return devBranchName;
|
|
42
42
|
}
|
|
43
|
-
/**
|
|
44
|
-
* Push a branch to remote
|
|
45
|
-
* Falls back to force-with-lease if normal push fails (e.g., after rebase)
|
|
46
|
-
*/
|
|
47
|
-
async function pushBranch(branchName, verbose) {
|
|
48
|
-
try {
|
|
49
|
-
if (verbose) {
|
|
50
|
-
logInfo(`📤 Pushing branch ${branchName} to remote...`);
|
|
51
|
-
}
|
|
52
|
-
// Try to push with -u flag (sets upstream if not already set)
|
|
53
|
-
try {
|
|
54
|
-
execSync(`git push -u origin ${branchName}`, {
|
|
55
|
-
encoding: 'utf-8',
|
|
56
|
-
stdio: verbose ? 'inherit' : 'pipe',
|
|
57
|
-
});
|
|
58
|
-
return { success: true };
|
|
59
|
-
}
|
|
60
|
-
catch (error) {
|
|
61
|
-
// If push fails, try without -u flag
|
|
62
|
-
try {
|
|
63
|
-
execSync(`git push origin ${branchName}`, {
|
|
64
|
-
encoding: 'utf-8',
|
|
65
|
-
stdio: verbose ? 'inherit' : 'pipe',
|
|
66
|
-
});
|
|
67
|
-
return { success: true };
|
|
68
|
-
}
|
|
69
|
-
catch (retryError) {
|
|
70
|
-
// If push still fails (likely non-fast-forward after rebase),
|
|
71
|
-
// use force-with-lease for safer force push
|
|
72
|
-
if (verbose) {
|
|
73
|
-
logInfo(`⚠️ Push rejected, attempting force push with lease...`);
|
|
74
|
-
}
|
|
75
|
-
try {
|
|
76
|
-
execSync(`git push --force-with-lease origin ${branchName}`, {
|
|
77
|
-
encoding: 'utf-8',
|
|
78
|
-
stdio: verbose ? 'inherit' : 'pipe',
|
|
79
|
-
});
|
|
80
|
-
if (verbose) {
|
|
81
|
-
logInfo(`✅ Successfully force pushed ${branchName}`);
|
|
82
|
-
}
|
|
83
|
-
return { success: true };
|
|
84
|
-
}
|
|
85
|
-
catch (forceError) {
|
|
86
|
-
const errorMessage = forceError instanceof Error
|
|
87
|
-
? forceError.message
|
|
88
|
-
: String(forceError);
|
|
89
|
-
return { success: false, error: errorMessage };
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
catch (error) {
|
|
95
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
96
|
-
return { success: false, error: errorMessage };
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
43
|
/**
|
|
100
44
|
* Create a pull request from a dev/ branch to its corresponding feat/ branch
|
|
101
45
|
* This is used after code implementation in multi-branch features
|
|
@@ -115,7 +59,7 @@ export async function createBranchPullRequest(config, devBranchName, featureName
|
|
|
115
59
|
if (verbose) {
|
|
116
60
|
logInfo(`📤 Pushing ${devBranchName} to remote...`);
|
|
117
61
|
}
|
|
118
|
-
const pushResult =
|
|
62
|
+
const pushResult = gitPush({ branchName: devBranchName, token: githubToken, verbose });
|
|
119
63
|
if (!pushResult.success) {
|
|
120
64
|
return {
|
|
121
65
|
success: false,
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { FeatureInfo, UserStory, TestCase } from '../../types/features.js';
|
|
2
|
+
import { type ProductInfo } from '../../api/products.js';
|
|
3
|
+
export interface CodeImplementationContext {
|
|
4
|
+
feature: FeatureInfo;
|
|
5
|
+
product: ProductInfo;
|
|
6
|
+
user_stories: UserStory[];
|
|
7
|
+
test_cases: TestCase[];
|
|
8
|
+
technical_design?: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Fetch all code implementation context information via MCP endpoints
|
|
12
|
+
*/
|
|
13
|
+
export declare function fetchCodeImplementationContext(featureId: string, verbose?: boolean): Promise<CodeImplementationContext>;
|
|
14
|
+
/**
|
|
15
|
+
* Format the context into a readable string for Claude Code
|
|
16
|
+
*/
|
|
17
|
+
export declare function formatContextForPrompt(context: CodeImplementationContext): string;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { logInfo, logError } from '../../utils/logger.js';
|
|
2
|
+
import { getFeature, getUserStories, getTestCases, } from '../../api/features/index.js';
|
|
3
|
+
import { getProduct } from '../../api/products.js';
|
|
4
|
+
/**
|
|
5
|
+
* Fetch all code implementation context information via MCP endpoints
|
|
6
|
+
*/
|
|
7
|
+
export async function fetchCodeImplementationContext(featureId, verbose) {
|
|
8
|
+
try {
|
|
9
|
+
if (verbose) {
|
|
10
|
+
logInfo(`Fetching complete code implementation context for feature: ${featureId}`);
|
|
11
|
+
}
|
|
12
|
+
// Fetch all required data in parallel for better performance
|
|
13
|
+
const [feature, user_stories, test_cases] = await Promise.all([
|
|
14
|
+
getFeature(featureId, verbose),
|
|
15
|
+
getUserStories(featureId, verbose),
|
|
16
|
+
getTestCases(featureId, verbose),
|
|
17
|
+
]);
|
|
18
|
+
const product = await getProduct(feature.product_id, verbose);
|
|
19
|
+
if (verbose) {
|
|
20
|
+
logInfo(`✅ Code implementation context fetched successfully:`);
|
|
21
|
+
logInfo(` Feature: ${feature.name}`);
|
|
22
|
+
logInfo(` Product: ${product.name}`);
|
|
23
|
+
logInfo(` User Stories: ${user_stories.length}`);
|
|
24
|
+
logInfo(` Test Cases: ${test_cases.length}`);
|
|
25
|
+
logInfo(` Technical Design: ${feature.technical_design ? 'Available' : 'Not available'}`);
|
|
26
|
+
}
|
|
27
|
+
return {
|
|
28
|
+
feature,
|
|
29
|
+
product,
|
|
30
|
+
user_stories,
|
|
31
|
+
test_cases,
|
|
32
|
+
technical_design: feature.technical_design,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
37
|
+
logError(`Failed to fetch code implementation context: ${errorMessage}`);
|
|
38
|
+
throw new Error(`Context fetch failed: ${errorMessage}`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Format the context into a readable string for Claude Code
|
|
43
|
+
*/
|
|
44
|
+
export function formatContextForPrompt(context) {
|
|
45
|
+
const formatUserStories = (stories) => {
|
|
46
|
+
if (stories.length === 0)
|
|
47
|
+
return 'No user stories defined.';
|
|
48
|
+
return stories
|
|
49
|
+
.map((story, index) => `${index + 1}. **${story.title}** (Status: ${story.status})
|
|
50
|
+
${story.description}`)
|
|
51
|
+
.join('\n\n');
|
|
52
|
+
};
|
|
53
|
+
const formatTestCases = (cases) => {
|
|
54
|
+
if (cases.length === 0)
|
|
55
|
+
return 'No test cases defined.';
|
|
56
|
+
return cases
|
|
57
|
+
.map((testCase, index) => `${index + 1}. **${testCase.name}** ${testCase.is_critical ? '[CRITICAL]' : '[OPTIONAL]'}
|
|
58
|
+
${testCase.description}`)
|
|
59
|
+
.join('\n\n');
|
|
60
|
+
};
|
|
61
|
+
return `# Code Implementation Context
|
|
62
|
+
|
|
63
|
+
## Feature Information
|
|
64
|
+
- **ID**: ${context.feature.id}
|
|
65
|
+
- **Name**: ${context.feature.name}
|
|
66
|
+
- **Description**: ${context.feature.description || 'No description provided'}
|
|
67
|
+
- **Current Status**: ${context.feature.status}
|
|
68
|
+
|
|
69
|
+
## Product Information
|
|
70
|
+
- **Product**: ${context.product.name}
|
|
71
|
+
- **Product ID**: ${context.product.id}
|
|
72
|
+
- **Description**: ${context.product.description || 'No product description'}
|
|
73
|
+
|
|
74
|
+
## User Stories to Implement (${context.user_stories.length})
|
|
75
|
+
${formatUserStories(context.user_stories)}
|
|
76
|
+
|
|
77
|
+
## Test Cases to Satisfy (${context.test_cases.length})
|
|
78
|
+
${formatTestCases(context.test_cases)}
|
|
79
|
+
|
|
80
|
+
## Technical Design
|
|
81
|
+
${context.technical_design || 'No technical design available - implement based on user stories and test cases'}
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
**Implementation Instructions**: Based on the above requirements, user stories, test cases, and technical design, implement the complete feature functionality. Ensure all user stories are implemented and all test cases can pass.`;
|
|
86
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { query } from '@anthropic-ai/claude-agent-sdk';
|
|
2
2
|
import { DEFAULT_MODEL } from '../../constants.js';
|
|
3
3
|
import { logInfo, logError } from '../../utils/logger.js';
|
|
4
|
+
import { gitPush } from '../../utils/git-push.js';
|
|
4
5
|
import { formatChecklistsForContext, } from '../../services/checklist.js';
|
|
5
6
|
import { getFeedbacksForPhase, formatFeedbacksForContext, } from '../../services/feedbacks.js';
|
|
6
7
|
import { fetchCodeImplementationContext, formatContextForPrompt, } from './context.js';
|
|
@@ -164,6 +165,7 @@ export const implementFeatureCode = async (options, config, checklistContext) =>
|
|
|
164
165
|
// Sync feat branch to main before rebase to ensure it's up to date
|
|
165
166
|
// This prevents the PR (dev → feat) from showing extra commits
|
|
166
167
|
let featSyncedToMain = false;
|
|
168
|
+
let githubTokenForPush;
|
|
167
169
|
if (devBranchName.startsWith('dev/')) {
|
|
168
170
|
try {
|
|
169
171
|
const githubConfig = await getGitHubConfig(featureId, verbose);
|
|
@@ -171,6 +173,7 @@ export const implementFeatureCode = async (options, config, checklistContext) =>
|
|
|
171
173
|
githubConfig.token &&
|
|
172
174
|
githubConfig.owner &&
|
|
173
175
|
githubConfig.repo) {
|
|
176
|
+
githubTokenForPush = githubConfig.token;
|
|
174
177
|
const { devBranchToFeatBranch } = await import('./branch-pr-creator.js');
|
|
175
178
|
const featBranchName = devBranchToFeatBranch(devBranchName);
|
|
176
179
|
if (verbose) {
|
|
@@ -200,6 +203,7 @@ export const implementFeatureCode = async (options, config, checklistContext) =>
|
|
|
200
203
|
},
|
|
201
204
|
forcePushAfterRebase: featSyncedToMain, // Trigger GitHub to recalculate PR diff
|
|
202
205
|
baseBranchCompleted, // Tell conflict resolver to use --theirs for all conflicts
|
|
206
|
+
githubToken: githubTokenForPush,
|
|
203
207
|
});
|
|
204
208
|
try {
|
|
205
209
|
// Fetch all required context information via MCP endpoints
|
|
@@ -462,7 +466,11 @@ export const implementFeatureCode = async (options, config, checklistContext) =>
|
|
|
462
466
|
if (verbose) {
|
|
463
467
|
logInfo(`📤 Pushing code to remote repository...`);
|
|
464
468
|
}
|
|
465
|
-
const pushResult =
|
|
469
|
+
const pushResult = gitPush({
|
|
470
|
+
branchName: structuredImplementationResult.branch_name || branchName,
|
|
471
|
+
token: githubTokenForPush,
|
|
472
|
+
verbose,
|
|
473
|
+
});
|
|
466
474
|
if (!pushResult.success && verbose) {
|
|
467
475
|
logError(`⚠️ Failed to push to remote: ${pushResult.error}`);
|
|
468
476
|
logInfo(' Code is committed locally and will be reviewed. Manual push may be needed.');
|
|
@@ -854,69 +862,3 @@ const parseImplementationResponse = (response, featureId) => {
|
|
|
854
862
|
};
|
|
855
863
|
}
|
|
856
864
|
};
|
|
857
|
-
/**
|
|
858
|
-
* Push branch to remote repository
|
|
859
|
-
* Falls back to force-with-lease if normal push fails (e.g., after rebase)
|
|
860
|
-
*/
|
|
861
|
-
async function pushToRemote(branchName, verbose) {
|
|
862
|
-
try {
|
|
863
|
-
// Import exec from child_process
|
|
864
|
-
const { execSync } = await import('child_process');
|
|
865
|
-
if (verbose) {
|
|
866
|
-
logInfo(`Pushing branch ${branchName} to remote...`);
|
|
867
|
-
}
|
|
868
|
-
// Try to push with -u flag (sets upstream if not already set)
|
|
869
|
-
try {
|
|
870
|
-
execSync(`git push -u origin ${branchName}`, {
|
|
871
|
-
encoding: 'utf-8',
|
|
872
|
-
stdio: verbose ? 'inherit' : 'pipe',
|
|
873
|
-
});
|
|
874
|
-
return { success: true };
|
|
875
|
-
}
|
|
876
|
-
catch (error) {
|
|
877
|
-
// If push fails, it might be because branch already has upstream
|
|
878
|
-
// Try without -u flag
|
|
879
|
-
try {
|
|
880
|
-
execSync(`git push origin ${branchName}`, {
|
|
881
|
-
encoding: 'utf-8',
|
|
882
|
-
stdio: verbose ? 'inherit' : 'pipe',
|
|
883
|
-
});
|
|
884
|
-
return { success: true };
|
|
885
|
-
}
|
|
886
|
-
catch (retryError) {
|
|
887
|
-
// If push still fails (likely non-fast-forward after rebase),
|
|
888
|
-
// use force-with-lease for safer force push
|
|
889
|
-
// force-with-lease ensures we don't overwrite others' work by checking remote state
|
|
890
|
-
if (verbose) {
|
|
891
|
-
logInfo(`⚠️ Push rejected, attempting force push with lease...`);
|
|
892
|
-
}
|
|
893
|
-
try {
|
|
894
|
-
execSync(`git push --force-with-lease origin ${branchName}`, {
|
|
895
|
-
encoding: 'utf-8',
|
|
896
|
-
stdio: verbose ? 'inherit' : 'pipe',
|
|
897
|
-
});
|
|
898
|
-
if (verbose) {
|
|
899
|
-
logInfo(`✅ Successfully force pushed ${branchName}`);
|
|
900
|
-
}
|
|
901
|
-
return { success: true };
|
|
902
|
-
}
|
|
903
|
-
catch (forceError) {
|
|
904
|
-
const errorMessage = forceError instanceof Error
|
|
905
|
-
? forceError.message
|
|
906
|
-
: String(forceError);
|
|
907
|
-
return {
|
|
908
|
-
success: false,
|
|
909
|
-
error: errorMessage,
|
|
910
|
-
};
|
|
911
|
-
}
|
|
912
|
-
}
|
|
913
|
-
}
|
|
914
|
-
}
|
|
915
|
-
catch (error) {
|
|
916
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
917
|
-
return {
|
|
918
|
-
success: false,
|
|
919
|
-
error: errorMessage,
|
|
920
|
-
};
|
|
921
|
-
}
|
|
922
|
-
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const createCodeImplementationMcpServer: () => import("@anthropic-ai/claude-code").McpSdkServerConfigWithInstance;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { createSdkMcpServer, tool } from '@anthropic-ai/claude-code';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { callMcpEndpoint } from '../../api/mcp-client.js';
|
|
4
|
+
// Create an SDK MCP server with custom tools for code implementation
|
|
5
|
+
export const createCodeImplementationMcpServer = () => {
|
|
6
|
+
return createSdkMcpServer({
|
|
7
|
+
name: 'edsger-code-implementation-mcp',
|
|
8
|
+
version: '1.0.0',
|
|
9
|
+
tools: [
|
|
10
|
+
tool('get_complete_feature_info', 'Get comprehensive feature information including product, user stories, test cases, and technical design', {
|
|
11
|
+
feature_id: z
|
|
12
|
+
.string()
|
|
13
|
+
.describe('Feature ID to get complete information for'),
|
|
14
|
+
}, async (args) => {
|
|
15
|
+
try {
|
|
16
|
+
// Get feature details
|
|
17
|
+
const featureResult = (await callMcpEndpoint('features/get', {
|
|
18
|
+
feature_id: args.feature_id,
|
|
19
|
+
}));
|
|
20
|
+
if (!featureResult.features ||
|
|
21
|
+
featureResult.features.length === 0) {
|
|
22
|
+
throw new Error('Feature not found');
|
|
23
|
+
}
|
|
24
|
+
const feature = featureResult.features[0];
|
|
25
|
+
// Get product details
|
|
26
|
+
const productResult = (await callMcpEndpoint('resources/read', {
|
|
27
|
+
uri: `product://${feature.product_id}`,
|
|
28
|
+
}));
|
|
29
|
+
const productText = productResult.contents?.[0]?.text || '{}';
|
|
30
|
+
let productInfo;
|
|
31
|
+
try {
|
|
32
|
+
productInfo = JSON.parse(productText);
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
productInfo = {
|
|
36
|
+
id: feature.product_id,
|
|
37
|
+
name: 'Unknown Product',
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
// Get user stories
|
|
41
|
+
const userStoriesResult = (await callMcpEndpoint('user_stories/list', { feature_id: args.feature_id }));
|
|
42
|
+
// Get test cases
|
|
43
|
+
const testCasesResult = (await callMcpEndpoint('test_cases/list', {
|
|
44
|
+
feature_id: args.feature_id,
|
|
45
|
+
}));
|
|
46
|
+
const completeInfo = {
|
|
47
|
+
feature,
|
|
48
|
+
product: productInfo,
|
|
49
|
+
user_stories: userStoriesResult.user_stories || [],
|
|
50
|
+
test_cases: testCasesResult.test_cases || [],
|
|
51
|
+
technical_design: feature.technical_design || null,
|
|
52
|
+
};
|
|
53
|
+
return {
|
|
54
|
+
content: [
|
|
55
|
+
{
|
|
56
|
+
type: 'text',
|
|
57
|
+
text: JSON.stringify(completeInfo, null, 2),
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
console.error('Error in get_complete_feature_info:', error);
|
|
64
|
+
throw error;
|
|
65
|
+
}
|
|
66
|
+
}),
|
|
67
|
+
tool('verify_implementation_complete', 'Verify that the code implementation is complete and all tests pass', {
|
|
68
|
+
feature_id: z
|
|
69
|
+
.string()
|
|
70
|
+
.describe('Feature ID to verify implementation'),
|
|
71
|
+
implementation_summary: z
|
|
72
|
+
.string()
|
|
73
|
+
.describe('Summary of what was implemented'),
|
|
74
|
+
}, async (args) => {
|
|
75
|
+
// This tool is a placeholder for verification
|
|
76
|
+
// In reality, it would check test results, lint results, etc.
|
|
77
|
+
return {
|
|
78
|
+
content: [
|
|
79
|
+
{
|
|
80
|
+
type: 'text',
|
|
81
|
+
text: JSON.stringify({
|
|
82
|
+
verified: true,
|
|
83
|
+
feature_id: args.feature_id,
|
|
84
|
+
summary: args.implementation_summary,
|
|
85
|
+
message: 'Implementation verification complete',
|
|
86
|
+
}, null, 2),
|
|
87
|
+
},
|
|
88
|
+
],
|
|
89
|
+
};
|
|
90
|
+
}),
|
|
91
|
+
],
|
|
92
|
+
});
|
|
93
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { ChecklistVerificationResult } from '../code-implementation-verification/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Create a prompt for the implementation agent to improve code based on verification feedback
|
|
4
|
+
*/
|
|
5
|
+
export declare const createCodeImplementationImprovementPrompt: (verificationResult: ChecklistVerificationResult, branchName: string, baseBranch: string) => string;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Create a prompt for the implementation agent to improve code based on verification feedback
|
|
3
|
+
*/
|
|
4
|
+
export const createCodeImplementationImprovementPrompt = (verificationResult, branchName, baseBranch) => {
|
|
5
|
+
// Format rejected items with specific feedback and improvement suggestions
|
|
6
|
+
const rejectedItemsSection = verificationResult.item_verifications
|
|
7
|
+
.filter((v) => v.verification_status === 'rejected')
|
|
8
|
+
.map((v, index) => {
|
|
9
|
+
return `### Rejected Requirement ${index + 1}
|
|
10
|
+
**Checklist Item ID**: ${v.checklist_item_id}
|
|
11
|
+
**Satisfaction Status**: ${v.is_satisfied ? '✅ Satisfied' : '❌ Not Satisfied'}
|
|
12
|
+
**Verification Result**: ❌ REJECTED
|
|
13
|
+
**Reason**: ${v.verification_reason}
|
|
14
|
+
${v.concerns && v.concerns.length > 0 ? `**Specific Concerns**:\n${v.concerns.map((c) => `- ${c}`).join('\n')}` : ''}
|
|
15
|
+
${v.improvement_suggestions && v.improvement_suggestions.length > 0 ? `\n**💡 Improvement Suggestions**:\n${v.improvement_suggestions.map((s) => `- ${s}`).join('\n')}` : ''}
|
|
16
|
+
`;
|
|
17
|
+
})
|
|
18
|
+
.join('\n---\n');
|
|
19
|
+
// Format uncertain items with improvement suggestions
|
|
20
|
+
const uncertainItemsSection = verificationResult.item_verifications
|
|
21
|
+
.filter((v) => v.verification_status === 'uncertain')
|
|
22
|
+
.map((v, index) => {
|
|
23
|
+
return `### Uncertain Requirement ${index + 1}
|
|
24
|
+
**Checklist Item ID**: ${v.checklist_item_id}
|
|
25
|
+
**Satisfaction Status**: ${v.is_satisfied ? '✅ Satisfied' : '⚠️ Partially Satisfied'}
|
|
26
|
+
**Verification Result**: ⚠️ UNCERTAIN
|
|
27
|
+
**Reason**: ${v.verification_reason}
|
|
28
|
+
${v.concerns && v.concerns.length > 0 ? `**Specific Concerns**:\n${v.concerns.map((c) => `- ${c}`).join('\n')}` : ''}
|
|
29
|
+
${v.improvement_suggestions && v.improvement_suggestions.length > 0 ? `\n**💡 Improvement Suggestions**:\n${v.improvement_suggestions.map((s) => `- ${s}`).join('\n')}` : ''}
|
|
30
|
+
`;
|
|
31
|
+
})
|
|
32
|
+
.join('\n---\n');
|
|
33
|
+
return `# Code Review Feedback - Improvements Required
|
|
34
|
+
|
|
35
|
+
Your code implementation was reviewed by an independent code reviewer, and **${verificationResult.rejected_count} checklist requirements were NOT SATISFIED** and **${verificationResult.uncertain_count} requirements are PARTIALLY SATISFIED**.
|
|
36
|
+
|
|
37
|
+
## Code Review Summary
|
|
38
|
+
${verificationResult.summary}
|
|
39
|
+
|
|
40
|
+
## Results Breakdown
|
|
41
|
+
- ✅ Satisfied: ${verificationResult.confirmed_count}
|
|
42
|
+
- ❌ Not Satisfied: ${verificationResult.rejected_count}
|
|
43
|
+
- ⚠️ Partially Satisfied: ${verificationResult.uncertain_count}
|
|
44
|
+
|
|
45
|
+
${verificationResult.overall_suggestions && verificationResult.overall_suggestions.length > 0 ? `## 💡 Overall Improvement Suggestions\n\n${verificationResult.overall_suggestions.map((s) => `- ${s}`).join('\n')}\n\n` : ''}
|
|
46
|
+
|
|
47
|
+
${verificationResult.rejected_count > 0 ? `## ❌ Unsatisfied Requirements\n\n${rejectedItemsSection}` : ''}
|
|
48
|
+
|
|
49
|
+
${verificationResult.uncertain_count > 0 ? `## ⚠️ Partially Satisfied Requirements\n\n${uncertainItemsSection}` : ''}
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Your Task: Improve Your Code Implementation
|
|
54
|
+
|
|
55
|
+
You are currently on branch **${branchName}** (based on ${baseBranch}). You need to **improve your code** to satisfy the checklist requirements.
|
|
56
|
+
|
|
57
|
+
**What You Should Do**:
|
|
58
|
+
|
|
59
|
+
1. **Review the improvement suggestions** provided above for each rejected/uncertain requirement
|
|
60
|
+
2. **Follow the specific, actionable suggestions** from the code reviewer
|
|
61
|
+
3. **Modify your code** to address the concerns and implement the suggested improvements
|
|
62
|
+
4. **Fix code quality issues**, bugs, or security concerns identified
|
|
63
|
+
5. **Ensure all requirements are adequately satisfied** based on the feedback
|
|
64
|
+
6. **Commit your improvements** to the same branch
|
|
65
|
+
|
|
66
|
+
**IMPORTANT Guidelines**:
|
|
67
|
+
- **Pay close attention to the 💡 Improvement Suggestions** - these tell you exactly what to fix
|
|
68
|
+
- **Address all concerns** raised by the reviewer
|
|
69
|
+
- **Test your changes** to ensure they work correctly
|
|
70
|
+
- **Follow best practices** for code quality, security, and performance
|
|
71
|
+
- **Commit your improvements** with a clear message explaining what was fixed
|
|
72
|
+
- The code will be reviewed again after your improvements
|
|
73
|
+
|
|
74
|
+
**Git Workflow**:
|
|
75
|
+
1. You are already on branch ${branchName}
|
|
76
|
+
2. Make the necessary code changes based on feedback
|
|
77
|
+
3. Run tests to ensure everything works
|
|
78
|
+
4. Commit your improvements: \`git commit -m "fix: address code review feedback - <brief description>"\`
|
|
79
|
+
|
|
80
|
+
**CRITICAL - Output Format**:
|
|
81
|
+
You MUST return ONLY the JSON object below after completing your improvements. Do NOT include any explanatory text, commentary, or markdown before or after the JSON. Return ONLY the JSON in this exact format:
|
|
82
|
+
|
|
83
|
+
\`\`\`json
|
|
84
|
+
{
|
|
85
|
+
"implementation_result": {
|
|
86
|
+
"feature_id": "...",
|
|
87
|
+
"branch_name": "${branchName}",
|
|
88
|
+
"files_modified": ["list", "of", "modified", "files"],
|
|
89
|
+
"commit_hash": "new commit hash after improvements",
|
|
90
|
+
"summary": "Brief description of improvements made based on code review feedback",
|
|
91
|
+
"tests_passed": true,
|
|
92
|
+
"pre_commit_passed": true,
|
|
93
|
+
"checklist_item_results": [
|
|
94
|
+
{
|
|
95
|
+
"checklist_item_id": "EXACT_CHECKLIST_ITEM_UUID_FROM_ID_FIELD",
|
|
96
|
+
"is_passed": true,
|
|
97
|
+
"value": "Result value based on item type",
|
|
98
|
+
"notes": "Optional notes about this checklist item"
|
|
99
|
+
}
|
|
100
|
+
]
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
\`\`\`
|
|
104
|
+
|
|
105
|
+
IMPORTANT: Return ONLY the JSON above. Do not add any text explaining what you did or how you improved the code. The JSON should be the complete and only content of your response.
|
|
106
|
+
|
|
107
|
+
Begin improving your code implementation based on the code review feedback.`;
|
|
108
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { EdsgerConfig } from '../../types/index.js';
|
|
2
|
+
export interface ChecklistItemVerificationResult {
|
|
3
|
+
checklist_item_id: string;
|
|
4
|
+
is_satisfied: boolean;
|
|
5
|
+
verification_status: 'confirmed' | 'rejected' | 'uncertain';
|
|
6
|
+
verification_reason: string;
|
|
7
|
+
concerns?: string[];
|
|
8
|
+
improvement_suggestions?: string[];
|
|
9
|
+
}
|
|
10
|
+
export interface ChecklistVerificationResult {
|
|
11
|
+
overall_status: 'passed' | 'failed' | 'partial';
|
|
12
|
+
summary: string;
|
|
13
|
+
confirmed_count: number;
|
|
14
|
+
rejected_count: number;
|
|
15
|
+
uncertain_count: number;
|
|
16
|
+
item_verifications: ChecklistItemVerificationResult[];
|
|
17
|
+
overall_suggestions?: string[];
|
|
18
|
+
}
|
|
19
|
+
export interface VerifyCodeImplementationOptions {
|
|
20
|
+
featureId: string;
|
|
21
|
+
branchName: string;
|
|
22
|
+
baseBranch: string;
|
|
23
|
+
featureName: string;
|
|
24
|
+
featureDescription?: string;
|
|
25
|
+
checklistContext: string;
|
|
26
|
+
verbose?: boolean;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Verify code implementation against checklist requirements by reviewing git diff
|
|
30
|
+
*/
|
|
31
|
+
export declare function verifyCodeImplementationCompliance(options: VerifyCodeImplementationOptions, config: EdsgerConfig): Promise<ChecklistVerificationResult>;
|