edsger 0.2.2 → 0.2.4
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/README.md +17 -0
- package/dist/api/features/batch-operations.d.ts +16 -0
- package/dist/api/features/batch-operations.js +100 -0
- package/dist/api/features/index.d.ts +1 -0
- package/dist/api/features/index.js +1 -0
- package/dist/api/features/test-cases.d.ts +8 -0
- package/dist/api/features/test-cases.js +45 -0
- package/dist/api/features/user-stories.d.ts +8 -0
- package/dist/api/features/user-stories.js +45 -0
- package/dist/cli/commands/refactor-command.d.ts +2 -0
- package/dist/cli/commands/refactor-command.js +107 -0
- package/dist/cli/index.js +7 -0
- package/dist/cli.d.ts +2 -2
- package/dist/cli.js +4 -99
- 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 +2 -0
- package/dist/phases/code-implementation/analyzer.js +308 -179
- package/dist/phases/code-implementation-verification/index.d.ts +1 -0
- package/dist/phases/code-implementation-verification/index.js +1 -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/feature-analysis/analyzer-helpers.d.ts +62 -0
- package/dist/phases/feature-analysis/analyzer-helpers.js +450 -0
- package/dist/phases/feature-analysis/analyzer.d.ts +1 -0
- package/dist/phases/feature-analysis/analyzer.js +132 -213
- package/dist/phases/feature-analysis-verification/index.d.ts +1 -0
- package/dist/phases/feature-analysis-verification/index.js +1 -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/pull-request/creator.js +10 -9
- package/dist/phases/technical-design/analyzer-helpers.d.ts +37 -0
- package/dist/phases/technical-design/analyzer-helpers.js +144 -0
- package/dist/phases/technical-design/analyzer.d.ts +3 -0
- package/dist/phases/technical-design/analyzer.js +282 -312
- package/dist/phases/technical-design-verification/index.d.ts +1 -0
- package/dist/phases/technical-design-verification/index.js +1 -0
- package/dist/phases/technical-design-verification/verifier.d.ts +36 -0
- package/dist/phases/technical-design-verification/verifier.js +147 -0
- package/dist/prompts/checklist-verification.d.ts +11 -0
- package/dist/prompts/checklist-verification.js +153 -0
- package/dist/prompts/code-implementation-improvement.d.ts +5 -0
- package/dist/prompts/code-implementation-improvement.js +108 -0
- package/dist/prompts/code-implementation-verification.d.ts +3 -0
- package/dist/prompts/code-implementation-verification.js +176 -0
- package/dist/prompts/feature-analysis-improvement.d.ts +8 -0
- package/dist/prompts/feature-analysis-improvement.js +109 -0
- package/dist/prompts/feature-analysis.js +1 -1
- package/dist/prompts/formatters.d.ts +17 -4
- package/dist/prompts/formatters.js +41 -12
- package/dist/prompts/technical-design-improvement.d.ts +5 -0
- package/dist/prompts/technical-design-improvement.js +93 -0
- package/dist/prompts/technical-design-verification.d.ts +11 -0
- package/dist/prompts/technical-design-verification.js +134 -0
- package/dist/prompts/technical-design.js +1 -1
- package/dist/services/audit-logs.d.ts +60 -0
- package/dist/services/audit-logs.js +115 -0
- package/dist/services/checklist.d.ts +1 -0
- package/dist/types/index.d.ts +19 -0
- package/dist/utils/image-downloader.d.ts +32 -0
- package/dist/utils/image-downloader.js +144 -0
- package/dist/workflow-runner/executors/phase-executor.js +56 -12
- package/package.json +1 -1
- package/dist/api/features.d.ts +0 -100
- package/dist/api/features.js +0 -219
- package/dist/logger.d.ts +0 -19
- package/dist/logger.js +0 -52
- package/dist/types.d.ts +0 -99
- package/dist/types.js +0 -1
- package/dist/workflow-runner/config/stage-configs.d.ts +0 -5
- package/dist/workflow-runner/config/stage-configs.js +0 -34
- package/dist/workflow-runner/core/feature-filter.test.d.ts +0 -4
- package/dist/workflow-runner/core/feature-filter.test.js +0 -127
- package/dist/workflow-runner/executors/stage-executor.d.ts +0 -8
- package/dist/workflow-runner/executors/stage-executor.js +0 -49
- package/dist/workflow-runner/feature-fetcher.d.ts +0 -41
- package/dist/workflow-runner/feature-fetcher.js +0 -121
- package/dist/workflow-runner/feature-service.d.ts +0 -17
- package/dist/workflow-runner/feature-service.js +0 -60
- package/dist/workflow-runner/pipeline.d.ts +0 -18
- package/dist/workflow-runner/pipeline.js +0 -197
- package/dist/workflow-runner/processor.d.ts +0 -40
- package/dist/workflow-runner/processor.js +0 -191
- package/dist/workflow-runner/status-updater.d.ts +0 -27
- package/dist/workflow-runner/status-updater.js +0 -80
- package/dist/workflow-runner/types.d.ts +0 -48
- package/dist/workflow-runner/types.js +0 -4
package/README.md
CHANGED
|
@@ -12,6 +12,13 @@ AI-powered software development CLI tool with comprehensive feature management,
|
|
|
12
12
|
- **Hook-Friendly**: Designed for pre-commit hooks and CI/CD automation
|
|
13
13
|
- **Detailed Output**: Clear feedback with blocking/warning/passing results
|
|
14
14
|
|
|
15
|
+
### 🔧 Code Refactoring
|
|
16
|
+
|
|
17
|
+
- **Intelligent Analysis**: AI-powered code quality and refactoring analysis
|
|
18
|
+
- **Pattern Detection**: Identifies code smells, duplication, and technical debt
|
|
19
|
+
- **Improvement Suggestions**: Provides prioritized recommendations for code improvement
|
|
20
|
+
- **Interactive Mode**: Ask for confirmation before applying refactoring changes
|
|
21
|
+
|
|
15
22
|
### 🎯 Feature Analysis
|
|
16
23
|
|
|
17
24
|
- **MCP Integration**: Analyze features using Model Context Protocol
|
|
@@ -68,6 +75,16 @@ edsger --review --files "**/*.ts" "**/*.js"
|
|
|
68
75
|
edsger --review --verbose
|
|
69
76
|
```
|
|
70
77
|
|
|
78
|
+
### Code Refactoring
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
# Analyze and refactor code in current directory
|
|
82
|
+
edsger --refactor
|
|
83
|
+
|
|
84
|
+
# Verbose refactoring output
|
|
85
|
+
edsger --refactor --verbose
|
|
86
|
+
```
|
|
87
|
+
|
|
71
88
|
### Feature Analysis
|
|
72
89
|
|
|
73
90
|
```bash
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Batch update user story statuses
|
|
3
|
+
*/
|
|
4
|
+
export declare function batchUpdateUserStoryStatus(mcpServerUrl: string, mcpToken: string, userStoryIds: string[], status: 'draft' | 'ready' | 'in_progress' | 'done' | 'cancelled', verbose?: boolean): Promise<boolean>;
|
|
5
|
+
/**
|
|
6
|
+
* Batch update test case statuses
|
|
7
|
+
*/
|
|
8
|
+
export declare function batchUpdateTestCaseStatus(mcpServerUrl: string, mcpToken: string, testCaseIds: string[], status: 'draft' | 'ready' | 'in_progress' | 'done' | 'cancelled', verbose?: boolean): Promise<boolean>;
|
|
9
|
+
/**
|
|
10
|
+
* Batch delete user stories
|
|
11
|
+
*/
|
|
12
|
+
export declare function batchDeleteUserStories(mcpServerUrl: string, mcpToken: string, userStoryIds: string[], verbose?: boolean): Promise<boolean>;
|
|
13
|
+
/**
|
|
14
|
+
* Batch delete test cases
|
|
15
|
+
*/
|
|
16
|
+
export declare function batchDeleteTestCases(mcpServerUrl: string, mcpToken: string, testCaseIds: string[], verbose?: boolean): Promise<boolean>;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { logInfo, logError } from '../../utils/logger.js';
|
|
2
|
+
import { callMcpEndpoint } from '../mcp-client.js';
|
|
3
|
+
/**
|
|
4
|
+
* Batch update user story statuses
|
|
5
|
+
*/
|
|
6
|
+
export async function batchUpdateUserStoryStatus(mcpServerUrl, mcpToken, userStoryIds, status, verbose) {
|
|
7
|
+
try {
|
|
8
|
+
if (verbose) {
|
|
9
|
+
logInfo(`Batch updating ${userStoryIds.length} user stories to status: ${status}`);
|
|
10
|
+
}
|
|
11
|
+
for (const id of userStoryIds) {
|
|
12
|
+
await callMcpEndpoint(mcpServerUrl, mcpToken, 'user_stories/update_status', {
|
|
13
|
+
user_story_id: id,
|
|
14
|
+
status,
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
if (verbose) {
|
|
18
|
+
logInfo('✅ Batch user story status update completed');
|
|
19
|
+
}
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
24
|
+
logError(`Failed to batch update user story statuses: ${errorMessage}`);
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Batch update test case statuses
|
|
30
|
+
*/
|
|
31
|
+
export async function batchUpdateTestCaseStatus(mcpServerUrl, mcpToken, testCaseIds, status, verbose) {
|
|
32
|
+
try {
|
|
33
|
+
if (verbose) {
|
|
34
|
+
logInfo(`Batch updating ${testCaseIds.length} test cases to status: ${status}`);
|
|
35
|
+
}
|
|
36
|
+
for (const id of testCaseIds) {
|
|
37
|
+
await callMcpEndpoint(mcpServerUrl, mcpToken, 'test_cases/update_status', {
|
|
38
|
+
test_case_id: id,
|
|
39
|
+
status,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
if (verbose) {
|
|
43
|
+
logInfo('✅ Batch test case status update completed');
|
|
44
|
+
}
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
49
|
+
logError(`Failed to batch update test case statuses: ${errorMessage}`);
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Batch delete user stories
|
|
55
|
+
*/
|
|
56
|
+
export async function batchDeleteUserStories(mcpServerUrl, mcpToken, userStoryIds, verbose) {
|
|
57
|
+
try {
|
|
58
|
+
if (verbose) {
|
|
59
|
+
logInfo(`Batch deleting ${userStoryIds.length} user stories`);
|
|
60
|
+
}
|
|
61
|
+
for (const id of userStoryIds) {
|
|
62
|
+
await callMcpEndpoint(mcpServerUrl, mcpToken, 'user_stories/delete', {
|
|
63
|
+
user_story_id: id,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
if (verbose) {
|
|
67
|
+
logInfo('✅ Batch user story deletion completed');
|
|
68
|
+
}
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
73
|
+
logError(`Failed to batch delete user stories: ${errorMessage}`);
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Batch delete test cases
|
|
79
|
+
*/
|
|
80
|
+
export async function batchDeleteTestCases(mcpServerUrl, mcpToken, testCaseIds, verbose) {
|
|
81
|
+
try {
|
|
82
|
+
if (verbose) {
|
|
83
|
+
logInfo(`Batch deleting ${testCaseIds.length} test cases`);
|
|
84
|
+
}
|
|
85
|
+
for (const id of testCaseIds) {
|
|
86
|
+
await callMcpEndpoint(mcpServerUrl, mcpToken, 'test_cases/delete', {
|
|
87
|
+
test_case_id: id,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
if (verbose) {
|
|
91
|
+
logInfo('✅ Batch test case deletion completed');
|
|
92
|
+
}
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
97
|
+
logError(`Failed to batch delete test cases: ${errorMessage}`);
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
@@ -19,3 +19,11 @@ export declare function createTestCases(mcpServerUrl: string, mcpToken: string,
|
|
|
19
19
|
description: string;
|
|
20
20
|
is_critical?: boolean;
|
|
21
21
|
}>, verbose?: boolean): Promise<boolean>;
|
|
22
|
+
/**
|
|
23
|
+
* Delete a test case
|
|
24
|
+
*/
|
|
25
|
+
export declare function deleteTestCase(mcpServerUrl: string, mcpToken: string, testCaseId: string, verbose?: boolean): Promise<boolean>;
|
|
26
|
+
/**
|
|
27
|
+
* Update test case status
|
|
28
|
+
*/
|
|
29
|
+
export declare function updateTestCaseStatus(mcpServerUrl: string, mcpToken: string, testCaseId: string, status: 'draft' | 'ready' | 'in_progress' | 'done' | 'cancelled', verbose?: boolean): Promise<boolean>;
|
|
@@ -61,3 +61,48 @@ export async function createTestCases(mcpServerUrl, mcpToken, featureId, testCas
|
|
|
61
61
|
return false;
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
|
+
/**
|
|
65
|
+
* Delete a test case
|
|
66
|
+
*/
|
|
67
|
+
export async function deleteTestCase(mcpServerUrl, mcpToken, testCaseId, verbose) {
|
|
68
|
+
try {
|
|
69
|
+
if (verbose) {
|
|
70
|
+
logInfo(`Deleting test case: ${testCaseId}`);
|
|
71
|
+
}
|
|
72
|
+
await callMcpEndpoint(mcpServerUrl, mcpToken, 'test_cases/delete', {
|
|
73
|
+
test_case_id: testCaseId,
|
|
74
|
+
});
|
|
75
|
+
if (verbose) {
|
|
76
|
+
logInfo('✅ Test case deleted successfully');
|
|
77
|
+
}
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
82
|
+
logError(`Failed to delete test case: ${errorMessage}`);
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Update test case status
|
|
88
|
+
*/
|
|
89
|
+
export async function updateTestCaseStatus(mcpServerUrl, mcpToken, testCaseId, status, verbose) {
|
|
90
|
+
try {
|
|
91
|
+
if (verbose) {
|
|
92
|
+
logInfo(`Updating test case ${testCaseId} status to: ${status}`);
|
|
93
|
+
}
|
|
94
|
+
await callMcpEndpoint(mcpServerUrl, mcpToken, 'test_cases/update_status', {
|
|
95
|
+
test_case_id: testCaseId,
|
|
96
|
+
status,
|
|
97
|
+
});
|
|
98
|
+
if (verbose) {
|
|
99
|
+
logInfo('✅ Test case status updated successfully');
|
|
100
|
+
}
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
105
|
+
logError(`Failed to update test case status: ${errorMessage}`);
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
@@ -19,3 +19,11 @@ export declare function createUserStories(mcpServerUrl: string, mcpToken: string
|
|
|
19
19
|
description: string;
|
|
20
20
|
status?: string;
|
|
21
21
|
}>, verbose?: boolean): Promise<boolean>;
|
|
22
|
+
/**
|
|
23
|
+
* Delete a user story
|
|
24
|
+
*/
|
|
25
|
+
export declare function deleteUserStory(mcpServerUrl: string, mcpToken: string, userStoryId: string, verbose?: boolean): Promise<boolean>;
|
|
26
|
+
/**
|
|
27
|
+
* Update user story status
|
|
28
|
+
*/
|
|
29
|
+
export declare function updateUserStoryStatus(mcpServerUrl: string, mcpToken: string, userStoryId: string, status: 'draft' | 'ready' | 'in_progress' | 'done' | 'cancelled', verbose?: boolean): Promise<boolean>;
|
|
@@ -61,3 +61,48 @@ export async function createUserStories(mcpServerUrl, mcpToken, featureId, userS
|
|
|
61
61
|
return false;
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
|
+
/**
|
|
65
|
+
* Delete a user story
|
|
66
|
+
*/
|
|
67
|
+
export async function deleteUserStory(mcpServerUrl, mcpToken, userStoryId, verbose) {
|
|
68
|
+
try {
|
|
69
|
+
if (verbose) {
|
|
70
|
+
logInfo(`Deleting user story: ${userStoryId}`);
|
|
71
|
+
}
|
|
72
|
+
await callMcpEndpoint(mcpServerUrl, mcpToken, 'user_stories/delete', {
|
|
73
|
+
user_story_id: userStoryId,
|
|
74
|
+
});
|
|
75
|
+
if (verbose) {
|
|
76
|
+
logInfo('✅ User story deleted successfully');
|
|
77
|
+
}
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
82
|
+
logError(`Failed to delete user story: ${errorMessage}`);
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Update user story status
|
|
88
|
+
*/
|
|
89
|
+
export async function updateUserStoryStatus(mcpServerUrl, mcpToken, userStoryId, status, verbose) {
|
|
90
|
+
try {
|
|
91
|
+
if (verbose) {
|
|
92
|
+
logInfo(`Updating user story ${userStoryId} status to: ${status}`);
|
|
93
|
+
}
|
|
94
|
+
await callMcpEndpoint(mcpServerUrl, mcpToken, 'user_stories/update_status', {
|
|
95
|
+
user_story_id: userStoryId,
|
|
96
|
+
status,
|
|
97
|
+
});
|
|
98
|
+
if (verbose) {
|
|
99
|
+
logInfo('✅ User story status updated successfully');
|
|
100
|
+
}
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
105
|
+
logError(`Failed to update user story status: ${errorMessage}`);
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { query } from '@anthropic-ai/claude-code';
|
|
2
|
+
import { logInfo, logError, logSuccess } from '../../utils/logger.js';
|
|
3
|
+
import { validateConfiguration } from '../utils/validation.js';
|
|
4
|
+
export const runRefactor = async (options) => {
|
|
5
|
+
// Load and validate configuration
|
|
6
|
+
const config = validateConfiguration(options);
|
|
7
|
+
if (options.verbose) {
|
|
8
|
+
logInfo('Starting code refactoring for current directory...');
|
|
9
|
+
}
|
|
10
|
+
logInfo('Analyzing code for refactoring opportunities...');
|
|
11
|
+
try {
|
|
12
|
+
const refactorPrompt = createRefactorPrompt(config);
|
|
13
|
+
const systemPrompt = createSystemPrompt();
|
|
14
|
+
let hasCompleted = false;
|
|
15
|
+
for await (const message of query({
|
|
16
|
+
prompt: refactorPrompt,
|
|
17
|
+
options: {
|
|
18
|
+
appendSystemPrompt: systemPrompt,
|
|
19
|
+
model: config.claude.model || 'sonnet',
|
|
20
|
+
},
|
|
21
|
+
})) {
|
|
22
|
+
// Stream the refactoring process
|
|
23
|
+
if (message.type === 'assistant' && message.message?.content) {
|
|
24
|
+
for (const content of message.message.content) {
|
|
25
|
+
if (content.type === 'text') {
|
|
26
|
+
console.log(`\n🤖 ${content.text}`);
|
|
27
|
+
}
|
|
28
|
+
else if (content.type === 'tool_use') {
|
|
29
|
+
console.log(`\n🔧 ${content.name}: ${content.input.description || content.input.command || 'Running...'}`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if (message.type === 'result') {
|
|
34
|
+
hasCompleted = true;
|
|
35
|
+
if (message.subtype === 'success') {
|
|
36
|
+
logSuccess('Refactoring analysis completed successfully');
|
|
37
|
+
process.exit(0);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
logError(`Refactoring incomplete: ${message.subtype}`);
|
|
41
|
+
if (message.subtype === 'error_max_turns') {
|
|
42
|
+
console.log('💡 Try simplifying the codebase or increase timeout');
|
|
43
|
+
}
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (!hasCompleted) {
|
|
49
|
+
logError('Refactoring process did not complete');
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
logError(`Refactoring failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
55
|
+
process.exit(1);
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
const createSystemPrompt = () => {
|
|
59
|
+
return `You are an expert code refactoring assistant using Claude Code. Your task is to analyze code in the current directory and suggest or perform refactoring improvements.
|
|
60
|
+
|
|
61
|
+
IMPORTANT INSTRUCTIONS:
|
|
62
|
+
1. Use the Bash tool to explore the project structure (ls, find, etc.)
|
|
63
|
+
2. Use the Read tool to examine file contents
|
|
64
|
+
3. Use the Grep tool to search for patterns, code smells, or duplications
|
|
65
|
+
4. Use the Edit tool to apply refactoring changes when appropriate
|
|
66
|
+
5. Analyze code quality, identify technical debt, and suggest improvements
|
|
67
|
+
|
|
68
|
+
REFACTORING FOCUS AREAS:
|
|
69
|
+
- Code duplication and DRY violations
|
|
70
|
+
- Complex functions that need simplification
|
|
71
|
+
- Poor naming conventions
|
|
72
|
+
- Missing type annotations (TypeScript)
|
|
73
|
+
- Inefficient algorithms or data structures
|
|
74
|
+
- Code organization and structure
|
|
75
|
+
- Missing or inadequate error handling
|
|
76
|
+
- Opportunities for better abstraction
|
|
77
|
+
- Performance improvements
|
|
78
|
+
|
|
79
|
+
WORKFLOW:
|
|
80
|
+
1. First, explore the project structure to understand the codebase
|
|
81
|
+
2. Identify files that would benefit from refactoring
|
|
82
|
+
3. Analyze specific issues and patterns
|
|
83
|
+
4. Suggest improvements with clear explanations
|
|
84
|
+
5. Ask for user confirmation before making significant changes
|
|
85
|
+
6. Apply changes using the Edit tool if approved
|
|
86
|
+
|
|
87
|
+
Be thorough but focused. Prioritize high-impact refactorings that improve code maintainability and quality.`;
|
|
88
|
+
};
|
|
89
|
+
const createRefactorPrompt = (config) => {
|
|
90
|
+
return `Please analyze the code in the current directory for refactoring opportunities.
|
|
91
|
+
|
|
92
|
+
Steps to follow:
|
|
93
|
+
1. Start by running "ls -la" to see the project structure
|
|
94
|
+
2. Identify key source files (focus on patterns: ${config.patterns.join(', ')})
|
|
95
|
+
3. Read and analyze relevant source files
|
|
96
|
+
4. Look for:
|
|
97
|
+
- Code duplication
|
|
98
|
+
- Complex or long functions
|
|
99
|
+
- Poor naming
|
|
100
|
+
- Missing types or documentation
|
|
101
|
+
- Error handling issues
|
|
102
|
+
- Performance bottlenecks
|
|
103
|
+
5. Provide a summary of findings with prioritized recommendations
|
|
104
|
+
6. Ask if I'd like you to proceed with any specific refactoring
|
|
105
|
+
|
|
106
|
+
Start by exploring the current directory structure.`;
|
|
107
|
+
};
|
package/dist/cli/index.js
CHANGED
|
@@ -11,6 +11,7 @@ import { runTechnicalDesign } from './commands/technical-design-command.js';
|
|
|
11
11
|
import { runCodeImplementation } from './commands/code-implementation-command.js';
|
|
12
12
|
import { runFunctionalTestingCommand } from './commands/functional-testing-command.js';
|
|
13
13
|
import { runCodeReview } from './commands/code-review-command.js';
|
|
14
|
+
import { runRefactor } from './commands/refactor-command.js';
|
|
14
15
|
// Get package.json version dynamically
|
|
15
16
|
const __filename = fileURLToPath(import.meta.url);
|
|
16
17
|
const __dirname = dirname(__filename);
|
|
@@ -28,6 +29,7 @@ program
|
|
|
28
29
|
.option('-r, --review', 'Review code changes')
|
|
29
30
|
.option('-s, --staged', 'Review only staged changes')
|
|
30
31
|
.option('-f, --files <patterns...>', 'Review specific file patterns')
|
|
32
|
+
.option('--refactor', 'Refactor code in current directory')
|
|
31
33
|
.option('--feature-analysis <featureId>', 'Analyze feature and generate user stories/test cases')
|
|
32
34
|
.option('--technical-design <featureId>', 'Generate technical design for a feature')
|
|
33
35
|
.option('--implement <featureId>', 'Implement code for a feature based on its specifications')
|
|
@@ -70,6 +72,11 @@ export const runEdsger = async (options) => {
|
|
|
70
72
|
await runFunctionalTestingCommand(options);
|
|
71
73
|
return;
|
|
72
74
|
}
|
|
75
|
+
// Handle refactor mode
|
|
76
|
+
if (options.refactor) {
|
|
77
|
+
await runRefactor(options);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
73
80
|
// Handle code review mode (explicit --review flag or as fallback)
|
|
74
81
|
if (options.review || options.staged || options.files) {
|
|
75
82
|
await runCodeReview(options);
|
package/dist/cli.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
export * from './cli/index.js';
|
|
3
|
+
import './cli/index.js';
|
package/dist/cli.js
CHANGED
|
@@ -1,100 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
import
|
|
6
|
-
import { fileURLToPath } from 'url';
|
|
7
|
-
import { config as dotenvConfig } from 'dotenv';
|
|
8
|
-
import { logError } from './utils/logger.js';
|
|
9
|
-
import { runWorkflow } from './cli/commands/workflow-command.js';
|
|
10
|
-
import { runFeatureAnalysis } from './cli/commands/feature-analysis-command.js';
|
|
11
|
-
import { runTechnicalDesign } from './cli/commands/technical-design-command.js';
|
|
12
|
-
import { runCodeImplementation } from './cli/commands/code-implementation-command.js';
|
|
13
|
-
import { runFunctionalTestingCommand } from './cli/commands/functional-testing-command.js';
|
|
14
|
-
import { runCodeReview } from './cli/commands/code-review-command.js';
|
|
15
|
-
// Get package.json version dynamically
|
|
16
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
17
|
-
const __dirname = dirname(__filename);
|
|
18
|
-
const packageJson = JSON.parse(readFileSync(join(__dirname, '../package.json'), 'utf-8'));
|
|
19
|
-
const version = packageJson.version;
|
|
20
|
-
// Load environment variables from .env file
|
|
21
|
-
// Load from current working directory (where the command is run)
|
|
22
|
-
dotenvConfig({ path: join(process.cwd(), '.env') });
|
|
23
|
-
const program = new Command();
|
|
24
|
-
program
|
|
25
|
-
.name('edsger')
|
|
26
|
-
.description('AI-powered code review CLI tool using Claude Code SDK')
|
|
27
|
-
.version(version);
|
|
28
|
-
program
|
|
29
|
-
.option('-r, --review', 'Review code changes')
|
|
30
|
-
.option('-s, --staged', 'Review only staged changes')
|
|
31
|
-
.option('-f, --files <patterns...>', 'Review specific file patterns')
|
|
32
|
-
.option('--feature-analysis <featureId>', 'Analyze feature and generate user stories/test cases')
|
|
33
|
-
.option('--technical-design <featureId>', 'Generate technical design for a feature')
|
|
34
|
-
.option('--implement <featureId>', 'Implement code for a feature based on its specifications')
|
|
35
|
-
.option('--test <featureId>', 'Run functional tests for a feature using Playwright')
|
|
36
|
-
.option('--workflow', 'Run continuous workflow processor to handle ready_for_dev features')
|
|
37
|
-
.option('-c, --config <path>', 'Path to config file')
|
|
38
|
-
.option('-v, --verbose', 'Verbose output');
|
|
39
|
-
program.action(async (options) => {
|
|
40
|
-
try {
|
|
41
|
-
await runEdsger(options);
|
|
42
|
-
}
|
|
43
|
-
catch (error) {
|
|
44
|
-
logError(error instanceof Error ? error.message : String(error));
|
|
45
|
-
process.exit(1);
|
|
46
|
-
}
|
|
47
|
-
});
|
|
48
|
-
export const runEdsger = async (options) => {
|
|
49
|
-
// Handle workflow mode
|
|
50
|
-
if (options.workflow) {
|
|
51
|
-
await runWorkflow(options);
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
// Handle feature analysis mode
|
|
55
|
-
if (options.featureAnalysis) {
|
|
56
|
-
await runFeatureAnalysis(options);
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
// Handle technical design mode
|
|
60
|
-
if (options.technicalDesign) {
|
|
61
|
-
await runTechnicalDesign(options);
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
// Handle code implementation mode
|
|
65
|
-
if (options.implement) {
|
|
66
|
-
await runCodeImplementation(options);
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
// Handle functional testing mode
|
|
70
|
-
if (options.test) {
|
|
71
|
-
await runFunctionalTestingCommand(options);
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
// Handle code review mode (explicit --review flag or as fallback)
|
|
75
|
-
if (options.review || options.staged || options.files) {
|
|
76
|
-
await runCodeReview(options);
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
79
|
-
// Default to workflow mode if environment is configured, otherwise code review
|
|
80
|
-
const productId = process.env.EDSGER_PRODUCT_ID;
|
|
81
|
-
const mcpToken = process.env.EDSGER_MCP_TOKEN;
|
|
82
|
-
if (productId && mcpToken) {
|
|
83
|
-
// Environment is configured for workflow, use that as default
|
|
84
|
-
options.workflow = true;
|
|
85
|
-
await runWorkflow(options);
|
|
86
|
-
}
|
|
87
|
-
else {
|
|
88
|
-
// Default to code review mode
|
|
89
|
-
await runCodeReview(options);
|
|
90
|
-
}
|
|
91
|
-
};
|
|
92
|
-
// Only parse when this file is run directly (not imported as module)
|
|
93
|
-
// Check if this is the main module being executed
|
|
94
|
-
const isMainModule = import.meta.url === `file://${process.argv[1]}` ||
|
|
95
|
-
((_a = process.argv[1]) === null || _a === void 0 ? void 0 : _a.endsWith('/edsger')) ||
|
|
96
|
-
((_b = process.argv[1]) === null || _b === void 0 ? void 0 : _b.endsWith('\\edsger')) ||
|
|
97
|
-
((_c = process.argv[1]) === null || _c === void 0 ? void 0 : _c.endsWith('cli.js'));
|
|
98
|
-
if (isMainModule) {
|
|
99
|
-
program.parse();
|
|
100
|
-
}
|
|
2
|
+
// Re-export the CLI module
|
|
3
|
+
export * from './cli/index.js';
|
|
4
|
+
// Import and trigger the CLI parsing if this file is run directly
|
|
5
|
+
import './cli/index.js';
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { EdsgerConfig } from '../../types/index.js';
|
|
2
|
+
import { ChecklistPhaseContext } from '../../services/checklist.js';
|
|
3
|
+
import { ChecklistVerificationResult } from '../code-implementation-verification/index.js';
|
|
4
|
+
import { CodeImplementationResult } from './analyzer.js';
|
|
5
|
+
export interface VerificationCycleResult {
|
|
6
|
+
passed: boolean;
|
|
7
|
+
verificationResult: ChecklistVerificationResult | null;
|
|
8
|
+
nextPrompt: string | null;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Perform a complete verification cycle:
|
|
12
|
+
* 1. Verify code implementation against checklist
|
|
13
|
+
* 2. Log results to audit logs
|
|
14
|
+
* 3. Create improvement prompt if verification failed
|
|
15
|
+
*/
|
|
16
|
+
export declare function performVerificationCycle(branchName: string, baseBranch: string, checklistContext: ChecklistPhaseContext | null, featureId: string, featureName: string, featureDescription: string | undefined, config: EdsgerConfig, currentIteration: number, maxIterations: number, mcpServerUrl: string, mcpToken: string, verbose?: boolean): Promise<VerificationCycleResult>;
|
|
17
|
+
/**
|
|
18
|
+
* Build successful implementation result
|
|
19
|
+
*/
|
|
20
|
+
export declare function buildImplementationResult(featureId: string, branchName: string, implementationSummary: string, filesModified: string[], commitHash: string, iterations: number, checklistResults?: any[], checklistItemResults?: any[]): CodeImplementationResult;
|
|
21
|
+
/**
|
|
22
|
+
* Build verification failure result
|
|
23
|
+
*/
|
|
24
|
+
export declare function buildVerificationFailureResult(featureId: string, branchName: string, implementationSummary: string, filesModified: string[], commitHash: string, verificationResult: ChecklistVerificationResult, iterations: number): CodeImplementationResult;
|
|
25
|
+
/**
|
|
26
|
+
* Build error result for no implementation
|
|
27
|
+
*/
|
|
28
|
+
export declare function buildNoResultsError(featureId: string, branchName: string): CodeImplementationResult;
|