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.
Files changed (89) hide show
  1. package/README.md +17 -0
  2. package/dist/api/features/batch-operations.d.ts +16 -0
  3. package/dist/api/features/batch-operations.js +100 -0
  4. package/dist/api/features/index.d.ts +1 -0
  5. package/dist/api/features/index.js +1 -0
  6. package/dist/api/features/test-cases.d.ts +8 -0
  7. package/dist/api/features/test-cases.js +45 -0
  8. package/dist/api/features/user-stories.d.ts +8 -0
  9. package/dist/api/features/user-stories.js +45 -0
  10. package/dist/cli/commands/refactor-command.d.ts +2 -0
  11. package/dist/cli/commands/refactor-command.js +123 -0
  12. package/dist/cli/formatters/formatter-utils.d.ts +23 -0
  13. package/dist/cli/formatters/formatter-utils.js +67 -0
  14. package/dist/cli/index.js +7 -0
  15. package/dist/cli/utils/command-handler.d.ts +23 -0
  16. package/dist/cli/utils/command-handler.js +39 -0
  17. package/dist/cli.d.ts +2 -2
  18. package/dist/cli.js +4 -99
  19. package/dist/phases/code-implementation/analyzer-helpers.d.ts +28 -0
  20. package/dist/phases/code-implementation/analyzer-helpers.js +177 -0
  21. package/dist/phases/code-implementation/analyzer.d.ts +2 -0
  22. package/dist/phases/code-implementation/analyzer.js +304 -175
  23. package/dist/phases/code-implementation-verification/index.d.ts +1 -0
  24. package/dist/phases/code-implementation-verification/index.js +1 -0
  25. package/dist/phases/code-implementation-verification/verifier.d.ts +31 -0
  26. package/dist/phases/code-implementation-verification/verifier.js +196 -0
  27. package/dist/phases/feature-analysis/analyzer-helpers.d.ts +62 -0
  28. package/dist/phases/feature-analysis/analyzer-helpers.js +450 -0
  29. package/dist/phases/feature-analysis/analyzer.d.ts +1 -0
  30. package/dist/phases/feature-analysis/analyzer.js +132 -219
  31. package/dist/phases/feature-analysis-verification/index.d.ts +1 -0
  32. package/dist/phases/feature-analysis-verification/index.js +1 -0
  33. package/dist/phases/feature-analysis-verification/verifier.d.ts +37 -0
  34. package/dist/phases/feature-analysis-verification/verifier.js +147 -0
  35. package/dist/phases/pull-request/creator.js +2 -1
  36. package/dist/phases/technical-design/analyzer-helpers.d.ts +37 -0
  37. package/dist/phases/technical-design/analyzer-helpers.js +144 -0
  38. package/dist/phases/technical-design/analyzer.d.ts +3 -0
  39. package/dist/phases/technical-design/analyzer.js +282 -318
  40. package/dist/phases/technical-design-verification/index.d.ts +1 -0
  41. package/dist/phases/technical-design-verification/index.js +1 -0
  42. package/dist/phases/technical-design-verification/verifier.d.ts +36 -0
  43. package/dist/phases/technical-design-verification/verifier.js +147 -0
  44. package/dist/prompts/checklist-verification.d.ts +11 -0
  45. package/dist/prompts/checklist-verification.js +153 -0
  46. package/dist/prompts/code-implementation-improvement.d.ts +5 -0
  47. package/dist/prompts/code-implementation-improvement.js +108 -0
  48. package/dist/prompts/code-implementation-verification.d.ts +3 -0
  49. package/dist/prompts/code-implementation-verification.js +176 -0
  50. package/dist/prompts/feature-analysis-improvement.d.ts +8 -0
  51. package/dist/prompts/feature-analysis-improvement.js +109 -0
  52. package/dist/prompts/feature-analysis.js +1 -1
  53. package/dist/prompts/technical-design-improvement.d.ts +5 -0
  54. package/dist/prompts/technical-design-improvement.js +93 -0
  55. package/dist/prompts/technical-design-verification.d.ts +11 -0
  56. package/dist/prompts/technical-design-verification.js +134 -0
  57. package/dist/prompts/technical-design.js +1 -1
  58. package/dist/services/audit-logs.d.ts +60 -0
  59. package/dist/services/audit-logs.js +115 -0
  60. package/dist/services/checklist.d.ts +1 -0
  61. package/dist/types/index.d.ts +19 -0
  62. package/dist/workflow-runner/executors/phase-executor.js +56 -12
  63. package/package.json +1 -1
  64. package/dist/api/features.d.ts +0 -100
  65. package/dist/api/features.js +0 -219
  66. package/dist/logger.d.ts +0 -19
  67. package/dist/logger.js +0 -52
  68. package/dist/types.d.ts +0 -99
  69. package/dist/types.js +0 -1
  70. package/dist/utils/image-processor.d.ts +0 -5
  71. package/dist/utils/image-processor.js +0 -55
  72. package/dist/workflow-runner/config/stage-configs.d.ts +0 -5
  73. package/dist/workflow-runner/config/stage-configs.js +0 -34
  74. package/dist/workflow-runner/core/feature-filter.test.d.ts +0 -4
  75. package/dist/workflow-runner/core/feature-filter.test.js +0 -127
  76. package/dist/workflow-runner/executors/stage-executor.d.ts +0 -8
  77. package/dist/workflow-runner/executors/stage-executor.js +0 -49
  78. package/dist/workflow-runner/feature-fetcher.d.ts +0 -41
  79. package/dist/workflow-runner/feature-fetcher.js +0 -121
  80. package/dist/workflow-runner/feature-service.d.ts +0 -17
  81. package/dist/workflow-runner/feature-service.js +0 -60
  82. package/dist/workflow-runner/pipeline.d.ts +0 -18
  83. package/dist/workflow-runner/pipeline.js +0 -197
  84. package/dist/workflow-runner/processor.d.ts +0 -40
  85. package/dist/workflow-runner/processor.js +0 -191
  86. package/dist/workflow-runner/status-updater.d.ts +0 -27
  87. package/dist/workflow-runner/status-updater.js +0 -80
  88. package/dist/workflow-runner/types.d.ts +0 -48
  89. 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
+ }
@@ -4,4 +4,5 @@ export * from './user-stories.js';
4
4
  export * from './test-cases.js';
5
5
  export * from './feature-utils.js';
6
6
  export * from './status-updater.js';
7
+ export * from './batch-operations.js';
7
8
  export * from '../../types/features.js';
@@ -5,5 +5,6 @@ export * from './user-stories.js';
5
5
  export * from './test-cases.js';
6
6
  export * from './feature-utils.js';
7
7
  export * from './status-updater.js';
8
+ export * from './batch-operations.js';
8
9
  // Re-export types
9
10
  export * from '../../types/features.js';
@@ -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,2 @@
1
+ import { CliOptions } from '../../types/index.js';
2
+ export declare const runRefactor: (options: CliOptions) => Promise<void>;
@@ -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
- import { CliOptions } from './types/index.js';
3
- export declare const runEdsger: (options: CliOptions) => Promise<void>;
2
+ export * from './cli/index.js';
3
+ import './cli/index.js';