edsger 0.2.3 â 0.2.5
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 +123 -0
- package/dist/cli/formatters/formatter-utils.d.ts +23 -0
- package/dist/cli/formatters/formatter-utils.js +67 -0
- package/dist/cli/index.js +7 -0
- package/dist/cli/utils/command-handler.d.ts +23 -0
- package/dist/cli/utils/command-handler.js +39 -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 +304 -175
- 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 -219
- 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 +2 -1
- 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 -318
- 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/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/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/utils/image-processor.d.ts +0 -5
- package/dist/utils/image-processor.js +0 -55
- 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,123 @@
|
|
|
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 automatic code refactoring for current directory...');
|
|
9
|
+
}
|
|
10
|
+
logInfo('Analyzing and refactoring code...');
|
|
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
|
+
permissionMode: 'bypassPermissions',
|
|
21
|
+
},
|
|
22
|
+
})) {
|
|
23
|
+
// Stream the refactoring process
|
|
24
|
+
if (message.type === 'assistant' && message.message?.content) {
|
|
25
|
+
for (const content of message.message.content) {
|
|
26
|
+
if (content.type === 'text') {
|
|
27
|
+
console.log(`\nđ¤ ${content.text}`);
|
|
28
|
+
}
|
|
29
|
+
else if (content.type === 'tool_use') {
|
|
30
|
+
console.log(`\nđ§ ${content.name}: ${content.input.description || content.input.command || 'Running...'}`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
if (message.type === 'result') {
|
|
35
|
+
hasCompleted = true;
|
|
36
|
+
if (message.subtype === 'success') {
|
|
37
|
+
logSuccess('Code refactoring completed successfully');
|
|
38
|
+
process.exit(0);
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
logError(`Refactoring incomplete: ${message.subtype}`);
|
|
42
|
+
if (message.subtype === 'error_max_turns') {
|
|
43
|
+
console.log('đĄ Try simplifying the codebase or increase timeout');
|
|
44
|
+
}
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
if (!hasCompleted) {
|
|
50
|
+
logError('Refactoring process did not complete');
|
|
51
|
+
process.exit(1);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
logError(`Refactoring failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
56
|
+
process.exit(1);
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
const createSystemPrompt = () => {
|
|
60
|
+
return `You are an expert code refactoring assistant using Claude Code. Your task is to analyze and AUTOMATICALLY REFACTOR code in the current directory to improve quality and maintainability.
|
|
61
|
+
|
|
62
|
+
IMPORTANT INSTRUCTIONS:
|
|
63
|
+
1. Use the Bash tool to explore the project structure (ls, find, etc.)
|
|
64
|
+
2. Use the Read tool to examine file contents
|
|
65
|
+
3. Use the Grep tool to search for patterns, code smells, or duplications
|
|
66
|
+
4. Use the Edit tool to DIRECTLY apply refactoring changes
|
|
67
|
+
5. You have FULL PERMISSION to make refactoring changes without asking for confirmation
|
|
68
|
+
|
|
69
|
+
REFACTORING FOCUS AREAS (prioritized):
|
|
70
|
+
1. Code duplication and DRY violations (HIGHEST PRIORITY)
|
|
71
|
+
2. Complex functions that need simplification
|
|
72
|
+
3. Poor naming conventions
|
|
73
|
+
4. Missing type annotations (TypeScript)
|
|
74
|
+
5. Inefficient algorithms or data structures
|
|
75
|
+
6. Code organization and structure
|
|
76
|
+
7. Missing or inadequate error handling
|
|
77
|
+
8. Opportunities for better abstraction
|
|
78
|
+
9. Performance improvements
|
|
79
|
+
|
|
80
|
+
WORKFLOW:
|
|
81
|
+
1. First, explore the project structure to understand the codebase
|
|
82
|
+
2. Identify files that would benefit from refactoring
|
|
83
|
+
3. Analyze specific issues and patterns (focus on high-impact issues first)
|
|
84
|
+
4. For each issue found:
|
|
85
|
+
- Explain what you're refactoring and why
|
|
86
|
+
- Apply the refactoring using the Edit tool
|
|
87
|
+
- Verify the change is correct
|
|
88
|
+
5. Continue until all high-priority refactorings are complete or you run out of turns
|
|
89
|
+
|
|
90
|
+
SAFETY GUIDELINES:
|
|
91
|
+
- Start with safest refactorings (extract utilities, remove duplication)
|
|
92
|
+
- Preserve existing functionality - only improve structure/quality
|
|
93
|
+
- Focus on non-breaking changes
|
|
94
|
+
- Make atomic commits for each logical refactoring
|
|
95
|
+
|
|
96
|
+
IMPORTANT: You should DIRECTLY perform refactorings without asking for permission. The user has granted you full bypass authority to improve the code.`;
|
|
97
|
+
};
|
|
98
|
+
const createRefactorPrompt = (config) => {
|
|
99
|
+
return `Please analyze and REFACTOR the code in the current directory. You have full permission to make improvements directly.
|
|
100
|
+
|
|
101
|
+
TASK: Automatically identify and fix code quality issues
|
|
102
|
+
|
|
103
|
+
Steps to follow:
|
|
104
|
+
1. Start by running "ls -la" to see the project structure
|
|
105
|
+
2. Identify key source files (focus on patterns: ${config.patterns.join(', ')})
|
|
106
|
+
3. Read and analyze relevant source files
|
|
107
|
+
4. Look for HIGH-PRIORITY issues:
|
|
108
|
+
- Code duplication (MOST IMPORTANT - fix first)
|
|
109
|
+
- Complex or long functions
|
|
110
|
+
- Poor naming
|
|
111
|
+
- Missing types or documentation
|
|
112
|
+
- Error handling issues
|
|
113
|
+
- Performance bottlenecks
|
|
114
|
+
5. For EACH issue found, IMMEDIATELY apply the fix:
|
|
115
|
+
- Use the Edit tool to make the change
|
|
116
|
+
- Explain what you changed and why
|
|
117
|
+
- Move to the next issue
|
|
118
|
+
6. Continue refactoring until all high-priority issues are addressed
|
|
119
|
+
|
|
120
|
+
IMPORTANT: Do NOT ask for permission. You have full bypass authority to improve the code directly. Start refactoring immediately after analysis.
|
|
121
|
+
|
|
122
|
+
Start by exploring the current directory structure and begin refactoring.`;
|
|
123
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface FormatterSection {
|
|
2
|
+
title: string;
|
|
3
|
+
content?: string;
|
|
4
|
+
items?: Array<{
|
|
5
|
+
label: string;
|
|
6
|
+
value?: string | number;
|
|
7
|
+
type?: 'success' | 'error' | 'info';
|
|
8
|
+
}>;
|
|
9
|
+
list?: Array<{
|
|
10
|
+
text: string;
|
|
11
|
+
isHighlight?: boolean;
|
|
12
|
+
}>;
|
|
13
|
+
}
|
|
14
|
+
export interface FormatterOptions {
|
|
15
|
+
title: string;
|
|
16
|
+
icon: string;
|
|
17
|
+
sections: FormatterSection[];
|
|
18
|
+
verbose?: boolean;
|
|
19
|
+
}
|
|
20
|
+
export declare const formatResults: (options: FormatterOptions) => void;
|
|
21
|
+
export declare const createStatusSection: (featureId: string, status: string) => FormatterSection;
|
|
22
|
+
export declare const createSummarySection: (summary?: string) => FormatterSection | null;
|
|
23
|
+
export declare const createContentPreview: (content: string, title: string, maxLines?: number) => FormatterSection;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
export const formatResults = (options) => {
|
|
2
|
+
const { title, icon, sections } = options;
|
|
3
|
+
console.log('\n' + '='.repeat(60));
|
|
4
|
+
console.log(`${icon} ${title}`);
|
|
5
|
+
console.log('='.repeat(60));
|
|
6
|
+
sections.forEach((section) => {
|
|
7
|
+
if (section.title) {
|
|
8
|
+
console.log(`\n${section.title}`);
|
|
9
|
+
}
|
|
10
|
+
if (section.content) {
|
|
11
|
+
console.log(section.content);
|
|
12
|
+
}
|
|
13
|
+
if (section.items) {
|
|
14
|
+
section.items.forEach((item) => {
|
|
15
|
+
const statusIcon = getStatusIcon(item.type);
|
|
16
|
+
const value = item.value !== undefined ? `: ${item.value}` : '';
|
|
17
|
+
console.log(`${statusIcon} ${item.label}${value}`);
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
if (section.list) {
|
|
21
|
+
section.list.forEach((listItem, index) => {
|
|
22
|
+
const prefix = listItem.isHighlight ? ' â' : ' ';
|
|
23
|
+
console.log(`${prefix}${index + 1}. ${listItem.text}`);
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
console.log('\n' + '='.repeat(60));
|
|
28
|
+
};
|
|
29
|
+
export const createStatusSection = (featureId, status) => ({
|
|
30
|
+
title: '',
|
|
31
|
+
items: [
|
|
32
|
+
{ label: 'đ Feature ID', value: featureId },
|
|
33
|
+
{
|
|
34
|
+
label: 'đ Status',
|
|
35
|
+
value: status === 'success' || status === 'testing_passed' ? 'â
Success' : 'â Failed',
|
|
36
|
+
type: status === 'success' || status === 'testing_passed' ? 'success' : 'error'
|
|
37
|
+
}
|
|
38
|
+
]
|
|
39
|
+
});
|
|
40
|
+
export const createSummarySection = (summary) => {
|
|
41
|
+
if (!summary)
|
|
42
|
+
return null;
|
|
43
|
+
return {
|
|
44
|
+
title: 'đ Summary:',
|
|
45
|
+
content: summary
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
export const createContentPreview = (content, title, maxLines = 10) => {
|
|
49
|
+
const lines = content.split('\n');
|
|
50
|
+
const previewLines = lines.slice(0, maxLines);
|
|
51
|
+
let displayContent = previewLines.join('\n');
|
|
52
|
+
if (lines.length > maxLines) {
|
|
53
|
+
displayContent += `\n... (${lines.length - maxLines} more lines)`;
|
|
54
|
+
}
|
|
55
|
+
return {
|
|
56
|
+
title: `${title}:`,
|
|
57
|
+
content: 'â'.repeat(40) + '\n' + displayContent + '\n' + 'â'.repeat(40)
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
function getStatusIcon(type) {
|
|
61
|
+
switch (type) {
|
|
62
|
+
case 'success': return 'â
';
|
|
63
|
+
case 'error': return 'â';
|
|
64
|
+
case 'info': return 'âšī¸';
|
|
65
|
+
default: return 'đ';
|
|
66
|
+
}
|
|
67
|
+
}
|
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);
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { CliOptions } from '../../types/index.js';
|
|
2
|
+
export interface CommandOptions {
|
|
3
|
+
featureId: string;
|
|
4
|
+
mcpServerUrl: string;
|
|
5
|
+
mcpToken: string;
|
|
6
|
+
verbose?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export interface CommandResult {
|
|
9
|
+
status: 'success' | 'error' | 'testing_passed' | 'testing_failed' | 'pending';
|
|
10
|
+
[key: string]: any;
|
|
11
|
+
}
|
|
12
|
+
export interface CommandConfig<TResult extends CommandResult> {
|
|
13
|
+
name: string;
|
|
14
|
+
getFeatureId: (options: CliOptions) => string | undefined;
|
|
15
|
+
checkRequirements: () => Promise<boolean>;
|
|
16
|
+
requirementsError: string;
|
|
17
|
+
startMessage: string;
|
|
18
|
+
successMessage: string;
|
|
19
|
+
errorMessage: string;
|
|
20
|
+
analyzer: (commandOptions: CommandOptions, config: any, ...args: any[]) => Promise<TResult>;
|
|
21
|
+
formatter: (result: TResult, verbose?: boolean) => void;
|
|
22
|
+
}
|
|
23
|
+
export declare function executeCommand<TResult extends CommandResult>(options: CliOptions, config: CommandConfig<TResult>): Promise<void>;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { logInfo, logError, logSuccess } from '../../utils/logger.js';
|
|
2
|
+
import { validateCommandEnvironment, validateRequirements, } from './validation.js';
|
|
3
|
+
export async function executeCommand(options, config) {
|
|
4
|
+
await validateRequirements(config.checkRequirements, config.requirementsError);
|
|
5
|
+
const { config: edsgerConfig, mcpServerUrl, mcpToken } = validateCommandEnvironment(options);
|
|
6
|
+
const featureId = config.getFeatureId(options);
|
|
7
|
+
if (!featureId) {
|
|
8
|
+
throw new Error(`Feature ID is required for ${config.name}`);
|
|
9
|
+
}
|
|
10
|
+
if (options.verbose) {
|
|
11
|
+
logInfo(`${config.startMessage}: ${featureId}`);
|
|
12
|
+
}
|
|
13
|
+
logInfo(`Starting ${config.name}...`);
|
|
14
|
+
try {
|
|
15
|
+
const result = await config.analyzer({
|
|
16
|
+
featureId,
|
|
17
|
+
mcpServerUrl,
|
|
18
|
+
mcpToken,
|
|
19
|
+
verbose: options.verbose,
|
|
20
|
+
}, edsgerConfig);
|
|
21
|
+
config.formatter(result, options.verbose);
|
|
22
|
+
if (result.status === 'success' || result.status === 'testing_passed') {
|
|
23
|
+
logSuccess(config.successMessage);
|
|
24
|
+
process.exit(0);
|
|
25
|
+
}
|
|
26
|
+
else if (result.status === 'error' || result.status === 'testing_failed') {
|
|
27
|
+
logError(config.errorMessage);
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
logError(`${config.errorMessage}: ${result.status}`);
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
logError(`${config.errorMessage}: ${error instanceof Error ? error.message : String(error)}`);
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
}
|
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';
|