edsger 0.2.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (178) hide show
  1. package/dist/api/features/feature-utils.d.ts +13 -0
  2. package/dist/api/features/feature-utils.js +46 -0
  3. package/dist/api/features/get-feature.d.ts +5 -0
  4. package/dist/api/features/get-feature.js +19 -0
  5. package/dist/api/features/index.d.ts +7 -0
  6. package/dist/api/features/index.js +9 -0
  7. package/dist/api/features/status-updater.d.ts +27 -0
  8. package/dist/api/features/status-updater.js +64 -0
  9. package/dist/api/features/test-cases.d.ts +21 -0
  10. package/dist/api/features/test-cases.js +63 -0
  11. package/dist/api/features/update-feature.d.ts +13 -0
  12. package/dist/api/features/update-feature.js +31 -0
  13. package/dist/api/features/user-stories.d.ts +21 -0
  14. package/dist/api/features/user-stories.js +63 -0
  15. package/dist/api/features.d.ts +100 -0
  16. package/dist/api/features.js +219 -0
  17. package/dist/api/mcp-client.d.ts +18 -0
  18. package/dist/api/mcp-client.js +58 -0
  19. package/dist/api/products.d.ts +10 -0
  20. package/dist/api/products.js +22 -0
  21. package/dist/api/test-reports.d.ts +9 -0
  22. package/dist/api/test-reports.js +25 -0
  23. package/dist/cli/commands/code-implementation-command.d.ts +2 -0
  24. package/dist/cli/commands/code-implementation-command.js +36 -0
  25. package/dist/cli/commands/code-review-command.d.ts +2 -0
  26. package/dist/cli/commands/code-review-command.js +39 -0
  27. package/dist/cli/commands/feature-analysis-command.d.ts +2 -0
  28. package/dist/cli/commands/feature-analysis-command.js +36 -0
  29. package/dist/cli/commands/functional-testing-command.d.ts +2 -0
  30. package/dist/cli/commands/functional-testing-command.js +36 -0
  31. package/dist/cli/commands/technical-design-command.d.ts +2 -0
  32. package/dist/cli/commands/technical-design-command.js +36 -0
  33. package/dist/cli/commands/workflow-command.d.ts +2 -0
  34. package/dist/cli/commands/workflow-command.js +34 -0
  35. package/dist/cli/formatters/code-implementation-formatter.d.ts +9 -0
  36. package/dist/cli/formatters/code-implementation-formatter.js +27 -0
  37. package/dist/cli/formatters/feature-analysis-formatter.d.ts +2 -0
  38. package/dist/cli/formatters/feature-analysis-formatter.js +27 -0
  39. package/dist/cli/formatters/functional-testing-formatter.d.ts +15 -0
  40. package/dist/cli/formatters/functional-testing-formatter.js +37 -0
  41. package/dist/cli/formatters/technical-design-formatter.d.ts +7 -0
  42. package/dist/cli/formatters/technical-design-formatter.js +30 -0
  43. package/dist/cli/index.d.ts +3 -0
  44. package/dist/cli/index.js +99 -0
  45. package/dist/cli/utils/validation.d.ts +25 -0
  46. package/dist/cli/utils/validation.js +58 -0
  47. package/dist/cli/utils/workflow-utils.d.ts +21 -0
  48. package/dist/cli/utils/workflow-utils.js +47 -0
  49. package/dist/cli.d.ts +1 -1
  50. package/dist/cli.js +11 -466
  51. package/dist/config.d.ts +1 -1
  52. package/dist/index.d.ts +3 -3
  53. package/dist/index.js +2 -2
  54. package/dist/{bug-fixing → phases/bug-fixing}/analyzer.d.ts +1 -1
  55. package/dist/{bug-fixing → phases/bug-fixing}/analyzer.js +1 -1
  56. package/dist/{bug-fixing → phases/bug-fixing}/context-fetcher.d.ts +4 -22
  57. package/dist/{bug-fixing → phases/bug-fixing}/context-fetcher.js +14 -58
  58. package/dist/{bug-fixing → phases/bug-fixing}/mcp-server.js +1 -30
  59. package/dist/phases/code-implementation/analyzer.d.ts +33 -0
  60. package/dist/{code-implementation → phases/code-implementation}/analyzer.js +174 -15
  61. package/dist/phases/code-implementation/context-fetcher.d.ts +17 -0
  62. package/dist/phases/code-implementation/context-fetcher.js +86 -0
  63. package/dist/{code-implementation → phases/code-implementation}/mcp-server.js +1 -30
  64. package/dist/{code-review → phases/code-review}/reviewer.d.ts +1 -1
  65. package/dist/{feature-analysis → phases/feature-analysis}/analyzer.d.ts +3 -2
  66. package/dist/{feature-analysis → phases/feature-analysis}/analyzer.js +29 -127
  67. package/dist/phases/feature-analysis/context-fetcher.d.ts +18 -0
  68. package/dist/phases/feature-analysis/context-fetcher.js +86 -0
  69. package/dist/{feature-analysis → phases/feature-analysis}/http-fallback.js +1 -1
  70. package/dist/{feature-analysis → phases/feature-analysis}/mcp-server.js +1 -24
  71. package/dist/{functional-testing → phases/functional-testing}/analyzer.d.ts +17 -2
  72. package/dist/{functional-testing → phases/functional-testing}/analyzer.js +225 -31
  73. package/dist/phases/functional-testing/context-fetcher.d.ts +16 -0
  74. package/dist/phases/functional-testing/context-fetcher.js +81 -0
  75. package/dist/{functional-testing → phases/functional-testing}/http-fallback.js +1 -1
  76. package/dist/{functional-testing → phases/functional-testing}/index.d.ts +1 -1
  77. package/dist/{functional-testing → phases/functional-testing}/index.js +1 -1
  78. package/dist/{functional-testing → phases/functional-testing}/mcp-server.js +1 -30
  79. package/dist/{functional-testing → phases/functional-testing}/test-report-creator.d.ts +26 -0
  80. package/dist/{functional-testing → phases/functional-testing}/test-report-creator.js +87 -5
  81. package/dist/phases/functional-testing/test-retry-handler.d.ts +16 -0
  82. package/dist/phases/functional-testing/test-retry-handler.js +75 -0
  83. package/dist/{pull-request → phases/pull-request}/creator.js +47 -6
  84. package/dist/phases/pull-request/handler.d.ts +16 -0
  85. package/dist/phases/pull-request/handler.js +60 -0
  86. package/dist/{technical-design → phases/technical-design}/analyzer.d.ts +7 -2
  87. package/dist/phases/technical-design/analyzer.js +418 -0
  88. package/dist/phases/technical-design/context-fetcher.d.ts +12 -0
  89. package/dist/phases/technical-design/context-fetcher.js +39 -0
  90. package/dist/{technical-design → phases/technical-design}/http-fallback.js +1 -1
  91. package/dist/{technical-design → phases/technical-design}/mcp-server.js +1 -30
  92. package/dist/prompts/bug-fixing.d.ts +2 -0
  93. package/dist/prompts/bug-fixing.js +63 -0
  94. package/dist/prompts/code-implementation.d.ts +3 -0
  95. package/dist/prompts/code-implementation.js +132 -0
  96. package/dist/prompts/feature-analysis.d.ts +3 -0
  97. package/dist/prompts/feature-analysis.js +149 -0
  98. package/dist/prompts/formatters.d.ts +29 -0
  99. package/dist/prompts/formatters.js +139 -0
  100. package/dist/prompts/functional-testing.d.ts +3 -0
  101. package/dist/prompts/functional-testing.js +126 -0
  102. package/dist/prompts/index.d.ts +6 -0
  103. package/dist/prompts/index.js +7 -0
  104. package/dist/prompts/technical-design.d.ts +3 -0
  105. package/dist/prompts/technical-design.js +130 -0
  106. package/dist/services/checklist.d.ts +99 -0
  107. package/dist/services/checklist.js +337 -0
  108. package/dist/types/features.d.ts +29 -0
  109. package/dist/types/features.js +1 -0
  110. package/dist/types/index.d.ts +112 -0
  111. package/dist/types/index.js +1 -0
  112. package/dist/types/pipeline.d.ts +25 -0
  113. package/dist/types/pipeline.js +4 -0
  114. package/dist/utils/logger.d.ts +19 -0
  115. package/dist/utils/logger.js +52 -0
  116. package/dist/utils/pipeline-logger.d.ts +8 -0
  117. package/dist/utils/pipeline-logger.js +35 -0
  118. package/dist/workflow-runner/config/phase-configs.d.ts +5 -0
  119. package/dist/workflow-runner/config/phase-configs.js +34 -0
  120. package/dist/workflow-runner/config/stage-configs.d.ts +5 -0
  121. package/dist/workflow-runner/config/stage-configs.js +34 -0
  122. package/dist/workflow-runner/core/feature-filter.d.ts +16 -0
  123. package/dist/workflow-runner/core/feature-filter.js +46 -0
  124. package/dist/workflow-runner/core/feature-filter.test.d.ts +4 -0
  125. package/dist/workflow-runner/core/feature-filter.test.js +127 -0
  126. package/dist/workflow-runner/core/index.d.ts +8 -0
  127. package/dist/workflow-runner/core/index.js +12 -0
  128. package/dist/workflow-runner/core/pipeline-evaluator.d.ts +24 -0
  129. package/dist/workflow-runner/core/pipeline-evaluator.js +32 -0
  130. package/dist/workflow-runner/core/state-manager.d.ts +24 -0
  131. package/dist/workflow-runner/core/state-manager.js +42 -0
  132. package/dist/workflow-runner/core/workflow-logger.d.ts +20 -0
  133. package/dist/workflow-runner/core/workflow-logger.js +65 -0
  134. package/dist/workflow-runner/executors/phase-executor.d.ts +8 -0
  135. package/dist/workflow-runner/executors/phase-executor.js +183 -0
  136. package/dist/workflow-runner/executors/stage-executor.d.ts +8 -0
  137. package/dist/workflow-runner/executors/stage-executor.js +49 -0
  138. package/dist/workflow-runner/feature-service.d.ts +17 -0
  139. package/dist/workflow-runner/feature-service.js +60 -0
  140. package/dist/workflow-runner/feature-workflow-runner.d.ts +26 -0
  141. package/dist/workflow-runner/feature-workflow-runner.js +113 -0
  142. package/dist/workflow-runner/index.d.ts +0 -1
  143. package/dist/workflow-runner/index.js +0 -1
  144. package/dist/workflow-runner/pipeline-runner.d.ts +9 -19
  145. package/dist/workflow-runner/pipeline-runner.js +247 -256
  146. package/dist/workflow-runner/pipeline.d.ts +18 -0
  147. package/dist/workflow-runner/pipeline.js +197 -0
  148. package/dist/workflow-runner/processor.d.ts +40 -0
  149. package/dist/workflow-runner/processor.js +191 -0
  150. package/dist/workflow-runner/types.d.ts +48 -0
  151. package/dist/workflow-runner/types.js +4 -0
  152. package/dist/workflow-runner/workflow-processor.d.ts +6 -23
  153. package/dist/workflow-runner/workflow-processor.js +38 -100
  154. package/package.json +2 -2
  155. package/dist/code-implementation/analyzer.d.ts +0 -19
  156. package/dist/code-implementation/context-fetcher.d.ts +0 -38
  157. package/dist/code-implementation/context-fetcher.js +0 -147
  158. package/dist/feature-analysis/context-fetcher.d.ts +0 -54
  159. package/dist/feature-analysis/context-fetcher.js +0 -193
  160. package/dist/functional-testing/context-fetcher.d.ts +0 -47
  161. package/dist/functional-testing/context-fetcher.js +0 -192
  162. package/dist/technical-design/analyzer.js +0 -338
  163. package/dist/technical-design/context-fetcher.d.ts +0 -42
  164. package/dist/technical-design/context-fetcher.js +0 -170
  165. /package/dist/{bug-fixing → phases/bug-fixing}/index.d.ts +0 -0
  166. /package/dist/{bug-fixing → phases/bug-fixing}/index.js +0 -0
  167. /package/dist/{bug-fixing → phases/bug-fixing}/mcp-server.d.ts +0 -0
  168. /package/dist/{code-implementation → phases/code-implementation}/mcp-server.d.ts +0 -0
  169. /package/dist/{code-review → phases/code-review}/reviewer.js +0 -0
  170. /package/dist/{feature-analysis → phases/feature-analysis}/http-fallback.d.ts +0 -0
  171. /package/dist/{feature-analysis → phases/feature-analysis}/index.d.ts +0 -0
  172. /package/dist/{feature-analysis → phases/feature-analysis}/index.js +0 -0
  173. /package/dist/{feature-analysis → phases/feature-analysis}/mcp-server.d.ts +0 -0
  174. /package/dist/{functional-testing → phases/functional-testing}/http-fallback.d.ts +0 -0
  175. /package/dist/{functional-testing → phases/functional-testing}/mcp-server.d.ts +0 -0
  176. /package/dist/{pull-request → phases/pull-request}/creator.d.ts +0 -0
  177. /package/dist/{technical-design → phases/technical-design}/http-fallback.d.ts +0 -0
  178. /package/dist/{technical-design → phases/technical-design}/mcp-server.d.ts +0 -0
@@ -1,7 +1,9 @@
1
1
  import { query } from '@anthropic-ai/claude-code';
2
- import { logInfo, logError } from '../logger.js';
2
+ import { logInfo, logError } from '../../utils/logger.js';
3
+ import { formatChecklistsForContext, } from '../../services/checklist.js';
3
4
  import { saveFunctionalTestResultsWithRetry } from './http-fallback.js';
4
- import { fetchFeatureTestingContext, updateFeatureTestStatus, formatContextForPrompt, } from './context-fetcher.js';
5
+ import { fetchFunctionalTestingContext, formatContextForPrompt, } from './context-fetcher.js';
6
+ import { updateFeatureStatus } from '../../api/features/index.js';
5
7
  import { createTestReport, } from './test-report-creator.js';
6
8
  function userMessage(content) {
7
9
  return {
@@ -13,7 +15,7 @@ async function* prompt(testingPrompt) {
13
15
  yield userMessage(testingPrompt);
14
16
  await new Promise((res) => setTimeout(res, 10000));
15
17
  }
16
- export const runFunctionalTesting = async (options, config) => {
18
+ export const runFunctionalTesting = async (options, config, checklistContext) => {
17
19
  const { featureId, mcpServerUrl, mcpToken, verbose } = options;
18
20
  if (verbose) {
19
21
  logInfo(`Starting functional testing for feature ID: ${featureId}`);
@@ -24,9 +26,9 @@ export const runFunctionalTesting = async (options, config) => {
24
26
  if (verbose) {
25
27
  logInfo('Fetching feature testing context via MCP endpoints...');
26
28
  }
27
- const context = await fetchFeatureTestingContext(mcpServerUrl, mcpToken, featureId, verbose);
28
- const systemPrompt = createSystemPrompt(config);
29
- const testingPrompt = createTestingPromptWithContext(featureId, context);
29
+ const context = await fetchFunctionalTestingContext(mcpServerUrl, mcpToken, featureId, verbose);
30
+ const systemPrompt = createSystemPrompt(config, mcpServerUrl, mcpToken, featureId);
31
+ const testingPrompt = createTestingPromptWithContext(featureId, context, checklistContext, verbose);
30
32
  let lastAssistantResponse = '';
31
33
  let structuredTestResult = null;
32
34
  let testStatus = 'testing_failed';
@@ -75,10 +77,89 @@ export const runFunctionalTesting = async (options, config) => {
75
77
  jsonResult = JSON.parse(jsonBlockMatch[1]);
76
78
  }
77
79
  else {
78
- // Try to parse the entire response as JSON
79
- jsonResult = JSON.parse(responseText);
80
+ // Search for JSON objects in the complete response
81
+ const lines = responseText.split('\n');
82
+ let foundJson = false;
83
+ for (let i = 0; i < lines.length; i++) {
84
+ const line = lines[i].trim();
85
+ if (line.includes('{') &&
86
+ (line.includes('"test_result"') ||
87
+ line.includes('"status"') ||
88
+ line.includes('"checklist_item_results"'))) {
89
+ // Found a potential JSON line, extract complete JSON object
90
+ let braceCount = 0;
91
+ let jsonStr = '';
92
+ let inString = false;
93
+ let escapeNext = false;
94
+ for (let j = i; j < lines.length; j++) {
95
+ const currentLine = lines[j];
96
+ for (let k = 0; k < currentLine.length; k++) {
97
+ const char = currentLine[k];
98
+ if (escapeNext) {
99
+ escapeNext = false;
100
+ jsonStr += char;
101
+ continue;
102
+ }
103
+ if (char === '\\') {
104
+ escapeNext = true;
105
+ jsonStr += char;
106
+ continue;
107
+ }
108
+ if (char === '"' && !escapeNext) {
109
+ inString = !inString;
110
+ }
111
+ if (!inString) {
112
+ if (char === '{')
113
+ braceCount++;
114
+ if (char === '}')
115
+ braceCount--;
116
+ }
117
+ jsonStr += char;
118
+ if (braceCount === 0 && jsonStr.includes('{')) {
119
+ try {
120
+ jsonResult = JSON.parse(jsonStr);
121
+ foundJson = true;
122
+ break;
123
+ }
124
+ catch {
125
+ // Continue searching
126
+ }
127
+ }
128
+ }
129
+ if (foundJson)
130
+ break;
131
+ if (j > i)
132
+ jsonStr += '\n';
133
+ }
134
+ if (foundJson)
135
+ break;
136
+ }
137
+ }
138
+ // Final fallback: Try to parse the entire response as JSON
139
+ if (!foundJson) {
140
+ jsonResult = JSON.parse(responseText);
141
+ }
80
142
  }
81
- if (jsonResult && typeof jsonResult === 'object') {
143
+ if (jsonResult && jsonResult.test_result) {
144
+ const testData = jsonResult.test_result;
145
+ structuredTestResult = {
146
+ status: testData.status || 'testing_failed',
147
+ title: testData.title || 'Functional Test Report',
148
+ summary: testData.summary || 'Test execution completed',
149
+ total_test_cases: testData.total_test_cases || 0,
150
+ passed_test_cases: testData.passed_test_cases || 0,
151
+ failed_test_cases: testData.failed_test_cases || 0,
152
+ test_cases: testData.test_cases || [],
153
+ execution_details: testData.execution_details || responseText,
154
+ timestamp: testData.timestamp || new Date().toISOString(),
155
+ checklist_item_results: testData.checklist_item_results || [],
156
+ };
157
+ testStatus = structuredTestResult.status;
158
+ }
159
+ else if (jsonResult &&
160
+ typeof jsonResult === 'object' &&
161
+ jsonResult.status) {
162
+ // Fallback: handle flat structure for backward compatibility
82
163
  structuredTestResult = {
83
164
  status: jsonResult.status || 'testing_failed',
84
165
  title: jsonResult.title || 'Functional Test Report',
@@ -89,6 +170,7 @@ export const runFunctionalTesting = async (options, config) => {
89
170
  test_cases: jsonResult.test_cases || [],
90
171
  execution_details: jsonResult.execution_details || responseText,
91
172
  timestamp: jsonResult.timestamp || new Date().toISOString(),
173
+ checklist_item_results: jsonResult.checklist_item_results || [],
92
174
  };
93
175
  testStatus = structuredTestResult.status;
94
176
  }
@@ -108,6 +190,7 @@ export const runFunctionalTesting = async (options, config) => {
108
190
  failed_test_cases: 1,
109
191
  execution_details: message.result || lastAssistantResponse,
110
192
  timestamp: new Date().toISOString(),
193
+ checklist_item_results: [],
111
194
  };
112
195
  testStatus = 'testing_failed';
113
196
  }
@@ -124,7 +207,13 @@ export const runFunctionalTesting = async (options, config) => {
124
207
  if (verbose) {
125
208
  logInfo('Saving test results...');
126
209
  }
127
- const statusSaved = await updateFeatureTestStatus(mcpServerUrl, mcpToken, featureId, testStatus, verbose);
210
+ const statusSaved = await updateFeatureStatus({
211
+ mcpServerUrl,
212
+ mcpToken,
213
+ featureId,
214
+ status: testStatus,
215
+ verbose,
216
+ });
128
217
  // Try HTTP fallback if direct update failed
129
218
  if (!statusSaved) {
130
219
  if (verbose) {
@@ -155,11 +244,68 @@ export const runFunctionalTesting = async (options, config) => {
155
244
  testResults: structuredTestResult.execution_details || lastAssistantResponse,
156
245
  status: testStatus,
157
246
  };
247
+ // Convert test cases to test results format for MCP
248
+ let testResults;
249
+ if (structuredTestResult.test_cases &&
250
+ structuredTestResult.test_cases.length > 0) {
251
+ // Fetch test cases for this feature to get proper test_case_ids
252
+ try {
253
+ const testCasesResponse = await fetch(`${mcpServerUrl}/mcp`, {
254
+ method: 'POST',
255
+ headers: {
256
+ 'Content-Type': 'application/json',
257
+ Authorization: `Bearer ${mcpToken}`,
258
+ },
259
+ body: JSON.stringify({
260
+ jsonrpc: '2.0',
261
+ method: 'test_cases/list',
262
+ params: {
263
+ feature_id: featureId,
264
+ },
265
+ id: Math.random().toString(36).substring(7),
266
+ }),
267
+ });
268
+ if (testCasesResponse.ok) {
269
+ const testCasesData = await testCasesResponse.json();
270
+ if (!testCasesData.error && testCasesData.result) {
271
+ const existingTestCases = testCasesData.result.test_cases || [];
272
+ // Map structured test results to existing test cases by name
273
+ testResults = structuredTestResult.test_cases
274
+ .map((testCase) => {
275
+ const matchingTestCase = existingTestCases.find((existing) => existing.name
276
+ .toLowerCase()
277
+ .includes(testCase.name.toLowerCase()) ||
278
+ testCase.name
279
+ .toLowerCase()
280
+ .includes(existing.name.toLowerCase()));
281
+ if (matchingTestCase) {
282
+ return {
283
+ test_case_id: matchingTestCase.id,
284
+ result: testCase.status,
285
+ notes: testCase.error_message || testCase.description || null,
286
+ };
287
+ }
288
+ return null;
289
+ })
290
+ .filter(Boolean);
291
+ if (verbose && testResults.length > 0) {
292
+ logInfo(`Mapped ${testResults.length} test results to existing test cases`);
293
+ }
294
+ }
295
+ }
296
+ }
297
+ catch (error) {
298
+ if (verbose) {
299
+ logError(`Failed to fetch test cases for mapping: ${error}`);
300
+ }
301
+ }
302
+ }
158
303
  testReportResult = await createTestReport({
159
304
  mcpServerUrl,
160
305
  mcpToken,
161
306
  featureId,
162
307
  testReportData,
308
+ testResults,
163
309
  verbose,
164
310
  });
165
311
  if (testReportResult.success && verbose) {
@@ -177,6 +323,9 @@ export const runFunctionalTesting = async (options, config) => {
177
323
  testReport: testReportResult,
178
324
  status: 'success',
179
325
  message: `Functional testing completed with status: ${testStatus}`,
326
+ data: {
327
+ checklist_item_results: structuredTestResult.checklist_item_results,
328
+ },
180
329
  };
181
330
  }
182
331
  else {
@@ -194,7 +343,13 @@ export const runFunctionalTesting = async (options, config) => {
194
343
  logError(`Functional testing failed: ${error instanceof Error ? error.message : String(error)}`);
195
344
  // Try to save error status
196
345
  try {
197
- const errorSaved = await updateFeatureTestStatus(mcpServerUrl, mcpToken, featureId, 'testing_failed', verbose);
346
+ const errorSaved = await updateFeatureStatus({
347
+ mcpServerUrl,
348
+ mcpToken,
349
+ featureId,
350
+ status: 'testing_failed',
351
+ verbose,
352
+ });
198
353
  if (!errorSaved) {
199
354
  // Try HTTP fallback
200
355
  await saveFunctionalTestResultsWithRetry({
@@ -221,7 +376,23 @@ export const runFunctionalTesting = async (options, config) => {
221
376
  };
222
377
  }
223
378
  };
224
- const createSystemPrompt = (_config) => {
379
+ const createSystemPrompt = (_config, mcpServerUrl, mcpToken, featureId) => {
380
+ let mcpInstructions = '';
381
+ if (mcpServerUrl && mcpToken && featureId) {
382
+ mcpInstructions = `
383
+
384
+ **MANDATORY Checklist Compliance**:
385
+ If you are provided with checklists in the context, you MUST satisfy ALL of them during your testing work. Checklists are mandatory requirements that define quality standards and cannot be ignored or skipped.
386
+
387
+ - Review each checklist carefully and ensure your testing addresses every requirement
388
+ - You MUST include ALL provided checklist item IDs in the "checklist_item_results" field of your JSON response (use the exact UUID from "ID:" field in items list)
389
+ - Set "is_passed": true for each checklist item you have completed successfully
390
+ - Provide appropriate "value" based on the item type (boolean: true/false, text: descriptive text, number: numeric value)
391
+ - If you cannot satisfy a checklist item requirement, set "is_passed": false and explain why in the "notes" field
392
+ - The system will validate that all checklist items have been addressed - missing items will cause the pipeline to fail
393
+
394
+ CRITICAL: Checklists are not optional suggestions - they are mandatory quality gates that must be satisfied.`;
395
+ }
225
396
  return `You are a professional QA automation engineer performing comprehensive functional testing using headless Playwright MCP.
226
397
 
227
398
  **Your Role**: Execute end-to-end functional tests for implemented features using headless browser automation.
@@ -269,32 +440,55 @@ You MUST end your response with a JSON object containing the test results in thi
269
440
 
270
441
  \`\`\`json
271
442
  {
272
- "status": "testing_passed" | "testing_failed",
273
- "title": "Descriptive test report title",
274
- "summary": "Brief summary of what was tested and results",
275
- "total_test_cases": number,
276
- "passed_test_cases": number,
277
- "failed_test_cases": number,
278
- "test_cases": [
279
- {
280
- "name": "Test case name",
281
- "status": "passed" | "failed" | "skipped",
282
- "description": "What this test validates",
283
- "error_message": "Error details if failed (optional)"
284
- }
285
- ],
286
- "execution_details": "Detailed execution log and findings",
287
- "timestamp": "ISO timestamp"
443
+ "test_result": {
444
+ "status": "testing_passed" | "testing_failed",
445
+ "title": "Descriptive test report title",
446
+ "summary": "Brief summary of what was tested and results",
447
+ "total_test_cases": number,
448
+ "passed_test_cases": number,
449
+ "failed_test_cases": number,
450
+ "test_cases": [
451
+ {
452
+ "name": "Test case name",
453
+ "status": "passed" | "failed" | "skipped",
454
+ "description": "What this test validates",
455
+ "error_message": "Error details if failed (optional)"
456
+ }
457
+ ],
458
+ "checklist_item_results": [
459
+ {
460
+ "checklist_item_id": "EXACT_CHECKLIST_ITEM_UUID_FROM_ID_FIELD",
461
+ "is_passed": true,
462
+ "value": "Result value based on item type (boolean, text, number, etc.)",
463
+ "notes": "Optional notes about this specific checklist item"
464
+ }
465
+ ],
466
+ "execution_details": "Detailed execution log and findings",
467
+ "timestamp": "ISO timestamp"
468
+ }
288
469
  }
289
470
  \`\`\`
290
471
 
291
- Focus on systematic testing based on the provided context information.`;
472
+ MANDATORY: If checklists are provided in the context, you MUST include checklist_item_results for ALL checklist items. 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.
473
+
474
+ IMPORTANT: In the checklist context, look for lines that say "ID: [UUID]" in the items list - use these exact UUIDs as checklist_item_id values. Do NOT use the item title or description as the checklist_item_id.
475
+
476
+ Focus on systematic testing based on the provided context information.${mcpInstructions}`;
292
477
  };
293
- const createTestingPromptWithContext = (featureId, context) => {
478
+ const createTestingPromptWithContext = (featureId, context, checklistContext, verbose) => {
294
479
  const contextInfo = formatContextForPrompt(context);
480
+ // Add checklist context to the testing prompt
481
+ let finalContextInfo = contextInfo;
482
+ if (checklistContext && checklistContext.checklists.length > 0) {
483
+ const checklistInfo = formatChecklistsForContext(checklistContext);
484
+ finalContextInfo = contextInfo + '\n\n' + checklistInfo;
485
+ if (verbose) {
486
+ logInfo(`Added ${checklistContext.checklists.length} checklists to testing context`);
487
+ }
488
+ }
295
489
  return `Please perform comprehensive functional testing for feature ID: ${featureId}
296
490
 
297
- ${contextInfo}
491
+ ${finalContextInfo}
298
492
 
299
493
  ## Testing Instructions
300
494
 
@@ -0,0 +1,16 @@
1
+ import type { FeatureInfo, UserStory, TestCase } from '../../types/features.js';
2
+ import { type ProductInfo } from '../../api/products.js';
3
+ export interface FunctionalTestingContext {
4
+ feature: FeatureInfo;
5
+ product: ProductInfo;
6
+ user_stories: UserStory[];
7
+ test_cases: TestCase[];
8
+ }
9
+ /**
10
+ * Fetch all functional testing context information via MCP endpoints
11
+ */
12
+ export declare function fetchFunctionalTestingContext(mcpServerUrl: string, mcpToken: string, featureId: string, verbose?: boolean): Promise<FunctionalTestingContext>;
13
+ /**
14
+ * Format the context into a readable string for Claude Code
15
+ */
16
+ export declare function formatContextForPrompt(context: FunctionalTestingContext): string;
@@ -0,0 +1,81 @@
1
+ import { logInfo, logError } from '../../utils/logger.js';
2
+ import { getFeature, getUserStories, getTestCases, } from '../../api/features/index.js';
3
+ import { getProduct } from '../../api/products.js';
4
+ /**
5
+ * Fetch all functional testing context information via MCP endpoints
6
+ */
7
+ export async function fetchFunctionalTestingContext(mcpServerUrl, mcpToken, featureId, verbose) {
8
+ try {
9
+ if (verbose) {
10
+ logInfo(`Fetching complete functional testing context for feature: ${featureId}`);
11
+ }
12
+ // Fetch all required data in parallel for better performance
13
+ const [feature, user_stories, test_cases] = await Promise.all([
14
+ getFeature(mcpServerUrl, mcpToken, featureId, verbose),
15
+ getUserStories(mcpServerUrl, mcpToken, featureId, verbose),
16
+ getTestCases(mcpServerUrl, mcpToken, featureId, verbose),
17
+ ]);
18
+ const product = await getProduct(mcpServerUrl, mcpToken, feature.product_id, verbose);
19
+ if (verbose) {
20
+ logInfo(`✅ Functional testing context fetched successfully:`);
21
+ logInfo(` Feature: ${feature.name}`);
22
+ logInfo(` Product: ${product.name}`);
23
+ logInfo(` User Stories: ${user_stories.length}`);
24
+ logInfo(` Test Cases: ${test_cases.length}`);
25
+ }
26
+ return {
27
+ feature,
28
+ product,
29
+ user_stories,
30
+ test_cases,
31
+ };
32
+ }
33
+ catch (error) {
34
+ const errorMessage = error instanceof Error ? error.message : String(error);
35
+ logError(`Failed to fetch functional testing context: ${errorMessage}`);
36
+ throw new Error(`Context fetch failed: ${errorMessage}`);
37
+ }
38
+ }
39
+ /**
40
+ * Format the context into a readable string for Claude Code
41
+ */
42
+ export function formatContextForPrompt(context) {
43
+ const formatUserStories = (stories) => {
44
+ if (stories.length === 0)
45
+ return 'No user stories defined.';
46
+ return stories
47
+ .map((story, index) => `${index + 1}. **${story.title}** (Status: ${story.status})
48
+ ${story.description}`)
49
+ .join('\n\n');
50
+ };
51
+ const formatTestCases = (cases) => {
52
+ if (cases.length === 0)
53
+ return 'No test cases defined.';
54
+ return cases
55
+ .map((testCase, index) => `${index + 1}. **${testCase.name}** ${testCase.is_critical ? '[CRITICAL]' : '[OPTIONAL]'}
56
+ ${testCase.description}`)
57
+ .join('\n\n');
58
+ };
59
+ return `# Functional Testing Context
60
+
61
+ ## Feature Information
62
+ - **ID**: ${context.feature.id}
63
+ - **Name**: ${context.feature.name}
64
+ - **Description**: ${context.feature.description || 'No description provided'}
65
+ - **Current Status**: ${context.feature.status}
66
+
67
+ ## Product Information
68
+ - **Product**: ${context.product.name}
69
+ - **Product ID**: ${context.product.id}
70
+ - **Description**: ${context.product.description || 'No product description'}
71
+
72
+ ## User Stories to Test (${context.user_stories.length})
73
+ ${formatUserStories(context.user_stories)}
74
+
75
+ ## Test Cases to Execute (${context.test_cases.length})
76
+ ${formatTestCases(context.test_cases)}
77
+
78
+ ---
79
+
80
+ **Testing Instructions**: The feature has been implemented. Execute comprehensive functional testing using headless Playwright to verify all user stories work correctly and all test cases pass. Test both positive and negative scenarios.`;
81
+ }
@@ -1,4 +1,4 @@
1
- import { logInfo, logError } from '../logger.js';
1
+ import { logInfo, logError } from '../../utils/logger.js';
2
2
  export async function saveFunctionalTestResultsViaHttp(options) {
3
3
  const { mcpServerUrl, mcpToken, featureId, testStatus, testResults: _testResults, verbose, } = options;
4
4
  try {
@@ -1,4 +1,4 @@
1
1
  export { runFunctionalTesting, checkFunctionalTestingRequirements, type FunctionalTestingOptions, type FunctionalTestingResult, } from './analyzer.js';
2
2
  export { createFunctionalTestingMcpServer } from './mcp-server.js';
3
3
  export { saveFunctionalTestResultsViaHttp, verifyTestStatusSaved, saveFunctionalTestResultsWithRetry, } from './http-fallback.js';
4
- export { fetchFeatureTestingContext, updateFeatureTestStatus, formatContextForPrompt, type FeatureTestingContext, } from './context-fetcher.js';
4
+ export { fetchFunctionalTestingContext, formatContextForPrompt, type FunctionalTestingContext, } from './context-fetcher.js';
@@ -1,4 +1,4 @@
1
1
  export { runFunctionalTesting, checkFunctionalTestingRequirements, } from './analyzer.js';
2
2
  export { createFunctionalTestingMcpServer } from './mcp-server.js';
3
3
  export { saveFunctionalTestResultsViaHttp, verifyTestStatusSaved, saveFunctionalTestResultsWithRetry, } from './http-fallback.js';
4
- export { fetchFeatureTestingContext, updateFeatureTestStatus, formatContextForPrompt, } from './context-fetcher.js';
4
+ export { fetchFunctionalTestingContext, formatContextForPrompt, } from './context-fetcher.js';
@@ -1,35 +1,6 @@
1
1
  import { createSdkMcpServer, tool } from '@anthropic-ai/claude-code';
2
2
  import { z } from 'zod';
3
- // Helper function to make HTTP requests to the MCP server
4
- async function callMcpEndpoint(mcpServerUrl, mcpToken, method, params) {
5
- try {
6
- const response = await fetch(`${mcpServerUrl}/mcp`, {
7
- method: 'POST',
8
- headers: {
9
- 'Content-Type': 'application/json',
10
- Authorization: `Bearer ${mcpToken}`,
11
- },
12
- body: JSON.stringify({
13
- jsonrpc: '2.0',
14
- method,
15
- params,
16
- id: Math.random().toString(36).substring(7),
17
- }),
18
- });
19
- if (!response.ok) {
20
- throw new Error(`HTTP ${response.status}: ${response.statusText}`);
21
- }
22
- const data = await response.json();
23
- if (data.error) {
24
- throw new Error(data.error.message || 'MCP call failed');
25
- }
26
- return data.result;
27
- }
28
- catch (error) {
29
- console.error(`MCP call failed for ${method}:`, error instanceof Error ? error.message : String(error));
30
- throw error;
31
- }
32
- }
3
+ import { callMcpEndpoint } from '../../api/mcp-client.js';
33
4
  // Create an SDK MCP server with custom tools for functional testing
34
5
  export const createFunctionalTestingMcpServer = (mcpServerUrl, mcpToken) => {
35
6
  return createSdkMcpServer({
@@ -31,16 +31,42 @@ export interface TestReportCreateOptions {
31
31
  mcpToken: string;
32
32
  featureId: string;
33
33
  testReportData: TestReportData;
34
+ testResults?: TestResultInput[];
34
35
  verbose?: boolean;
35
36
  }
37
+ export interface TestResultInput {
38
+ test_case_id: string;
39
+ result: 'passed' | 'failed' | 'skipped';
40
+ notes?: string;
41
+ }
36
42
  export interface TestReportResult {
37
43
  success: boolean;
38
44
  testReport?: TestReport;
39
45
  testReportUrl?: string;
40
46
  error?: string;
41
47
  }
48
+ export interface TestReportResultsOptions {
49
+ mcpServerUrl: string;
50
+ mcpToken: string;
51
+ testReportId: string;
52
+ testResults: TestResultInput[];
53
+ verbose?: boolean;
54
+ }
55
+ export interface TestReportResultsResponse {
56
+ success: boolean;
57
+ resultsCreated?: number;
58
+ error?: string;
59
+ }
42
60
  /**
43
61
  * Create a test report via MCP endpoint
44
62
  * Uses structured data generated by Claude Code
45
63
  */
46
64
  export declare function createTestReport(options: TestReportCreateOptions): Promise<TestReportResult>;
65
+ /**
66
+ * Manual fallback: Call MCP endpoint with structured data
67
+ * This is used when Claude Code fails to call MCP directly
68
+ */
69
+ /**
70
+ * Create test report results via MCP endpoint
71
+ */
72
+ export declare function createTestReportResults(options: TestReportResultsOptions): Promise<TestReportResultsResponse>;