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
|
@@ -4,10 +4,13 @@
|
|
|
4
4
|
import { updateFeatureStatusForPhase } from '../../api/features/index.js';
|
|
5
5
|
import { phaseConfigs } from '../config/phase-configs.js';
|
|
6
6
|
import { getChecklistsForPhase, validateChecklistsForPhase, validateRequiredChecklistResults, processChecklistResultsFromResponse, processChecklistItemResultsFromResponse, } from '../../services/checklist.js';
|
|
7
|
+
import { logFeaturePhaseEvent } from '../../services/audit-logs.js';
|
|
7
8
|
// Higher-order function for phase execution
|
|
8
9
|
export const createPhaseRunner = (phaseConfig) => async (options, config) => {
|
|
9
10
|
const { featureId, mcpServerUrl, mcpToken, verbose } = options;
|
|
10
11
|
const { name, checkRequirements, execute, requirementsError } = phaseConfig;
|
|
12
|
+
// Track phase duration for logging
|
|
13
|
+
const phaseStartTime = Date.now();
|
|
11
14
|
try {
|
|
12
15
|
// Check requirements
|
|
13
16
|
const hasRequirements = await checkRequirements();
|
|
@@ -24,6 +27,16 @@ export const createPhaseRunner = (phaseConfig) => async (options, config) => {
|
|
|
24
27
|
if (verbose) {
|
|
25
28
|
console.log(`🎯 Starting ${name} for: ${featureId}`);
|
|
26
29
|
}
|
|
30
|
+
// Log phase start
|
|
31
|
+
await logFeaturePhaseEvent(mcpServerUrl, mcpToken, {
|
|
32
|
+
featureId,
|
|
33
|
+
eventType: 'phase_started',
|
|
34
|
+
phase: name.replace(/-/g, '_'),
|
|
35
|
+
result: 'info',
|
|
36
|
+
metadata: {
|
|
37
|
+
timestamp: new Date().toISOString(),
|
|
38
|
+
},
|
|
39
|
+
}, verbose);
|
|
27
40
|
// Fetch checklists for this phase as context
|
|
28
41
|
let checklistContext = null;
|
|
29
42
|
try {
|
|
@@ -42,18 +55,6 @@ export const createPhaseRunner = (phaseConfig) => async (options, config) => {
|
|
|
42
55
|
}
|
|
43
56
|
// Execute the phase with checklist context
|
|
44
57
|
const result = await execute(options, config, checklistContext);
|
|
45
|
-
console.log({
|
|
46
|
-
result,
|
|
47
|
-
});
|
|
48
|
-
console.log({
|
|
49
|
-
status: result.status,
|
|
50
|
-
});
|
|
51
|
-
console.log({
|
|
52
|
-
data: result.data,
|
|
53
|
-
});
|
|
54
|
-
console.log({
|
|
55
|
-
checklist_item_results: result.data?.checklist_item_results,
|
|
56
|
-
});
|
|
57
58
|
// Process checklist results from phase response if phase was successful
|
|
58
59
|
if (result.status === 'success') {
|
|
59
60
|
try {
|
|
@@ -154,6 +155,35 @@ export const createPhaseRunner = (phaseConfig) => async (options, config) => {
|
|
|
154
155
|
};
|
|
155
156
|
}
|
|
156
157
|
}
|
|
158
|
+
// Log phase completion
|
|
159
|
+
const phaseEndTime = Date.now();
|
|
160
|
+
const phaseDuration = phaseEndTime - phaseStartTime;
|
|
161
|
+
if (result.status === 'success') {
|
|
162
|
+
await logFeaturePhaseEvent(mcpServerUrl, mcpToken, {
|
|
163
|
+
featureId,
|
|
164
|
+
eventType: 'phase_completed',
|
|
165
|
+
phase: name.replace(/-/g, '_'),
|
|
166
|
+
result: 'success',
|
|
167
|
+
metadata: {
|
|
168
|
+
duration_ms: phaseDuration,
|
|
169
|
+
iterations: result.data?.iterations,
|
|
170
|
+
artifacts: result.data,
|
|
171
|
+
checklist_validation: checklistValidation,
|
|
172
|
+
},
|
|
173
|
+
}, verbose);
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
await logFeaturePhaseEvent(mcpServerUrl, mcpToken, {
|
|
177
|
+
featureId,
|
|
178
|
+
eventType: 'phase_failed',
|
|
179
|
+
phase: name.replace(/-/g, '_'),
|
|
180
|
+
result: 'error',
|
|
181
|
+
metadata: {
|
|
182
|
+
duration_ms: phaseDuration,
|
|
183
|
+
},
|
|
184
|
+
errorMessage: result.summary || 'Phase execution failed',
|
|
185
|
+
}, verbose);
|
|
186
|
+
}
|
|
157
187
|
return {
|
|
158
188
|
featureId,
|
|
159
189
|
phase: name,
|
|
@@ -169,6 +199,20 @@ export const createPhaseRunner = (phaseConfig) => async (options, config) => {
|
|
|
169
199
|
};
|
|
170
200
|
}
|
|
171
201
|
catch (error) {
|
|
202
|
+
// Log phase failure for exceptions
|
|
203
|
+
const phaseEndTime = Date.now();
|
|
204
|
+
const phaseDuration = phaseEndTime - phaseStartTime;
|
|
205
|
+
await logFeaturePhaseEvent(mcpServerUrl, mcpToken, {
|
|
206
|
+
featureId,
|
|
207
|
+
eventType: 'phase_failed',
|
|
208
|
+
phase: name.replace(/-/g, '_'),
|
|
209
|
+
result: 'error',
|
|
210
|
+
metadata: {
|
|
211
|
+
duration_ms: phaseDuration,
|
|
212
|
+
error_type: 'exception',
|
|
213
|
+
},
|
|
214
|
+
errorMessage: error instanceof Error ? error.message : String(error),
|
|
215
|
+
}, verbose);
|
|
172
216
|
return {
|
|
173
217
|
featureId,
|
|
174
218
|
phase: name,
|
package/package.json
CHANGED
package/dist/api/features.d.ts
DELETED
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
export interface FeatureInfo {
|
|
2
|
-
id: string;
|
|
3
|
-
name: string;
|
|
4
|
-
description?: string;
|
|
5
|
-
technical_design?: string;
|
|
6
|
-
status: string;
|
|
7
|
-
product_id: string;
|
|
8
|
-
created_at?: string;
|
|
9
|
-
updated_at?: string;
|
|
10
|
-
}
|
|
11
|
-
/**
|
|
12
|
-
* Get feature details by ID
|
|
13
|
-
*/
|
|
14
|
-
export declare function getFeature(mcpServerUrl: string, mcpToken: string, featureId: string, verbose?: boolean): Promise<FeatureInfo>;
|
|
15
|
-
/**
|
|
16
|
-
* Update feature with new data
|
|
17
|
-
*/
|
|
18
|
-
export declare function updateFeature(mcpServerUrl: string, mcpToken: string, featureId: string, updates: {
|
|
19
|
-
technical_design?: string;
|
|
20
|
-
status?: string;
|
|
21
|
-
pull_request_url?: string;
|
|
22
|
-
}, verbose?: boolean): Promise<boolean>;
|
|
23
|
-
/**
|
|
24
|
-
* Update technical design for a feature
|
|
25
|
-
*/
|
|
26
|
-
export declare function updateTechnicalDesign(mcpServerUrl: string, mcpToken: string, featureId: string, technicalDesign: string, verbose?: boolean): Promise<boolean>;
|
|
27
|
-
/**
|
|
28
|
-
* Update feature status
|
|
29
|
-
*/
|
|
30
|
-
export declare function updateFeatureStatus(mcpServerUrl: string, mcpToken: string, featureId: string, status: string, verbose?: boolean): Promise<boolean>;
|
|
31
|
-
export interface UserStory {
|
|
32
|
-
id: string;
|
|
33
|
-
title: string;
|
|
34
|
-
description: string;
|
|
35
|
-
status: string;
|
|
36
|
-
created_at?: string;
|
|
37
|
-
updated_at?: string;
|
|
38
|
-
[key: string]: any;
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Get user stories for a feature
|
|
42
|
-
*/
|
|
43
|
-
export declare function getUserStories(mcpServerUrl: string, mcpToken: string, featureId: string, verbose?: boolean): Promise<UserStory[]>;
|
|
44
|
-
/**
|
|
45
|
-
* Create a new user story for a feature
|
|
46
|
-
*/
|
|
47
|
-
export declare function createUserStory(mcpServerUrl: string, mcpToken: string, featureId: string, userStory: {
|
|
48
|
-
title: string;
|
|
49
|
-
description: string;
|
|
50
|
-
status?: string;
|
|
51
|
-
}, verbose?: boolean): Promise<boolean>;
|
|
52
|
-
/**
|
|
53
|
-
* Create multiple user stories for a feature
|
|
54
|
-
*/
|
|
55
|
-
export declare function createUserStories(mcpServerUrl: string, mcpToken: string, featureId: string, userStories: Array<{
|
|
56
|
-
title: string;
|
|
57
|
-
description: string;
|
|
58
|
-
status?: string;
|
|
59
|
-
}>, verbose?: boolean): Promise<boolean>;
|
|
60
|
-
export interface TestCase {
|
|
61
|
-
id: string;
|
|
62
|
-
name: string;
|
|
63
|
-
description: string;
|
|
64
|
-
is_critical: boolean;
|
|
65
|
-
created_at?: string;
|
|
66
|
-
updated_at?: string;
|
|
67
|
-
[key: string]: any;
|
|
68
|
-
}
|
|
69
|
-
/**
|
|
70
|
-
* Get test cases for a feature
|
|
71
|
-
*/
|
|
72
|
-
export declare function getTestCases(mcpServerUrl: string, mcpToken: string, featureId: string, verbose?: boolean): Promise<TestCase[]>;
|
|
73
|
-
/**
|
|
74
|
-
* Create a new test case for a feature
|
|
75
|
-
*/
|
|
76
|
-
export declare function createTestCase(mcpServerUrl: string, mcpToken: string, featureId: string, testCase: {
|
|
77
|
-
name: string;
|
|
78
|
-
description: string;
|
|
79
|
-
is_critical?: boolean;
|
|
80
|
-
}, verbose?: boolean): Promise<boolean>;
|
|
81
|
-
/**
|
|
82
|
-
* Create multiple test cases for a feature
|
|
83
|
-
*/
|
|
84
|
-
export declare function createTestCases(mcpServerUrl: string, mcpToken: string, featureId: string, testCases: Array<{
|
|
85
|
-
name: string;
|
|
86
|
-
description: string;
|
|
87
|
-
is_critical?: boolean;
|
|
88
|
-
}>, verbose?: boolean): Promise<boolean>;
|
|
89
|
-
/**
|
|
90
|
-
* Filter features by status
|
|
91
|
-
*/
|
|
92
|
-
export declare function filterFeaturesByStatus(features: FeatureInfo[], status: string): FeatureInfo[];
|
|
93
|
-
/**
|
|
94
|
-
* Sort features by updated_at (most recent first)
|
|
95
|
-
*/
|
|
96
|
-
export declare function sortFeaturesByUpdatedAt(features: FeatureInfo[]): FeatureInfo[];
|
|
97
|
-
/**
|
|
98
|
-
* Get features with ready_for_dev status for a product
|
|
99
|
-
*/
|
|
100
|
-
export declare function getReadyForDevFeatures(mcpServerUrl: string, mcpToken: string, productId: string, verbose?: boolean): Promise<FeatureInfo[]>;
|
package/dist/api/features.js
DELETED
|
@@ -1,219 +0,0 @@
|
|
|
1
|
-
import { logInfo, logError } from '../logger.js';
|
|
2
|
-
import { callMcpEndpoint } from './mcp-client.js';
|
|
3
|
-
/**
|
|
4
|
-
* Get feature details by ID
|
|
5
|
-
*/
|
|
6
|
-
export async function getFeature(mcpServerUrl, mcpToken, featureId, verbose) {
|
|
7
|
-
if (verbose) {
|
|
8
|
-
logInfo(`Fetching feature details for: ${featureId}`);
|
|
9
|
-
}
|
|
10
|
-
const result = (await callMcpEndpoint(mcpServerUrl, mcpToken, 'features/get', { feature_id: featureId }));
|
|
11
|
-
if (!result.features || result.features.length === 0) {
|
|
12
|
-
throw new Error(`Feature not found: ${featureId}`);
|
|
13
|
-
}
|
|
14
|
-
return result.features[0];
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* Update feature with new data
|
|
18
|
-
*/
|
|
19
|
-
export async function updateFeature(mcpServerUrl, mcpToken, featureId, updates, verbose) {
|
|
20
|
-
try {
|
|
21
|
-
if (verbose) {
|
|
22
|
-
logInfo(`Updating feature: ${featureId}`);
|
|
23
|
-
}
|
|
24
|
-
await callMcpEndpoint(mcpServerUrl, mcpToken, 'features/update', {
|
|
25
|
-
feature_id: featureId,
|
|
26
|
-
...updates,
|
|
27
|
-
});
|
|
28
|
-
if (verbose) {
|
|
29
|
-
logInfo('✅ Feature updated successfully');
|
|
30
|
-
}
|
|
31
|
-
return true;
|
|
32
|
-
}
|
|
33
|
-
catch (error) {
|
|
34
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
35
|
-
logError(`Failed to update feature: ${errorMessage}`);
|
|
36
|
-
return false;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* Update technical design for a feature
|
|
41
|
-
*/
|
|
42
|
-
export async function updateTechnicalDesign(mcpServerUrl, mcpToken, featureId, technicalDesign, verbose) {
|
|
43
|
-
return updateFeature(mcpServerUrl, mcpToken, featureId, { technical_design: technicalDesign }, verbose);
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* Update feature status
|
|
47
|
-
*/
|
|
48
|
-
export async function updateFeatureStatus(mcpServerUrl, mcpToken, featureId, status, verbose) {
|
|
49
|
-
return updateFeature(mcpServerUrl, mcpToken, featureId, { status }, verbose);
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* Get user stories for a feature
|
|
53
|
-
*/
|
|
54
|
-
export async function getUserStories(mcpServerUrl, mcpToken, featureId, verbose) {
|
|
55
|
-
if (verbose) {
|
|
56
|
-
logInfo(`Fetching user stories for feature: ${featureId}`);
|
|
57
|
-
}
|
|
58
|
-
const result = (await callMcpEndpoint(mcpServerUrl, mcpToken, 'user_stories/list', { feature_id: featureId }));
|
|
59
|
-
return (result.user_stories || []);
|
|
60
|
-
}
|
|
61
|
-
/**
|
|
62
|
-
* Create a new user story for a feature
|
|
63
|
-
*/
|
|
64
|
-
export async function createUserStory(mcpServerUrl, mcpToken, featureId, userStory, verbose) {
|
|
65
|
-
try {
|
|
66
|
-
if (verbose) {
|
|
67
|
-
logInfo(`Creating user story for feature: ${featureId}`);
|
|
68
|
-
}
|
|
69
|
-
await callMcpEndpoint(mcpServerUrl, mcpToken, 'user_stories/create', {
|
|
70
|
-
feature_id: featureId,
|
|
71
|
-
user_stories: [
|
|
72
|
-
{
|
|
73
|
-
title: userStory.title,
|
|
74
|
-
description: userStory.description,
|
|
75
|
-
status: userStory.status || 'draft',
|
|
76
|
-
},
|
|
77
|
-
],
|
|
78
|
-
});
|
|
79
|
-
if (verbose) {
|
|
80
|
-
logInfo('✅ User story created successfully');
|
|
81
|
-
}
|
|
82
|
-
return true;
|
|
83
|
-
}
|
|
84
|
-
catch (error) {
|
|
85
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
86
|
-
logError(`Failed to create user story: ${errorMessage}`);
|
|
87
|
-
return false;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
/**
|
|
91
|
-
* Create multiple user stories for a feature
|
|
92
|
-
*/
|
|
93
|
-
export async function createUserStories(mcpServerUrl, mcpToken, featureId, userStories, verbose) {
|
|
94
|
-
try {
|
|
95
|
-
if (verbose) {
|
|
96
|
-
logInfo(`Creating ${userStories.length} user stories for feature: ${featureId}`);
|
|
97
|
-
}
|
|
98
|
-
for (const story of userStories) {
|
|
99
|
-
await createUserStory(mcpServerUrl, mcpToken, featureId, story, false);
|
|
100
|
-
}
|
|
101
|
-
if (verbose) {
|
|
102
|
-
logInfo('✅ All user stories created successfully');
|
|
103
|
-
}
|
|
104
|
-
return true;
|
|
105
|
-
}
|
|
106
|
-
catch (error) {
|
|
107
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
108
|
-
logError(`Failed to create user stories: ${errorMessage}`);
|
|
109
|
-
return false;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
/**
|
|
113
|
-
* Get test cases for a feature
|
|
114
|
-
*/
|
|
115
|
-
export async function getTestCases(mcpServerUrl, mcpToken, featureId, verbose) {
|
|
116
|
-
if (verbose) {
|
|
117
|
-
logInfo(`Fetching test cases for feature: ${featureId}`);
|
|
118
|
-
}
|
|
119
|
-
const result = (await callMcpEndpoint(mcpServerUrl, mcpToken, 'test_cases/list', { feature_id: featureId }));
|
|
120
|
-
return (result.test_cases || []);
|
|
121
|
-
}
|
|
122
|
-
/**
|
|
123
|
-
* Create a new test case for a feature
|
|
124
|
-
*/
|
|
125
|
-
export async function createTestCase(mcpServerUrl, mcpToken, featureId, testCase, verbose) {
|
|
126
|
-
try {
|
|
127
|
-
if (verbose) {
|
|
128
|
-
logInfo(`Creating test case for feature: ${featureId}`);
|
|
129
|
-
}
|
|
130
|
-
await callMcpEndpoint(mcpServerUrl, mcpToken, 'test_cases/create', {
|
|
131
|
-
feature_id: featureId,
|
|
132
|
-
test_cases: [
|
|
133
|
-
{
|
|
134
|
-
name: testCase.name,
|
|
135
|
-
description: testCase.description,
|
|
136
|
-
is_critical: testCase.is_critical || false,
|
|
137
|
-
},
|
|
138
|
-
],
|
|
139
|
-
});
|
|
140
|
-
if (verbose) {
|
|
141
|
-
logInfo('✅ Test case created successfully');
|
|
142
|
-
}
|
|
143
|
-
return true;
|
|
144
|
-
}
|
|
145
|
-
catch (error) {
|
|
146
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
147
|
-
logError(`Failed to create test case: ${errorMessage}`);
|
|
148
|
-
return false;
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
/**
|
|
152
|
-
* Create multiple test cases for a feature
|
|
153
|
-
*/
|
|
154
|
-
export async function createTestCases(mcpServerUrl, mcpToken, featureId, testCases, verbose) {
|
|
155
|
-
try {
|
|
156
|
-
if (verbose) {
|
|
157
|
-
logInfo(`Creating ${testCases.length} test cases for feature: ${featureId}`);
|
|
158
|
-
}
|
|
159
|
-
for (const testCase of testCases) {
|
|
160
|
-
await createTestCase(mcpServerUrl, mcpToken, featureId, testCase, false);
|
|
161
|
-
}
|
|
162
|
-
if (verbose) {
|
|
163
|
-
logInfo('✅ All test cases created successfully');
|
|
164
|
-
}
|
|
165
|
-
return true;
|
|
166
|
-
}
|
|
167
|
-
catch (error) {
|
|
168
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
169
|
-
logError(`Failed to create test cases: ${errorMessage}`);
|
|
170
|
-
return false;
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
// ============================================================================
|
|
174
|
-
// FEATURE UTILITY FUNCTIONS
|
|
175
|
-
// ============================================================================
|
|
176
|
-
/**
|
|
177
|
-
* Filter features by status
|
|
178
|
-
*/
|
|
179
|
-
export function filterFeaturesByStatus(features, status) {
|
|
180
|
-
return features.filter(feature => feature.status === status);
|
|
181
|
-
}
|
|
182
|
-
/**
|
|
183
|
-
* Sort features by updated_at (most recent first)
|
|
184
|
-
*/
|
|
185
|
-
export function sortFeaturesByUpdatedAt(features) {
|
|
186
|
-
return [...features].sort((a, b) => {
|
|
187
|
-
const dateA = new Date(a.updated_at || 0).getTime();
|
|
188
|
-
const dateB = new Date(b.updated_at || 0).getTime();
|
|
189
|
-
return dateB - dateA;
|
|
190
|
-
});
|
|
191
|
-
}
|
|
192
|
-
/**
|
|
193
|
-
* Get features with ready_for_dev status for a product
|
|
194
|
-
*/
|
|
195
|
-
export async function getReadyForDevFeatures(mcpServerUrl, mcpToken, productId, verbose) {
|
|
196
|
-
if (verbose) {
|
|
197
|
-
logInfo(`Fetching ready_for_dev features for product: ${productId}`);
|
|
198
|
-
}
|
|
199
|
-
try {
|
|
200
|
-
const result = await callMcpEndpoint(mcpServerUrl, mcpToken, 'features/list', {
|
|
201
|
-
product_id: productId,
|
|
202
|
-
status: 'ready_for_dev',
|
|
203
|
-
});
|
|
204
|
-
const features = result.features || [];
|
|
205
|
-
const sortedFeatures = sortFeaturesByUpdatedAt(features);
|
|
206
|
-
if (verbose) {
|
|
207
|
-
logInfo(`✅ Found ${sortedFeatures.length} ready_for_dev features`);
|
|
208
|
-
sortedFeatures.forEach((feature, index) => {
|
|
209
|
-
logInfo(` ${index + 1}. ${feature.name} (updated: ${feature.updated_at})`);
|
|
210
|
-
});
|
|
211
|
-
}
|
|
212
|
-
return sortedFeatures;
|
|
213
|
-
}
|
|
214
|
-
catch (error) {
|
|
215
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
216
|
-
logError(`Failed to fetch ready_for_dev features: ${errorMessage}`);
|
|
217
|
-
throw error;
|
|
218
|
-
}
|
|
219
|
-
}
|
package/dist/logger.d.ts
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { ReviewResult } from './types.js';
|
|
2
|
-
export declare const colors: {
|
|
3
|
-
reset: string;
|
|
4
|
-
bright: string;
|
|
5
|
-
red: string;
|
|
6
|
-
green: string;
|
|
7
|
-
yellow: string;
|
|
8
|
-
blue: string;
|
|
9
|
-
magenta: string;
|
|
10
|
-
cyan: string;
|
|
11
|
-
gray: string;
|
|
12
|
-
};
|
|
13
|
-
export declare const colorize: (text: string, color: keyof typeof colors) => string;
|
|
14
|
-
export declare const logInfo: (message: string) => void;
|
|
15
|
-
export declare const logSuccess: (message: string) => void;
|
|
16
|
-
export declare const logWarning: (message: string) => void;
|
|
17
|
-
export declare const logError: (message: string) => void;
|
|
18
|
-
export declare const logProgress: (current: number, total: number, file: string) => void;
|
|
19
|
-
export declare const logResults: (results: ReviewResult[], verbose?: boolean) => void;
|
package/dist/logger.js
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
export const colors = {
|
|
2
|
-
reset: '\x1b[0m',
|
|
3
|
-
bright: '\x1b[1m',
|
|
4
|
-
red: '\x1b[31m',
|
|
5
|
-
green: '\x1b[32m',
|
|
6
|
-
yellow: '\x1b[33m',
|
|
7
|
-
blue: '\x1b[34m',
|
|
8
|
-
magenta: '\x1b[35m',
|
|
9
|
-
cyan: '\x1b[36m',
|
|
10
|
-
gray: '\x1b[90m'
|
|
11
|
-
};
|
|
12
|
-
export const colorize = (text, color) => {
|
|
13
|
-
return `${colors[color]}${text}${colors.reset}`;
|
|
14
|
-
};
|
|
15
|
-
export const logInfo = (message) => {
|
|
16
|
-
console.log(colorize(`ℹ ${message}`, 'blue'));
|
|
17
|
-
};
|
|
18
|
-
export const logSuccess = (message) => {
|
|
19
|
-
console.log(colorize(`✓ ${message}`, 'green'));
|
|
20
|
-
};
|
|
21
|
-
export const logWarning = (message) => {
|
|
22
|
-
console.log(colorize(`⚠ ${message}`, 'yellow'));
|
|
23
|
-
};
|
|
24
|
-
export const logError = (message) => {
|
|
25
|
-
console.error(colorize(`✗ ${message}`, 'red'));
|
|
26
|
-
};
|
|
27
|
-
export const logProgress = (current, total, file) => {
|
|
28
|
-
const percentage = Math.round((current / total) * 100);
|
|
29
|
-
const progress = `[${current}/${total}] ${percentage}%`;
|
|
30
|
-
console.log(colorize(`${progress} Reviewing ${file}`, 'gray'));
|
|
31
|
-
};
|
|
32
|
-
export const logResults = (results, verbose = false) => {
|
|
33
|
-
const okCount = results.filter(r => r.status === 'OK').length;
|
|
34
|
-
const warnCount = results.filter(r => r.status === 'WARN').length;
|
|
35
|
-
const blockCount = results.filter(r => r.status === 'BLOCK').length;
|
|
36
|
-
console.log('\n' + colorize('='.repeat(60), 'gray'));
|
|
37
|
-
console.log(colorize('Review Results', 'bright'));
|
|
38
|
-
console.log(colorize('='.repeat(60), 'gray'));
|
|
39
|
-
results.forEach(result => {
|
|
40
|
-
const icon = result.status === 'OK' ? '✓' : result.status === 'WARN' ? '⚠' : '✗';
|
|
41
|
-
const color = result.status === 'OK' ? 'green' : result.status === 'WARN' ? 'yellow' : 'red';
|
|
42
|
-
console.log(colorize(`${icon} ${result.file}: ${result.message}`, color));
|
|
43
|
-
if (verbose && result.details && result.status !== 'OK') {
|
|
44
|
-
console.log(colorize(` Details: ${result.details}`, 'gray'));
|
|
45
|
-
}
|
|
46
|
-
});
|
|
47
|
-
console.log('\n' + colorize('Summary:', 'bright'));
|
|
48
|
-
console.log(colorize(` ✓ Passed: ${okCount}`, 'green'));
|
|
49
|
-
console.log(colorize(` ⚠ Warnings: ${warnCount}`, 'yellow'));
|
|
50
|
-
console.log(colorize(` ✗ Blocked: ${blockCount}`, 'red'));
|
|
51
|
-
console.log(colorize(` Total: ${results.length} files reviewed`, 'gray'));
|
|
52
|
-
};
|
package/dist/types.d.ts
DELETED
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
export interface EdsgerConfig {
|
|
2
|
-
patterns: string[];
|
|
3
|
-
exclude: string[];
|
|
4
|
-
severity: 'error' | 'warning';
|
|
5
|
-
maxFiles: number;
|
|
6
|
-
claude: {
|
|
7
|
-
model?: string;
|
|
8
|
-
timeout?: number;
|
|
9
|
-
};
|
|
10
|
-
}
|
|
11
|
-
export interface GitFile {
|
|
12
|
-
path: string;
|
|
13
|
-
content: string;
|
|
14
|
-
status: 'modified' | 'added' | 'deleted' | 'renamed';
|
|
15
|
-
}
|
|
16
|
-
export interface ReviewResult {
|
|
17
|
-
file: string;
|
|
18
|
-
status: 'OK' | 'WARN' | 'BLOCK';
|
|
19
|
-
message: string;
|
|
20
|
-
details?: string;
|
|
21
|
-
}
|
|
22
|
-
export interface CliOptions {
|
|
23
|
-
review?: boolean;
|
|
24
|
-
staged?: boolean;
|
|
25
|
-
files?: string[];
|
|
26
|
-
config?: string;
|
|
27
|
-
verbose?: boolean;
|
|
28
|
-
featureAnalysis?: string;
|
|
29
|
-
technicalDesign?: string;
|
|
30
|
-
implement?: string;
|
|
31
|
-
test?: string;
|
|
32
|
-
workflow?: boolean;
|
|
33
|
-
}
|
|
34
|
-
export type ReviewSeverity = 'error' | 'warning';
|
|
35
|
-
export type ExitCode = 0 | 1;
|
|
36
|
-
export interface FeatureAnalysisResult {
|
|
37
|
-
featureId: string;
|
|
38
|
-
productInfo: unknown;
|
|
39
|
-
featureInfo: unknown;
|
|
40
|
-
existingUserStories: UserStory[];
|
|
41
|
-
existingTestCases: TestCase[];
|
|
42
|
-
createdUserStories: UserStory[];
|
|
43
|
-
createdTestCases: TestCase[];
|
|
44
|
-
summary: string;
|
|
45
|
-
status: 'pending' | 'success' | 'error';
|
|
46
|
-
}
|
|
47
|
-
export interface FeatureData {
|
|
48
|
-
feature: {
|
|
49
|
-
id: string;
|
|
50
|
-
name: string;
|
|
51
|
-
description: string;
|
|
52
|
-
status: string;
|
|
53
|
-
product_id: string;
|
|
54
|
-
created_at: string;
|
|
55
|
-
updated_at: string;
|
|
56
|
-
};
|
|
57
|
-
product: {
|
|
58
|
-
id: string;
|
|
59
|
-
name: string;
|
|
60
|
-
description: string;
|
|
61
|
-
status: string;
|
|
62
|
-
features: unknown[];
|
|
63
|
-
metadata: {
|
|
64
|
-
created_at: string;
|
|
65
|
-
updated_at: string;
|
|
66
|
-
};
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
export interface UserStory {
|
|
70
|
-
id: string;
|
|
71
|
-
title: string;
|
|
72
|
-
description: string;
|
|
73
|
-
status: 'draft' | 'ready' | 'in_progress' | 'done' | 'cancelled';
|
|
74
|
-
created_at: string;
|
|
75
|
-
updated_at: string;
|
|
76
|
-
}
|
|
77
|
-
export interface TestCase {
|
|
78
|
-
id: string;
|
|
79
|
-
name: string;
|
|
80
|
-
description: string;
|
|
81
|
-
is_critical: boolean;
|
|
82
|
-
created_at: string;
|
|
83
|
-
updated_at: string;
|
|
84
|
-
}
|
|
85
|
-
export interface DisplayUserStory {
|
|
86
|
-
title: string;
|
|
87
|
-
}
|
|
88
|
-
export interface DisplayTestCase {
|
|
89
|
-
name: string;
|
|
90
|
-
is_critical?: boolean;
|
|
91
|
-
}
|
|
92
|
-
export interface FeatureAnalysisDisplayResult {
|
|
93
|
-
featureId: string;
|
|
94
|
-
status: string;
|
|
95
|
-
summary?: string;
|
|
96
|
-
createdUserStories?: DisplayUserStory[];
|
|
97
|
-
createdTestCases?: DisplayTestCase[];
|
|
98
|
-
}
|
|
99
|
-
export type FeatureStatus = 'backlog' | 'ready_for_dev' | 'feature_analysis' | 'technical_design' | 'code_implementation' | 'code_review' | 'ready_for_review' | 'shipped' | 'testing_in_progress' | 'testing_passed' | 'testing_failed';
|
package/dist/types.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Convert HTML description to Markdown format
|
|
3
|
-
* Preserves image URLs so Claude Code can view them
|
|
4
|
-
*/
|
|
5
|
-
export function htmlToMarkdown(html) {
|
|
6
|
-
if (!html)
|
|
7
|
-
return '';
|
|
8
|
-
return (html
|
|
9
|
-
// Convert images to markdown format with original URL
|
|
10
|
-
.replace(/<img[^>]+src="([^">]+)"[^>]*alt="([^">]*)"[^>]*>/gi, '')
|
|
11
|
-
.replace(/<img[^>]+src="([^">]+)"[^>]*>/gi, '')
|
|
12
|
-
// Convert links
|
|
13
|
-
.replace(/<a[^>]+href="([^">]+)"[^>]*>(.*?)<\/a>/gi, '[$2]($1)')
|
|
14
|
-
// Convert headings
|
|
15
|
-
.replace(/<h1[^>]*>(.*?)<\/h1>/gi, '\n# $1\n')
|
|
16
|
-
.replace(/<h2[^>]*>(.*?)<\/h2>/gi, '\n## $1\n')
|
|
17
|
-
.replace(/<h3[^>]*>(.*?)<\/h3>/gi, '\n### $1\n')
|
|
18
|
-
.replace(/<h4[^>]*>(.*?)<\/h4>/gi, '\n#### $1\n')
|
|
19
|
-
.replace(/<h5[^>]*>(.*?)<\/h5>/gi, '\n##### $1\n')
|
|
20
|
-
.replace(/<h6[^>]*>(.*?)<\/h6>/gi, '\n###### $1\n')
|
|
21
|
-
// Convert lists
|
|
22
|
-
.replace(/<ul[^>]*>/gi, '\n')
|
|
23
|
-
.replace(/<\/ul>/gi, '\n')
|
|
24
|
-
.replace(/<ol[^>]*>/gi, '\n')
|
|
25
|
-
.replace(/<\/ol>/gi, '\n')
|
|
26
|
-
.replace(/<li[^>]*>(.*?)<\/li>/gi, '- $1\n')
|
|
27
|
-
// Convert paragraphs
|
|
28
|
-
.replace(/<\/p>/gi, '\n\n')
|
|
29
|
-
.replace(/<p[^>]*>/gi, '')
|
|
30
|
-
// Convert line breaks
|
|
31
|
-
.replace(/<br\s*\/?>/gi, '\n')
|
|
32
|
-
// Convert text formatting
|
|
33
|
-
.replace(/<strong[^>]*>(.*?)<\/strong>/gi, '**$1**')
|
|
34
|
-
.replace(/<b[^>]*>(.*?)<\/b>/gi, '**$1**')
|
|
35
|
-
.replace(/<em[^>]*>(.*?)<\/em>/gi, '*$1*')
|
|
36
|
-
.replace(/<i[^>]*>(.*?)<\/i>/gi, '*$1*')
|
|
37
|
-
.replace(/<u[^>]*>(.*?)<\/u>/gi, '__$1__')
|
|
38
|
-
// Convert code
|
|
39
|
-
.replace(/<code[^>]*>(.*?)<\/code>/gi, '`$1`')
|
|
40
|
-
.replace(/<pre[^>]*>(.*?)<\/pre>/gi, '\n```\n$1\n```\n')
|
|
41
|
-
// Convert blockquotes
|
|
42
|
-
.replace(/<blockquote[^>]*>(.*?)<\/blockquote>/gi, '\n> $1\n')
|
|
43
|
-
// Remove remaining HTML tags
|
|
44
|
-
.replace(/<[^>]+>/g, '')
|
|
45
|
-
// Decode HTML entities
|
|
46
|
-
.replace(/</g, '<')
|
|
47
|
-
.replace(/>/g, '>')
|
|
48
|
-
.replace(/&/g, '&')
|
|
49
|
-
.replace(/"/g, '"')
|
|
50
|
-
.replace(/'/g, "'")
|
|
51
|
-
.replace(/ /g, ' ')
|
|
52
|
-
// Clean up extra whitespace
|
|
53
|
-
.replace(/\n{3,}/g, '\n\n')
|
|
54
|
-
.trim());
|
|
55
|
-
}
|