edsger 0.51.0 → 0.52.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +23 -3
- package/.env.local +12 -0
- package/dist/commands/find-smells/index.d.ts +21 -0
- package/dist/commands/find-smells/index.js +65 -0
- package/dist/index.js +29 -0
- package/dist/phases/find-bugs/index.js +7 -92
- package/dist/phases/find-bugs/state.d.ts +10 -35
- package/dist/phases/find-bugs/state.js +12 -120
- package/dist/phases/find-features/index.js +16 -83
- package/dist/phases/find-features/prompts.d.ts +7 -1
- package/dist/phases/find-features/prompts.js +31 -11
- package/dist/phases/find-features/state.d.ts +15 -19
- package/dist/phases/find-features/state.js +17 -89
- package/dist/phases/find-features/types.d.ts +1 -1
- package/dist/phases/find-shared/git.d.ts +24 -0
- package/dist/phases/find-shared/git.js +60 -0
- package/dist/phases/find-shared/mcp.d.ts +33 -0
- package/dist/phases/find-shared/mcp.js +69 -0
- package/dist/phases/find-shared/scan-state.d.ts +33 -0
- package/dist/phases/find-shared/scan-state.js +112 -0
- package/dist/phases/find-smells/index.d.ts +47 -0
- package/dist/phases/find-smells/index.js +278 -0
- package/dist/phases/find-smells/prompts.d.ts +30 -0
- package/dist/phases/find-smells/prompts.js +129 -0
- package/dist/phases/find-smells/state.d.ts +21 -0
- package/dist/phases/find-smells/state.js +17 -0
- package/dist/phases/find-smells/types.d.ts +51 -0
- package/dist/phases/find-smells/types.js +64 -0
- package/package.json +1 -1
- package/vitest.config.ts +2 -0
- package/dist/api/__tests__/app-store.test.d.ts +0 -7
- package/dist/api/__tests__/app-store.test.js +0 -60
- package/dist/api/__tests__/intelligence.test.d.ts +0 -11
- package/dist/api/__tests__/intelligence.test.js +0 -315
- package/dist/api/features/__tests__/feature-utils.test.d.ts +0 -4
- package/dist/api/features/__tests__/feature-utils.test.js +0 -370
- package/dist/api/features/__tests__/status-updater.test.d.ts +0 -4
- package/dist/api/features/__tests__/status-updater.test.js +0 -88
- package/dist/api/features/approval-checker.d.ts +0 -20
- package/dist/api/features/approval-checker.js +0 -152
- package/dist/api/features/batch-operations.d.ts +0 -17
- package/dist/api/features/batch-operations.js +0 -100
- package/dist/api/features/feature-utils.d.ts +0 -23
- package/dist/api/features/feature-utils.js +0 -80
- package/dist/api/features/get-feature.d.ts +0 -5
- package/dist/api/features/get-feature.js +0 -21
- package/dist/api/features/index.d.ts +0 -8
- package/dist/api/features/index.js +0 -10
- package/dist/api/features/status-updater.d.ts +0 -41
- package/dist/api/features/status-updater.js +0 -122
- package/dist/api/features/test-cases.d.ts +0 -29
- package/dist/api/features/test-cases.js +0 -110
- package/dist/api/features/update-feature.d.ts +0 -20
- package/dist/api/features/update-feature.js +0 -83
- package/dist/api/features/user-stories.d.ts +0 -21
- package/dist/api/features/user-stories.js +0 -88
- package/dist/commands/agent-workflow/feature-worker.d.ts +0 -14
- package/dist/commands/agent-workflow/feature-worker.js +0 -65
- package/dist/commands/build/__tests__/build.test.d.ts +0 -5
- package/dist/commands/build/__tests__/build.test.js +0 -206
- package/dist/commands/build/__tests__/detect-project.test.d.ts +0 -6
- package/dist/commands/build/__tests__/detect-project.test.js +0 -160
- package/dist/commands/build/__tests__/run-build.test.d.ts +0 -6
- package/dist/commands/build/__tests__/run-build.test.js +0 -433
- package/dist/commands/intelligence/__tests__/command.test.d.ts +0 -4
- package/dist/commands/intelligence/__tests__/command.test.js +0 -48
- package/dist/commands/workflow/core/__tests__/feature-filter.test.d.ts +0 -5
- package/dist/commands/workflow/core/__tests__/feature-filter.test.js +0 -316
- package/dist/commands/workflow/core/__tests__/pipeline-evaluator.test.d.ts +0 -4
- package/dist/commands/workflow/core/__tests__/pipeline-evaluator.test.js +0 -397
- package/dist/commands/workflow/core/__tests__/state-manager.test.d.ts +0 -4
- package/dist/commands/workflow/core/__tests__/state-manager.test.js +0 -384
- package/dist/commands/workflow/core/feature-filter.d.ts +0 -16
- package/dist/commands/workflow/core/feature-filter.js +0 -47
- package/dist/commands/workflow/feature-coordinator.d.ts +0 -18
- package/dist/commands/workflow/feature-coordinator.js +0 -161
- package/dist/config/__tests__/config.test.d.ts +0 -4
- package/dist/config/__tests__/config.test.js +0 -286
- package/dist/config/__tests__/feature-status.test.d.ts +0 -4
- package/dist/config/__tests__/feature-status.test.js +0 -111
- package/dist/config/feature-status.d.ts +0 -56
- package/dist/config/feature-status.js +0 -130
- package/dist/errors/__tests__/index.test.d.ts +0 -4
- package/dist/errors/__tests__/index.test.js +0 -349
- package/dist/phases/app-store-generation/__tests__/agent.test.d.ts +0 -5
- package/dist/phases/app-store-generation/__tests__/agent.test.js +0 -142
- package/dist/phases/app-store-generation/__tests__/context.test.d.ts +0 -4
- package/dist/phases/app-store-generation/__tests__/context.test.js +0 -284
- package/dist/phases/app-store-generation/__tests__/prompts.test.d.ts +0 -4
- package/dist/phases/app-store-generation/__tests__/prompts.test.js +0 -122
- package/dist/phases/app-store-generation/__tests__/screenshot-composer.test.d.ts +0 -5
- package/dist/phases/app-store-generation/__tests__/screenshot-composer.test.js +0 -826
- package/dist/phases/code-review/__tests__/diff-utils.test.d.ts +0 -1
- package/dist/phases/code-review/__tests__/diff-utils.test.js +0 -101
- package/dist/phases/feature-analysis/agent.d.ts +0 -13
- package/dist/phases/feature-analysis/agent.js +0 -112
- package/dist/phases/feature-analysis/context.d.ts +0 -24
- package/dist/phases/feature-analysis/context.js +0 -138
- package/dist/phases/feature-analysis/index.d.ts +0 -8
- package/dist/phases/feature-analysis/index.js +0 -199
- package/dist/phases/feature-analysis/outcome.d.ts +0 -40
- package/dist/phases/feature-analysis/outcome.js +0 -280
- package/dist/phases/feature-analysis/prompts.d.ts +0 -10
- package/dist/phases/feature-analysis/prompts.js +0 -212
- package/dist/phases/feature-analysis-verification/agent.d.ts +0 -33
- package/dist/phases/feature-analysis-verification/agent.js +0 -124
- package/dist/phases/feature-analysis-verification/index.d.ts +0 -25
- package/dist/phases/feature-analysis-verification/index.js +0 -92
- package/dist/phases/feature-analysis-verification/prompts.d.ts +0 -10
- package/dist/phases/feature-analysis-verification/prompts.js +0 -100
- package/dist/phases/intelligence-analysis/__tests__/context.test.d.ts +0 -4
- package/dist/phases/intelligence-analysis/__tests__/context.test.js +0 -192
- package/dist/phases/intelligence-analysis/__tests__/matching.test.d.ts +0 -13
- package/dist/phases/intelligence-analysis/__tests__/matching.test.js +0 -154
- package/dist/phases/intelligence-analysis/__tests__/orchestration.test.d.ts +0 -5
- package/dist/phases/intelligence-analysis/__tests__/orchestration.test.js +0 -378
- package/dist/phases/intelligence-analysis/__tests__/prompts.test.d.ts +0 -4
- package/dist/phases/intelligence-analysis/__tests__/prompts.test.js +0 -33
- package/dist/phases/pr-execution/__tests__/file-assigner.test.d.ts +0 -1
- package/dist/phases/pr-execution/__tests__/file-assigner.test.js +0 -303
- package/dist/phases/pr-resolve/__tests__/checklist-learner.test.d.ts +0 -1
- package/dist/phases/pr-resolve/__tests__/checklist-learner.test.js +0 -157
- package/dist/phases/pr-resolve/__tests__/prompts.test.d.ts +0 -1
- package/dist/phases/pr-resolve/__tests__/prompts.test.js +0 -116
- package/dist/phases/pr-resolve/__tests__/resolve-mapping.test.d.ts +0 -1
- package/dist/phases/pr-resolve/__tests__/resolve-mapping.test.js +0 -138
- package/dist/phases/pr-resolve/__tests__/types.test.d.ts +0 -1
- package/dist/phases/pr-resolve/__tests__/types.test.js +0 -43
- package/dist/phases/pr-resolve/__tests__/workspace.test.d.ts +0 -1
- package/dist/phases/pr-resolve/__tests__/workspace.test.js +0 -111
- package/dist/phases/pr-review/__tests__/prompts.test.d.ts +0 -1
- package/dist/phases/pr-review/__tests__/prompts.test.js +0 -49
- package/dist/phases/pr-review/__tests__/review-comments.test.d.ts +0 -1
- package/dist/phases/pr-review/__tests__/review-comments.test.js +0 -110
- package/dist/phases/pr-shared/__tests__/agent-utils.test.d.ts +0 -1
- package/dist/phases/pr-shared/__tests__/agent-utils.test.js +0 -91
- package/dist/phases/pr-shared/__tests__/context.test.d.ts +0 -1
- package/dist/phases/pr-shared/__tests__/context.test.js +0 -94
- package/dist/phases/pr-splitting/__tests__/import-dep-validator.test.d.ts +0 -1
- package/dist/phases/pr-splitting/__tests__/import-dep-validator.test.js +0 -331
- package/dist/phases/run-sheet/render.d.ts +0 -60
- package/dist/phases/run-sheet/render.js +0 -297
- package/dist/phases/smoke-test/__tests__/agent.test.d.ts +0 -4
- package/dist/phases/smoke-test/__tests__/agent.test.js +0 -84
- package/dist/phases/smoke-test/__tests__/github.test.d.ts +0 -9
- package/dist/phases/smoke-test/__tests__/github.test.js +0 -120
- package/dist/phases/smoke-test/__tests__/snapshot.test.d.ts +0 -8
- package/dist/phases/smoke-test/__tests__/snapshot.test.js +0 -93
- package/dist/phases/smoke-test/github.d.ts +0 -54
- package/dist/phases/smoke-test/github.js +0 -101
- package/dist/phases/smoke-test/snapshot.d.ts +0 -27
- package/dist/phases/smoke-test/snapshot.js +0 -157
- package/dist/services/coaching/__tests__/coaching-agent.test.d.ts +0 -1
- package/dist/services/coaching/__tests__/coaching-agent.test.js +0 -74
- package/dist/services/coaching/__tests__/coaching-loop.test.d.ts +0 -1
- package/dist/services/coaching/__tests__/coaching-loop.test.js +0 -59
- package/dist/services/coaching/__tests__/self-rating.test.d.ts +0 -1
- package/dist/services/coaching/__tests__/self-rating.test.js +0 -188
- package/dist/services/lifecycle-agent/__tests__/phase-criteria.test.d.ts +0 -4
- package/dist/services/lifecycle-agent/__tests__/phase-criteria.test.js +0 -133
- package/dist/services/lifecycle-agent/__tests__/transition-rules.test.d.ts +0 -4
- package/dist/services/lifecycle-agent/__tests__/transition-rules.test.js +0 -336
- package/dist/services/lifecycle-agent/index.d.ts +0 -24
- package/dist/services/lifecycle-agent/index.js +0 -25
- package/dist/services/lifecycle-agent/phase-criteria.d.ts +0 -57
- package/dist/services/lifecycle-agent/phase-criteria.js +0 -335
- package/dist/services/lifecycle-agent/transition-rules.d.ts +0 -60
- package/dist/services/lifecycle-agent/transition-rules.js +0 -184
- package/dist/services/lifecycle-agent/types.d.ts +0 -190
- package/dist/services/lifecycle-agent/types.js +0 -12
- package/dist/services/phase-hooks/__tests__/bindings-fetcher.test.d.ts +0 -1
- package/dist/services/phase-hooks/__tests__/bindings-fetcher.test.js +0 -122
- package/dist/services/phase-hooks/__tests__/hook-executor.test.d.ts +0 -1
- package/dist/services/phase-hooks/__tests__/hook-executor.test.js +0 -321
- package/dist/services/phase-hooks/__tests__/hook-runner.test.d.ts +0 -1
- package/dist/services/phase-hooks/__tests__/hook-runner.test.js +0 -261
- package/dist/services/phase-hooks/__tests__/plugin-loader.test.d.ts +0 -1
- package/dist/services/phase-hooks/__tests__/plugin-loader.test.js +0 -158
- package/dist/services/video/__tests__/video-pipeline.test.d.ts +0 -6
- package/dist/services/video/__tests__/video-pipeline.test.js +0 -249
- package/dist/types/features.d.ts +0 -35
- package/dist/types/features.js +0 -1
- package/dist/workspace/__tests__/workspace-manager.test.d.ts +0 -7
- package/dist/workspace/__tests__/workspace-manager.test.js +0 -52
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert';
|
|
2
|
-
import { describe, it } from 'node:test';
|
|
3
|
-
import { buildLineToPositionMap, findClosestPosition } from '../diff-utils.js';
|
|
4
|
-
void describe('buildLineToPositionMap', () => {
|
|
5
|
-
void it('maps simple additions correctly', () => {
|
|
6
|
-
const patch = `@@ -1,3 +1,4 @@
|
|
7
|
-
line 1
|
|
8
|
-
+new line
|
|
9
|
-
line 2
|
|
10
|
-
line 3`;
|
|
11
|
-
const map = buildLineToPositionMap(patch);
|
|
12
|
-
// line 1 is at position 1 (new file line 1)
|
|
13
|
-
assert.strictEqual(map.get(1), 1);
|
|
14
|
-
// new line is at position 2 (new file line 2)
|
|
15
|
-
assert.strictEqual(map.get(2), 2);
|
|
16
|
-
// line 2 is at position 3 (new file line 3)
|
|
17
|
-
assert.strictEqual(map.get(3), 3);
|
|
18
|
-
// line 3 is at position 4 (new file line 4)
|
|
19
|
-
assert.strictEqual(map.get(4), 4);
|
|
20
|
-
});
|
|
21
|
-
void it('handles deletions - deleted lines have no new file line number', () => {
|
|
22
|
-
const patch = `@@ -1,3 +1,2 @@
|
|
23
|
-
line 1
|
|
24
|
-
-deleted line
|
|
25
|
-
line 3`;
|
|
26
|
-
const map = buildLineToPositionMap(patch);
|
|
27
|
-
assert.strictEqual(map.get(1), 1);
|
|
28
|
-
// deleted line takes position 2 but no new line
|
|
29
|
-
// line 3 in old file becomes line 2 in new file, position 3
|
|
30
|
-
assert.strictEqual(map.get(2), 3);
|
|
31
|
-
});
|
|
32
|
-
void it('handles multiple hunks', () => {
|
|
33
|
-
const patch = `@@ -1,2 +1,2 @@
|
|
34
|
-
line 1
|
|
35
|
-
+added
|
|
36
|
-
@@ -10,2 +10,2 @@
|
|
37
|
-
line 10
|
|
38
|
-
+added at 11`;
|
|
39
|
-
const map = buildLineToPositionMap(patch);
|
|
40
|
-
// First hunk: line 1 -> pos 1, added -> pos 2
|
|
41
|
-
assert.strictEqual(map.get(1), 1);
|
|
42
|
-
assert.strictEqual(map.get(2), 2);
|
|
43
|
-
// Second hunk: line 10 -> pos 3, added at 11 -> pos 4
|
|
44
|
-
assert.strictEqual(map.get(10), 3);
|
|
45
|
-
assert.strictEqual(map.get(11), 4);
|
|
46
|
-
});
|
|
47
|
-
void it('returns empty map for patch with only hunk header', () => {
|
|
48
|
-
const patch = '@@ -0,0 +1 @@';
|
|
49
|
-
const map = buildLineToPositionMap(patch);
|
|
50
|
-
// Hunk header only, no content lines
|
|
51
|
-
assert.strictEqual(map.size, 0);
|
|
52
|
-
});
|
|
53
|
-
void it('handles hunk starting at line other than 1', () => {
|
|
54
|
-
const patch = `@@ -50,3 +50,3 @@
|
|
55
|
-
context
|
|
56
|
-
-old
|
|
57
|
-
+new`;
|
|
58
|
-
const map = buildLineToPositionMap(patch);
|
|
59
|
-
assert.strictEqual(map.get(50), 1);
|
|
60
|
-
// -old takes position 2 (no new line)
|
|
61
|
-
// +new takes position 3, new file line 51
|
|
62
|
-
assert.strictEqual(map.get(51), 3);
|
|
63
|
-
});
|
|
64
|
-
});
|
|
65
|
-
void describe('findClosestPosition', () => {
|
|
66
|
-
void it('returns exact match when available', () => {
|
|
67
|
-
const map = new Map([
|
|
68
|
-
[10, 5],
|
|
69
|
-
[11, 6],
|
|
70
|
-
[12, 7],
|
|
71
|
-
]);
|
|
72
|
-
const result = findClosestPosition(11, map);
|
|
73
|
-
assert.deepStrictEqual(result, { position: 6, actualLine: 11 });
|
|
74
|
-
});
|
|
75
|
-
void it('returns nearby line below first', () => {
|
|
76
|
-
const map = new Map([
|
|
77
|
-
[10, 5],
|
|
78
|
-
[15, 8],
|
|
79
|
-
]);
|
|
80
|
-
// Line 12 not in map, closest below is 15 (offset 3)
|
|
81
|
-
// closest above is 10 (offset 2) - but we check below first at each offset
|
|
82
|
-
// offset 1: check 13 (no), check 11 (no)
|
|
83
|
-
// offset 2: check 14 (no), check 10 (yes!)
|
|
84
|
-
const result = findClosestPosition(12, map);
|
|
85
|
-
assert.deepStrictEqual(result, { position: 5, actualLine: 10 });
|
|
86
|
-
});
|
|
87
|
-
void it('returns null when no line within range', () => {
|
|
88
|
-
const map = new Map([
|
|
89
|
-
[1, 1],
|
|
90
|
-
[100, 50],
|
|
91
|
-
]);
|
|
92
|
-
// Line 50 is too far from both 1 and 100
|
|
93
|
-
const result = findClosestPosition(50, map);
|
|
94
|
-
assert.strictEqual(result, null);
|
|
95
|
-
});
|
|
96
|
-
void it('returns null for empty map', () => {
|
|
97
|
-
const map = new Map();
|
|
98
|
-
const result = findClosestPosition(5, map);
|
|
99
|
-
assert.strictEqual(result, null);
|
|
100
|
-
});
|
|
101
|
-
});
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { type EdsgerConfig, type WithExecutionSessionId } from '../../types/index.js';
|
|
2
|
-
interface ParsedAnalysisResult {
|
|
3
|
-
analysis?: any;
|
|
4
|
-
error?: string;
|
|
5
|
-
}
|
|
6
|
-
/** Analysis result with typed session ID */
|
|
7
|
-
export type AnalysisQueryResult = Record<string, unknown> & WithExecutionSessionId;
|
|
8
|
-
/**
|
|
9
|
-
* Parse JSON result from Claude Code response
|
|
10
|
-
*/
|
|
11
|
-
export declare function parseAnalysisResult(responseText: string): ParsedAnalysisResult;
|
|
12
|
-
export declare function executeAnalysisQuery(currentPrompt: string, systemPrompt: string, config: EdsgerConfig, verbose?: boolean): Promise<AnalysisQueryResult | null>;
|
|
13
|
-
export {};
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import { query } from '@anthropic-ai/claude-agent-sdk';
|
|
2
|
-
import { DEFAULT_MODEL } from '../../constants.js';
|
|
3
|
-
import { logDebug, logError, logInfo } from '../../utils/logger.js';
|
|
4
|
-
/**
|
|
5
|
-
* Parse JSON result from Claude Code response
|
|
6
|
-
*/
|
|
7
|
-
export function parseAnalysisResult(responseText) {
|
|
8
|
-
try {
|
|
9
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
10
|
-
let jsonResult = null;
|
|
11
|
-
// First try to extract JSON from markdown code block
|
|
12
|
-
const jsonBlockMatch = responseText.match(/```json\s*\n([\s\S]*?)\n\s*```/);
|
|
13
|
-
if (jsonBlockMatch) {
|
|
14
|
-
jsonResult = JSON.parse(jsonBlockMatch[1]);
|
|
15
|
-
}
|
|
16
|
-
else {
|
|
17
|
-
// Try to parse the entire response as JSON
|
|
18
|
-
jsonResult = JSON.parse(responseText);
|
|
19
|
-
}
|
|
20
|
-
if (jsonResult && jsonResult.analysis) {
|
|
21
|
-
return { analysis: jsonResult.analysis };
|
|
22
|
-
}
|
|
23
|
-
return { error: 'Invalid JSON structure' };
|
|
24
|
-
}
|
|
25
|
-
catch (error) {
|
|
26
|
-
return {
|
|
27
|
-
error: `JSON parsing failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
function userMessage(content) {
|
|
32
|
-
return {
|
|
33
|
-
type: 'user',
|
|
34
|
-
message: { role: 'user', content },
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
// eslint-disable-next-line @typescript-eslint/require-await -- async generator required by SDK interface
|
|
38
|
-
async function* prompt(analysisPrompt) {
|
|
39
|
-
yield userMessage(analysisPrompt);
|
|
40
|
-
}
|
|
41
|
-
export async function executeAnalysisQuery(currentPrompt, systemPrompt, config, verbose) {
|
|
42
|
-
let lastAssistantResponse = '';
|
|
43
|
-
let structuredAnalysisResult = null;
|
|
44
|
-
let executionSessionId = '';
|
|
45
|
-
for await (const message of query({
|
|
46
|
-
prompt: prompt(currentPrompt),
|
|
47
|
-
options: {
|
|
48
|
-
systemPrompt: {
|
|
49
|
-
type: 'preset',
|
|
50
|
-
preset: 'claude_code',
|
|
51
|
-
append: systemPrompt,
|
|
52
|
-
},
|
|
53
|
-
model: DEFAULT_MODEL,
|
|
54
|
-
maxTurns: 1000,
|
|
55
|
-
permissionMode: 'bypassPermissions',
|
|
56
|
-
},
|
|
57
|
-
})) {
|
|
58
|
-
if (verbose) {
|
|
59
|
-
logInfo(`Received message type: ${message.type}`);
|
|
60
|
-
}
|
|
61
|
-
// Stream the analysis process and capture assistant responses
|
|
62
|
-
if (message.type === 'assistant' && message.message?.content) {
|
|
63
|
-
for (const content of message.message.content) {
|
|
64
|
-
if (content.type === 'text') {
|
|
65
|
-
lastAssistantResponse += `${content.text}\n`;
|
|
66
|
-
logDebug(`🤖 ${content.text}`, verbose);
|
|
67
|
-
}
|
|
68
|
-
else if (content.type === 'tool_use') {
|
|
69
|
-
logDebug(`🔧 ${content.name}: ${content.input.description || 'Running...'}`, verbose);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
if (message.type === 'result') {
|
|
74
|
-
executionSessionId = message.session_id || executionSessionId;
|
|
75
|
-
if (message.subtype === 'success') {
|
|
76
|
-
logInfo('\n📊 Feature analysis completed, parsing results...');
|
|
77
|
-
const responseText = message.result || lastAssistantResponse;
|
|
78
|
-
const parsed = parseAnalysisResult(responseText);
|
|
79
|
-
if (parsed.error) {
|
|
80
|
-
logError(`Failed to parse structured analysis result: ${parsed.error}`);
|
|
81
|
-
structuredAnalysisResult = {
|
|
82
|
-
status: 'error',
|
|
83
|
-
summary: 'Failed to parse analysis results from Claude Code response',
|
|
84
|
-
created_user_stories: [],
|
|
85
|
-
created_test_cases: [],
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
else {
|
|
89
|
-
structuredAnalysisResult = parsed.analysis;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
else {
|
|
93
|
-
logError(`\n⚠️ Analysis incomplete: ${message.subtype}`);
|
|
94
|
-
if (message.subtype === 'error_max_turns') {
|
|
95
|
-
logError('💡 Try increasing timeout or reducing complexity');
|
|
96
|
-
}
|
|
97
|
-
// Try to parse results from the last assistant response
|
|
98
|
-
if (lastAssistantResponse) {
|
|
99
|
-
const parsed = parseAnalysisResult(lastAssistantResponse);
|
|
100
|
-
if (!parsed.error) {
|
|
101
|
-
structuredAnalysisResult = parsed.analysis;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
if (structuredAnalysisResult) {
|
|
108
|
-
structuredAnalysisResult.execution_session_id =
|
|
109
|
-
executionSessionId || undefined;
|
|
110
|
-
}
|
|
111
|
-
return structuredAnalysisResult;
|
|
112
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { type ProductInfo } from '../../api/products.js';
|
|
2
|
-
import { type ChecklistPhaseContext } from '../../services/checklist.js';
|
|
3
|
-
import type { FeatureInfo, TestCase, UserStory } from '../../types/features.js';
|
|
4
|
-
export interface FeatureAnalysisContext {
|
|
5
|
-
feature: FeatureInfo;
|
|
6
|
-
product: ProductInfo;
|
|
7
|
-
existing_user_stories: UserStory[];
|
|
8
|
-
existing_test_cases: TestCase[];
|
|
9
|
-
}
|
|
10
|
-
/**
|
|
11
|
-
* Fetch all feature analysis context information via MCP endpoints
|
|
12
|
-
*/
|
|
13
|
-
export declare function fetchFeatureAnalysisContext(featureId: string, verbose?: boolean): Promise<FeatureAnalysisContext>;
|
|
14
|
-
/**
|
|
15
|
-
* Format the context into a readable string for Claude Code
|
|
16
|
-
*/
|
|
17
|
-
export declare function formatContextForPrompt(context: FeatureAnalysisContext): string;
|
|
18
|
-
/**
|
|
19
|
-
* Prepare all context information needed for analysis
|
|
20
|
-
*/
|
|
21
|
-
export declare function prepareAnalysisContext(featureId: string, checklistContext: ChecklistPhaseContext | null | undefined, verbose?: boolean): Promise<{
|
|
22
|
-
featureContext: FeatureAnalysisContext;
|
|
23
|
-
analysisPrompt: string;
|
|
24
|
-
}>;
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
import { getFeature, getTestCases, getUserStories, } from '../../api/features/index.js';
|
|
2
|
-
import { getProduct } from '../../api/products.js';
|
|
3
|
-
import { formatChecklistsForContext, } from '../../services/checklist.js';
|
|
4
|
-
import { formatFeedbacksForContext, getFeedbacksForPhase, } from '../../services/feedbacks.js';
|
|
5
|
-
import { formatFeatureAnalysisContext } from '../../utils/formatters.js';
|
|
6
|
-
import { logError, logInfo } from '../../utils/logger.js';
|
|
7
|
-
import { createFeatureAnalysisPromptWithContext } from './prompts.js';
|
|
8
|
-
/**
|
|
9
|
-
* Fetch all feature analysis context information via MCP endpoints
|
|
10
|
-
*/
|
|
11
|
-
export async function fetchFeatureAnalysisContext(featureId, verbose) {
|
|
12
|
-
try {
|
|
13
|
-
if (verbose) {
|
|
14
|
-
logInfo(`Fetching complete feature analysis context for feature: ${featureId}`);
|
|
15
|
-
}
|
|
16
|
-
// Fetch all required data in parallel for better performance
|
|
17
|
-
const [feature, existingUserStories, existingTestCases] = await Promise.all([
|
|
18
|
-
getFeature(featureId, verbose),
|
|
19
|
-
getUserStories(featureId, verbose),
|
|
20
|
-
getTestCases(featureId, verbose),
|
|
21
|
-
]);
|
|
22
|
-
const product = await getProduct(feature.product_id, verbose);
|
|
23
|
-
if (verbose) {
|
|
24
|
-
logInfo(`✅ Feature analysis context fetched successfully:`);
|
|
25
|
-
logInfo(` Feature: ${feature.name}`);
|
|
26
|
-
logInfo(` Product: ${product.name}`);
|
|
27
|
-
logInfo(` Existing User Stories: ${existingUserStories.length}`);
|
|
28
|
-
logInfo(` Existing Test Cases: ${existingTestCases.length}`);
|
|
29
|
-
}
|
|
30
|
-
return {
|
|
31
|
-
feature,
|
|
32
|
-
product,
|
|
33
|
-
existing_user_stories: existingUserStories,
|
|
34
|
-
existing_test_cases: existingTestCases,
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
catch (error) {
|
|
38
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
39
|
-
logError(`Failed to fetch feature analysis context: ${errorMessage}`);
|
|
40
|
-
throw new Error(`Context fetch failed: ${errorMessage}`);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* Format the context into a readable string for Claude Code
|
|
45
|
-
*/
|
|
46
|
-
export function formatContextForPrompt(context) {
|
|
47
|
-
const formatUserStories = (stories) => {
|
|
48
|
-
if (stories.length === 0) {
|
|
49
|
-
return 'No user stories defined.';
|
|
50
|
-
}
|
|
51
|
-
return stories
|
|
52
|
-
.map((story, index) => `${index + 1}. **${story.title}** (Status: ${story.status})
|
|
53
|
-
ID: ${story.id}${story.status === 'draft' ? ' [DELETABLE]' : ''}
|
|
54
|
-
${story.description}`)
|
|
55
|
-
.join('\n\n');
|
|
56
|
-
};
|
|
57
|
-
const formatTestCases = (cases) => {
|
|
58
|
-
if (cases.length === 0) {
|
|
59
|
-
return 'No test cases defined.';
|
|
60
|
-
}
|
|
61
|
-
return cases
|
|
62
|
-
.map((testCase, index) => {
|
|
63
|
-
return `${index + 1}. **${testCase.name}** ${testCase.is_critical ? '[CRITICAL]' : '[OPTIONAL]'} (Status: ${testCase.status || 'unknown'})
|
|
64
|
-
ID: ${testCase.id}${testCase.status === 'draft' ? ' [DELETABLE]' : ''}
|
|
65
|
-
${testCase.description}`;
|
|
66
|
-
})
|
|
67
|
-
.join('\n\n');
|
|
68
|
-
};
|
|
69
|
-
return `# Feature Analysis Context
|
|
70
|
-
|
|
71
|
-
## Feature Information
|
|
72
|
-
- **ID**: ${context.feature.id}
|
|
73
|
-
- **Name**: ${context.feature.name}
|
|
74
|
-
- **Description**: ${context.feature.description || 'No description provided'}
|
|
75
|
-
- **Current Status**: ${context.feature.status}
|
|
76
|
-
|
|
77
|
-
## Product Information
|
|
78
|
-
- **Product**: ${context.product.name}
|
|
79
|
-
- **Product ID**: ${context.product.id}
|
|
80
|
-
- **Description**: ${context.product.description || 'No product description'}
|
|
81
|
-
|
|
82
|
-
## Existing User Stories (${context.existing_user_stories.length})
|
|
83
|
-
${formatUserStories(context.existing_user_stories)}
|
|
84
|
-
|
|
85
|
-
## Existing Test Cases (${context.existing_test_cases.length})
|
|
86
|
-
${formatTestCases(context.existing_test_cases)}
|
|
87
|
-
|
|
88
|
-
## Current Technical Design
|
|
89
|
-
${context.feature.technical_design || 'No technical design available yet'}
|
|
90
|
-
|
|
91
|
-
---
|
|
92
|
-
|
|
93
|
-
**Analysis Instructions**: Based on the above feature information and existing user stories/test cases, conduct comprehensive business analysis to identify gaps and create additional user stories and test cases that add business value.`;
|
|
94
|
-
}
|
|
95
|
-
/**
|
|
96
|
-
* Prepare all context information needed for analysis
|
|
97
|
-
*/
|
|
98
|
-
export async function prepareAnalysisContext(featureId, checklistContext, verbose) {
|
|
99
|
-
if (verbose) {
|
|
100
|
-
logInfo('Fetching feature analysis context via MCP endpoints...');
|
|
101
|
-
}
|
|
102
|
-
const featureContext = await fetchFeatureAnalysisContext(featureId, verbose);
|
|
103
|
-
const { content: contextInfo, downloadedImages } = await formatFeatureAnalysisContext(featureContext);
|
|
104
|
-
if (verbose && downloadedImages.length > 0) {
|
|
105
|
-
logInfo(`Downloaded ${downloadedImages.length} images for Claude Code:`);
|
|
106
|
-
downloadedImages.forEach((img) => {
|
|
107
|
-
logInfo(` - ${img.url} -> ${img.localPath}`);
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
let finalContextInfo = contextInfo;
|
|
111
|
-
// Add feedbacks context to the analysis prompt
|
|
112
|
-
try {
|
|
113
|
-
const feedbacksContext = await getFeedbacksForPhase({ featureId, verbose }, 'feature-analysis');
|
|
114
|
-
if (feedbacksContext.feedbacks.length > 0) {
|
|
115
|
-
const feedbacksInfo = await formatFeedbacksForContext(feedbacksContext);
|
|
116
|
-
finalContextInfo = `${finalContextInfo}\n\n${feedbacksInfo}`;
|
|
117
|
-
if (verbose) {
|
|
118
|
-
logInfo(`Added ${feedbacksContext.feedbacks.length} human feedbacks to context`);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
catch (error) {
|
|
123
|
-
// Don't fail if feedbacks fetch fails - just log and continue
|
|
124
|
-
if (verbose) {
|
|
125
|
-
logInfo(`Note: Could not fetch feedbacks (${error instanceof Error ? error.message : String(error)})`);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
// Add checklist context to the analysis prompt
|
|
129
|
-
if (checklistContext && checklistContext.checklists.length > 0) {
|
|
130
|
-
const checklistInfo = formatChecklistsForContext(checklistContext);
|
|
131
|
-
finalContextInfo = `${finalContextInfo}\n\n${checklistInfo}`;
|
|
132
|
-
if (verbose) {
|
|
133
|
-
logInfo(`Added ${checklistContext.checklists.length} checklists to analysis context`);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
const analysisPrompt = createFeatureAnalysisPromptWithContext(featureId, finalContextInfo);
|
|
137
|
-
return { featureContext, analysisPrompt };
|
|
138
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { type ChecklistPhaseContext } from '../../services/checklist.js';
|
|
2
|
-
import { type EdsgerConfig, type FeatureAnalysisResult } from '../../types/index.js';
|
|
3
|
-
export interface FeatureAnalysisOptions {
|
|
4
|
-
featureId: string;
|
|
5
|
-
verbose?: boolean;
|
|
6
|
-
maxVerificationIterations?: number;
|
|
7
|
-
}
|
|
8
|
-
export declare const analyseFeature: (options: FeatureAnalysisOptions, config: EdsgerConfig, checklistContext?: ChecklistPhaseContext | null) => Promise<FeatureAnalysisResult>;
|
|
@@ -1,199 +0,0 @@
|
|
|
1
|
-
import { logFeaturePhaseEvent } from '../../services/audit-logs.js';
|
|
2
|
-
import { extractChecklistItems, runPhaseCoaching, } from '../../services/coaching/index.js';
|
|
3
|
-
import { logError, logInfo, logWarning } from '../../utils/logger.js';
|
|
4
|
-
import { performVerificationCycle } from '../feature-analysis-verification/index.js';
|
|
5
|
-
import { executeAnalysisQuery, parseAnalysisResult } from './agent.js';
|
|
6
|
-
import { prepareAnalysisContext } from './context.js';
|
|
7
|
-
import { buildAnalysisResult, deleteArtifacts, deleteSpecificArtifacts, getAllDraftArtifactIds, resetReadyArtifactsToDraft, saveAnalysisArtifactsAsDraft, updateArtifactsToReady, } from './outcome.js';
|
|
8
|
-
import { createFeatureAnalysisSystemPrompt } from './prompts.js';
|
|
9
|
-
// eslint-disable-next-line complexity
|
|
10
|
-
export const analyseFeature = async (options, config, checklistContext) => {
|
|
11
|
-
const { featureId, verbose } = options;
|
|
12
|
-
if (verbose) {
|
|
13
|
-
logInfo(`Starting feature analysis for feature ID: ${featureId}`);
|
|
14
|
-
}
|
|
15
|
-
try {
|
|
16
|
-
// Reset pending_approval artifacts to draft so AI can manage them on re-run
|
|
17
|
-
const resetResult = await resetReadyArtifactsToDraft(featureId, verbose);
|
|
18
|
-
if (verbose &&
|
|
19
|
-
(resetResult.resetUserStories > 0 || resetResult.resetTestCases > 0)) {
|
|
20
|
-
logInfo(`✅ Reset ${resetResult.resetUserStories} user stories and ${resetResult.resetTestCases} test cases to draft for re-analysis`);
|
|
21
|
-
}
|
|
22
|
-
const context = await prepareAnalysisContext(featureId, checklistContext, verbose);
|
|
23
|
-
const systemPrompt = await createFeatureAnalysisSystemPrompt();
|
|
24
|
-
const initialAnalysisPrompt = context.analysisPrompt;
|
|
25
|
-
const maxIterations = options.maxVerificationIterations || 10;
|
|
26
|
-
let currentIteration = 0;
|
|
27
|
-
let currentPrompt = initialAnalysisPrompt;
|
|
28
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
29
|
-
let structuredAnalysisResult = null;
|
|
30
|
-
let verificationResult = null;
|
|
31
|
-
if (verbose) {
|
|
32
|
-
logInfo('Starting Claude Code query with pre-fetched information...');
|
|
33
|
-
}
|
|
34
|
-
// Iterative improvement loop: analysis → save draft → verification → update ready or delete → re-analysis
|
|
35
|
-
let currentDraftUserStoryIds = [];
|
|
36
|
-
let currentDraftTestCaseIds = [];
|
|
37
|
-
while (currentIteration < maxIterations) {
|
|
38
|
-
currentIteration++;
|
|
39
|
-
if (verbose && currentIteration > 1) {
|
|
40
|
-
logInfo(`\n🔄 Iteration ${currentIteration}/${maxIterations}: Improving analysis based on verification feedback...`);
|
|
41
|
-
}
|
|
42
|
-
// Log iteration start (for iterations after the first)
|
|
43
|
-
if (currentIteration > 1) {
|
|
44
|
-
await logFeaturePhaseEvent({
|
|
45
|
-
featureId,
|
|
46
|
-
eventType: 'phase_started',
|
|
47
|
-
phase: 'feature_analysis',
|
|
48
|
-
result: 'info',
|
|
49
|
-
metadata: {
|
|
50
|
-
iteration: currentIteration,
|
|
51
|
-
max_iterations: maxIterations,
|
|
52
|
-
re_analysis: true,
|
|
53
|
-
timestamp: new Date().toISOString(),
|
|
54
|
-
},
|
|
55
|
-
}, verbose);
|
|
56
|
-
}
|
|
57
|
-
// Execute analysis query
|
|
58
|
-
structuredAnalysisResult = await executeAnalysisQuery(currentPrompt, systemPrompt, config, verbose);
|
|
59
|
-
if (!structuredAnalysisResult) {
|
|
60
|
-
break;
|
|
61
|
-
}
|
|
62
|
-
await logFeaturePhaseEvent({
|
|
63
|
-
featureId,
|
|
64
|
-
eventType: 'phase_completed',
|
|
65
|
-
phase: 'feature_analysis',
|
|
66
|
-
result: 'success',
|
|
67
|
-
metadata: {
|
|
68
|
-
iteration: currentIteration,
|
|
69
|
-
max_iterations: maxIterations,
|
|
70
|
-
analysis_step: 'completed',
|
|
71
|
-
user_stories_count: structuredAnalysisResult.created_user_stories?.length || 0,
|
|
72
|
-
test_cases_count: structuredAnalysisResult.created_test_cases?.length || 0,
|
|
73
|
-
deleted_user_stories_count: structuredAnalysisResult.deleted_user_story_ids?.length || 0,
|
|
74
|
-
deleted_test_cases_count: structuredAnalysisResult.deleted_test_case_ids?.length || 0,
|
|
75
|
-
timestamp: new Date().toISOString(),
|
|
76
|
-
},
|
|
77
|
-
}, verbose);
|
|
78
|
-
// Handle deletions identified by AI
|
|
79
|
-
if (structuredAnalysisResult.deleted_user_story_ids?.length > 0 ||
|
|
80
|
-
structuredAnalysisResult.deleted_test_case_ids?.length > 0) {
|
|
81
|
-
if (verbose) {
|
|
82
|
-
logInfo('🗑️ Processing deletions identified by AI during analysis...');
|
|
83
|
-
}
|
|
84
|
-
await deleteSpecificArtifacts(featureId, structuredAnalysisResult.deleted_user_story_ids || [], structuredAnalysisResult.deleted_test_case_ids || [], structuredAnalysisResult.deletion_reasons || {}, verbose);
|
|
85
|
-
}
|
|
86
|
-
// Save artifacts as draft and get their IDs
|
|
87
|
-
const { userStoryIds, testCaseIds } = await saveAnalysisArtifactsAsDraft(featureId, structuredAnalysisResult.created_user_stories || [], structuredAnalysisResult.created_test_cases || [], verbose);
|
|
88
|
-
currentDraftUserStoryIds = userStoryIds;
|
|
89
|
-
currentDraftTestCaseIds = testCaseIds;
|
|
90
|
-
// Coaching loop between execute and verify
|
|
91
|
-
await runPhaseCoaching({
|
|
92
|
-
featureId,
|
|
93
|
-
phase: 'feature_analysis',
|
|
94
|
-
phaseResult: structuredAnalysisResult,
|
|
95
|
-
checklistItems: extractChecklistItems(checklistContext),
|
|
96
|
-
onImproved: async (_sessionId, responseText) => {
|
|
97
|
-
const parsed = parseAnalysisResult(responseText);
|
|
98
|
-
if (parsed.analysis) {
|
|
99
|
-
// Delete old drafts and save improved ones
|
|
100
|
-
await deleteArtifacts(currentDraftUserStoryIds, currentDraftTestCaseIds, verbose);
|
|
101
|
-
const { userStoryIds: newUserStoryIds, testCaseIds: newTestCaseIds, } = await saveAnalysisArtifactsAsDraft(featureId, parsed.analysis.created_user_stories || [], parsed.analysis.created_test_cases || [], verbose);
|
|
102
|
-
currentDraftUserStoryIds = newUserStoryIds;
|
|
103
|
-
currentDraftTestCaseIds = newTestCaseIds;
|
|
104
|
-
structuredAnalysisResult = parsed.analysis;
|
|
105
|
-
}
|
|
106
|
-
else {
|
|
107
|
-
logWarning(`Coaching improvement response could not be parsed for feature-analysis. Keeping previous drafts. ${parsed.error || ''}`);
|
|
108
|
-
}
|
|
109
|
-
},
|
|
110
|
-
verbose,
|
|
111
|
-
});
|
|
112
|
-
// Perform verification cycle
|
|
113
|
-
const verificationCycle = await performVerificationCycle({
|
|
114
|
-
structuredAnalysisResult,
|
|
115
|
-
checklistContext: checklistContext || null,
|
|
116
|
-
context: context.featureContext,
|
|
117
|
-
config,
|
|
118
|
-
currentIteration,
|
|
119
|
-
maxIterations,
|
|
120
|
-
featureId,
|
|
121
|
-
verbose,
|
|
122
|
-
});
|
|
123
|
-
({ verificationResult } = verificationCycle);
|
|
124
|
-
// If verification passed, update ALL remaining draft artifacts to pending_approval and exit
|
|
125
|
-
if (verificationCycle.passed) {
|
|
126
|
-
if (verbose) {
|
|
127
|
-
logInfo('✅ Verification passed! Updating all draft artifacts to pending_approval status...');
|
|
128
|
-
}
|
|
129
|
-
const allDrafts = await getAllDraftArtifactIds(featureId, verbose);
|
|
130
|
-
await updateArtifactsToReady(allDrafts.userStoryIds, allDrafts.testCaseIds, verbose);
|
|
131
|
-
break;
|
|
132
|
-
}
|
|
133
|
-
// Verification failed
|
|
134
|
-
if (currentIteration < maxIterations && verificationCycle.nextPrompt) {
|
|
135
|
-
// We have more iterations - delete draft artifacts and retry
|
|
136
|
-
if (verbose) {
|
|
137
|
-
logInfo('🗑️ Deleting draft artifacts for re-analysis...');
|
|
138
|
-
}
|
|
139
|
-
await deleteArtifacts(currentDraftUserStoryIds, currentDraftTestCaseIds, verbose);
|
|
140
|
-
// Continue with improvement prompt
|
|
141
|
-
currentPrompt = verificationCycle.nextPrompt;
|
|
142
|
-
}
|
|
143
|
-
else {
|
|
144
|
-
// Max iterations reached or no next prompt - exit loop
|
|
145
|
-
// Draft artifacts remain in database for manual review
|
|
146
|
-
if (verbose) {
|
|
147
|
-
logInfo('⚠️ Max iterations reached. Draft artifacts kept for manual review.');
|
|
148
|
-
}
|
|
149
|
-
break;
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
// Handle results
|
|
153
|
-
if (!structuredAnalysisResult) {
|
|
154
|
-
throw new Error('No analysis results received');
|
|
155
|
-
}
|
|
156
|
-
// If no checklist was used, update all draft artifacts to pending_approval now
|
|
157
|
-
if (!checklistContext ||
|
|
158
|
-
checklistContext.checklists.length === 0 ||
|
|
159
|
-
!verificationResult) {
|
|
160
|
-
const allDrafts = await getAllDraftArtifactIds(featureId, verbose);
|
|
161
|
-
if (allDrafts.userStoryIds.length > 0 ||
|
|
162
|
-
allDrafts.testCaseIds.length > 0) {
|
|
163
|
-
if (verbose) {
|
|
164
|
-
logInfo('✅ No checklist verification needed. Updating all draft artifacts to pending_approval status...');
|
|
165
|
-
}
|
|
166
|
-
await updateArtifactsToReady(allDrafts.userStoryIds, allDrafts.testCaseIds, verbose);
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
// Check if verification failed after all iterations
|
|
170
|
-
// Note: Artifacts are already saved as draft in the database
|
|
171
|
-
// If verification failed, they remain as draft for manual review
|
|
172
|
-
if (verificationResult &&
|
|
173
|
-
verificationResult.rejected_count > 0 &&
|
|
174
|
-
checklistContext &&
|
|
175
|
-
checklistContext.checklists.length > 0) {
|
|
176
|
-
logError(`❌ Final result: Checklist verification FAILED after ${currentIteration} iterations`);
|
|
177
|
-
logError(` Draft artifacts (${currentDraftUserStoryIds.length} user stories, ${currentDraftTestCaseIds.length} test cases) kept for manual review`);
|
|
178
|
-
throw new Error(`Checklist verification failed after ${currentIteration} iterations`);
|
|
179
|
-
}
|
|
180
|
-
// Return success result
|
|
181
|
-
// Note: Artifacts have already been saved and updated to 'pending_approval' status (if verification passed)
|
|
182
|
-
// or remain as draft (if verification failed)
|
|
183
|
-
return buildAnalysisResult(featureId, context.featureContext, structuredAnalysisResult, currentIteration);
|
|
184
|
-
}
|
|
185
|
-
catch (error) {
|
|
186
|
-
logError(`Feature analysis failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
187
|
-
return {
|
|
188
|
-
featureId,
|
|
189
|
-
productInfo: null,
|
|
190
|
-
featureInfo: null,
|
|
191
|
-
existingUserStories: [],
|
|
192
|
-
existingTestCases: [],
|
|
193
|
-
createdUserStories: [],
|
|
194
|
-
createdTestCases: [],
|
|
195
|
-
summary: `Analysis failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
196
|
-
status: 'error',
|
|
197
|
-
};
|
|
198
|
-
}
|
|
199
|
-
};
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { type FeatureAnalysisResult } from '../../types/index.js';
|
|
2
|
-
import { type FeatureAnalysisContext } from './context.js';
|
|
3
|
-
/**
|
|
4
|
-
* Reset ready user stories and test cases to draft for re-analysis
|
|
5
|
-
*/
|
|
6
|
-
export declare function resetReadyArtifactsToDraft(featureId: string, verbose?: boolean): Promise<{
|
|
7
|
-
resetUserStories: number;
|
|
8
|
-
resetTestCases: number;
|
|
9
|
-
}>;
|
|
10
|
-
/**
|
|
11
|
-
* Get all draft artifact IDs for a feature
|
|
12
|
-
*/
|
|
13
|
-
export declare function getAllDraftArtifactIds(featureId: string, verbose?: boolean): Promise<{
|
|
14
|
-
userStoryIds: string[];
|
|
15
|
-
testCaseIds: string[];
|
|
16
|
-
}>;
|
|
17
|
-
/**
|
|
18
|
-
* Delete artifacts after verification failure
|
|
19
|
-
*/
|
|
20
|
-
export declare function deleteArtifacts(userStoryIds: string[], testCaseIds: string[], verbose?: boolean): Promise<void>;
|
|
21
|
-
/**
|
|
22
|
-
* Delete specific artifacts identified by AI during analysis
|
|
23
|
-
* Only deletes artifacts with status 'draft'
|
|
24
|
-
*/
|
|
25
|
-
export declare function deleteSpecificArtifacts(featureId: string, deletedUserStoryIds: string[], deletedTestCaseIds: string[], deletionReasons: Record<string, string>, verbose?: boolean): Promise<void>;
|
|
26
|
-
/**
|
|
27
|
-
* Update artifacts to pending_approval status after successful verification
|
|
28
|
-
*/
|
|
29
|
-
export declare function updateArtifactsToReady(userStoryIds: string[], testCaseIds: string[], verbose?: boolean): Promise<void>;
|
|
30
|
-
/**
|
|
31
|
-
* Save analysis artifacts as draft and return their IDs
|
|
32
|
-
*/
|
|
33
|
-
export declare function saveAnalysisArtifactsAsDraft(featureId: string, createdUserStories: Record<string, unknown>[], createdTestCases: Record<string, unknown>[], verbose?: boolean): Promise<{
|
|
34
|
-
userStoryIds: string[];
|
|
35
|
-
testCaseIds: string[];
|
|
36
|
-
}>;
|
|
37
|
-
/**
|
|
38
|
-
* Build the final analysis result object
|
|
39
|
-
*/
|
|
40
|
-
export declare function buildAnalysisResult(featureId: string, context: FeatureAnalysisContext, structuredAnalysisResult: any, currentIteration: number): FeatureAnalysisResult;
|