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,561 @@
1
+ /**
2
+ * Code Refine Analyzer
3
+ * Processes GitHub PR review feedback and refines code accordingly
4
+ */
5
+ import { query } from '@anthropic-ai/claude-code';
6
+ import { logInfo, logError } from '../../utils/logger.js';
7
+ import { execSync } from 'child_process';
8
+ import { fetchCodeRefineContext, formatContextForPrompt, } from './context-fetcher.js';
9
+ import { getFeedbacksForPhase, formatFeedbacksForContext, } from '../../services/feedbacks.js';
10
+ function userMessage(content) {
11
+ return {
12
+ type: 'user',
13
+ message: { role: 'user', content: content },
14
+ };
15
+ }
16
+ async function* prompt(refinePrompt) {
17
+ yield userMessage(refinePrompt);
18
+ await new Promise((res) => setTimeout(res, 10000));
19
+ }
20
+ /**
21
+ * Get current Git branch name
22
+ */
23
+ const getCurrentBranch = () => {
24
+ try {
25
+ return execSync('git branch --show-current', { encoding: 'utf-8' }).trim();
26
+ }
27
+ catch (error) {
28
+ throw new Error(`Failed to get current branch: ${error instanceof Error ? error.message : String(error)}`);
29
+ }
30
+ };
31
+ /**
32
+ * Check if there are uncommitted changes in the working directory
33
+ */
34
+ const hasUncommittedChanges = () => {
35
+ try {
36
+ const status = execSync('git status --porcelain', { encoding: 'utf-8' });
37
+ return status.trim().length > 0;
38
+ }
39
+ catch (error) {
40
+ throw new Error(`Failed to check git status: ${error instanceof Error ? error.message : String(error)}`);
41
+ }
42
+ };
43
+ /**
44
+ * Get list of uncommitted files
45
+ */
46
+ const getUncommittedFiles = () => {
47
+ try {
48
+ const status = execSync('git status --porcelain', { encoding: 'utf-8' });
49
+ return status
50
+ .trim()
51
+ .split('\n')
52
+ .filter((line) => line.length > 0)
53
+ .map((line) => line.trim());
54
+ }
55
+ catch (error) {
56
+ throw new Error(`Failed to get uncommitted files: ${error instanceof Error ? error.message : String(error)}`);
57
+ }
58
+ };
59
+ /**
60
+ * Reset uncommitted changes in the working directory
61
+ */
62
+ const resetUncommittedChanges = (verbose) => {
63
+ try {
64
+ if (verbose) {
65
+ logInfo(`🔄 Resetting uncommitted changes...`);
66
+ }
67
+ execSync('git reset --hard HEAD', { encoding: 'utf-8' });
68
+ execSync('git clean -fd', { encoding: 'utf-8' });
69
+ if (verbose) {
70
+ logInfo(`✅ Reset working directory to clean state`);
71
+ }
72
+ }
73
+ catch (error) {
74
+ throw new Error(`Failed to reset uncommitted changes: ${error instanceof Error ? error.message : String(error)}`);
75
+ }
76
+ };
77
+ /**
78
+ * Switch to a specific Git branch
79
+ */
80
+ const switchToBranch = (branch, verbose) => {
81
+ try {
82
+ if (verbose) {
83
+ logInfo(`🔄 Switching to branch ${branch}...`);
84
+ }
85
+ execSync(`git checkout ${branch}`, { encoding: 'utf-8' });
86
+ if (verbose) {
87
+ logInfo(`✅ Switched to ${branch} branch`);
88
+ }
89
+ }
90
+ catch (error) {
91
+ throw new Error(`Failed to switch to ${branch} branch: ${error instanceof Error ? error.message : String(error)}`);
92
+ }
93
+ };
94
+ /**
95
+ * Pull latest changes from remote
96
+ */
97
+ const pullLatestChanges = (verbose) => {
98
+ try {
99
+ // Check for uncommitted changes and reset if found
100
+ if (hasUncommittedChanges()) {
101
+ if (verbose) {
102
+ logInfo(`⚠️ Found uncommitted changes from previous attempt. Resetting to clean state...`);
103
+ }
104
+ resetUncommittedChanges(verbose);
105
+ }
106
+ if (verbose) {
107
+ logInfo(`📥 Pulling latest changes from remote...`);
108
+ }
109
+ execSync('git pull origin $(git branch --show-current) --rebase', {
110
+ encoding: 'utf-8',
111
+ });
112
+ if (verbose) {
113
+ logInfo(`✅ Successfully pulled latest changes`);
114
+ }
115
+ }
116
+ catch (error) {
117
+ throw new Error(`Failed to pull latest changes: ${error instanceof Error ? error.message : String(error)}`);
118
+ }
119
+ };
120
+ /**
121
+ * Push changes to remote branch
122
+ */
123
+ const pushChanges = (verbose) => {
124
+ try {
125
+ if (verbose) {
126
+ logInfo(`📤 Pushing changes to remote...`);
127
+ }
128
+ execSync('git push origin $(git branch --show-current)', {
129
+ encoding: 'utf-8',
130
+ });
131
+ if (verbose) {
132
+ logInfo(`✅ Successfully pushed changes`);
133
+ }
134
+ }
135
+ catch (error) {
136
+ throw new Error(`Failed to push changes: ${error instanceof Error ? error.message : String(error)}`);
137
+ }
138
+ };
139
+ /**
140
+ * Main code refine function
141
+ */
142
+ export const refineCodeFromPRFeedback = async (options, config) => {
143
+ const { featureId, githubToken, verbose } = options;
144
+ if (verbose) {
145
+ logInfo(`Starting code refine for feature ID: ${featureId}`);
146
+ }
147
+ try {
148
+ // Fetch code refine context (PR reviews and comments)
149
+ if (verbose) {
150
+ logInfo('Fetching code refine context from GitHub PR...');
151
+ }
152
+ const context = await fetchCodeRefineContext(featureId, githubToken, verbose);
153
+ // Check if there are any reviews or comments to address
154
+ if (context.reviews.length === 0 && context.reviewComments.length === 0) {
155
+ if (verbose) {
156
+ logInfo('✅ No review comments or change requests found. Nothing to refine.');
157
+ }
158
+ return {
159
+ featureId,
160
+ status: 'success',
161
+ message: 'No review feedback to address',
162
+ summary: 'No change requests or review comments found on the PR',
163
+ };
164
+ }
165
+ if (verbose) {
166
+ logInfo(`📋 Found ${context.reviews.length} reviews and ${context.reviewComments.length} comments to address`);
167
+ }
168
+ // Fetch additional feedbacks for code-refine phase
169
+ let feedbacksInfo;
170
+ try {
171
+ const feedbacksContext = await getFeedbacksForPhase({ featureId, verbose }, 'code_refine');
172
+ if (feedbacksContext.feedbacks.length > 0) {
173
+ feedbacksInfo = formatFeedbacksForContext(feedbacksContext);
174
+ if (verbose) {
175
+ logInfo(`Added ${feedbacksContext.feedbacks.length} human feedbacks to code refine context`);
176
+ }
177
+ }
178
+ }
179
+ catch (error) {
180
+ if (verbose) {
181
+ logInfo(`Note: Could not fetch feedbacks (${error instanceof Error ? error.message : String(error)})`);
182
+ }
183
+ }
184
+ // Get current branch and switch to dev/feature-id if needed
185
+ const currentBranch = getCurrentBranch();
186
+ const targetBranch = `dev/${featureId}`;
187
+ if (currentBranch !== targetBranch) {
188
+ if (verbose) {
189
+ logInfo(`Current branch is ${currentBranch}, switching to ${targetBranch}...`);
190
+ }
191
+ switchToBranch(targetBranch, verbose);
192
+ }
193
+ // Pull latest changes
194
+ pullLatestChanges(verbose);
195
+ // Create prompt for code refine
196
+ const systemPrompt = createSystemPrompt(config);
197
+ const refinePrompt = createCodeRefinePrompt(featureId, context, feedbacksInfo, options.verificationFailureContext);
198
+ let lastAssistantResponse = '';
199
+ let structuredRefineResult = null;
200
+ if (verbose) {
201
+ logInfo('Starting Claude Code query for code refine...');
202
+ }
203
+ // Use Claude Code SDK to refine the code
204
+ for await (const message of query({
205
+ prompt: prompt(refinePrompt),
206
+ options: {
207
+ appendSystemPrompt: systemPrompt,
208
+ model: config.claude.model || 'sonnet',
209
+ maxTurns: 2000,
210
+ permissionMode: 'bypassPermissions',
211
+ },
212
+ })) {
213
+ if (verbose) {
214
+ logInfo(`Received message type: ${message.type}`);
215
+ }
216
+ // Stream the code refine process
217
+ if (message.type === 'assistant' && message.message?.content) {
218
+ for (const content of message.message.content) {
219
+ if (content.type === 'text') {
220
+ lastAssistantResponse += content.text + '\n';
221
+ if (verbose) {
222
+ console.log(`\n🔧 ${content.text}`);
223
+ }
224
+ }
225
+ else if (content.type === 'tool_use') {
226
+ if (verbose) {
227
+ console.log(`\n🛠️ ${content.name}: ${content.input.description || 'Running...'}`);
228
+ }
229
+ }
230
+ }
231
+ }
232
+ else if (message.type === 'result') {
233
+ if (message.subtype === 'success') {
234
+ logInfo('\n🛠️ Code refine completed, parsing results...');
235
+ try {
236
+ const responseText = message.result || lastAssistantResponse;
237
+ let jsonResult = null;
238
+ const jsonBlockMatch = responseText.match(/```json\s*\n([\s\S]*?)\n\s*```/);
239
+ if (jsonBlockMatch) {
240
+ jsonResult = JSON.parse(jsonBlockMatch[1]);
241
+ }
242
+ else {
243
+ jsonResult = JSON.parse(responseText);
244
+ }
245
+ if (jsonResult && jsonResult.refine_result) {
246
+ structuredRefineResult = jsonResult.refine_result;
247
+ }
248
+ else {
249
+ throw new Error('Invalid JSON structure');
250
+ }
251
+ }
252
+ catch (error) {
253
+ logError(`Failed to parse structured refine result: ${error}`);
254
+ structuredRefineResult = parseCodeRefineResponse(message.result || lastAssistantResponse);
255
+ }
256
+ }
257
+ else {
258
+ logError(`\n⚠️ Code refine incomplete: ${message.subtype}`);
259
+ if (message.subtype === 'error_max_turns') {
260
+ logError('💡 Try simplifying the changes or reducing scope');
261
+ }
262
+ if (lastAssistantResponse) {
263
+ try {
264
+ const responseText = lastAssistantResponse;
265
+ let jsonResult = null;
266
+ const jsonBlockMatch = responseText.match(/```json\s*\n([\s\S]*?)\n\s*```/);
267
+ if (jsonBlockMatch) {
268
+ jsonResult = JSON.parse(jsonBlockMatch[1]);
269
+ if (jsonResult && jsonResult.refine_result) {
270
+ structuredRefineResult = jsonResult.refine_result;
271
+ }
272
+ }
273
+ else {
274
+ structuredRefineResult = parseCodeRefineResponse(lastAssistantResponse);
275
+ }
276
+ }
277
+ catch (error) {
278
+ logError(`Failed to parse assistant response: ${error}`);
279
+ }
280
+ }
281
+ }
282
+ }
283
+ }
284
+ // Push changes to remote
285
+ if (structuredRefineResult) {
286
+ // Verify all changes are committed before pushing
287
+ if (hasUncommittedChanges()) {
288
+ const uncommittedFiles = getUncommittedFiles();
289
+ const errorMsg = `Code refine completed but there are uncommitted changes. All changes must be committed before verification.
290
+
291
+ Uncommitted files:
292
+ ${uncommittedFiles.join('\n')}
293
+
294
+ Please ensure Claude Code commits all changes before completing the refine phase.`;
295
+ logError(`❌ ${errorMsg}`);
296
+ return {
297
+ featureId,
298
+ status: 'error',
299
+ message: errorMsg,
300
+ };
301
+ }
302
+ if (verbose) {
303
+ logInfo('✅ All changes committed. Pushing to remote...');
304
+ }
305
+ try {
306
+ pushChanges(verbose);
307
+ const { summary, files_modified, commits_created } = structuredRefineResult;
308
+ if (verbose) {
309
+ logInfo(`Code refine completed for feature: ${featureId}`);
310
+ if (files_modified?.length > 0) {
311
+ logInfo(`Files modified: ${files_modified.join(', ')}`);
312
+ }
313
+ if (commits_created) {
314
+ logInfo(`Commits created: ${commits_created}`);
315
+ }
316
+ }
317
+ return {
318
+ featureId,
319
+ status: 'success',
320
+ message: 'Code successfully refined based on PR feedback',
321
+ summary: summary || 'Code refined based on PR review feedback',
322
+ filesModified: files_modified || [],
323
+ commitsCreated: commits_created || 1,
324
+ };
325
+ }
326
+ catch (pushError) {
327
+ logError(`Failed to push changes: ${pushError}`);
328
+ return {
329
+ featureId,
330
+ status: 'error',
331
+ message: `Code refined but failed to push: ${pushError}`,
332
+ };
333
+ }
334
+ }
335
+ else {
336
+ return {
337
+ featureId,
338
+ status: 'error',
339
+ message: 'Code refine failed or incomplete',
340
+ };
341
+ }
342
+ }
343
+ catch (error) {
344
+ const errorMessage = error instanceof Error ? error.message : String(error);
345
+ logError(`Code refine failed: ${errorMessage}`);
346
+ return {
347
+ featureId,
348
+ status: 'error',
349
+ message: `Code refine failed: ${errorMessage}`,
350
+ };
351
+ }
352
+ };
353
+ function createSystemPrompt(_config) {
354
+ return `You are an expert software engineer specializing in addressing code review feedback. Your goal is to carefully analyze review comments and refine the code to address all concerns raised by human reviewers.
355
+
356
+ **Your Role**: Refine code based on PR review feedback while maintaining code quality and functionality.
357
+
358
+ **Available Tools**:
359
+ - Bash: Run commands, tests, and git operations
360
+ - Glob: Find files and understand project structure
361
+ - Read: Examine existing code and files
362
+ - Edit: Modify existing files to address feedback
363
+ - Write: Create new files if necessary
364
+ - TodoWrite: Track code refine tasks (use proactively)
365
+
366
+ **Code Refine Process**:
367
+ 1. **Analyze Feedback**: Carefully study all review comments and change requests
368
+ 2. **Understand Context**: Review the code, technical design, and related files
369
+ 3. **Plan Changes**: Create a systematic plan to address each review comment
370
+ 4. **Refine Code**: Make targeted, thoughtful changes that address the feedback
371
+ 5. **Test Changes**: Ensure your changes work and don't break functionality
372
+ 6. **Commit Changes**: Create clear, descriptive commits for your refinements
373
+ 7. **Final Check**: Before finishing, run \`git status\` and commit any remaining uncommitted changes
374
+ 8. **Document**: Explain what changes were made and why
375
+
376
+ **Important Guidelines**:
377
+ - Address ALL review comments and change requests
378
+ - Maintain code quality and follow best practices
379
+ - Preserve existing functionality
380
+ - Write clear commit messages that reference the feedback
381
+ - Test your changes thoroughly
382
+ - Be respectful of the reviewer's time and expertise
383
+
384
+ **CRITICAL - Commit Requirements**:
385
+ - You MUST commit ALL your changes using git before finishing
386
+ - DO NOT leave any uncommitted changes in the working directory
387
+ - Verification will fail if there are uncommitted changes
388
+ - Use clear, descriptive commit messages that explain what feedback was addressed
389
+
390
+ **CRITICAL - Result Format**:
391
+ You MUST end your response with a JSON object containing the code refine results in this EXACT format:
392
+
393
+ \`\`\`json
394
+ {
395
+ "refine_result": {
396
+ "feature_id": "FEATURE_ID_PLACEHOLDER",
397
+ "summary": "Brief description of changes made",
398
+ "files_modified": ["file1.ts", "file2.tsx"],
399
+ "commits_created": 1,
400
+ "feedback_addressed": [
401
+ {
402
+ "comment_id": "Comment reference or ID",
403
+ "issue": "Description of the reviewer's concern",
404
+ "resolution": "Description of how it was addressed",
405
+ "files": ["path/to/file.ts"]
406
+ }
407
+ ]
408
+ }
409
+ }
410
+ \`\`\`
411
+
412
+ Focus on systematic code refinement based on the provided PR review feedback.`;
413
+ }
414
+ function createCodeRefinePrompt(featureId, context, feedbacksInfo, verificationFailureContext) {
415
+ let contextInfo = formatContextForPrompt(context);
416
+ if (feedbacksInfo) {
417
+ contextInfo = contextInfo + '\n\n' + feedbacksInfo;
418
+ }
419
+ // Add verification failure context if this is a retry
420
+ let verificationSection = '';
421
+ if (verificationFailureContext) {
422
+ verificationSection = `
423
+
424
+ ## ⚠️ PREVIOUS ATTEMPT FAILED VERIFICATION (Attempt ${verificationFailureContext.attempt})
425
+
426
+ Your previous code refine attempt did NOT successfully address all the review feedback.
427
+ The verification phase found the following unresolved issues:
428
+
429
+ ### Verification Failure Summary
430
+ ${verificationFailureContext.suggestions.map((s) => `- ${s}`).join('\n')}
431
+
432
+ ### Unresolved Comments Still Needing Attention
433
+ ${verificationFailureContext.unresolvedCommentDetails
434
+ .map((detail, idx) => `${idx + 1}. **${detail.file}${detail.line ? `:${detail.line}` : ''}** by @${detail.author}
435
+ Comment: ${detail.body}
436
+ **Failure Reason**: ${detail.failureReason}
437
+ URL: ${detail.url}`)
438
+ .join('\n\n')}
439
+
440
+ ${verificationFailureContext.unresolvedReviewDetails &&
441
+ verificationFailureContext.unresolvedReviewDetails.length > 0
442
+ ? `
443
+ ### Unresolved Reviews Still Requesting Changes
444
+ ${verificationFailureContext.unresolvedReviewDetails
445
+ .map((review, idx) => `${idx + 1}. Review by @${review.author} (${review.state})
446
+ ${review.body || 'No review body provided'}`)
447
+ .join('\n\n')}
448
+ `
449
+ : ''}
450
+
451
+ **CRITICAL**: You MUST address all the above issues in this iteration. Pay special attention to:
452
+ 1. Read each unresolved comment carefully and understand what change is being requested
453
+ 2. Locate the exact file and line mentioned
454
+ 3. Make the specific changes requested by the reviewer
455
+ 4. Test your changes to ensure they work correctly
456
+ 5. Do not skip or overlook any comments - address ALL of them
457
+ `;
458
+ }
459
+ return `Refine code based on PR review feedback for feature: ${featureId}
460
+ ${verificationFailureContext ? '\n🔄 **This is a RETRY after verification failure**\n' : ''}
461
+ ${contextInfo}
462
+ ${verificationSection}
463
+
464
+ ## Code Refine Instructions
465
+
466
+ Follow this systematic approach:
467
+
468
+ 1. **Analyze All Feedback**: Study all review comments and change requests above:
469
+ ${verificationFailureContext ? ' - **FOCUS ON THE UNRESOLVED COMMENTS listed in the verification failure section**' : ''}
470
+ - What specific concerns were raised?
471
+ - Which files and code sections need changes?
472
+ - What are the underlying issues?
473
+ - Are there any patterns in the feedback?
474
+
475
+ 2. **Examine Current Code**: Use Read and Glob tools to:
476
+ - Understand the current implementation
477
+ - Identify the code sections mentioned in reviews
478
+ - Review related files and dependencies
479
+ - Understand the broader context
480
+
481
+ 3. **Plan Your Changes**: Create a systematic plan:
482
+ - Address each review comment one by one
483
+ - Prioritize critical feedback
484
+ - Consider how changes relate to each other
485
+ - Ensure changes align with technical design
486
+
487
+ 4. **Refine the Code**: Make targeted improvements:
488
+ - Address each reviewer's concern thoughtfully
489
+ - Follow code quality best practices
490
+ - Maintain consistency with existing patterns
491
+ - Make code more maintainable and readable
492
+
493
+ 5. **Test Your Changes**: Verify everything works:
494
+ - Run relevant tests
495
+ - Check that functionality still works
496
+ - Ensure no regressions were introduced
497
+
498
+ 6. **Commit Your Changes**: Create clear commits:
499
+ - Write descriptive commit messages
500
+ - Reference the feedback being addressed
501
+ - Group related changes logically
502
+
503
+ 7. **Final Verification** - BEFORE generating the JSON result:
504
+ - Run \`git status\` to check for any uncommitted changes
505
+ - If there are ANY uncommitted files, commit them immediately
506
+ - Ensure working directory is completely clean (no output from \`git status --porcelain\`)
507
+ - Only after confirming everything is committed, generate the final JSON result
508
+
509
+ ## Important Notes
510
+ - Be thorough - address ALL review comments
511
+ - Be respectful - reviewers are trying to help improve the code
512
+ - Be systematic - don't rush through the feedback
513
+ - Test your changes - ensure nothing breaks
514
+ - Communicate clearly in commit messages
515
+ - **CRITICAL**: You MUST commit all changes before finishing - no uncommitted files allowed
516
+
517
+ ## ⚠️ CRITICAL - Pre-Completion Checklist
518
+ BEFORE you generate the final JSON result, you MUST complete this checklist:
519
+
520
+ 1. **Run git status check**:
521
+ \`\`\`bash
522
+ git status --porcelain
523
+ \`\`\`
524
+ - If this command returns ANY output, you have uncommitted changes
525
+
526
+ 2. **If uncommitted changes exist**:
527
+ - Review what files are uncommitted
528
+ - Stage and commit ALL remaining changes with appropriate commit messages
529
+ - Run \`git status --porcelain\` again to verify it returns empty output
530
+
531
+ 3. **Only generate JSON result when**:
532
+ - \`git status --porcelain\` returns completely empty output
533
+ - All tests pass
534
+ - All review feedback has been addressed
535
+
536
+ **FAILURE TO COMMIT ALL CHANGES WILL CAUSE THE PIPELINE TO FAIL**
537
+
538
+ You are currently on the \`dev/${featureId}\` branch. Make your changes, commit them, and they will be pushed to the remote repository.
539
+
540
+ Begin by analyzing all the review feedback and creating a plan to address each comment.`;
541
+ }
542
+ function parseCodeRefineResponse(response) {
543
+ const summaryMatch = response.match(/## Refine Summary\n([\s\S]*?)(?=\n##|\n\n|$)/);
544
+ const summary = summaryMatch
545
+ ? summaryMatch[1].trim()
546
+ : 'Code refined based on PR feedback';
547
+ const filesMatch = response.match(/## Files Modified\n([\s\S]*?)(?=\n##|\n\n|$)/);
548
+ let files_modified = [];
549
+ if (filesMatch) {
550
+ files_modified = filesMatch[1]
551
+ .split('\n')
552
+ .filter((line) => line.trim().startsWith('-'))
553
+ .map((line) => line.replace(/^-\s*/, '').trim());
554
+ }
555
+ return {
556
+ summary,
557
+ files_modified,
558
+ commits_created: 1,
559
+ feedback_addressed: [],
560
+ };
561
+ }
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Context fetcher for code refine phase
3
+ * Fetches GitHub PR review comments and reviews using GraphQL API
4
+ */
5
+ import { Octokit } from '@octokit/rest';
6
+ export interface PRReviewComment {
7
+ id: number;
8
+ body: string;
9
+ path: string | null;
10
+ line: number | null;
11
+ user: {
12
+ login: string;
13
+ };
14
+ created_at: string;
15
+ position: number | null;
16
+ original_position: number | null;
17
+ diff_hunk: string | null;
18
+ in_reply_to_id?: number;
19
+ url?: string;
20
+ }
21
+ export interface PRReview {
22
+ id: number;
23
+ user: {
24
+ login: string;
25
+ };
26
+ body: string | null;
27
+ state: string;
28
+ submitted_at: string | null;
29
+ }
30
+ export interface PRReviewThread {
31
+ id: string;
32
+ isResolved: boolean;
33
+ isOutdated: boolean;
34
+ line: number | null;
35
+ originalLine: number | null;
36
+ startLine: number | null;
37
+ originalStartLine: number | null;
38
+ diffSide: string;
39
+ comments: PRReviewComment[];
40
+ }
41
+ export interface CodeRefineContext {
42
+ featureId: string;
43
+ featureName: string;
44
+ featureDescription: string | null;
45
+ pullRequestUrl: string;
46
+ pullRequestNumber: number;
47
+ owner: string;
48
+ repo: string;
49
+ reviews: PRReview[];
50
+ reviewComments: PRReviewComment[];
51
+ reviewThreads?: PRReviewThread[];
52
+ technicalDesign?: string;
53
+ userStories?: any[];
54
+ testCases?: any[];
55
+ }
56
+ /**
57
+ * Extract owner, repo, and PR number from GitHub PR URL
58
+ */
59
+ export declare function parsePullRequestUrl(pullRequestUrl: string): {
60
+ owner: string;
61
+ repo: string;
62
+ prNumber: number;
63
+ } | null;
64
+ /**
65
+ * Fetch PR reviews that request changes
66
+ */
67
+ export declare function fetchPRReviews(octokit: Octokit, owner: string, repo: string, prNumber: number, verbose?: boolean): Promise<PRReview[]>;
68
+ /**
69
+ * Fetch PR review comments
70
+ */
71
+ export declare function fetchPRReviewComments(octokit: Octokit, owner: string, repo: string, prNumber: number, verbose?: boolean): Promise<PRReviewComment[]>;
72
+ /**
73
+ * Fetch PR data using GraphQL API including review threads and reviews
74
+ */
75
+ export declare function fetchPRDataGraphQL(octokit: Octokit, owner: string, repo: string, prNumber: number, verbose?: boolean): Promise<{
76
+ reviewThreads: PRReviewThread[];
77
+ reviews: PRReview[];
78
+ }>;
79
+ /**
80
+ * Fetch user stories via MCP
81
+ */
82
+ export declare function fetchUserStories(featureId: string, verbose?: boolean): Promise<any[]>;
83
+ /**
84
+ * Fetch test cases via MCP
85
+ */
86
+ export declare function fetchTestCases(featureId: string, verbose?: boolean): Promise<any[]>;
87
+ /**
88
+ * Fetch complete code refine context
89
+ */
90
+ export declare function fetchCodeRefineContext(featureId: string, githubToken: string, verbose?: boolean): Promise<CodeRefineContext>;
91
+ /**
92
+ * Format code refine context for prompt
93
+ */
94
+ export declare function formatContextForPrompt(context: CodeRefineContext): string;