edsger 0.51.0 ā 0.53.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/dist/phases/pr-execution/context.js +40 -32
- package/dist/phases/pr-splitting/context.js +18 -13
- package/dist/utils/github-repo-info.d.ts +13 -1
- package/dist/utils/github-repo-info.js +32 -6
- 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,280 +0,0 @@
|
|
|
1
|
-
import { batchDeleteTestCases, batchDeleteUserStories, batchUpdateTestCaseStatus, batchUpdateUserStoryStatus, getTestCases, getUserStories, } from '../../api/features/index.js';
|
|
2
|
-
import { callMcpEndpoint } from '../../api/mcp-client.js';
|
|
3
|
-
import { logError, logInfo } from '../../utils/logger.js';
|
|
4
|
-
/**
|
|
5
|
-
* Reset ready user stories and test cases to draft for re-analysis
|
|
6
|
-
*/
|
|
7
|
-
export async function resetReadyArtifactsToDraft(featureId, verbose) {
|
|
8
|
-
const [stories, testCases] = await Promise.all([
|
|
9
|
-
getUserStories(featureId, false),
|
|
10
|
-
getTestCases(featureId, false),
|
|
11
|
-
]);
|
|
12
|
-
const readyStoryIds = stories
|
|
13
|
-
.filter((s) => s.status === 'pending_approval')
|
|
14
|
-
.map((s) => s.id);
|
|
15
|
-
const readyTestCaseIds = testCases
|
|
16
|
-
.filter((tc) => tc.status === 'pending_approval')
|
|
17
|
-
.map((tc) => tc.id);
|
|
18
|
-
if (readyStoryIds.length > 0) {
|
|
19
|
-
if (verbose) {
|
|
20
|
-
logInfo(`š Resetting ${readyStoryIds.length} ready user stories to draft for re-analysis...`);
|
|
21
|
-
}
|
|
22
|
-
await batchUpdateUserStoryStatus(readyStoryIds, 'draft', verbose);
|
|
23
|
-
}
|
|
24
|
-
if (readyTestCaseIds.length > 0) {
|
|
25
|
-
if (verbose) {
|
|
26
|
-
logInfo(`š Resetting ${readyTestCaseIds.length} ready test cases to draft for re-analysis...`);
|
|
27
|
-
}
|
|
28
|
-
await batchUpdateTestCaseStatus(readyTestCaseIds, 'draft', verbose);
|
|
29
|
-
}
|
|
30
|
-
return {
|
|
31
|
-
resetUserStories: readyStoryIds.length,
|
|
32
|
-
resetTestCases: readyTestCaseIds.length,
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Get all draft artifact IDs for a feature
|
|
37
|
-
*/
|
|
38
|
-
export async function getAllDraftArtifactIds(featureId, verbose) {
|
|
39
|
-
const [stories, testCases] = await Promise.all([
|
|
40
|
-
getUserStories(featureId, false),
|
|
41
|
-
getTestCases(featureId, false),
|
|
42
|
-
]);
|
|
43
|
-
const userStoryIds = stories
|
|
44
|
-
.filter((s) => s.status === 'draft')
|
|
45
|
-
.map((s) => s.id);
|
|
46
|
-
const testCaseIds = testCases
|
|
47
|
-
.filter((tc) => tc.status === 'draft')
|
|
48
|
-
.map((tc) => tc.id);
|
|
49
|
-
if (verbose) {
|
|
50
|
-
logInfo(`Found ${userStoryIds.length} draft user stories and ${testCaseIds.length} draft test cases`);
|
|
51
|
-
}
|
|
52
|
-
return { userStoryIds, testCaseIds };
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Delete artifacts after verification failure
|
|
56
|
-
*/
|
|
57
|
-
export async function deleteArtifacts(userStoryIds, testCaseIds, verbose) {
|
|
58
|
-
if (userStoryIds.length > 0) {
|
|
59
|
-
if (verbose) {
|
|
60
|
-
logInfo(`Deleting ${userStoryIds.length} user stories due to verification failure...`);
|
|
61
|
-
}
|
|
62
|
-
await batchDeleteUserStories(userStoryIds, verbose);
|
|
63
|
-
}
|
|
64
|
-
if (testCaseIds.length > 0) {
|
|
65
|
-
if (verbose) {
|
|
66
|
-
logInfo(`Deleting ${testCaseIds.length} test cases due to verification failure...`);
|
|
67
|
-
}
|
|
68
|
-
await batchDeleteTestCases(testCaseIds, verbose);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
/**
|
|
72
|
-
* Validate UUID format
|
|
73
|
-
*/
|
|
74
|
-
function isValidUUID(id) {
|
|
75
|
-
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
76
|
-
return uuidRegex.test(id);
|
|
77
|
-
}
|
|
78
|
-
/**
|
|
79
|
-
* Delete specific artifacts identified by AI during analysis
|
|
80
|
-
* Only deletes artifacts with status 'draft'
|
|
81
|
-
*/
|
|
82
|
-
export async function deleteSpecificArtifacts(featureId, deletedUserStoryIds, deletedTestCaseIds, deletionReasons, verbose) {
|
|
83
|
-
// Fetch current artifacts to verify their status
|
|
84
|
-
const [currentUserStories, currentTestCases] = await Promise.all([
|
|
85
|
-
getUserStories(featureId, false),
|
|
86
|
-
getTestCases(featureId, false),
|
|
87
|
-
]);
|
|
88
|
-
// Create maps for quick lookup
|
|
89
|
-
const userStoryStatusMap = new Map(currentUserStories.map((story) => [story.id, story.status]));
|
|
90
|
-
const testCaseStatusMap = new Map(currentTestCases.map((testCase) => [testCase.id, testCase.status]));
|
|
91
|
-
// Filter user story IDs: only valid UUIDs with draft status
|
|
92
|
-
const validUserStoryIds = deletedUserStoryIds.filter((id) => {
|
|
93
|
-
if (!isValidUUID(id)) {
|
|
94
|
-
logError(`Invalid user story UUID format: ${id}`);
|
|
95
|
-
return false;
|
|
96
|
-
}
|
|
97
|
-
const status = userStoryStatusMap.get(id);
|
|
98
|
-
if (!status) {
|
|
99
|
-
logError(`User story not found: ${id}`);
|
|
100
|
-
return false;
|
|
101
|
-
}
|
|
102
|
-
if (status !== 'draft') {
|
|
103
|
-
logError(`Cannot delete user story ${id}: status is '${status}', only 'draft' items can be deleted`);
|
|
104
|
-
return false;
|
|
105
|
-
}
|
|
106
|
-
return true;
|
|
107
|
-
});
|
|
108
|
-
// Filter test case IDs: only valid UUIDs with draft status
|
|
109
|
-
const validTestCaseIds = deletedTestCaseIds.filter((id) => {
|
|
110
|
-
if (!isValidUUID(id)) {
|
|
111
|
-
logError(`Invalid test case UUID format: ${id}`);
|
|
112
|
-
return false;
|
|
113
|
-
}
|
|
114
|
-
const status = testCaseStatusMap.get(id);
|
|
115
|
-
if (!status) {
|
|
116
|
-
logError(`Test case not found: ${id}`);
|
|
117
|
-
return false;
|
|
118
|
-
}
|
|
119
|
-
if (status !== 'draft') {
|
|
120
|
-
logError(`Cannot delete test case ${id}: status is '${status}', only 'draft' items can be deleted`);
|
|
121
|
-
return false;
|
|
122
|
-
}
|
|
123
|
-
return true;
|
|
124
|
-
});
|
|
125
|
-
if (validUserStoryIds.length > 0) {
|
|
126
|
-
if (verbose) {
|
|
127
|
-
logInfo(`Deleting ${validUserStoryIds.length} draft user stories identified by AI...`);
|
|
128
|
-
validUserStoryIds.forEach((id) => {
|
|
129
|
-
const reason = deletionReasons[id] || 'No reason provided';
|
|
130
|
-
logInfo(` - ${id}: ${reason}`);
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
await batchDeleteUserStories(validUserStoryIds, verbose);
|
|
134
|
-
}
|
|
135
|
-
if (validTestCaseIds.length > 0) {
|
|
136
|
-
if (verbose) {
|
|
137
|
-
logInfo(`Deleting ${validTestCaseIds.length} draft test cases identified by AI...`);
|
|
138
|
-
validTestCaseIds.forEach((id) => {
|
|
139
|
-
const reason = deletionReasons[id] || 'No reason provided';
|
|
140
|
-
logInfo(` - ${id}: ${reason}`);
|
|
141
|
-
});
|
|
142
|
-
}
|
|
143
|
-
await batchDeleteTestCases(validTestCaseIds, verbose);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
/**
|
|
147
|
-
* Update artifacts to pending_approval status after successful verification
|
|
148
|
-
*/
|
|
149
|
-
export async function updateArtifactsToReady(userStoryIds, testCaseIds, verbose) {
|
|
150
|
-
if (userStoryIds.length > 0) {
|
|
151
|
-
if (verbose) {
|
|
152
|
-
logInfo(`Updating ${userStoryIds.length} user stories from draft to pending_approval...`);
|
|
153
|
-
}
|
|
154
|
-
await batchUpdateUserStoryStatus(userStoryIds, 'pending_approval', verbose);
|
|
155
|
-
}
|
|
156
|
-
if (testCaseIds.length > 0) {
|
|
157
|
-
if (verbose) {
|
|
158
|
-
logInfo(`Updating ${testCaseIds.length} test cases from draft to pending_approval...`);
|
|
159
|
-
}
|
|
160
|
-
await batchUpdateTestCaseStatus(testCaseIds, 'pending_approval', verbose);
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
/**
|
|
164
|
-
* Save analysis artifacts as draft and return their IDs
|
|
165
|
-
*/
|
|
166
|
-
export async function saveAnalysisArtifactsAsDraft(featureId, createdUserStories, createdTestCases, verbose) {
|
|
167
|
-
const userStoryIds = [];
|
|
168
|
-
const testCaseIds = [];
|
|
169
|
-
// Save user stories as draft
|
|
170
|
-
if (createdUserStories && createdUserStories.length > 0) {
|
|
171
|
-
if (verbose) {
|
|
172
|
-
logInfo(`Saving ${createdUserStories.length} user stories as draft...`);
|
|
173
|
-
}
|
|
174
|
-
try {
|
|
175
|
-
const result = (await callMcpEndpoint('user_stories/create', {
|
|
176
|
-
feature_id: featureId,
|
|
177
|
-
user_stories: createdUserStories.map((story) => ({
|
|
178
|
-
title: story.title,
|
|
179
|
-
description: story.description,
|
|
180
|
-
status: 'draft',
|
|
181
|
-
})),
|
|
182
|
-
}));
|
|
183
|
-
if (result.created_user_stories) {
|
|
184
|
-
userStoryIds.push(...result.created_user_stories.map((story) => story.id));
|
|
185
|
-
if (verbose) {
|
|
186
|
-
logInfo(`ā
Saved ${userStoryIds.length} user stories as draft`);
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
catch (error) {
|
|
191
|
-
logError(`Failed to save user stories: ${error instanceof Error ? error.message : String(error)}`);
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
// Save test cases as draft
|
|
195
|
-
if (createdTestCases && createdTestCases.length > 0) {
|
|
196
|
-
if (verbose) {
|
|
197
|
-
logInfo(`Saving ${createdTestCases.length} test cases as draft...`);
|
|
198
|
-
}
|
|
199
|
-
try {
|
|
200
|
-
const result = (await callMcpEndpoint('test_cases/create', {
|
|
201
|
-
feature_id: featureId,
|
|
202
|
-
test_cases: createdTestCases.map((testCase) => ({
|
|
203
|
-
name: testCase.name,
|
|
204
|
-
description: testCase.description,
|
|
205
|
-
is_critical: testCase.is_critical || false,
|
|
206
|
-
status: 'draft',
|
|
207
|
-
})),
|
|
208
|
-
}));
|
|
209
|
-
if (result.created_test_cases) {
|
|
210
|
-
testCaseIds.push(...result.created_test_cases.map((testCase) => testCase.id));
|
|
211
|
-
if (verbose) {
|
|
212
|
-
logInfo(`ā
Saved ${testCaseIds.length} test cases as draft`);
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
catch (error) {
|
|
217
|
-
logError(`Failed to save test cases: ${error instanceof Error ? error.message : String(error)}`);
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
return { userStoryIds, testCaseIds };
|
|
221
|
-
}
|
|
222
|
-
/**
|
|
223
|
-
* Build the final analysis result object
|
|
224
|
-
*/
|
|
225
|
-
export function buildAnalysisResult(featureId, context,
|
|
226
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
227
|
-
structuredAnalysisResult, currentIteration) {
|
|
228
|
-
const { created_user_stories, created_test_cases, deleted_user_story_ids, deleted_test_case_ids, deletion_reasons, checklist_results, checklist_item_results, } = structuredAnalysisResult;
|
|
229
|
-
return {
|
|
230
|
-
featureId,
|
|
231
|
-
productInfo: context.product,
|
|
232
|
-
featureInfo: context.feature,
|
|
233
|
-
existingUserStories: context.existing_user_stories.map((story) => {
|
|
234
|
-
const approvedOrDraft = story.status === 'approved' ? 'approved' : 'draft';
|
|
235
|
-
return {
|
|
236
|
-
...story,
|
|
237
|
-
status: story.status === 'pending_approval'
|
|
238
|
-
? 'pending_approval'
|
|
239
|
-
: approvedOrDraft,
|
|
240
|
-
created_at: story.created_at || new Date().toISOString(),
|
|
241
|
-
updated_at: story.updated_at || new Date().toISOString(),
|
|
242
|
-
};
|
|
243
|
-
}),
|
|
244
|
-
existingTestCases: context.existing_test_cases.map((testCase) => ({
|
|
245
|
-
...testCase,
|
|
246
|
-
created_at: testCase.created_at || new Date().toISOString(),
|
|
247
|
-
updated_at: testCase.updated_at || new Date().toISOString(),
|
|
248
|
-
})),
|
|
249
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
250
|
-
createdUserStories: (created_user_stories || []).map((story) => ({
|
|
251
|
-
id: '',
|
|
252
|
-
title: story.title,
|
|
253
|
-
description: story.description,
|
|
254
|
-
status: 'draft',
|
|
255
|
-
created_at: new Date().toISOString(),
|
|
256
|
-
updated_at: new Date().toISOString(),
|
|
257
|
-
})),
|
|
258
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
259
|
-
createdTestCases: (created_test_cases || []).map((testCase) => ({
|
|
260
|
-
id: '',
|
|
261
|
-
name: testCase.name,
|
|
262
|
-
description: testCase.description,
|
|
263
|
-
is_critical: testCase.is_critical || false,
|
|
264
|
-
created_at: new Date().toISOString(),
|
|
265
|
-
updated_at: new Date().toISOString(),
|
|
266
|
-
})),
|
|
267
|
-
summary: structuredAnalysisResult.summary ||
|
|
268
|
-
`Analysis completed${currentIteration > 1 ? ` after ${currentIteration} iterations` : ''}`,
|
|
269
|
-
status: structuredAnalysisResult.status === 'success' ? 'success' : 'error',
|
|
270
|
-
data: {
|
|
271
|
-
checklist_results,
|
|
272
|
-
checklist_item_results,
|
|
273
|
-
verification_result: structuredAnalysisResult.verification_result,
|
|
274
|
-
iterations: currentIteration,
|
|
275
|
-
deleted_user_story_ids: deleted_user_story_ids || [],
|
|
276
|
-
deleted_test_case_ids: deleted_test_case_ids || [],
|
|
277
|
-
deletion_reasons: deletion_reasons || {},
|
|
278
|
-
},
|
|
279
|
-
};
|
|
280
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { type ChecklistVerificationResult } from '../feature-analysis-verification/agent.js';
|
|
2
|
-
export declare const createFeatureAnalysisSystemPrompt: (projectDir?: string) => Promise<string>;
|
|
3
|
-
export declare const createFeatureAnalysisPromptWithContext: (featureId: string, contextInfo: string) => string;
|
|
4
|
-
/**
|
|
5
|
-
* Create a prompt for the analysis agent to improve based on verification feedback
|
|
6
|
-
*/
|
|
7
|
-
export declare const createImprovementPrompt: (verificationResult: ChecklistVerificationResult, previousAnalysis: {
|
|
8
|
-
created_user_stories: Record<string, unknown>[];
|
|
9
|
-
created_test_cases: Record<string, unknown>[];
|
|
10
|
-
}) => string;
|
|
@@ -1,212 +0,0 @@
|
|
|
1
|
-
import { resolveSkill } from '../../services/skill-resolver.js';
|
|
2
|
-
import { OUTPUT_CONTRACTS } from '../output-contracts.js';
|
|
3
|
-
export const createFeatureAnalysisSystemPrompt = async (projectDir) => {
|
|
4
|
-
const skill = await resolveSkill('phase/feature-analysis', { projectDir });
|
|
5
|
-
if (!skill) {
|
|
6
|
-
throw new Error('Failed to load skill: phase/feature-analysis');
|
|
7
|
-
}
|
|
8
|
-
return `${skill.prompt}\n\n${OUTPUT_CONTRACTS['feature-analysis']}`;
|
|
9
|
-
};
|
|
10
|
-
export const createFeatureAnalysisPromptWithContext = (featureId, contextInfo) => {
|
|
11
|
-
return `Please conduct comprehensive business analysis for feature ID: ${featureId}
|
|
12
|
-
|
|
13
|
-
${contextInfo}
|
|
14
|
-
|
|
15
|
-
## Analysis Instructions
|
|
16
|
-
|
|
17
|
-
Follow this systematic approach:
|
|
18
|
-
|
|
19
|
-
1. **Review Feature Context**: Analyze the feature information, product context, and technical design above
|
|
20
|
-
|
|
21
|
-
2. **Review Existing Items**: Study the existing user stories and test cases to understand:
|
|
22
|
-
- What scenarios are already covered
|
|
23
|
-
- What user perspectives are already addressed
|
|
24
|
-
- Where gaps might exist
|
|
25
|
-
|
|
26
|
-
3. **Business Analysis**: Think about the feature from a business perspective:
|
|
27
|
-
- Who are the different types of users?
|
|
28
|
-
- What problems does this feature solve?
|
|
29
|
-
- What are the different use cases and user workflows?
|
|
30
|
-
- What edge cases and error scenarios might occur?
|
|
31
|
-
- How does this integrate with other features?
|
|
32
|
-
|
|
33
|
-
4. **Create New User Stories**: Generate user stories that ADD VALUE by covering:
|
|
34
|
-
- Different user types or personas not yet covered
|
|
35
|
-
- New use cases or workflows
|
|
36
|
-
- Edge cases or error scenarios
|
|
37
|
-
- Different permission levels or access patterns
|
|
38
|
-
- Integration scenarios
|
|
39
|
-
|
|
40
|
-
5. **Design Test Cases**: Create test cases that ensure comprehensive coverage:
|
|
41
|
-
- Happy path scenarios
|
|
42
|
-
- Edge cases and boundary conditions
|
|
43
|
-
- Error handling and validation
|
|
44
|
-
- Security and permission testing
|
|
45
|
-
- Performance and usability aspects
|
|
46
|
-
- Integration testing scenarios
|
|
47
|
-
|
|
48
|
-
6. **Provide Results**: Output your analysis in the required JSON format
|
|
49
|
-
|
|
50
|
-
## Important Notes
|
|
51
|
-
- Focus on creating NEW user stories and test cases that add business value
|
|
52
|
-
- Avoid duplicating existing user stories and test cases
|
|
53
|
-
- Consider different user types (admin, regular user, guest, etc.)
|
|
54
|
-
- Think about accessibility, security, and performance implications
|
|
55
|
-
- The feature should already have some design - you're analyzing business requirements
|
|
56
|
-
- Be thorough but focus on practical, testable scenarios
|
|
57
|
-
|
|
58
|
-
Begin your systematic analysis based on the above context.`;
|
|
59
|
-
};
|
|
60
|
-
/**
|
|
61
|
-
* Create a prompt for the analysis agent to improve based on verification feedback
|
|
62
|
-
*/
|
|
63
|
-
export const createImprovementPrompt = (verificationResult, previousAnalysis) => {
|
|
64
|
-
// Format rejected items with specific feedback and improvement suggestions
|
|
65
|
-
const rejectedItemsSection = verificationResult.item_verifications
|
|
66
|
-
.filter((v) => v.verification_status === 'rejected')
|
|
67
|
-
.map((v, index) => {
|
|
68
|
-
return `### Rejected Requirement ${index + 1}
|
|
69
|
-
**Checklist Item ID**: ${v.checklist_item_id}
|
|
70
|
-
**Satisfaction Status**: ${v.is_satisfied ? 'ā
Satisfied' : 'ā Not Satisfied'}
|
|
71
|
-
**Verification Result**: ā REJECTED
|
|
72
|
-
**Reason**: ${v.verification_reason}
|
|
73
|
-
${v.concerns && v.concerns.length > 0 ? `**Specific Concerns**:\n${v.concerns.map((c) => `- ${c}`).join('\n')}` : ''}
|
|
74
|
-
${v.improvement_suggestions && v.improvement_suggestions.length > 0 ? `\n**š” Improvement Suggestions**:\n${v.improvement_suggestions.map((s) => `- ${s}`).join('\n')}` : ''}
|
|
75
|
-
`;
|
|
76
|
-
})
|
|
77
|
-
.join('\n---\n');
|
|
78
|
-
// Format uncertain items with improvement suggestions
|
|
79
|
-
const uncertainItemsSection = verificationResult.item_verifications
|
|
80
|
-
.filter((v) => v.verification_status === 'uncertain')
|
|
81
|
-
.map((v, index) => {
|
|
82
|
-
return `### Uncertain Requirement ${index + 1}
|
|
83
|
-
**Checklist Item ID**: ${v.checklist_item_id}
|
|
84
|
-
**Satisfaction Status**: ${v.is_satisfied ? 'ā
Satisfied' : 'ā ļø Partially Satisfied'}
|
|
85
|
-
**Verification Result**: ā ļø UNCERTAIN
|
|
86
|
-
**Reason**: ${v.verification_reason}
|
|
87
|
-
${v.concerns && v.concerns.length > 0 ? `**Specific Concerns**:\n${v.concerns.map((c) => `- ${c}`).join('\n')}` : ''}
|
|
88
|
-
${v.improvement_suggestions && v.improvement_suggestions.length > 0 ? `\n**š” Improvement Suggestions**:\n${v.improvement_suggestions.map((s) => `- ${s}`).join('\n')}` : ''}
|
|
89
|
-
`;
|
|
90
|
-
})
|
|
91
|
-
.join('\n---\n');
|
|
92
|
-
return `# Verification Feedback - Improvements Required
|
|
93
|
-
|
|
94
|
-
Your previous analysis was verified, and **${verificationResult.rejected_count} checklist requirements were NOT SATISFIED** and **${verificationResult.uncertain_count} requirements are PARTIALLY SATISFIED**.
|
|
95
|
-
|
|
96
|
-
## Verification Summary
|
|
97
|
-
${verificationResult.summary}
|
|
98
|
-
|
|
99
|
-
## Results Breakdown
|
|
100
|
-
- ā
Satisfied: ${verificationResult.confirmed_count}
|
|
101
|
-
- ā Not Satisfied: ${verificationResult.rejected_count}
|
|
102
|
-
- ā ļø Partially Satisfied: ${verificationResult.uncertain_count}
|
|
103
|
-
|
|
104
|
-
${verificationResult.overall_suggestions && verificationResult.overall_suggestions.length > 0 ? `## š” Overall Improvement Suggestions\n\n${verificationResult.overall_suggestions.map((s) => `- ${s}`).join('\n')}\n\n` : ''}
|
|
105
|
-
|
|
106
|
-
${verificationResult.rejected_count > 0 ? `## ā Unsatisfied Requirements\n\n${rejectedItemsSection}` : ''}
|
|
107
|
-
|
|
108
|
-
${verificationResult.uncertain_count > 0 ? `## ā ļø Partially Satisfied Requirements\n\n${uncertainItemsSection}` : ''}
|
|
109
|
-
|
|
110
|
-
## Your Previous Work
|
|
111
|
-
|
|
112
|
-
### User Stories You Created (${previousAnalysis.created_user_stories.length})
|
|
113
|
-
${previousAnalysis.created_user_stories
|
|
114
|
-
.map((story, index) => `${index + 1}. **${story.title}**
|
|
115
|
-
${story.description}
|
|
116
|
-
Status: ${story.status || 'draft'}`)
|
|
117
|
-
.join('\n\n')}
|
|
118
|
-
|
|
119
|
-
### Test Cases You Created (${previousAnalysis.created_test_cases.length})
|
|
120
|
-
${previousAnalysis.created_test_cases
|
|
121
|
-
.map((tc, index) => `${index + 1}. **${tc.name}** ${tc.is_critical ? '[CRITICAL]' : '[OPTIONAL]'}
|
|
122
|
-
${tc.description}`)
|
|
123
|
-
.join('\n\n')}
|
|
124
|
-
|
|
125
|
-
---
|
|
126
|
-
|
|
127
|
-
## Your Task: Improve Your Artifacts
|
|
128
|
-
|
|
129
|
-
You need to **revise and improve** your user stories and test cases to satisfy the checklist requirements.
|
|
130
|
-
|
|
131
|
-
**What You Should Do**:
|
|
132
|
-
|
|
133
|
-
1. **Review the improvement suggestions** provided above for each rejected/uncertain requirement
|
|
134
|
-
2. **Follow the specific, actionable suggestions** - they tell you exactly what to add or modify
|
|
135
|
-
3. **Add NEW user stories and test cases** as suggested by the verifier
|
|
136
|
-
4. **DELETE user stories or test cases** that are duplicates, no longer relevant, or conflict with requirements
|
|
137
|
-
5. **Improve the quality and specificity** of your artifacts
|
|
138
|
-
6. **Ensure each requirement is adequately covered** based on the feedback
|
|
139
|
-
|
|
140
|
-
**IMPORTANT Guidelines**:
|
|
141
|
-
- **Pay close attention to the š” Improvement Suggestions** - these are specific actions you should take
|
|
142
|
-
- You can **keep your existing user stories and test cases** that are good
|
|
143
|
-
- **Add NEW items** exactly as suggested to satisfy the unsatisfied requirements
|
|
144
|
-
- **DELETE items** that are duplicates, no longer relevant, or don't add value
|
|
145
|
-
- **Make your artifacts concrete and specific** - they will be verified again
|
|
146
|
-
- The suggestions are your roadmap - follow them to ensure verification passes
|
|
147
|
-
- Ensure your artifacts directly address the checklist requirements
|
|
148
|
-
|
|
149
|
-
**CRITICAL - Output Format**:
|
|
150
|
-
You MUST return ONLY the JSON object below. Do NOT include any explanatory text, commentary, or markdown before or after the JSON. Return ONLY the JSON in this exact format:
|
|
151
|
-
|
|
152
|
-
\`\`\`json
|
|
153
|
-
{
|
|
154
|
-
"analysis": {
|
|
155
|
-
"feature_id": "...",
|
|
156
|
-
"status": "success",
|
|
157
|
-
"summary": "Improved analysis based on verification feedback",
|
|
158
|
-
"created_user_stories": [
|
|
159
|
-
{
|
|
160
|
-
"title": "User story title",
|
|
161
|
-
"description": "As a [user], I want [goal] so that [benefit]",
|
|
162
|
-
"status": "draft",
|
|
163
|
-
"differentiation": "REQUIRED: Explain how this differs from existing user stories",
|
|
164
|
-
"invest_compliance": {
|
|
165
|
-
"independent": "How this story can be developed independently",
|
|
166
|
-
"negotiable": "What aspects are open for discussion",
|
|
167
|
-
"valuable": "The specific business value delivered",
|
|
168
|
-
"estimable": "Why this story is clear enough to estimate",
|
|
169
|
-
"small": "Confirmation this fits within a sprint",
|
|
170
|
-
"testable": "How this story can be verified/tested"
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
],
|
|
174
|
-
"created_test_cases": [
|
|
175
|
-
{
|
|
176
|
-
"name": "Test case name",
|
|
177
|
-
"description": "Detailed test case description",
|
|
178
|
-
"is_critical": true,
|
|
179
|
-
"differentiation": "REQUIRED: Explain how this differs from existing test cases"
|
|
180
|
-
}
|
|
181
|
-
],
|
|
182
|
-
"deleted_user_story_ids": [
|
|
183
|
-
// UUIDs of user stories to delete
|
|
184
|
-
],
|
|
185
|
-
"deleted_test_case_ids": [
|
|
186
|
-
// UUIDs of test cases to delete
|
|
187
|
-
],
|
|
188
|
-
"deletion_reasons": {
|
|
189
|
-
// UUID -> reason mapping for all deletions
|
|
190
|
-
},
|
|
191
|
-
"checklist_item_results": [
|
|
192
|
-
{
|
|
193
|
-
"checklist_item_id": "EXACT_CHECKLIST_ITEM_UUID_FROM_ID_FIELD",
|
|
194
|
-
"is_passed": true,
|
|
195
|
-
"value": "Result value based on item type (boolean, text, number, etc.)",
|
|
196
|
-
"notes": "Optional notes about this specific checklist item"
|
|
197
|
-
}
|
|
198
|
-
],
|
|
199
|
-
"recommendations": "..."
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
\`\`\`
|
|
203
|
-
|
|
204
|
-
**CRITICAL - Differentiation Requirement**:
|
|
205
|
-
- The "differentiation" field is MANDATORY for every user story and test case
|
|
206
|
-
- You MUST explain WHY each item is NOT a duplicate of existing items
|
|
207
|
-
- If you cannot clearly articulate the difference, DO NOT include the item
|
|
208
|
-
|
|
209
|
-
MANDATORY: You MUST include checklist_item_results for ALL checklist items in your response. Every checklist item ID must be addressed - either passed or with explanation in notes why it cannot be satisfied. Missing any checklist item will cause the pipeline to fail again.
|
|
210
|
-
|
|
211
|
-
IMPORTANT: Return ONLY the JSON above. Do not add any text explaining what you did or how you improved the analysis. The JSON should be the complete and only content of your response.`;
|
|
212
|
-
};
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { type ChecklistPhaseContext } from '../../services/checklist.js';
|
|
2
|
-
import { type EdsgerConfig } from '../../types/index.js';
|
|
3
|
-
import { type FeatureAnalysisContext } from '../feature-analysis/context.js';
|
|
4
|
-
export interface ChecklistItemVerificationResult {
|
|
5
|
-
checklist_item_id: string;
|
|
6
|
-
is_satisfied: boolean;
|
|
7
|
-
verification_status: 'confirmed' | 'rejected' | 'uncertain';
|
|
8
|
-
verification_reason: string;
|
|
9
|
-
concerns?: string[];
|
|
10
|
-
improvement_suggestions?: string[];
|
|
11
|
-
}
|
|
12
|
-
export interface ChecklistVerificationResult {
|
|
13
|
-
all_verified: boolean;
|
|
14
|
-
total_items: number;
|
|
15
|
-
confirmed_count: number;
|
|
16
|
-
rejected_count: number;
|
|
17
|
-
uncertain_count: number;
|
|
18
|
-
item_verifications: ChecklistItemVerificationResult[];
|
|
19
|
-
summary: string;
|
|
20
|
-
overall_suggestions?: string[];
|
|
21
|
-
}
|
|
22
|
-
export interface VerifyChecklistOptions {
|
|
23
|
-
checklistContext: ChecklistPhaseContext;
|
|
24
|
-
analysisContext: FeatureAnalysisContext;
|
|
25
|
-
createdUserStories: any[];
|
|
26
|
-
createdTestCases: any[];
|
|
27
|
-
verbose?: boolean;
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Verify checklist compliance using an independent AI agent
|
|
31
|
-
* This agent acts as a "challenger" to validate the claims made by the analysis agent
|
|
32
|
-
*/
|
|
33
|
-
export declare function verifyChecklistCompliance(options: VerifyChecklistOptions, _config: EdsgerConfig): Promise<ChecklistVerificationResult>;
|
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Checklist verification agent for feature analysis
|
|
3
|
-
* This agent independently reviews checklist compliance to ensure objectivity
|
|
4
|
-
*/
|
|
5
|
-
import { query } from '@anthropic-ai/claude-agent-sdk';
|
|
6
|
-
import { DEFAULT_MODEL } from '../../constants.js';
|
|
7
|
-
import { logDebug, logError, logInfo } from '../../utils/logger.js';
|
|
8
|
-
import { createChecklistVerificationPrompt, createChecklistVerificationSystemPrompt, } from './prompts.js';
|
|
9
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
10
|
-
function extractTextFromContent(content, verbose) {
|
|
11
|
-
let text = '';
|
|
12
|
-
for (const item of content) {
|
|
13
|
-
if (item.type === 'text') {
|
|
14
|
-
text += `${item.text}\n`;
|
|
15
|
-
logDebug(`š ${item.text}`, verbose);
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
return text;
|
|
19
|
-
}
|
|
20
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
21
|
-
function parseVerificationJson(responseText) {
|
|
22
|
-
try {
|
|
23
|
-
const jsonBlockMatch = responseText.match(/```json\s*\n([\s\S]*?)\n\s*```/);
|
|
24
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
25
|
-
const jsonResult = jsonBlockMatch
|
|
26
|
-
? JSON.parse(jsonBlockMatch[1])
|
|
27
|
-
: JSON.parse(responseText);
|
|
28
|
-
if (jsonResult && jsonResult.verification) {
|
|
29
|
-
return jsonResult.verification;
|
|
30
|
-
}
|
|
31
|
-
throw new Error('Invalid verification JSON structure');
|
|
32
|
-
}
|
|
33
|
-
catch (error) {
|
|
34
|
-
logError(`Failed to parse verification result: ${error}`);
|
|
35
|
-
return null;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
function userMessage(content) {
|
|
39
|
-
return {
|
|
40
|
-
type: 'user',
|
|
41
|
-
message: { role: 'user', content },
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
// eslint-disable-next-line @typescript-eslint/require-await -- async generator required by SDK interface
|
|
45
|
-
async function* prompt(verificationPrompt) {
|
|
46
|
-
yield userMessage(verificationPrompt);
|
|
47
|
-
}
|
|
48
|
-
/**
|
|
49
|
-
* Verify checklist compliance using an independent AI agent
|
|
50
|
-
* This agent acts as a "challenger" to validate the claims made by the analysis agent
|
|
51
|
-
*/
|
|
52
|
-
export async function verifyChecklistCompliance(options, _config) {
|
|
53
|
-
const { checklistContext, analysisContext, createdUserStories, createdTestCases, verbose, } = options;
|
|
54
|
-
const totalChecklistItems = checklistContext.checklists.reduce((sum, checklist) => sum + checklist.items.length, 0);
|
|
55
|
-
if (verbose) {
|
|
56
|
-
logInfo('š Starting checklist verification...');
|
|
57
|
-
logInfo(` Verifying ${totalChecklistItems} checklist items`);
|
|
58
|
-
}
|
|
59
|
-
const systemPrompt = await createChecklistVerificationSystemPrompt();
|
|
60
|
-
const verificationPrompt = createChecklistVerificationPrompt({
|
|
61
|
-
checklistContext,
|
|
62
|
-
analysisContext,
|
|
63
|
-
createdUserStories,
|
|
64
|
-
createdTestCases,
|
|
65
|
-
});
|
|
66
|
-
let lastAssistantResponse = '';
|
|
67
|
-
let verificationResult = null;
|
|
68
|
-
if (verbose) {
|
|
69
|
-
logInfo('š¤ Starting verification agent query...');
|
|
70
|
-
}
|
|
71
|
-
// Use Claude Code SDK for verification
|
|
72
|
-
for await (const message of query({
|
|
73
|
-
prompt: prompt(verificationPrompt),
|
|
74
|
-
options: {
|
|
75
|
-
systemPrompt: {
|
|
76
|
-
type: 'preset',
|
|
77
|
-
preset: 'claude_code',
|
|
78
|
-
append: systemPrompt,
|
|
79
|
-
},
|
|
80
|
-
model: DEFAULT_MODEL,
|
|
81
|
-
maxTurns: 100,
|
|
82
|
-
permissionMode: 'bypassPermissions',
|
|
83
|
-
},
|
|
84
|
-
})) {
|
|
85
|
-
if (verbose) {
|
|
86
|
-
logInfo(` Received message type: ${message.type}`);
|
|
87
|
-
}
|
|
88
|
-
// Capture assistant responses
|
|
89
|
-
if (message.type === 'assistant' && message.message?.content) {
|
|
90
|
-
lastAssistantResponse += extractTextFromContent(message.message.content, verbose);
|
|
91
|
-
}
|
|
92
|
-
if (message.type !== 'result') {
|
|
93
|
-
continue;
|
|
94
|
-
}
|
|
95
|
-
if (message.subtype === 'success') {
|
|
96
|
-
logInfo('\nā
Verification completed, parsing results...');
|
|
97
|
-
verificationResult = parseVerificationJson(message.result || lastAssistantResponse);
|
|
98
|
-
}
|
|
99
|
-
else {
|
|
100
|
-
logError(`\nā ļø Verification incomplete: ${message.subtype}`);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
if (!verificationResult) {
|
|
104
|
-
throw new Error('No verification result received');
|
|
105
|
-
}
|
|
106
|
-
if (verbose) {
|
|
107
|
-
logInfo('\nš Verification Summary:');
|
|
108
|
-
logInfo(` Total items: ${verificationResult.total_items}`);
|
|
109
|
-
logInfo(` ā
Confirmed: ${verificationResult.confirmed_count}`);
|
|
110
|
-
logInfo(` ā Rejected: ${verificationResult.rejected_count}`);
|
|
111
|
-
logInfo(` ā ļø Uncertain: ${verificationResult.uncertain_count}`);
|
|
112
|
-
logInfo(` Summary: ${verificationResult.summary}`);
|
|
113
|
-
if (verificationResult.rejected_count > 0) {
|
|
114
|
-
logInfo('\nā Rejected items:');
|
|
115
|
-
verificationResult.item_verifications
|
|
116
|
-
.filter((v) => v.verification_status === 'rejected')
|
|
117
|
-
.forEach((v) => {
|
|
118
|
-
logInfo(` - ${v.checklist_item_id}`);
|
|
119
|
-
logInfo(` Reason: ${v.verification_reason}`);
|
|
120
|
-
});
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
return verificationResult;
|
|
124
|
-
}
|