edsger 0.41.1 → 0.41.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 (103) hide show
  1. package/.claude/settings.local.json +23 -3
  2. package/.env.local +12 -0
  3. package/dist/api/features/__tests__/regression-prevention.test.d.ts +5 -0
  4. package/dist/api/features/__tests__/regression-prevention.test.js +338 -0
  5. package/dist/api/features/__tests__/status-updater.integration.test.d.ts +5 -0
  6. package/dist/api/features/__tests__/status-updater.integration.test.js +497 -0
  7. package/dist/commands/workflow/pipeline-runner.d.ts +17 -0
  8. package/dist/commands/workflow/pipeline-runner.js +393 -0
  9. package/dist/commands/workflow/runner.d.ts +26 -0
  10. package/dist/commands/workflow/runner.js +119 -0
  11. package/dist/commands/workflow/workflow-runner.d.ts +26 -0
  12. package/dist/commands/workflow/workflow-runner.js +119 -0
  13. package/dist/index.js +0 -0
  14. package/dist/phases/code-implementation/analyzer-helpers.d.ts +28 -0
  15. package/dist/phases/code-implementation/analyzer-helpers.js +177 -0
  16. package/dist/phases/code-implementation/analyzer.d.ts +32 -0
  17. package/dist/phases/code-implementation/analyzer.js +629 -0
  18. package/dist/phases/code-implementation/context-fetcher.d.ts +17 -0
  19. package/dist/phases/code-implementation/context-fetcher.js +86 -0
  20. package/dist/phases/code-implementation/mcp-server.d.ts +1 -0
  21. package/dist/phases/code-implementation/mcp-server.js +93 -0
  22. package/dist/phases/code-implementation/prompts-improvement.d.ts +5 -0
  23. package/dist/phases/code-implementation/prompts-improvement.js +108 -0
  24. package/dist/phases/code-implementation-verification/verifier.d.ts +31 -0
  25. package/dist/phases/code-implementation-verification/verifier.js +196 -0
  26. package/dist/phases/code-refine/analyzer.d.ts +41 -0
  27. package/dist/phases/code-refine/analyzer.js +561 -0
  28. package/dist/phases/code-refine/context-fetcher.d.ts +94 -0
  29. package/dist/phases/code-refine/context-fetcher.js +423 -0
  30. package/dist/phases/code-refine-verification/analysis/llm-analyzer.d.ts +22 -0
  31. package/dist/phases/code-refine-verification/analysis/llm-analyzer.js +134 -0
  32. package/dist/phases/code-refine-verification/verifier.d.ts +47 -0
  33. package/dist/phases/code-refine-verification/verifier.js +597 -0
  34. package/dist/phases/code-review/analyzer.d.ts +29 -0
  35. package/dist/phases/code-review/analyzer.js +363 -0
  36. package/dist/phases/code-review/context-fetcher.d.ts +92 -0
  37. package/dist/phases/code-review/context-fetcher.js +296 -0
  38. package/dist/phases/feature-analysis/analyzer-helpers.d.ts +10 -0
  39. package/dist/phases/feature-analysis/analyzer-helpers.js +47 -0
  40. package/dist/phases/feature-analysis/analyzer.d.ts +11 -0
  41. package/dist/phases/feature-analysis/analyzer.js +208 -0
  42. package/dist/phases/feature-analysis/context-fetcher.d.ts +26 -0
  43. package/dist/phases/feature-analysis/context-fetcher.js +134 -0
  44. package/dist/phases/feature-analysis/http-fallback.d.ts +20 -0
  45. package/dist/phases/feature-analysis/http-fallback.js +95 -0
  46. package/dist/phases/feature-analysis/mcp-server.d.ts +1 -0
  47. package/dist/phases/feature-analysis/mcp-server.js +144 -0
  48. package/dist/phases/feature-analysis/prompts-improvement.d.ts +8 -0
  49. package/dist/phases/feature-analysis/prompts-improvement.js +109 -0
  50. package/dist/phases/feature-analysis-verification/verifier.d.ts +37 -0
  51. package/dist/phases/feature-analysis-verification/verifier.js +147 -0
  52. package/dist/phases/pr-execution/file-assigner.js +20 -12
  53. package/dist/phases/technical-design/analyzer-helpers.d.ts +25 -0
  54. package/dist/phases/technical-design/analyzer-helpers.js +39 -0
  55. package/dist/phases/technical-design/analyzer.d.ts +21 -0
  56. package/dist/phases/technical-design/analyzer.js +461 -0
  57. package/dist/phases/technical-design/context-fetcher.d.ts +12 -0
  58. package/dist/phases/technical-design/context-fetcher.js +39 -0
  59. package/dist/phases/technical-design/http-fallback.d.ts +17 -0
  60. package/dist/phases/technical-design/http-fallback.js +151 -0
  61. package/dist/phases/technical-design/mcp-server.d.ts +1 -0
  62. package/dist/phases/technical-design/mcp-server.js +157 -0
  63. package/dist/phases/technical-design/prompts-improvement.d.ts +5 -0
  64. package/dist/phases/technical-design/prompts-improvement.js +93 -0
  65. package/dist/phases/technical-design-verification/verifier.d.ts +53 -0
  66. package/dist/phases/technical-design-verification/verifier.js +170 -0
  67. package/dist/services/feature-branches.d.ts +77 -0
  68. package/dist/services/feature-branches.js +205 -0
  69. package/dist/workflow-runner/config/phase-configs.d.ts +5 -0
  70. package/dist/workflow-runner/config/phase-configs.js +120 -0
  71. package/dist/workflow-runner/core/feature-filter.d.ts +16 -0
  72. package/dist/workflow-runner/core/feature-filter.js +46 -0
  73. package/dist/workflow-runner/core/index.d.ts +8 -0
  74. package/dist/workflow-runner/core/index.js +12 -0
  75. package/dist/workflow-runner/core/pipeline-evaluator.d.ts +24 -0
  76. package/dist/workflow-runner/core/pipeline-evaluator.js +32 -0
  77. package/dist/workflow-runner/core/state-manager.d.ts +24 -0
  78. package/dist/workflow-runner/core/state-manager.js +42 -0
  79. package/dist/workflow-runner/core/workflow-logger.d.ts +20 -0
  80. package/dist/workflow-runner/core/workflow-logger.js +65 -0
  81. package/dist/workflow-runner/executors/phase-executor.d.ts +8 -0
  82. package/dist/workflow-runner/executors/phase-executor.js +248 -0
  83. package/dist/workflow-runner/feature-workflow-runner.d.ts +26 -0
  84. package/dist/workflow-runner/feature-workflow-runner.js +119 -0
  85. package/dist/workflow-runner/index.d.ts +2 -0
  86. package/dist/workflow-runner/index.js +2 -0
  87. package/dist/workflow-runner/pipeline-runner.d.ts +17 -0
  88. package/dist/workflow-runner/pipeline-runner.js +393 -0
  89. package/dist/workflow-runner/workflow-processor.d.ts +54 -0
  90. package/dist/workflow-runner/workflow-processor.js +170 -0
  91. package/package.json +1 -1
  92. package/dist/services/lifecycle-agent/__tests__/phase-criteria.test.d.ts +0 -4
  93. package/dist/services/lifecycle-agent/__tests__/phase-criteria.test.js +0 -133
  94. package/dist/services/lifecycle-agent/__tests__/transition-rules.test.d.ts +0 -4
  95. package/dist/services/lifecycle-agent/__tests__/transition-rules.test.js +0 -336
  96. package/dist/services/lifecycle-agent/index.d.ts +0 -24
  97. package/dist/services/lifecycle-agent/index.js +0 -25
  98. package/dist/services/lifecycle-agent/phase-criteria.d.ts +0 -57
  99. package/dist/services/lifecycle-agent/phase-criteria.js +0 -335
  100. package/dist/services/lifecycle-agent/transition-rules.d.ts +0 -60
  101. package/dist/services/lifecycle-agent/transition-rules.js +0 -184
  102. package/dist/services/lifecycle-agent/types.d.ts +0 -190
  103. package/dist/services/lifecycle-agent/types.js +0 -12
@@ -0,0 +1,629 @@
1
+ import { query } from '@anthropic-ai/claude-code';
2
+ import { logInfo, logError } from '../../utils/logger.js';
3
+ import { formatChecklistsForContext, } from '../../services/checklist.js';
4
+ import { getFeedbacksForPhase, formatFeedbacksForContext, } from '../../services/feedbacks.js';
5
+ import { fetchCodeImplementationContext, formatContextForPrompt, } from './context-fetcher.js';
6
+ import { logFeaturePhaseEvent } from '../../services/audit-logs.js';
7
+ import { performVerificationCycle, buildImplementationResult, buildVerificationFailureResult, buildNoResultsError, } from './analyzer-helpers.js';
8
+ function userMessage(content) {
9
+ return {
10
+ type: 'user',
11
+ message: { role: 'user', content: content },
12
+ };
13
+ }
14
+ async function* prompt(implementationPrompt) {
15
+ yield userMessage(implementationPrompt);
16
+ await new Promise((res) => setTimeout(res, 10000));
17
+ }
18
+ export const implementFeatureCode = async (options, config, checklistContext) => {
19
+ const { featureId, verbose, baseBranch = 'main' } = options;
20
+ if (verbose) {
21
+ logInfo(`Starting code implementation for feature ID: ${featureId}`);
22
+ logInfo(`Base branch: ${baseBranch}`);
23
+ }
24
+ try {
25
+ // Fetch all required context information via MCP endpoints
26
+ if (verbose) {
27
+ logInfo('Fetching code implementation context via MCP endpoints...');
28
+ }
29
+ const context = await fetchCodeImplementationContext(featureId, verbose);
30
+ // Fetch feedbacks for code implementation phase
31
+ let feedbacksInfo;
32
+ try {
33
+ const feedbacksContext = await getFeedbacksForPhase({ featureId, verbose }, 'code_implementation');
34
+ if (feedbacksContext.feedbacks.length > 0) {
35
+ feedbacksInfo = formatFeedbacksForContext(feedbacksContext);
36
+ if (verbose) {
37
+ logInfo(`Added ${feedbacksContext.feedbacks.length} human feedbacks to implementation context`);
38
+ }
39
+ }
40
+ }
41
+ catch (error) {
42
+ // Don't fail if feedbacks fetch fails - just log and continue
43
+ if (verbose) {
44
+ logInfo(`Note: Could not fetch feedbacks (${error instanceof Error ? error.message : String(error)})`);
45
+ }
46
+ }
47
+ const systemPrompt = createSystemPrompt(config, baseBranch, featureId);
48
+ const initialImplementationPrompt = createImplementationPromptWithContext(featureId, context, baseBranch, checklistContext, verbose, feedbacksInfo);
49
+ const maxIterations = options.maxVerificationIterations || 10;
50
+ let currentIteration = 0;
51
+ let currentPrompt = initialImplementationPrompt;
52
+ let structuredImplementationResult = null;
53
+ let verificationResult = null;
54
+ const branchName = `dev/${featureId}`;
55
+ if (verbose) {
56
+ logInfo('Starting Claude Code query with pre-fetched information...');
57
+ }
58
+ // Iterative improvement loop: implement → verify → improve → re-implement
59
+ while (currentIteration < maxIterations) {
60
+ currentIteration++;
61
+ if (verbose && currentIteration > 1) {
62
+ logInfo(`\n🔄 Iteration ${currentIteration}/${maxIterations}: Improving implementation based on code review feedback...`);
63
+ }
64
+ // Log iteration start (for iterations after the first)
65
+ if (currentIteration > 1) {
66
+ await logFeaturePhaseEvent({
67
+ featureId,
68
+ eventType: 'phase_started',
69
+ phase: 'code_implementation',
70
+ result: 'info',
71
+ metadata: {
72
+ iteration: currentIteration,
73
+ max_iterations: maxIterations,
74
+ re_implementation: true,
75
+ timestamp: new Date().toISOString(),
76
+ },
77
+ }, verbose);
78
+ }
79
+ let lastAssistantResponse = '';
80
+ let newImplementationResult = null;
81
+ // DEBUG: Log checklist context before query
82
+ console.log('=== DEBUG: Checklist Context Before Claude Query ===');
83
+ console.log('Has checklistContext:', !!checklistContext);
84
+ if (checklistContext) {
85
+ console.log('Number of checklists:', checklistContext.checklists.length);
86
+ const totalItems = checklistContext.checklists.reduce((sum, checklist) => sum + (checklist.items?.length || 0), 0);
87
+ console.log('Total checklist items:', totalItems);
88
+ }
89
+ console.log('Implementation prompt includes checklist:', currentPrompt.includes('checklist'));
90
+ console.log('System prompt includes checklist:', systemPrompt.includes('checklist'));
91
+ // Execute implementation query
92
+ for await (const message of query({
93
+ prompt: prompt(currentPrompt),
94
+ options: {
95
+ appendSystemPrompt: systemPrompt,
96
+ model: config.claude.model || 'sonnet',
97
+ maxTurns: 3000,
98
+ permissionMode: 'bypassPermissions',
99
+ },
100
+ })) {
101
+ if (verbose) {
102
+ logInfo(`Received message type: ${message.type}`);
103
+ }
104
+ // Stream the implementation process
105
+ if (message.type === 'assistant' && message.message?.content) {
106
+ for (const content of message.message.content) {
107
+ if (content.type === 'text') {
108
+ lastAssistantResponse += content.text + '\n';
109
+ if (verbose) {
110
+ console.log(`\n🤖 ${content.text}`);
111
+ }
112
+ }
113
+ else if (content.type === 'tool_use') {
114
+ if (verbose) {
115
+ console.log(`\n🔧 ${content.name}: ${content.input.description || 'Running...'}`);
116
+ }
117
+ }
118
+ }
119
+ }
120
+ if (message.type === 'result') {
121
+ if (message.subtype === 'success') {
122
+ logInfo('\n💻 Code implementation completed, parsing results...');
123
+ try {
124
+ // Try to extract JSON from markdown code block or parse directly
125
+ const responseText = message.result || lastAssistantResponse;
126
+ let jsonResult = null;
127
+ // DEBUG: Log response text details and checklist content
128
+ console.log('=== DEBUG: Code Implementation Response Analysis ===');
129
+ console.log('message.result exists:', !!message.result);
130
+ console.log('lastAssistantResponse exists:', !!lastAssistantResponse);
131
+ console.log('responseText length:', responseText.length);
132
+ console.log('responseText first 200 chars:', JSON.stringify(responseText.substring(0, 200)));
133
+ console.log('responseText last 200 chars:', JSON.stringify(responseText.substring(responseText.length - 200)));
134
+ console.log('Contains ```json:', responseText.includes('```json'));
135
+ console.log('Contains implementation_result:', responseText.includes('"implementation_result"'));
136
+ console.log('=== DEBUG: Checklist Content in Response ===');
137
+ console.log('Contains "checklist":', responseText.toLowerCase().includes('checklist'));
138
+ console.log('Contains "checklist_item_results":', responseText.includes('checklist_item_results'));
139
+ console.log('Contains checklist_item_id:', responseText.includes('checklist_item_id'));
140
+ console.log('Contains is_passed:', responseText.includes('is_passed'));
141
+ // Count checklist-related occurrences
142
+ const checklistMatches = responseText.match(/checklist/gi) || [];
143
+ const checklistItemMatches = responseText.match(/checklist_item/gi) || [];
144
+ console.log('Total "checklist" mentions:', checklistMatches.length);
145
+ console.log('Total "checklist_item" mentions:', checklistItemMatches.length);
146
+ // First try to extract JSON from markdown code block
147
+ const jsonBlockMatch = responseText.match(/```json\s*\n([\s\S]*?)\n\s*```/);
148
+ console.log('=== DEBUG: Markdown Block Match ===');
149
+ console.log('jsonBlockMatch found:', !!jsonBlockMatch);
150
+ if (jsonBlockMatch) {
151
+ console.log('Matched JSON length:', jsonBlockMatch[1].length);
152
+ console.log('Matched JSON first 100 chars:', JSON.stringify(jsonBlockMatch[1].substring(0, 100)));
153
+ jsonResult = JSON.parse(jsonBlockMatch[1]);
154
+ }
155
+ else {
156
+ console.log('=== DEBUG: Trying direct JSON parse ===');
157
+ // Try to parse the entire response as JSON
158
+ jsonResult = JSON.parse(responseText);
159
+ }
160
+ console.log('=== DEBUG: Final Result Processing ===');
161
+ console.log('jsonResult exists:', !!jsonResult);
162
+ console.log('jsonResult has implementation_result:', !!(jsonResult && jsonResult.implementation_result));
163
+ if (jsonResult && jsonResult.implementation_result) {
164
+ const implResult = jsonResult.implementation_result;
165
+ console.log('=== DEBUG: Implementation Result Structure ===');
166
+ console.log('Keys in implementation_result:', Object.keys(implResult));
167
+ console.log('Has checklist_item_results field:', 'checklist_item_results' in implResult);
168
+ console.log('checklist_item_results value type:', typeof implResult.checklist_item_results);
169
+ console.log('checklist_item_results is array:', Array.isArray(implResult.checklist_item_results));
170
+ if (implResult.checklist_item_results) {
171
+ console.log('checklist_item_results length:', implResult.checklist_item_results.length);
172
+ if (implResult.checklist_item_results.length > 0) {
173
+ console.log('First checklist item keys:', Object.keys(implResult.checklist_item_results[0]));
174
+ console.log('First checklist item sample:', JSON.stringify(implResult.checklist_item_results[0], null, 2));
175
+ }
176
+ }
177
+ else {
178
+ console.log('checklist_item_results is null/undefined/empty');
179
+ }
180
+ newImplementationResult = jsonResult.implementation_result;
181
+ console.log('Successfully extracted implementation_result');
182
+ }
183
+ else {
184
+ console.log('ERROR: Invalid JSON structure - missing implementation_result');
185
+ throw new Error('Invalid JSON structure');
186
+ }
187
+ }
188
+ catch (error) {
189
+ console.log('=== DEBUG: JSON Parsing Failed ===');
190
+ console.log('Error type:', error instanceof SyntaxError
191
+ ? 'SyntaxError'
192
+ : error instanceof Error
193
+ ? error.constructor.name
194
+ : 'Unknown');
195
+ console.log('Error message:', error instanceof Error ? error.message : String(error));
196
+ logError(`Failed to parse structured implementation result: ${error}`);
197
+ console.log('=== DEBUG: Using Fallback Parsing ===');
198
+ // Fallback parsing
199
+ const parsedResult = parseImplementationResponse(message.result || lastAssistantResponse, featureId);
200
+ console.log('Fallback parsed result:', {
201
+ branchName: parsedResult.branchName,
202
+ filesModifiedCount: parsedResult.filesModified?.length || 0,
203
+ hasSummary: !!parsedResult.summary,
204
+ commitHash: parsedResult.commitHash,
205
+ });
206
+ newImplementationResult = {
207
+ branch_name: parsedResult.branchName,
208
+ files_modified: parsedResult.filesModified,
209
+ commit_hash: parsedResult.commitHash,
210
+ summary: parsedResult.summary || 'Implementation completed',
211
+ tests_passed: true,
212
+ pre_commit_passed: true,
213
+ checklist_item_results: parsedResult.checklist_item_results || [],
214
+ };
215
+ }
216
+ }
217
+ else {
218
+ logError(`\n⚠️ Code implementation incomplete: ${message.subtype}`);
219
+ if (message.subtype === 'error_max_turns') {
220
+ logError('💡 Try breaking down the feature into smaller tasks');
221
+ }
222
+ // Try to parse results from the last assistant response
223
+ if (lastAssistantResponse) {
224
+ console.log('=== DEBUG: Fallback for incomplete result ===');
225
+ console.log('message.subtype:', message.subtype);
226
+ try {
227
+ const responseText = lastAssistantResponse;
228
+ let jsonResult = null;
229
+ console.log('lastAssistantResponse length:', responseText.length);
230
+ console.log('lastAssistantResponse first 200 chars:', JSON.stringify(responseText.substring(0, 200)));
231
+ const jsonBlockMatch = responseText.match(/```json\s*\n([\s\S]*?)\n\s*```/);
232
+ console.log('jsonBlockMatch in fallback found:', !!jsonBlockMatch);
233
+ if (jsonBlockMatch) {
234
+ jsonResult = JSON.parse(jsonBlockMatch[1]);
235
+ if (jsonResult && jsonResult.implementation_result) {
236
+ newImplementationResult = jsonResult.implementation_result;
237
+ }
238
+ }
239
+ }
240
+ catch (error) {
241
+ logError(`Failed to parse assistant response: ${error}`);
242
+ }
243
+ }
244
+ }
245
+ }
246
+ }
247
+ // Check if implementation produced results
248
+ if (!newImplementationResult) {
249
+ if (verbose) {
250
+ logError('⚠️ Implementation failed in this iteration');
251
+ }
252
+ break;
253
+ }
254
+ // Update with new implementation result
255
+ structuredImplementationResult = newImplementationResult;
256
+ // Log implementation completion for this iteration
257
+ await logFeaturePhaseEvent({
258
+ featureId,
259
+ eventType: 'phase_completed',
260
+ phase: 'code_implementation',
261
+ result: 'success',
262
+ metadata: {
263
+ iteration: currentIteration,
264
+ max_iterations: maxIterations,
265
+ implementation_step: 'completed',
266
+ branch_name: structuredImplementationResult.branch_name,
267
+ files_modified: structuredImplementationResult.files_modified || [],
268
+ commit_hash: structuredImplementationResult.commit_hash || '',
269
+ timestamp: new Date().toISOString(),
270
+ },
271
+ }, verbose);
272
+ // Push code to remote after commit
273
+ if (verbose) {
274
+ logInfo(`📤 Pushing code to remote repository...`);
275
+ }
276
+ const pushResult = await pushToRemote(structuredImplementationResult.branch_name || branchName, verbose);
277
+ if (!pushResult.success && verbose) {
278
+ logError(`⚠️ Failed to push to remote: ${pushResult.error}`);
279
+ logInfo(' Code is committed locally and will be reviewed. Manual push may be needed.');
280
+ }
281
+ else if (verbose) {
282
+ logInfo('✅ Code pushed to remote successfully');
283
+ }
284
+ // Perform verification cycle
285
+ const verificationCycle = await performVerificationCycle(structuredImplementationResult.branch_name || branchName, baseBranch, checklistContext || null, featureId, context.feature.name, context.feature.description, config, currentIteration, maxIterations, verbose);
286
+ verificationResult = verificationCycle.verificationResult;
287
+ // If verification passed, exit
288
+ if (verificationCycle.passed) {
289
+ if (verbose) {
290
+ logInfo('✅ Verification passed! Code implementation complete.');
291
+ }
292
+ break;
293
+ }
294
+ // Verification failed
295
+ if (currentIteration < maxIterations && verificationCycle.nextPrompt) {
296
+ // We have more iterations - retry with improvement prompt
297
+ if (verbose) {
298
+ logInfo(`🔄 Will improve implementation in next iteration (${maxIterations - currentIteration} attempts remaining)`);
299
+ }
300
+ currentPrompt = verificationCycle.nextPrompt;
301
+ }
302
+ else {
303
+ // Max iterations reached or no next prompt - exit loop
304
+ if (verbose) {
305
+ logInfo('⚠️ Max iterations reached. Last implementation committed.');
306
+ }
307
+ break;
308
+ }
309
+ }
310
+ // Handle results
311
+ if (!structuredImplementationResult) {
312
+ return buildNoResultsError(featureId, branchName);
313
+ }
314
+ const { branch_name, files_modified, commit_hash, summary, checklist_results, checklist_item_results, } = structuredImplementationResult;
315
+ // Check if verification failed after all iterations
316
+ if (verificationResult &&
317
+ verificationResult.rejected_count > 0 &&
318
+ checklistContext &&
319
+ checklistContext.checklists.length > 0) {
320
+ logError(`❌ Final result: Code verification FAILED after ${currentIteration} iterations`);
321
+ logError(` Code committed for manual review`);
322
+ return buildVerificationFailureResult(featureId, branch_name || branchName, summary || 'Implementation completed with verification failures', files_modified || [], commit_hash || '', verificationResult, currentIteration);
323
+ }
324
+ // Return success result
325
+ return buildImplementationResult(featureId, branch_name || branchName, summary || 'Implementation completed successfully', files_modified || [], commit_hash || '', currentIteration, checklist_results, checklist_item_results);
326
+ }
327
+ catch (error) {
328
+ logError(`Code implementation failed: ${error instanceof Error ? error.message : String(error)}`);
329
+ return {
330
+ featureId,
331
+ branchName: `dev/${featureId}`,
332
+ implementationSummary: null,
333
+ status: 'error',
334
+ message: `Implementation failed: ${error instanceof Error ? error.message : String(error)}`,
335
+ };
336
+ }
337
+ };
338
+ const createSystemPrompt = (_config, baseBranch, mcpServerUrl, mcpToken, featureId) => {
339
+ let mcpInstructions = '';
340
+ if (mcpServerUrl && mcpToken && featureId) {
341
+ mcpInstructions = `
342
+
343
+ **MANDATORY Checklist Compliance**:
344
+ If you are provided with checklists in the context, you MUST satisfy ALL of them during your implementation work. Checklists are mandatory requirements that define quality standards and cannot be ignored or skipped.
345
+
346
+ - Review each checklist carefully and ensure your implementation addresses every requirement
347
+ - You MUST include ALL provided checklist item IDs in the "checklist_item_results" field of your JSON response
348
+ - CRITICAL: Use the exact UUID from the "ID:" field in each checklist ITEM, NOT the item title or description
349
+ - Set "is_passed": true for each checklist item you have completed successfully
350
+ - Provide appropriate "value" based on the item type (boolean: true/false, text: descriptive text, number: numeric value)
351
+ - If you cannot satisfy a checklist item requirement, set "is_passed": false and explain why in the "notes" field
352
+ - The system will validate that all checklists have been addressed - missing checklists will cause the pipeline to fail
353
+
354
+ CRITICAL: Checklists are not optional suggestions - they are mandatory quality gates that must be satisfied.`;
355
+ }
356
+ return `You are an expert full-stack developer implementing features based on specifications. Your task is to implement complete, production-ready code based on feature requirements, user stories, test cases, and technical design.
357
+
358
+ **Your Role**: Implement complete, working features based on provided specifications and requirements.
359
+
360
+ **Available Tools**:
361
+ - Bash: Git operations, running commands, tests, and builds
362
+ - Glob: Find files and understand project structure
363
+ - Read: Examine existing code, configuration, and documentation files
364
+ - Edit: Modify existing files
365
+ - Write: Create new files
366
+ - TodoWrite: Track implementation tasks (use proactively)${mcpInstructions}
367
+
368
+ **CRITICAL WORKFLOW - YOU MUST FOLLOW THESE STEPS IN ORDER**:
369
+
370
+ 1. **GIT PULL REBASE**: First, ensure main branch is up to date with remote:
371
+ - git checkout ${baseBranch}
372
+ - git pull origin ${baseBranch} --rebase
373
+ 2. **CREATE BRANCH**: Create a new feature branch from ${baseBranch}
374
+ 3. **ANALYZE CODEBASE**: Use Glob and Read to understand the existing code structure
375
+ 4. **IMPLEMENT CODE**: Write the actual implementation using Edit/Write tools
376
+ 5. **FIX ISSUES**: Address any lint or build failures
377
+ 6. **COMMIT**: Commit your changes with a descriptive message
378
+ 7. **HANDLE PRE-COMMIT**: This project has strict pre-commit hooks - handle them properly:
379
+ - If lint-staged fails: Fix formatting and linting issues, then retry commit
380
+ - If AI code review fails: Either fix code quality issues or use SKIP_REVIEW=1
381
+ - If other issues persist: Only use --no-verify as last resort after confirming code quality
382
+
383
+ **Important Rules**:
384
+ 1. **Git Workflow**:
385
+ - ALWAYS pull latest changes from main before creating branch: git pull origin ${baseBranch} --rebase
386
+ - ALWAYS create a new branch before making changes: git checkout -b dev/<feature-id>
387
+ - Use descriptive commit messages that explain what and why
388
+ - Handle pre-commit checks properly: fix issues first, use workarounds only when necessary
389
+
390
+ 2. **Code Quality**:
391
+ - Follow existing code patterns and conventions in the repository
392
+ - Ensure proper TypeScript types and interfaces
393
+ - Add appropriate error handling and validation
394
+ - Write clean, maintainable code with proper comments where necessary
395
+
396
+ 3. **Pre-commit Handling**:
397
+ - This project has strict pre-commit hooks including lint-staged, linting, and AI code review
398
+ - When pre-commit hooks fail, READ the error messages carefully
399
+ - Fix ALL issues reported (lint errors, type errors, formatting, code quality)
400
+ - Re-run the commit after fixing issues
401
+ - If you encounter persistent issues with AI code review or non-critical pre-commit failures:
402
+ * First attempt to fix the actual issues
403
+ * Only use --no-verify as a last resort if you are 100% confident your code is correct
404
+ * When using --no-verify, add a comment explaining why it was necessary
405
+ - IMPORTANT: AI code review can be skipped with SKIP_REVIEW=1 environment variable if needed
406
+
407
+ 5. **File Modification**:
408
+ - Prefer modifying existing files over creating new ones
409
+ - Follow the existing file structure and naming conventions
410
+ - Use the appropriate tools (Edit for existing files, Write for new files)
411
+
412
+ **CRITICAL - Result Format**:
413
+ You MUST end your response with a JSON object containing the implementation results in this EXACT format:
414
+
415
+ \`\`\`json
416
+ {
417
+ "implementation_result": {
418
+ "feature_id": "FEATURE_ID_PLACEHOLDER",
419
+ "branch_name": "dev/FEATURE_ID",
420
+ "files_modified": ["file1.ts", "file2.tsx"],
421
+ "commit_hash": "abc123...",
422
+ "summary": "Brief description of what was implemented",
423
+ "tests_passed": true,
424
+ "pre_commit_passed": true,
425
+ "checklist_item_results": [
426
+ {
427
+ "checklist_item_id": "EXACT_CHECKLIST_ITEM_UUID_FROM_ID_FIELD",
428
+ "is_passed": true,
429
+ "value": "Result value based on item type (boolean, text, number, etc.)",
430
+ "notes": "Optional notes about this specific checklist item"
431
+ }
432
+ ]
433
+ }
434
+ }
435
+ \`\`\`
436
+
437
+ 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.
438
+
439
+ 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.
440
+
441
+ Remember: Quality over speed. It's better to implement correctly than to rush and create bugs.`;
442
+ };
443
+ const createImplementationPromptWithContext = (featureId, context, baseBranch, checklistContext, verbose, feedbacksInfo) => {
444
+ const contextInfo = formatContextForPrompt(context);
445
+ let finalContextInfo = contextInfo;
446
+ // Add feedbacks context to the implementation prompt
447
+ if (feedbacksInfo) {
448
+ finalContextInfo = finalContextInfo + '\n\n' + feedbacksInfo;
449
+ }
450
+ // Add checklist context to the implementation prompt
451
+ let checklistInstructions = '';
452
+ if (checklistContext && checklistContext.checklists.length > 0) {
453
+ const checklistInfo = formatChecklistsForContext(checklistContext);
454
+ finalContextInfo = finalContextInfo + '\n\n' + checklistInfo;
455
+ // DEBUG: Log checklist context details
456
+ console.log('=== DEBUG: Checklist Context for Code Implementation ===');
457
+ console.log('Number of checklists:', checklistContext.checklists.length);
458
+ console.log('Checklist info length:', checklistInfo.length);
459
+ console.log('Checklist info preview:', checklistInfo.substring(0, 300));
460
+ checklistContext.checklists.forEach((checklist, index) => {
461
+ console.log(`Checklist ${index + 1}:`, {
462
+ id: checklist.id,
463
+ name: checklist.name,
464
+ phase: checklist.phase,
465
+ role: checklist.role,
466
+ itemCount: checklist.items?.length || 0,
467
+ });
468
+ if (checklist.items) {
469
+ checklist.items.forEach((item, itemIndex) => {
470
+ console.log(` Item ${itemIndex + 1}:`, {
471
+ id: item.id,
472
+ title: item.title?.substring(0, 50) || 'No title',
473
+ description: item.description?.substring(0, 50) || 'No description',
474
+ });
475
+ });
476
+ }
477
+ });
478
+ // Add specific instructions for creating checklist results
479
+ checklistInstructions = `
480
+
481
+ ## MANDATORY Checklist Compliance
482
+
483
+ **CRITICAL**: You MUST address ALL checklists provided in the context above. Checklists are mandatory quality requirements that cannot be ignored.
484
+
485
+ - Review each checklist carefully during your implementation
486
+ - Ensure your code and processes satisfy every checklist requirement
487
+ - Include ALL checklist item IDs in your final JSON response under "checklist_item_results" (use the exact UUID from "ID:" field in items list)
488
+ - Set "is_passed": true for completed checklist items, or explain in "notes" why a requirement cannot be met
489
+ - Missing any checklist will cause the entire pipeline to fail
490
+
491
+ Remember: Checklists are not suggestions - they are mandatory quality gates.`;
492
+ if (verbose) {
493
+ logInfo(`Added ${checklistContext.checklists.length} checklists to implementation context`);
494
+ }
495
+ }
496
+ return `Implement the complete feature for feature ID: ${featureId}
497
+
498
+ ${finalContextInfo}
499
+
500
+ ## Implementation Instructions
501
+
502
+ Follow this systematic approach:
503
+
504
+ 1. **GIT PULL REBASE**: First ensure ${baseBranch} is up to date:
505
+ \`git checkout ${baseBranch}\`
506
+ \`git pull origin ${baseBranch} --rebase\`
507
+
508
+ 2. **CREATE BRANCH**: Create a new git branch from ${baseBranch}:
509
+ \`git checkout -b dev/${featureId}\`
510
+
511
+ 2. **ANALYZE CODEBASE**: Study the existing codebase structure to understand:
512
+ - Technology stack and architecture
513
+ - Existing patterns and conventions
514
+ - Where to place new components/files
515
+ - How to integrate with existing systems
516
+
517
+ 3. **IMPLEMENT FEATURE**: Based on the context above, implement the feature by:
518
+ - Following the technical design (if available)
519
+ - Satisfying all user stories
520
+ - Creating components, services, APIs, database changes as needed
521
+ - Following existing code patterns and conventions
522
+ - Adding proper error handling and validation
523
+
524
+ 4. **COMMIT CHANGES**: Commit your work with a descriptive message
525
+ - This project has strict pre-commit hooks (lint-staged, linting, AI code review)
526
+ - If hooks fail, try these approaches in order:
527
+ 1. Fix the reported issues (preferred)
528
+ 2. For AI code review issues: SKIP_REVIEW=1 git commit -m "message"
529
+ 3. Last resort only: git commit --no-verify -m "message" (explain why in commit message)
530
+
531
+ ## Important Notes
532
+ - Focus on implementing ALL user stories completely
533
+ - Follow the technical design if provided, or create your own approach
534
+ - Maintain existing code quality and patterns
535
+ - Never skip pre-commit checks - always fix the issues
536
+ - Focus on implementation only - automated tests will be written in a separate phase
537
+
538
+ ${checklistInstructions}
539
+
540
+ Begin by creating a feature branch and analyzing the codebase structure.`;
541
+ };
542
+ const parseImplementationResponse = (response, featureId) => {
543
+ console.log('Parsing implementation response...');
544
+ try {
545
+ // Try to find JSON in the response
546
+ const jsonMatch = response.match(/```json\s*([\s\S]*?)\s*```/) ||
547
+ response.match(/\{[\s\S]*"implementation_result"[\s\S]*\}/);
548
+ if (jsonMatch) {
549
+ const jsonStr = jsonMatch[1] || jsonMatch[0];
550
+ const parsed = JSON.parse(jsonStr);
551
+ if (parsed.implementation_result) {
552
+ const result = parsed.implementation_result;
553
+ return {
554
+ branchName: result.branch_name || `dev/${featureId}`,
555
+ filesModified: result.files_modified || [],
556
+ commitHash: result.commit_hash || '',
557
+ summary: result.summary || '',
558
+ checklist_item_results: result.checklist_item_results || [],
559
+ };
560
+ }
561
+ }
562
+ // Fallback: try to extract information from the text
563
+ const branchMatch = response.match(/branch[:\s]+(\S+)/i);
564
+ const filesMatch = response.match(/files?[:\s]+([^\n]+)/i);
565
+ const commitMatch = response.match(/commit[:\s]+([a-f0-9]{7,})/i);
566
+ return {
567
+ branchName: branchMatch?.[1] || `dev/${featureId}`,
568
+ filesModified: filesMatch
569
+ ? filesMatch[1].split(/[,\s]+/).filter((f) => f)
570
+ : [],
571
+ commitHash: commitMatch?.[1] || '',
572
+ summary: 'Implementation completed',
573
+ };
574
+ }
575
+ catch (error) {
576
+ console.log('Response parsing failed:', error);
577
+ return {
578
+ branchName: `dev/${featureId}`,
579
+ filesModified: [],
580
+ commitHash: '',
581
+ summary: 'Implementation completed',
582
+ };
583
+ }
584
+ };
585
+ /**
586
+ * Push branch to remote repository
587
+ */
588
+ async function pushToRemote(branchName, verbose) {
589
+ try {
590
+ // Import exec from child_process
591
+ const { execSync } = await import('child_process');
592
+ if (verbose) {
593
+ logInfo(`Pushing branch ${branchName} to remote...`);
594
+ }
595
+ // Try to push with -u flag (sets upstream if not already set)
596
+ try {
597
+ execSync(`git push -u origin ${branchName}`, {
598
+ encoding: 'utf-8',
599
+ stdio: verbose ? 'inherit' : 'pipe',
600
+ });
601
+ return { success: true };
602
+ }
603
+ catch (error) {
604
+ // If push fails, it might be because branch already has upstream
605
+ // Try without -u flag
606
+ try {
607
+ execSync(`git push origin ${branchName}`, {
608
+ encoding: 'utf-8',
609
+ stdio: verbose ? 'inherit' : 'pipe',
610
+ });
611
+ return { success: true };
612
+ }
613
+ catch (retryError) {
614
+ const errorMessage = retryError instanceof Error ? retryError.message : String(retryError);
615
+ return {
616
+ success: false,
617
+ error: errorMessage,
618
+ };
619
+ }
620
+ }
621
+ }
622
+ catch (error) {
623
+ const errorMessage = error instanceof Error ? error.message : String(error);
624
+ return {
625
+ success: false,
626
+ error: errorMessage,
627
+ };
628
+ }
629
+ }
@@ -0,0 +1,17 @@
1
+ import type { FeatureInfo, UserStory, TestCase } from '../../types/features.js';
2
+ import { type ProductInfo } from '../../api/products.js';
3
+ export interface CodeImplementationContext {
4
+ feature: FeatureInfo;
5
+ product: ProductInfo;
6
+ user_stories: UserStory[];
7
+ test_cases: TestCase[];
8
+ technical_design?: string;
9
+ }
10
+ /**
11
+ * Fetch all code implementation context information via MCP endpoints
12
+ */
13
+ export declare function fetchCodeImplementationContext(featureId: string, verbose?: boolean): Promise<CodeImplementationContext>;
14
+ /**
15
+ * Format the context into a readable string for Claude Code
16
+ */
17
+ export declare function formatContextForPrompt(context: CodeImplementationContext): string;