edsger 0.41.1 → 0.41.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 +23 -3
- 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/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/context-fetcher.d.ts +17 -0
- package/dist/phases/code-implementation/context-fetcher.js +86 -0
- 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-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/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/file-assigner.js +20 -12
- 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/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/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
|
@@ -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
|
+
}
|
|
@@ -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>;
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import { query } from '@anthropic-ai/claude-code';
|
|
2
|
+
import { logInfo, logError } from '../../utils/logger.js';
|
|
3
|
+
import { createCodeImplementationVerificationSystemPrompt, createCodeImplementationVerificationPrompt, } from './prompts.js';
|
|
4
|
+
function userMessage(content) {
|
|
5
|
+
return {
|
|
6
|
+
type: 'user',
|
|
7
|
+
message: { role: 'user', content: content },
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
async function* prompt(verificationPrompt) {
|
|
11
|
+
yield userMessage(verificationPrompt);
|
|
12
|
+
await new Promise((res) => setTimeout(res, 10000));
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Verify code implementation against checklist requirements by reviewing git diff
|
|
16
|
+
*/
|
|
17
|
+
export async function verifyCodeImplementationCompliance(options, config) {
|
|
18
|
+
const { featureId, branchName, baseBranch, featureName, featureDescription, checklistContext, verbose, } = options;
|
|
19
|
+
if (verbose) {
|
|
20
|
+
logInfo(`\n🔍 Starting code implementation verification for feature: ${featureName}`);
|
|
21
|
+
logInfo(` Branch: ${branchName}`);
|
|
22
|
+
logInfo(` Base: ${baseBranch}`);
|
|
23
|
+
}
|
|
24
|
+
try {
|
|
25
|
+
const systemPrompt = createCodeImplementationVerificationSystemPrompt(config);
|
|
26
|
+
const verificationPrompt = createCodeImplementationVerificationPrompt(featureId, branchName, baseBranch, featureName, featureDescription || '', checklistContext);
|
|
27
|
+
let lastAssistantResponse = '';
|
|
28
|
+
let verificationResult = null;
|
|
29
|
+
if (verbose) {
|
|
30
|
+
logInfo('🤖 Starting verification agent query...');
|
|
31
|
+
}
|
|
32
|
+
// Use Claude Code SDK for verification
|
|
33
|
+
for await (const message of query({
|
|
34
|
+
prompt: prompt(verificationPrompt),
|
|
35
|
+
options: {
|
|
36
|
+
appendSystemPrompt: systemPrompt,
|
|
37
|
+
model: config.claude.model || 'sonnet',
|
|
38
|
+
maxTurns: 1000,
|
|
39
|
+
permissionMode: 'bypassPermissions',
|
|
40
|
+
},
|
|
41
|
+
})) {
|
|
42
|
+
if (verbose) {
|
|
43
|
+
logInfo(` Received message type: ${message.type}`);
|
|
44
|
+
}
|
|
45
|
+
// Stream verification process
|
|
46
|
+
if (message.type === 'assistant' && message.message?.content) {
|
|
47
|
+
for (const content of message.message.content) {
|
|
48
|
+
if (content.type === 'text') {
|
|
49
|
+
lastAssistantResponse += content.text + '\n';
|
|
50
|
+
if (verbose) {
|
|
51
|
+
console.log(`\n🔍 ${content.text}`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
else if (content.type === 'tool_use') {
|
|
55
|
+
if (verbose) {
|
|
56
|
+
console.log(`\n🔧 ${content.name}: ${content.input.description || 'Running...'}`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
if (message.type === 'result') {
|
|
62
|
+
if (message.subtype === 'success') {
|
|
63
|
+
if (verbose) {
|
|
64
|
+
logInfo('\n✅ Code verification completed, parsing results...');
|
|
65
|
+
}
|
|
66
|
+
try {
|
|
67
|
+
const responseText = message.result || lastAssistantResponse;
|
|
68
|
+
let jsonResult = null;
|
|
69
|
+
// Try to extract JSON from markdown code block
|
|
70
|
+
const jsonBlockMatch = responseText.match(/```json\s*\n([\s\S]*?)\n\s*```/);
|
|
71
|
+
if (jsonBlockMatch) {
|
|
72
|
+
jsonResult = JSON.parse(jsonBlockMatch[1]);
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
// Try to find JSON object containing "verification_result"
|
|
76
|
+
let jsonStartIndex = -1;
|
|
77
|
+
if (responseText.includes('"verification_result"')) {
|
|
78
|
+
const targetIndex = responseText.indexOf('"verification_result"');
|
|
79
|
+
// Work backwards to find opening brace
|
|
80
|
+
for (let i = targetIndex; i >= 0; i--) {
|
|
81
|
+
if (responseText[i] === '{') {
|
|
82
|
+
jsonStartIndex = i;
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
if (jsonStartIndex !== -1) {
|
|
88
|
+
// Find matching closing brace
|
|
89
|
+
let braceCount = 0;
|
|
90
|
+
let endIndex = jsonStartIndex;
|
|
91
|
+
let inString = false;
|
|
92
|
+
let escapeNext = false;
|
|
93
|
+
for (let i = jsonStartIndex; i < responseText.length; i++) {
|
|
94
|
+
const char = responseText[i];
|
|
95
|
+
if (escapeNext) {
|
|
96
|
+
escapeNext = false;
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
if (char === '\\' && inString) {
|
|
100
|
+
escapeNext = true;
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
if (char === '"') {
|
|
104
|
+
inString = !inString;
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
if (!inString) {
|
|
108
|
+
if (char === '{') {
|
|
109
|
+
braceCount++;
|
|
110
|
+
}
|
|
111
|
+
else if (char === '}') {
|
|
112
|
+
braceCount--;
|
|
113
|
+
if (braceCount === 0) {
|
|
114
|
+
endIndex = i;
|
|
115
|
+
break;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
const jsonStr = responseText.substring(jsonStartIndex, endIndex + 1);
|
|
121
|
+
try {
|
|
122
|
+
jsonResult = JSON.parse(jsonStr);
|
|
123
|
+
}
|
|
124
|
+
catch (parseError) {
|
|
125
|
+
logError(`Failed to parse extracted JSON: ${parseError}`);
|
|
126
|
+
jsonResult = JSON.parse(responseText);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
jsonResult = JSON.parse(responseText);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
if (jsonResult && jsonResult.verification_result) {
|
|
134
|
+
verificationResult = jsonResult.verification_result;
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
throw new Error('Invalid JSON structure');
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
catch (error) {
|
|
141
|
+
logError(`Failed to parse verification result: ${error}`);
|
|
142
|
+
// Return a failed verification result
|
|
143
|
+
verificationResult = {
|
|
144
|
+
overall_status: 'failed',
|
|
145
|
+
summary: 'Verification failed due to parse error',
|
|
146
|
+
confirmed_count: 0,
|
|
147
|
+
rejected_count: 1,
|
|
148
|
+
uncertain_count: 0,
|
|
149
|
+
item_verifications: [],
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
logError(`\n⚠️ Verification incomplete: ${message.subtype}`);
|
|
155
|
+
verificationResult = {
|
|
156
|
+
overall_status: 'failed',
|
|
157
|
+
summary: 'Verification incomplete',
|
|
158
|
+
confirmed_count: 0,
|
|
159
|
+
rejected_count: 1,
|
|
160
|
+
uncertain_count: 0,
|
|
161
|
+
item_verifications: [],
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
if (!verificationResult) {
|
|
167
|
+
return {
|
|
168
|
+
overall_status: 'failed',
|
|
169
|
+
summary: 'No verification result received',
|
|
170
|
+
confirmed_count: 0,
|
|
171
|
+
rejected_count: 1,
|
|
172
|
+
uncertain_count: 0,
|
|
173
|
+
item_verifications: [],
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
if (verbose) {
|
|
177
|
+
logInfo('\n📊 Verification Results:');
|
|
178
|
+
logInfo(` Status: ${verificationResult.overall_status}`);
|
|
179
|
+
logInfo(` ✅ Confirmed: ${verificationResult.confirmed_count}`);
|
|
180
|
+
logInfo(` ❌ Rejected: ${verificationResult.rejected_count}`);
|
|
181
|
+
logInfo(` ⚠️ Uncertain: ${verificationResult.uncertain_count}`);
|
|
182
|
+
}
|
|
183
|
+
return verificationResult;
|
|
184
|
+
}
|
|
185
|
+
catch (error) {
|
|
186
|
+
logError(`Code verification failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
187
|
+
return {
|
|
188
|
+
overall_status: 'failed',
|
|
189
|
+
summary: `Verification error: ${error instanceof Error ? error.message : String(error)}`,
|
|
190
|
+
confirmed_count: 0,
|
|
191
|
+
rejected_count: 1,
|
|
192
|
+
uncertain_count: 0,
|
|
193
|
+
item_verifications: [],
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Code Refine Analyzer
|
|
3
|
+
* Processes GitHub PR review feedback and refines code accordingly
|
|
4
|
+
*/
|
|
5
|
+
import { EdsgerConfig } from '../../types/index.js';
|
|
6
|
+
export interface CodeRefineOptions {
|
|
7
|
+
featureId: string;
|
|
8
|
+
githubToken: string;
|
|
9
|
+
verbose?: boolean;
|
|
10
|
+
verificationFailureContext?: {
|
|
11
|
+
attempt: number;
|
|
12
|
+
suggestions: string[];
|
|
13
|
+
unresolvedCommentDetails: Array<{
|
|
14
|
+
commentId: string;
|
|
15
|
+
author: string;
|
|
16
|
+
file: string;
|
|
17
|
+
line: number | null;
|
|
18
|
+
body: string;
|
|
19
|
+
failureReason: string;
|
|
20
|
+
url: string;
|
|
21
|
+
}>;
|
|
22
|
+
unresolvedReviewDetails?: Array<{
|
|
23
|
+
reviewId: number;
|
|
24
|
+
author: string;
|
|
25
|
+
state: string;
|
|
26
|
+
body: string | null;
|
|
27
|
+
}>;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
export interface CodeRefineResult {
|
|
31
|
+
featureId: string;
|
|
32
|
+
status: 'success' | 'error';
|
|
33
|
+
message: string;
|
|
34
|
+
summary?: string;
|
|
35
|
+
filesModified?: string[];
|
|
36
|
+
commitsCreated?: number;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Main code refine function
|
|
40
|
+
*/
|
|
41
|
+
export declare const refineCodeFromPRFeedback: (options: CodeRefineOptions, config: EdsgerConfig) => Promise<CodeRefineResult>;
|