edsger 0.2.3 → 0.2.5

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 (89) hide show
  1. package/README.md +17 -0
  2. package/dist/api/features/batch-operations.d.ts +16 -0
  3. package/dist/api/features/batch-operations.js +100 -0
  4. package/dist/api/features/index.d.ts +1 -0
  5. package/dist/api/features/index.js +1 -0
  6. package/dist/api/features/test-cases.d.ts +8 -0
  7. package/dist/api/features/test-cases.js +45 -0
  8. package/dist/api/features/user-stories.d.ts +8 -0
  9. package/dist/api/features/user-stories.js +45 -0
  10. package/dist/cli/commands/refactor-command.d.ts +2 -0
  11. package/dist/cli/commands/refactor-command.js +123 -0
  12. package/dist/cli/formatters/formatter-utils.d.ts +23 -0
  13. package/dist/cli/formatters/formatter-utils.js +67 -0
  14. package/dist/cli/index.js +7 -0
  15. package/dist/cli/utils/command-handler.d.ts +23 -0
  16. package/dist/cli/utils/command-handler.js +39 -0
  17. package/dist/cli.d.ts +2 -2
  18. package/dist/cli.js +4 -99
  19. package/dist/phases/code-implementation/analyzer-helpers.d.ts +28 -0
  20. package/dist/phases/code-implementation/analyzer-helpers.js +177 -0
  21. package/dist/phases/code-implementation/analyzer.d.ts +2 -0
  22. package/dist/phases/code-implementation/analyzer.js +304 -175
  23. package/dist/phases/code-implementation-verification/index.d.ts +1 -0
  24. package/dist/phases/code-implementation-verification/index.js +1 -0
  25. package/dist/phases/code-implementation-verification/verifier.d.ts +31 -0
  26. package/dist/phases/code-implementation-verification/verifier.js +196 -0
  27. package/dist/phases/feature-analysis/analyzer-helpers.d.ts +62 -0
  28. package/dist/phases/feature-analysis/analyzer-helpers.js +450 -0
  29. package/dist/phases/feature-analysis/analyzer.d.ts +1 -0
  30. package/dist/phases/feature-analysis/analyzer.js +132 -219
  31. package/dist/phases/feature-analysis-verification/index.d.ts +1 -0
  32. package/dist/phases/feature-analysis-verification/index.js +1 -0
  33. package/dist/phases/feature-analysis-verification/verifier.d.ts +37 -0
  34. package/dist/phases/feature-analysis-verification/verifier.js +147 -0
  35. package/dist/phases/pull-request/creator.js +2 -1
  36. package/dist/phases/technical-design/analyzer-helpers.d.ts +37 -0
  37. package/dist/phases/technical-design/analyzer-helpers.js +144 -0
  38. package/dist/phases/technical-design/analyzer.d.ts +3 -0
  39. package/dist/phases/technical-design/analyzer.js +282 -318
  40. package/dist/phases/technical-design-verification/index.d.ts +1 -0
  41. package/dist/phases/technical-design-verification/index.js +1 -0
  42. package/dist/phases/technical-design-verification/verifier.d.ts +36 -0
  43. package/dist/phases/technical-design-verification/verifier.js +147 -0
  44. package/dist/prompts/checklist-verification.d.ts +11 -0
  45. package/dist/prompts/checklist-verification.js +153 -0
  46. package/dist/prompts/code-implementation-improvement.d.ts +5 -0
  47. package/dist/prompts/code-implementation-improvement.js +108 -0
  48. package/dist/prompts/code-implementation-verification.d.ts +3 -0
  49. package/dist/prompts/code-implementation-verification.js +176 -0
  50. package/dist/prompts/feature-analysis-improvement.d.ts +8 -0
  51. package/dist/prompts/feature-analysis-improvement.js +109 -0
  52. package/dist/prompts/feature-analysis.js +1 -1
  53. package/dist/prompts/technical-design-improvement.d.ts +5 -0
  54. package/dist/prompts/technical-design-improvement.js +93 -0
  55. package/dist/prompts/technical-design-verification.d.ts +11 -0
  56. package/dist/prompts/technical-design-verification.js +134 -0
  57. package/dist/prompts/technical-design.js +1 -1
  58. package/dist/services/audit-logs.d.ts +60 -0
  59. package/dist/services/audit-logs.js +115 -0
  60. package/dist/services/checklist.d.ts +1 -0
  61. package/dist/types/index.d.ts +19 -0
  62. package/dist/workflow-runner/executors/phase-executor.js +56 -12
  63. package/package.json +1 -1
  64. package/dist/api/features.d.ts +0 -100
  65. package/dist/api/features.js +0 -219
  66. package/dist/logger.d.ts +0 -19
  67. package/dist/logger.js +0 -52
  68. package/dist/types.d.ts +0 -99
  69. package/dist/types.js +0 -1
  70. package/dist/utils/image-processor.d.ts +0 -5
  71. package/dist/utils/image-processor.js +0 -55
  72. package/dist/workflow-runner/config/stage-configs.d.ts +0 -5
  73. package/dist/workflow-runner/config/stage-configs.js +0 -34
  74. package/dist/workflow-runner/core/feature-filter.test.d.ts +0 -4
  75. package/dist/workflow-runner/core/feature-filter.test.js +0 -127
  76. package/dist/workflow-runner/executors/stage-executor.d.ts +0 -8
  77. package/dist/workflow-runner/executors/stage-executor.js +0 -49
  78. package/dist/workflow-runner/feature-fetcher.d.ts +0 -41
  79. package/dist/workflow-runner/feature-fetcher.js +0 -121
  80. package/dist/workflow-runner/feature-service.d.ts +0 -17
  81. package/dist/workflow-runner/feature-service.js +0 -60
  82. package/dist/workflow-runner/pipeline.d.ts +0 -18
  83. package/dist/workflow-runner/pipeline.js +0 -197
  84. package/dist/workflow-runner/processor.d.ts +0 -40
  85. package/dist/workflow-runner/processor.js +0 -191
  86. package/dist/workflow-runner/status-updater.d.ts +0 -27
  87. package/dist/workflow-runner/status-updater.js +0 -80
  88. package/dist/workflow-runner/types.d.ts +0 -48
  89. package/dist/workflow-runner/types.js +0 -4
@@ -2,6 +2,8 @@ import { query } from '@anthropic-ai/claude-code';
2
2
  import { logInfo, logError } from '../../utils/logger.js';
3
3
  import { formatChecklistsForContext, } from '../../services/checklist.js';
4
4
  import { fetchCodeImplementationContext, formatContextForPrompt, } from './context-fetcher.js';
5
+ import { logFeaturePhaseEvent } from '../../services/audit-logs.js';
6
+ import { performVerificationCycle, buildImplementationResult, buildVerificationFailureResult, buildNoResultsError, } from './analyzer-helpers.js';
5
7
  function userMessage(content) {
6
8
  return {
7
9
  type: 'user',
@@ -26,204 +28,284 @@ export const implementFeatureCode = async (options, config, checklistContext) =>
26
28
  }
27
29
  const context = await fetchCodeImplementationContext(mcpServerUrl, mcpToken, featureId, verbose);
28
30
  const systemPrompt = createSystemPrompt(config, baseBranch, mcpServerUrl, mcpToken, featureId);
29
- const implementationPrompt = createImplementationPromptWithContext(featureId, context, baseBranch, checklistContext, verbose);
30
- let lastAssistantResponse = '';
31
+ const initialImplementationPrompt = createImplementationPromptWithContext(featureId, context, baseBranch, checklistContext, verbose);
32
+ const maxIterations = options.maxVerificationIterations || 10;
33
+ let currentIteration = 0;
34
+ let currentPrompt = initialImplementationPrompt;
31
35
  let structuredImplementationResult = null;
36
+ let verificationResult = null;
37
+ const branchName = `dev/${featureId}`;
32
38
  if (verbose) {
33
39
  logInfo('Starting Claude Code query with pre-fetched information...');
34
40
  }
35
- // DEBUG: Log checklist context before query
36
- console.log('=== DEBUG: Checklist Context Before Claude Query ===');
37
- console.log('Has checklistContext:', !!checklistContext);
38
- if (checklistContext) {
39
- console.log('Number of checklists:', checklistContext.checklists.length);
40
- const totalItems = checklistContext.checklists.reduce((sum, checklist) => sum + (checklist.items?.length || 0), 0);
41
- console.log('Total checklist items:', totalItems);
42
- }
43
- console.log('Implementation prompt includes checklist:', implementationPrompt.includes('checklist'));
44
- console.log('System prompt includes checklist:', systemPrompt.includes('checklist'));
45
- // Use Claude Code SDK without MCP servers - all info is pre-fetched
46
- for await (const message of query({
47
- prompt: prompt(implementationPrompt),
48
- options: {
49
- appendSystemPrompt: systemPrompt,
50
- model: config.claude.model || 'sonnet',
51
- maxTurns: 3000,
52
- permissionMode: 'bypassPermissions',
53
- },
54
- })) {
55
- if (verbose) {
56
- logInfo(`Received message type: ${message.type}`);
41
+ // Iterative improvement loop: implement verify improve → re-implement
42
+ while (currentIteration < maxIterations) {
43
+ currentIteration++;
44
+ if (verbose && currentIteration > 1) {
45
+ logInfo(`\n🔄 Iteration ${currentIteration}/${maxIterations}: Improving implementation based on code review feedback...`);
57
46
  }
58
- // Stream the implementation process
59
- if (message.type === 'assistant' && message.message?.content) {
60
- for (const content of message.message.content) {
61
- if (content.type === 'text') {
62
- lastAssistantResponse += content.text + '\n';
63
- if (verbose) {
64
- console.log(`\n🤖 ${content.text}`);
65
- }
66
- }
67
- else if (content.type === 'tool_use') {
68
- if (verbose) {
69
- console.log(`\n🔧 ${content.name}: ${content.input.description || 'Running...'}`);
70
- }
71
- }
72
- }
47
+ // Log iteration start (for iterations after the first)
48
+ if (currentIteration > 1) {
49
+ await logFeaturePhaseEvent(mcpServerUrl, mcpToken, {
50
+ featureId,
51
+ eventType: 'phase_started',
52
+ phase: 'code_implementation',
53
+ result: 'info',
54
+ metadata: {
55
+ iteration: currentIteration,
56
+ max_iterations: maxIterations,
57
+ re_implementation: true,
58
+ timestamp: new Date().toISOString(),
59
+ },
60
+ }, verbose);
73
61
  }
74
- if (message.type === 'result') {
75
- if (message.subtype === 'success') {
76
- logInfo('\n💻 Code implementation completed, parsing results...');
77
- try {
78
- // Try to extract JSON from markdown code block or parse directly
79
- const responseText = message.result || lastAssistantResponse;
80
- let jsonResult = null;
81
- // DEBUG: Log response text details and checklist content
82
- console.log('=== DEBUG: Code Implementation Response Analysis ===');
83
- console.log('message.result exists:', !!message.result);
84
- console.log('lastAssistantResponse exists:', !!lastAssistantResponse);
85
- console.log('responseText length:', responseText.length);
86
- console.log('responseText first 200 chars:', JSON.stringify(responseText.substring(0, 200)));
87
- console.log('responseText last 200 chars:', JSON.stringify(responseText.substring(responseText.length - 200)));
88
- console.log('Contains ```json:', responseText.includes('```json'));
89
- console.log('Contains implementation_result:', responseText.includes('"implementation_result"'));
90
- console.log('=== DEBUG: Checklist Content in Response ===');
91
- console.log('Contains "checklist":', responseText.toLowerCase().includes('checklist'));
92
- console.log('Contains "checklist_item_results":', responseText.includes('checklist_item_results'));
93
- console.log('Contains checklist_item_id:', responseText.includes('checklist_item_id'));
94
- console.log('Contains is_passed:', responseText.includes('is_passed'));
95
- // Count checklist-related occurrences
96
- const checklistMatches = responseText.match(/checklist/gi) || [];
97
- const checklistItemMatches = responseText.match(/checklist_item/gi) || [];
98
- console.log('Total "checklist" mentions:', checklistMatches.length);
99
- console.log('Total "checklist_item" mentions:', checklistItemMatches.length);
100
- // First try to extract JSON from markdown code block
101
- const jsonBlockMatch = responseText.match(/```json\s*\n([\s\S]*?)\n\s*```/);
102
- console.log('=== DEBUG: Markdown Block Match ===');
103
- console.log('jsonBlockMatch found:', !!jsonBlockMatch);
104
- if (jsonBlockMatch) {
105
- console.log('Matched JSON length:', jsonBlockMatch[1].length);
106
- console.log('Matched JSON first 100 chars:', JSON.stringify(jsonBlockMatch[1].substring(0, 100)));
107
- jsonResult = JSON.parse(jsonBlockMatch[1]);
108
- }
109
- else {
110
- console.log('=== DEBUG: Trying direct JSON parse ===');
111
- // Try to parse the entire response as JSON
112
- jsonResult = JSON.parse(responseText);
113
- }
114
- console.log('=== DEBUG: Final Result Processing ===');
115
- console.log('jsonResult exists:', !!jsonResult);
116
- console.log('jsonResult has implementation_result:', !!(jsonResult && jsonResult.implementation_result));
117
- if (jsonResult && jsonResult.implementation_result) {
118
- const implResult = jsonResult.implementation_result;
119
- console.log('=== DEBUG: Implementation Result Structure ===');
120
- console.log('Keys in implementation_result:', Object.keys(implResult));
121
- console.log('Has checklist_item_results field:', 'checklist_item_results' in implResult);
122
- console.log('checklist_item_results value type:', typeof implResult.checklist_item_results);
123
- console.log('checklist_item_results is array:', Array.isArray(implResult.checklist_item_results));
124
- if (implResult.checklist_item_results) {
125
- console.log('checklist_item_results length:', implResult.checklist_item_results.length);
126
- if (implResult.checklist_item_results.length > 0) {
127
- console.log('First checklist item keys:', Object.keys(implResult.checklist_item_results[0]));
128
- console.log('First checklist item sample:', JSON.stringify(implResult.checklist_item_results[0], null, 2));
129
- }
130
- }
131
- else {
132
- console.log('checklist_item_results is null/undefined/empty');
62
+ let lastAssistantResponse = '';
63
+ let newImplementationResult = null;
64
+ // DEBUG: Log checklist context before query
65
+ console.log('=== DEBUG: Checklist Context Before Claude Query ===');
66
+ console.log('Has checklistContext:', !!checklistContext);
67
+ if (checklistContext) {
68
+ console.log('Number of checklists:', checklistContext.checklists.length);
69
+ const totalItems = checklistContext.checklists.reduce((sum, checklist) => sum + (checklist.items?.length || 0), 0);
70
+ console.log('Total checklist items:', totalItems);
71
+ }
72
+ console.log('Implementation prompt includes checklist:', currentPrompt.includes('checklist'));
73
+ console.log('System prompt includes checklist:', systemPrompt.includes('checklist'));
74
+ // Execute implementation query
75
+ for await (const message of query({
76
+ prompt: prompt(currentPrompt),
77
+ options: {
78
+ appendSystemPrompt: systemPrompt,
79
+ model: config.claude.model || 'sonnet',
80
+ maxTurns: 3000,
81
+ permissionMode: 'bypassPermissions',
82
+ },
83
+ })) {
84
+ if (verbose) {
85
+ logInfo(`Received message type: ${message.type}`);
86
+ }
87
+ // Stream the implementation process
88
+ if (message.type === 'assistant' && message.message?.content) {
89
+ for (const content of message.message.content) {
90
+ if (content.type === 'text') {
91
+ lastAssistantResponse += content.text + '\n';
92
+ if (verbose) {
93
+ console.log(`\n🤖 ${content.text}`);
133
94
  }
134
- structuredImplementationResult = jsonResult.implementation_result;
135
- console.log('Successfully extracted implementation_result');
136
95
  }
137
- else {
138
- console.log('ERROR: Invalid JSON structure - missing implementation_result');
139
- throw new Error('Invalid JSON structure');
96
+ else if (content.type === 'tool_use') {
97
+ if (verbose) {
98
+ console.log(`\n🔧 ${content.name}: ${content.input.description || 'Running...'}`);
99
+ }
140
100
  }
141
101
  }
142
- catch (error) {
143
- console.log('=== DEBUG: JSON Parsing Failed ===');
144
- console.log('Error type:', error instanceof SyntaxError
145
- ? 'SyntaxError'
146
- : error instanceof Error
147
- ? error.constructor.name
148
- : 'Unknown');
149
- console.log('Error message:', error instanceof Error ? error.message : String(error));
150
- logError(`Failed to parse structured implementation result: ${error}`);
151
- console.log('=== DEBUG: Using Fallback Parsing ===');
152
- // Fallback parsing
153
- const parsedResult = parseImplementationResponse(message.result || lastAssistantResponse, featureId);
154
- console.log('Fallback parsed result:', {
155
- branchName: parsedResult.branchName,
156
- filesModifiedCount: parsedResult.filesModified?.length || 0,
157
- hasSummary: !!parsedResult.summary,
158
- commitHash: parsedResult.commitHash,
159
- });
160
- structuredImplementationResult = {
161
- branch_name: parsedResult.branchName,
162
- files_modified: parsedResult.filesModified,
163
- commit_hash: parsedResult.commitHash,
164
- summary: parsedResult.summary || 'Implementation completed',
165
- tests_passed: true,
166
- pre_commit_passed: true,
167
- checklist_item_results: parsedResult.checklist_item_results || [],
168
- };
169
- }
170
102
  }
171
- else {
172
- logError(`\n⚠️ Code implementation incomplete: ${message.subtype}`);
173
- if (message.subtype === 'error_max_turns') {
174
- logError('💡 Try breaking down the feature into smaller tasks');
175
- }
176
- // Try to parse results from the last assistant response
177
- if (lastAssistantResponse) {
178
- console.log('=== DEBUG: Fallback for incomplete result ===');
179
- console.log('message.subtype:', message.subtype);
103
+ if (message.type === 'result') {
104
+ if (message.subtype === 'success') {
105
+ logInfo('\n💻 Code implementation completed, parsing results...');
180
106
  try {
181
- const responseText = lastAssistantResponse;
107
+ // Try to extract JSON from markdown code block or parse directly
108
+ const responseText = message.result || lastAssistantResponse;
182
109
  let jsonResult = null;
183
- console.log('lastAssistantResponse length:', responseText.length);
184
- console.log('lastAssistantResponse first 200 chars:', JSON.stringify(responseText.substring(0, 200)));
110
+ // DEBUG: Log response text details and checklist content
111
+ console.log('=== DEBUG: Code Implementation Response Analysis ===');
112
+ console.log('message.result exists:', !!message.result);
113
+ console.log('lastAssistantResponse exists:', !!lastAssistantResponse);
114
+ console.log('responseText length:', responseText.length);
115
+ console.log('responseText first 200 chars:', JSON.stringify(responseText.substring(0, 200)));
116
+ console.log('responseText last 200 chars:', JSON.stringify(responseText.substring(responseText.length - 200)));
117
+ console.log('Contains ```json:', responseText.includes('```json'));
118
+ console.log('Contains implementation_result:', responseText.includes('"implementation_result"'));
119
+ console.log('=== DEBUG: Checklist Content in Response ===');
120
+ console.log('Contains "checklist":', responseText.toLowerCase().includes('checklist'));
121
+ console.log('Contains "checklist_item_results":', responseText.includes('checklist_item_results'));
122
+ console.log('Contains checklist_item_id:', responseText.includes('checklist_item_id'));
123
+ console.log('Contains is_passed:', responseText.includes('is_passed'));
124
+ // Count checklist-related occurrences
125
+ const checklistMatches = responseText.match(/checklist/gi) || [];
126
+ const checklistItemMatches = responseText.match(/checklist_item/gi) || [];
127
+ console.log('Total "checklist" mentions:', checklistMatches.length);
128
+ console.log('Total "checklist_item" mentions:', checklistItemMatches.length);
129
+ // First try to extract JSON from markdown code block
185
130
  const jsonBlockMatch = responseText.match(/```json\s*\n([\s\S]*?)\n\s*```/);
186
- console.log('jsonBlockMatch in fallback found:', !!jsonBlockMatch);
131
+ console.log('=== DEBUG: Markdown Block Match ===');
132
+ console.log('jsonBlockMatch found:', !!jsonBlockMatch);
187
133
  if (jsonBlockMatch) {
134
+ console.log('Matched JSON length:', jsonBlockMatch[1].length);
135
+ console.log('Matched JSON first 100 chars:', JSON.stringify(jsonBlockMatch[1].substring(0, 100)));
188
136
  jsonResult = JSON.parse(jsonBlockMatch[1]);
189
- if (jsonResult && jsonResult.implementation_result) {
190
- structuredImplementationResult =
191
- jsonResult.implementation_result;
137
+ }
138
+ else {
139
+ console.log('=== DEBUG: Trying direct JSON parse ===');
140
+ // Try to parse the entire response as JSON
141
+ jsonResult = JSON.parse(responseText);
142
+ }
143
+ console.log('=== DEBUG: Final Result Processing ===');
144
+ console.log('jsonResult exists:', !!jsonResult);
145
+ console.log('jsonResult has implementation_result:', !!(jsonResult && jsonResult.implementation_result));
146
+ if (jsonResult && jsonResult.implementation_result) {
147
+ const implResult = jsonResult.implementation_result;
148
+ console.log('=== DEBUG: Implementation Result Structure ===');
149
+ console.log('Keys in implementation_result:', Object.keys(implResult));
150
+ console.log('Has checklist_item_results field:', 'checklist_item_results' in implResult);
151
+ console.log('checklist_item_results value type:', typeof implResult.checklist_item_results);
152
+ console.log('checklist_item_results is array:', Array.isArray(implResult.checklist_item_results));
153
+ if (implResult.checklist_item_results) {
154
+ console.log('checklist_item_results length:', implResult.checklist_item_results.length);
155
+ if (implResult.checklist_item_results.length > 0) {
156
+ console.log('First checklist item keys:', Object.keys(implResult.checklist_item_results[0]));
157
+ console.log('First checklist item sample:', JSON.stringify(implResult.checklist_item_results[0], null, 2));
158
+ }
159
+ }
160
+ else {
161
+ console.log('checklist_item_results is null/undefined/empty');
192
162
  }
163
+ newImplementationResult = jsonResult.implementation_result;
164
+ console.log('Successfully extracted implementation_result');
165
+ }
166
+ else {
167
+ console.log('ERROR: Invalid JSON structure - missing implementation_result');
168
+ throw new Error('Invalid JSON structure');
193
169
  }
194
170
  }
195
171
  catch (error) {
196
- logError(`Failed to parse assistant response: ${error}`);
172
+ console.log('=== DEBUG: JSON Parsing Failed ===');
173
+ console.log('Error type:', error instanceof SyntaxError
174
+ ? 'SyntaxError'
175
+ : error instanceof Error
176
+ ? error.constructor.name
177
+ : 'Unknown');
178
+ console.log('Error message:', error instanceof Error ? error.message : String(error));
179
+ logError(`Failed to parse structured implementation result: ${error}`);
180
+ console.log('=== DEBUG: Using Fallback Parsing ===');
181
+ // Fallback parsing
182
+ const parsedResult = parseImplementationResponse(message.result || lastAssistantResponse, featureId);
183
+ console.log('Fallback parsed result:', {
184
+ branchName: parsedResult.branchName,
185
+ filesModifiedCount: parsedResult.filesModified?.length || 0,
186
+ hasSummary: !!parsedResult.summary,
187
+ commitHash: parsedResult.commitHash,
188
+ });
189
+ newImplementationResult = {
190
+ branch_name: parsedResult.branchName,
191
+ files_modified: parsedResult.filesModified,
192
+ commit_hash: parsedResult.commitHash,
193
+ summary: parsedResult.summary || 'Implementation completed',
194
+ tests_passed: true,
195
+ pre_commit_passed: true,
196
+ checklist_item_results: parsedResult.checklist_item_results || [],
197
+ };
198
+ }
199
+ }
200
+ else {
201
+ logError(`\n⚠️ Code implementation incomplete: ${message.subtype}`);
202
+ if (message.subtype === 'error_max_turns') {
203
+ logError('💡 Try breaking down the feature into smaller tasks');
204
+ }
205
+ // Try to parse results from the last assistant response
206
+ if (lastAssistantResponse) {
207
+ console.log('=== DEBUG: Fallback for incomplete result ===');
208
+ console.log('message.subtype:', message.subtype);
209
+ try {
210
+ const responseText = lastAssistantResponse;
211
+ let jsonResult = null;
212
+ console.log('lastAssistantResponse length:', responseText.length);
213
+ console.log('lastAssistantResponse first 200 chars:', JSON.stringify(responseText.substring(0, 200)));
214
+ const jsonBlockMatch = responseText.match(/```json\s*\n([\s\S]*?)\n\s*```/);
215
+ console.log('jsonBlockMatch in fallback found:', !!jsonBlockMatch);
216
+ if (jsonBlockMatch) {
217
+ jsonResult = JSON.parse(jsonBlockMatch[1]);
218
+ if (jsonResult && jsonResult.implementation_result) {
219
+ newImplementationResult = jsonResult.implementation_result;
220
+ }
221
+ }
222
+ }
223
+ catch (error) {
224
+ logError(`Failed to parse assistant response: ${error}`);
225
+ }
197
226
  }
198
227
  }
199
228
  }
200
229
  }
201
- }
202
- if (structuredImplementationResult) {
203
- const { branch_name, files_modified, commit_hash, summary, checklist_results, checklist_item_results, } = structuredImplementationResult;
204
- return {
230
+ // Check if implementation produced results
231
+ if (!newImplementationResult) {
232
+ if (verbose) {
233
+ logError('⚠️ Implementation failed in this iteration');
234
+ }
235
+ break;
236
+ }
237
+ // Update with new implementation result
238
+ structuredImplementationResult = newImplementationResult;
239
+ // Log implementation completion for this iteration
240
+ await logFeaturePhaseEvent(mcpServerUrl, mcpToken, {
205
241
  featureId,
206
- branchName: branch_name || `dev/${featureId}`,
207
- implementationSummary: summary || 'Implementation completed',
208
- status: 'success',
209
- message: 'Code implementation completed successfully',
210
- filesModified: files_modified || [],
211
- commitHash: commit_hash || '',
212
- data: {
213
- checklist_results,
214
- checklist_item_results,
242
+ eventType: 'phase_completed',
243
+ phase: 'code_implementation',
244
+ result: 'success',
245
+ metadata: {
246
+ iteration: currentIteration,
247
+ max_iterations: maxIterations,
248
+ implementation_step: 'completed',
249
+ branch_name: structuredImplementationResult.branch_name,
250
+ files_modified: structuredImplementationResult.files_modified || [],
251
+ commit_hash: structuredImplementationResult.commit_hash || '',
252
+ timestamp: new Date().toISOString(),
215
253
  },
216
- };
254
+ }, verbose);
255
+ // Push code to remote after commit
256
+ if (verbose) {
257
+ logInfo(`📤 Pushing code to remote repository...`);
258
+ }
259
+ const pushResult = await pushToRemote(structuredImplementationResult.branch_name || branchName, verbose);
260
+ if (!pushResult.success && verbose) {
261
+ logError(`⚠️ Failed to push to remote: ${pushResult.error}`);
262
+ logInfo(' Code is committed locally and will be reviewed. Manual push may be needed.');
263
+ }
264
+ else if (verbose) {
265
+ logInfo('✅ Code pushed to remote successfully');
266
+ }
267
+ // Perform verification cycle
268
+ const verificationCycle = await performVerificationCycle(structuredImplementationResult.branch_name || branchName, baseBranch, checklistContext || null, featureId, context.feature.name, context.feature.description, config, currentIteration, maxIterations, mcpServerUrl, mcpToken, verbose);
269
+ verificationResult = verificationCycle.verificationResult;
270
+ // If verification passed, exit
271
+ if (verificationCycle.passed) {
272
+ if (verbose) {
273
+ logInfo('✅ Verification passed! Code implementation complete.');
274
+ }
275
+ break;
276
+ }
277
+ // Verification failed
278
+ if (currentIteration < maxIterations && verificationCycle.nextPrompt) {
279
+ // We have more iterations - retry with improvement prompt
280
+ if (verbose) {
281
+ logInfo(`🔄 Will improve implementation in next iteration (${maxIterations - currentIteration} attempts remaining)`);
282
+ }
283
+ currentPrompt = verificationCycle.nextPrompt;
284
+ }
285
+ else {
286
+ // Max iterations reached or no next prompt - exit loop
287
+ if (verbose) {
288
+ logInfo('⚠️ Max iterations reached. Last implementation committed.');
289
+ }
290
+ break;
291
+ }
217
292
  }
218
- else {
219
- return {
220
- featureId,
221
- branchName: `dev/${featureId}`,
222
- implementationSummary: null,
223
- status: 'error',
224
- message: 'Code implementation failed or incomplete',
225
- };
293
+ // Handle results
294
+ if (!structuredImplementationResult) {
295
+ return buildNoResultsError(featureId, branchName);
296
+ }
297
+ const { branch_name, files_modified, commit_hash, summary, checklist_results, checklist_item_results, } = structuredImplementationResult;
298
+ // Check if verification failed after all iterations
299
+ if (verificationResult &&
300
+ verificationResult.rejected_count > 0 &&
301
+ checklistContext &&
302
+ checklistContext.checklists.length > 0) {
303
+ logError(`❌ Final result: Code verification FAILED after ${currentIteration} iterations`);
304
+ logError(` Code committed for manual review`);
305
+ return buildVerificationFailureResult(featureId, branch_name || branchName, summary || 'Implementation completed with verification failures', files_modified || [], commit_hash || '', verificationResult, currentIteration);
226
306
  }
307
+ // Return success result
308
+ return buildImplementationResult(featureId, branch_name || branchName, summary || 'Implementation completed successfully', files_modified || [], commit_hash || '', currentIteration, checklist_results, checklist_item_results);
227
309
  }
228
310
  catch (error) {
229
311
  logError(`Code implementation failed: ${error instanceof Error ? error.message : String(error)}`);
@@ -273,11 +355,11 @@ CRITICAL: Checklists are not optional suggestions - they are mandatory quality g
273
355
  - git pull origin ${baseBranch} --rebase
274
356
  2. **CREATE BRANCH**: Create a new feature branch from ${baseBranch}
275
357
  3. **ANALYZE CODEBASE**: Use Glob and Read to understand the existing code structure
276
- 3. **IMPLEMENT CODE**: Write the actual implementation using Edit/Write tools
277
- 4. **TEST**: Run tests to ensure everything works
278
- 5. **FIX ISSUES**: Address any lint or test failures
279
- 6. **COMMIT**: Commit your changes with a descriptive message
280
- 7. **HANDLE PRE-COMMIT**: This project has strict pre-commit hooks - handle them properly:
358
+ 4. **IMPLEMENT CODE**: Write the actual implementation using Edit/Write tools
359
+ 5. **TEST**: Run tests to ensure everything works
360
+ 6. **FIX ISSUES**: Address any lint or test failures
361
+ 7. **COMMIT**: Commit your changes with a descriptive message
362
+ 8. **HANDLE PRE-COMMIT**: This project has strict pre-commit hooks - handle them properly:
281
363
  - If lint-staged fails: Fix formatting and linting issues, then retry commit
282
364
  - If AI code review fails: Either fix code quality issues or use SKIP_REVIEW=1
283
365
  - If other issues persist: Only use --no-verify as last resort after confirming code quality
@@ -490,6 +572,53 @@ const parseImplementationResponse = (response, featureId) => {
490
572
  };
491
573
  }
492
574
  };
575
+ /**
576
+ * Push branch to remote repository
577
+ */
578
+ async function pushToRemote(branchName, verbose) {
579
+ try {
580
+ // Import exec from child_process
581
+ const { execSync } = await import('child_process');
582
+ if (verbose) {
583
+ logInfo(`Pushing branch ${branchName} to remote...`);
584
+ }
585
+ // Try to push with -u flag (sets upstream if not already set)
586
+ try {
587
+ execSync(`git push -u origin ${branchName}`, {
588
+ encoding: 'utf-8',
589
+ stdio: verbose ? 'inherit' : 'pipe',
590
+ });
591
+ return { success: true };
592
+ }
593
+ catch (error) {
594
+ // If push fails, it might be because branch already has upstream
595
+ // Try without -u flag
596
+ try {
597
+ execSync(`git push origin ${branchName}`, {
598
+ encoding: 'utf-8',
599
+ stdio: verbose ? 'inherit' : 'pipe',
600
+ });
601
+ return { success: true };
602
+ }
603
+ catch (retryError) {
604
+ const errorMessage = retryError instanceof Error
605
+ ? retryError.message
606
+ : String(retryError);
607
+ return {
608
+ success: false,
609
+ error: errorMessage,
610
+ };
611
+ }
612
+ }
613
+ }
614
+ catch (error) {
615
+ const errorMessage = error instanceof Error ? error.message : String(error);
616
+ return {
617
+ success: false,
618
+ error: errorMessage,
619
+ };
620
+ }
621
+ }
493
622
  export const checkCodeImplementationRequirements = async () => {
494
623
  try {
495
624
  // Check if Claude Code SDK is available
@@ -0,0 +1 @@
1
+ export { verifyCodeImplementationCompliance, type ChecklistItemVerificationResult, type ChecklistVerificationResult, type VerifyCodeImplementationOptions, } from './verifier.js';
@@ -0,0 +1 @@
1
+ export { verifyCodeImplementationCompliance, } from './verifier.js';
@@ -0,0 +1,31 @@
1
+ import { EdsgerConfig } from '../../types/index.js';
2
+ export interface ChecklistItemVerificationResult {
3
+ checklist_item_id: string;
4
+ is_satisfied: boolean;
5
+ verification_status: 'confirmed' | 'rejected' | 'uncertain';
6
+ verification_reason: string;
7
+ concerns?: string[];
8
+ improvement_suggestions?: string[];
9
+ }
10
+ export interface ChecklistVerificationResult {
11
+ overall_status: 'passed' | 'failed' | 'partial';
12
+ summary: string;
13
+ confirmed_count: number;
14
+ rejected_count: number;
15
+ uncertain_count: number;
16
+ item_verifications: ChecklistItemVerificationResult[];
17
+ overall_suggestions?: string[];
18
+ }
19
+ export interface VerifyCodeImplementationOptions {
20
+ featureId: string;
21
+ branchName: string;
22
+ baseBranch: string;
23
+ featureName: string;
24
+ featureDescription?: string;
25
+ checklistContext: string;
26
+ verbose?: boolean;
27
+ }
28
+ /**
29
+ * Verify code implementation against checklist requirements by reviewing git diff
30
+ */
31
+ export declare function verifyCodeImplementationCompliance(options: VerifyCodeImplementationOptions, config: EdsgerConfig): Promise<ChecklistVerificationResult>;