edsger 0.34.0 → 0.35.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/dist/api/features/approval-checker.js +6 -8
  2. package/dist/commands/agent-workflow/chat-worker.js +2 -1
  3. package/dist/commands/agent-workflow/processor.js +3 -1
  4. package/dist/commands/code-review/index.js +5 -7
  5. package/dist/commands/workflow/phase-orchestrator.js +16 -32
  6. package/dist/constants.js +2 -0
  7. package/dist/index.js +3 -1
  8. package/dist/phases/app-store-generation/__tests__/agent.test.js +1 -3
  9. package/dist/phases/app-store-generation/__tests__/screenshot-composer.test.js +2 -4
  10. package/dist/phases/app-store-generation/agent.js +1 -3
  11. package/dist/phases/app-store-generation/index.js +4 -3
  12. package/dist/phases/app-store-generation/screenshot-composer.js +3 -5
  13. package/dist/phases/autonomous/index.js +4 -3
  14. package/dist/phases/branch-planning/context.js +7 -7
  15. package/dist/phases/branch-planning/index.js +5 -3
  16. package/dist/phases/bug-fixing/analyzer.js +13 -13
  17. package/dist/phases/bug-fixing/context-fetcher.js +9 -9
  18. package/dist/phases/bug-fixing/mcp-server.js +14 -17
  19. package/dist/phases/code-implementation/context.js +5 -5
  20. package/dist/phases/code-implementation/index.js +5 -4
  21. package/dist/phases/code-implementation-verification/agent.js +3 -1
  22. package/dist/phases/code-refine/context.js +1 -1
  23. package/dist/phases/code-refine/index.js +4 -6
  24. package/dist/phases/code-refine/refine-iteration.js +10 -10
  25. package/dist/phases/code-refine-verification/index.js +80 -82
  26. package/dist/phases/code-review/index.js +8 -8
  27. package/dist/phases/code-testing/analyzer.js +3 -1
  28. package/dist/phases/code-testing/context-fetcher.js +5 -5
  29. package/dist/phases/feature-analysis/agent.js +1 -3
  30. package/dist/phases/feature-analysis/context.js +5 -5
  31. package/dist/phases/feature-analysis/index.js +4 -4
  32. package/dist/phases/feature-analysis/outcome.d.ts +1 -1
  33. package/dist/phases/feature-analysis/outcome.js +7 -7
  34. package/dist/phases/feature-analysis-verification/index.js +6 -6
  35. package/dist/phases/functional-testing/analyzer.js +4 -2
  36. package/dist/phases/functional-testing/context-fetcher.js +5 -5
  37. package/dist/phases/functional-testing/http-fallback.js +4 -2
  38. package/dist/phases/functional-testing/mcp-server.js +3 -3
  39. package/dist/phases/growth-analysis/agent.js +1 -3
  40. package/dist/phases/pr-execution/index.js +3 -1
  41. package/dist/phases/pr-splitting/context.js +6 -6
  42. package/dist/phases/pr-splitting/index.js +3 -1
  43. package/dist/phases/pull-request/handler.js +2 -4
  44. package/dist/phases/task/agent.js +6 -8
  45. package/dist/phases/technical-design/context.js +5 -5
  46. package/dist/phases/technical-design/index.js +9 -8
  47. package/dist/phases/test-cases-analysis/agent.js +1 -3
  48. package/dist/phases/test-cases-analysis/context.js +5 -5
  49. package/dist/phases/test-cases-analysis/index.js +3 -3
  50. package/dist/phases/test-cases-analysis/outcome.d.ts +1 -1
  51. package/dist/phases/test-cases-analysis/outcome.js +4 -4
  52. package/dist/phases/user-stories-analysis/agent.js +1 -3
  53. package/dist/phases/user-stories-analysis/context.js +5 -5
  54. package/dist/phases/user-stories-analysis/index.js +3 -3
  55. package/dist/phases/user-stories-analysis/outcome.d.ts +1 -1
  56. package/dist/phases/user-stories-analysis/outcome.js +4 -4
  57. package/dist/services/coaching/coaching-loop.js +1 -1
  58. package/dist/services/coaching/self-rating.js +1 -1
  59. package/dist/services/phase-ratings.js +2 -1
  60. package/dist/services/video/__tests__/video-pipeline.test.js +3 -1
  61. package/dist/services/video/retry.js +5 -2
  62. package/dist/services/video/screenshot-generator.js +1 -1
  63. package/dist/services/video/video-assembler.d.ts +1 -1
  64. package/dist/services/video/video-assembler.js +3 -3
  65. package/dist/utils/conflict-resolver.js +13 -15
  66. package/dist/utils/git-branch-manager-async.js +5 -7
  67. package/dist/utils/git-push.js +2 -2
  68. package/package.json +1 -1
@@ -17,7 +17,9 @@ function userMessage(content) {
17
17
  }
18
18
  async function* prompt(refinePrompt) {
19
19
  yield userMessage(refinePrompt);
20
- await new Promise((res) => setTimeout(res, 10000));
20
+ await new Promise((res) => {
21
+ setTimeout(res, 10000);
22
+ });
21
23
  }
22
24
  // eslint-disable-next-line complexity -- agent loop with message processing and result extraction
23
25
  export async function executeRefineIteration(opts) {
@@ -135,12 +137,10 @@ export async function executeRefineIteration(opts) {
135
137
  execution_session_id: executionSessionId || undefined,
136
138
  };
137
139
  }
138
- else {
139
- return {
140
- status: 'error',
141
- message: 'Code refine failed or incomplete',
142
- };
143
- }
140
+ return {
141
+ status: 'error',
142
+ message: 'Code refine failed or incomplete',
143
+ };
144
144
  }
145
145
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
146
146
  function parseCodeRefineResponse(response) {
@@ -149,16 +149,16 @@ function parseCodeRefineResponse(response) {
149
149
  ? summaryMatch[1].trim()
150
150
  : 'Code refined based on PR feedback';
151
151
  const filesMatch = response.match(/## Files Modified\n([\s\S]*?)(?=\n##|\n\n|$)/);
152
- let files_modified = [];
152
+ let filesModified = [];
153
153
  if (filesMatch) {
154
- files_modified = filesMatch[1]
154
+ filesModified = filesMatch[1]
155
155
  .split('\n')
156
156
  .filter((line) => line.trim().startsWith('-'))
157
157
  .map((line) => line.replace(/^-\s*/, '').trim());
158
158
  }
159
159
  return {
160
160
  summary,
161
- files_modified,
161
+ files_modified: filesModified,
162
162
  commits_created: 1,
163
163
  feedback_addressed: [],
164
164
  };
@@ -147,97 +147,95 @@ export async function verifyAndResolveComments(options) {
147
147
  },
148
148
  };
149
149
  }
150
- else {
151
- // Verification failed - build detailed info with specific failure reasons from LLM analysis
152
- // Calculate remaining reviews that weren't dismissed
153
- const remainingReviewsCount = changesRequestedReviews.length - dismissedReviewsCount;
154
- if (verbose) {
155
- if (remainingReviewsCount > 0) {
156
- logInfo(`⚠️ ${remainingReviewsCount} reviews still requesting changes (failed to dismiss)`);
157
- changesRequestedReviews.forEach((review) => {
158
- logInfo(` - Review ${review.id} by @${review.user.login}`);
159
- if (review.body) {
160
- logInfo(` ${review.body.substring(0, 100)}...`);
161
- }
162
- });
163
- }
164
- if (trulyUnresolvedThreads.length > 0) {
165
- logInfo(`⚠️ ${trulyUnresolvedThreads.length} review threads still need to be addressed`);
166
- trulyUnresolvedThreads.forEach((result) => {
167
- const firstComment = result.thread.comments.nodes[0];
168
- if (firstComment) {
169
- logInfo(` - Comment by @${firstComment.author.login}`);
170
- logInfo(` File: ${firstComment.path}:${firstComment.line || '?'}`);
171
- logInfo(` ${firstComment.body.substring(0, 100)}...`);
172
- logInfo(` LLM Analysis: ${result.analysis.reason}`);
173
- }
174
- });
175
- }
176
- }
177
- // Build targeted suggestions based on LLM analysis
178
- const suggestions = [];
179
- // Create specific suggestions for each truly unresolved comment (based on LLM analysis)
180
- trulyUnresolvedThreads.forEach((result, index) => {
181
- const firstComment = result.thread.comments.nodes[0];
182
- if (firstComment) {
183
- suggestions.push(`${index + 1}. [${firstComment.path}:${firstComment.line || '?'}] by @${firstComment.author.login}: ${result.analysis.reason}`);
184
- }
185
- });
186
- // Add review-specific suggestions if any reviews failed to dismiss
150
+ // Verification failed - build detailed info with specific failure reasons from LLM analysis
151
+ // Calculate remaining reviews that weren't dismissed
152
+ const remainingReviewsCount = changesRequestedReviews.length - dismissedReviewsCount;
153
+ if (verbose) {
187
154
  if (remainingReviewsCount > 0) {
188
- suggestions.push(`\n${remainingReviewsCount} review(s) requesting changes could not be automatically dismissed:`);
155
+ logInfo(`⚠️ ${remainingReviewsCount} reviews still requesting changes (failed to dismiss)`);
189
156
  changesRequestedReviews.forEach((review) => {
190
- suggestions.push(` - @${review.user.login}: ${review.body ? review.body.substring(0, 150) : 'No details provided'}${review.body && review.body.length > 150 ? '...' : ''}`);
157
+ logInfo(` - Review ${review.id} by @${review.user.login}`);
158
+ if (review.body) {
159
+ logInfo(` ${review.body.substring(0, 100)}...`);
160
+ }
191
161
  });
192
162
  }
193
- // Build detailed unresolved info with LLM-analyzed failure reasons
194
- const unresolvedCommentDetails = trulyUnresolvedThreads.map((result) => {
195
- const firstComment = result.thread.comments.nodes[0];
196
- return {
197
- commentId: firstComment.id,
198
- author: firstComment.author.login,
199
- file: firstComment.path,
200
- line: firstComment.line,
201
- body: firstComment.body,
202
- failureReason: result.analysis.reason, // Use LLM analysis result
203
- url: firstComment.url,
204
- };
205
- });
206
- const unresolvedReviewDetails = changesRequestedReviews.map((review) => ({
207
- reviewId: review.id,
208
- author: review.user.login,
209
- state: review.state,
210
- body: review.body,
211
- submittedAt: review.submitted_at,
212
- }));
213
- let errorMessage = '';
214
- if (remainingReviewsCount > 0 && trulyUnresolvedThreads.length > 0) {
215
- errorMessage = `${remainingReviewsCount} reviews and ${trulyUnresolvedThreads.length} review threads still need to be addressed (based on LLM analysis)`;
216
- }
217
- else if (remainingReviewsCount > 0) {
218
- errorMessage = `${remainingReviewsCount} reviews could not be dismissed`;
163
+ if (trulyUnresolvedThreads.length > 0) {
164
+ logInfo(`⚠️ ${trulyUnresolvedThreads.length} review threads still need to be addressed`);
165
+ trulyUnresolvedThreads.forEach((result) => {
166
+ const firstComment = result.thread.comments.nodes[0];
167
+ if (firstComment) {
168
+ logInfo(` - Comment by @${firstComment.author.login}`);
169
+ logInfo(` File: ${firstComment.path}:${firstComment.line || '?'}`);
170
+ logInfo(` ${firstComment.body.substring(0, 100)}...`);
171
+ logInfo(` LLM Analysis: ${result.analysis.reason}`);
172
+ }
173
+ });
219
174
  }
220
- else {
221
- errorMessage = `${trulyUnresolvedThreads.length} review comments still need to be addressed (based on LLM analysis)`;
175
+ }
176
+ // Build targeted suggestions based on LLM analysis
177
+ const suggestions = [];
178
+ // Create specific suggestions for each truly unresolved comment (based on LLM analysis)
179
+ trulyUnresolvedThreads.forEach((result, index) => {
180
+ const firstComment = result.thread.comments.nodes[0];
181
+ if (firstComment) {
182
+ suggestions.push(`${index + 1}. [${firstComment.path}:${firstComment.line || '?'}] by @${firstComment.author.login}: ${result.analysis.reason}`);
222
183
  }
184
+ });
185
+ // Add review-specific suggestions if any reviews failed to dismiss
186
+ if (remainingReviewsCount > 0) {
187
+ suggestions.push(`\n${remainingReviewsCount} review(s) requesting changes could not be automatically dismissed:`);
188
+ changesRequestedReviews.forEach((review) => {
189
+ suggestions.push(` - @${review.user.login}: ${review.body ? review.body.substring(0, 150) : 'No details provided'}${review.body && review.body.length > 150 ? '...' : ''}`);
190
+ });
191
+ }
192
+ // Build detailed unresolved info with LLM-analyzed failure reasons
193
+ const unresolvedCommentDetails = trulyUnresolvedThreads.map((result) => {
194
+ const firstComment = result.thread.comments.nodes[0];
223
195
  return {
224
- status: 'error',
225
- message: errorMessage,
226
- data: {
227
- featureId,
228
- totalReviews: reviews.length,
229
- unresolvedReviews: remainingReviewsCount,
230
- totalComments: unresolvedThreads.length, // Original count before LLM analysis
231
- resolvedComments: addressedThreads.length, // LLM determined these are addressed
232
- unresolvedComments: trulyUnresolvedThreads.length, // LLM determined these still need work
233
- commentsMarkedResolved: addressedThreads.length,
234
- dismissedReviews: dismissedReviewsCount,
235
- suggestions,
236
- unresolvedReviewDetails,
237
- unresolvedCommentDetails,
238
- },
196
+ commentId: firstComment.id,
197
+ author: firstComment.author.login,
198
+ file: firstComment.path,
199
+ line: firstComment.line,
200
+ body: firstComment.body,
201
+ failureReason: result.analysis.reason, // Use LLM analysis result
202
+ url: firstComment.url,
239
203
  };
204
+ });
205
+ const unresolvedReviewDetails = changesRequestedReviews.map((review) => ({
206
+ reviewId: review.id,
207
+ author: review.user.login,
208
+ state: review.state,
209
+ body: review.body,
210
+ submittedAt: review.submitted_at,
211
+ }));
212
+ let errorMessage = '';
213
+ if (remainingReviewsCount > 0 && trulyUnresolvedThreads.length > 0) {
214
+ errorMessage = `${remainingReviewsCount} reviews and ${trulyUnresolvedThreads.length} review threads still need to be addressed (based on LLM analysis)`;
215
+ }
216
+ else if (remainingReviewsCount > 0) {
217
+ errorMessage = `${remainingReviewsCount} reviews could not be dismissed`;
218
+ }
219
+ else {
220
+ errorMessage = `${trulyUnresolvedThreads.length} review comments still need to be addressed (based on LLM analysis)`;
240
221
  }
222
+ return {
223
+ status: 'error',
224
+ message: errorMessage,
225
+ data: {
226
+ featureId,
227
+ totalReviews: reviews.length,
228
+ unresolvedReviews: remainingReviewsCount,
229
+ totalComments: unresolvedThreads.length, // Original count before LLM analysis
230
+ resolvedComments: addressedThreads.length, // LLM determined these are addressed
231
+ unresolvedComments: trulyUnresolvedThreads.length, // LLM determined these still need work
232
+ commentsMarkedResolved: addressedThreads.length,
233
+ dismissedReviews: dismissedReviewsCount,
234
+ suggestions,
235
+ unresolvedReviewDetails,
236
+ unresolvedCommentDetails,
237
+ },
238
+ };
241
239
  }
242
240
  catch (error) {
243
241
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -21,7 +21,9 @@ function userMessage(content) {
21
21
  }
22
22
  async function* prompt(reviewPrompt) {
23
23
  yield userMessage(reviewPrompt);
24
- await new Promise((res) => setTimeout(res, 10000));
24
+ await new Promise((res) => {
25
+ setTimeout(res, 10000);
26
+ });
25
27
  }
26
28
  /**
27
29
  * Parse unified diff patch to build a mapping from file line numbers to diff positions
@@ -561,13 +563,11 @@ export const reviewPullRequest = async (options, config, checklistContext
561
563
  },
562
564
  };
563
565
  }
564
- else {
565
- return {
566
- featureId,
567
- status: 'error',
568
- message: 'Code review analysis failed or incomplete',
569
- };
570
- }
566
+ return {
567
+ featureId,
568
+ status: 'error',
569
+ message: 'Code review analysis failed or incomplete',
570
+ };
571
571
  }
572
572
  catch (error) {
573
573
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -27,7 +27,9 @@ function userMessage(content) {
27
27
  }
28
28
  async function* prompt(testingPrompt) {
29
29
  yield userMessage(testingPrompt);
30
- await new Promise((res) => setTimeout(res, 10000));
30
+ await new Promise((res) => {
31
+ setTimeout(res, 10000);
32
+ });
31
33
  }
32
34
  export const writeCodeTests = async (options, config
33
35
  // eslint-disable-next-line complexity -- orchestration function with context fetching, agent execution, and test result processing
@@ -10,7 +10,7 @@ export async function fetchCodeTestingContext(featureId, verbose) {
10
10
  logInfo(`Fetching complete code testing context for feature: ${featureId}`);
11
11
  }
12
12
  // Fetch all required data in parallel for better performance
13
- const [feature, user_stories, test_cases] = await Promise.all([
13
+ const [feature, userStories, testCases] = await Promise.all([
14
14
  getFeature(featureId, verbose),
15
15
  getUserStories(featureId, verbose),
16
16
  getTestCases(featureId, verbose),
@@ -20,14 +20,14 @@ export async function fetchCodeTestingContext(featureId, verbose) {
20
20
  logInfo(`✅ Code testing context fetched successfully:`);
21
21
  logInfo(` Feature: ${feature.name}`);
22
22
  logInfo(` Product: ${product.name}`);
23
- logInfo(` User Stories: ${user_stories.length}`);
24
- logInfo(` Test Cases: ${test_cases.length}`);
23
+ logInfo(` User Stories: ${userStories.length}`);
24
+ logInfo(` Test Cases: ${testCases.length}`);
25
25
  }
26
26
  return {
27
27
  feature,
28
28
  product,
29
- user_stories,
30
- test_cases,
29
+ user_stories: userStories,
30
+ test_cases: testCases,
31
31
  };
32
32
  }
33
33
  catch (error) {
@@ -20,9 +20,7 @@ export function parseAnalysisResult(responseText) {
20
20
  if (jsonResult && jsonResult.analysis) {
21
21
  return { analysis: jsonResult.analysis };
22
22
  }
23
- else {
24
- return { error: 'Invalid JSON structure' };
25
- }
23
+ return { error: 'Invalid JSON structure' };
26
24
  }
27
25
  catch (error) {
28
26
  return {
@@ -14,7 +14,7 @@ export async function fetchFeatureAnalysisContext(featureId, verbose) {
14
14
  logInfo(`Fetching complete feature analysis context for feature: ${featureId}`);
15
15
  }
16
16
  // Fetch all required data in parallel for better performance
17
- const [feature, existing_user_stories, existing_test_cases] = await Promise.all([
17
+ const [feature, existingUserStories, existingTestCases] = await Promise.all([
18
18
  getFeature(featureId, verbose),
19
19
  getUserStories(featureId, verbose),
20
20
  getTestCases(featureId, verbose),
@@ -24,14 +24,14 @@ export async function fetchFeatureAnalysisContext(featureId, verbose) {
24
24
  logInfo(`✅ Feature analysis context fetched successfully:`);
25
25
  logInfo(` Feature: ${feature.name}`);
26
26
  logInfo(` Product: ${product.name}`);
27
- logInfo(` Existing User Stories: ${existing_user_stories.length}`);
28
- logInfo(` Existing Test Cases: ${existing_test_cases.length}`);
27
+ logInfo(` Existing User Stories: ${existingUserStories.length}`);
28
+ logInfo(` Existing Test Cases: ${existingTestCases.length}`);
29
29
  }
30
30
  return {
31
31
  feature,
32
32
  product,
33
- existing_user_stories,
34
- existing_test_cases,
33
+ existing_user_stories: existingUserStories,
34
+ existing_test_cases: existingTestCases,
35
35
  };
36
36
  }
37
37
  catch (error) {
@@ -99,9 +99,9 @@ export const analyseFeature = async (options, config, checklistContext
99
99
  if (parsed.analysis) {
100
100
  // Delete old drafts and save improved ones
101
101
  await deleteArtifacts(currentDraftUserStoryIds, currentDraftTestCaseIds, verbose);
102
- const { userStoryIds, testCaseIds } = await saveAnalysisArtifactsAsDraft(featureId, parsed.analysis.created_user_stories || [], parsed.analysis.created_test_cases || [], verbose);
103
- currentDraftUserStoryIds = userStoryIds;
104
- currentDraftTestCaseIds = testCaseIds;
102
+ const { userStoryIds: newUserStoryIds, testCaseIds: newTestCaseIds, } = await saveAnalysisArtifactsAsDraft(featureId, parsed.analysis.created_user_stories || [], parsed.analysis.created_test_cases || [], verbose);
103
+ currentDraftUserStoryIds = newUserStoryIds;
104
+ currentDraftTestCaseIds = newTestCaseIds;
105
105
  structuredAnalysisResult = parsed.analysis;
106
106
  }
107
107
  else {
@@ -121,7 +121,7 @@ export const analyseFeature = async (options, config, checklistContext
121
121
  featureId,
122
122
  verbose,
123
123
  });
124
- verificationResult = verificationCycle.verificationResult;
124
+ ({ verificationResult } = verificationCycle);
125
125
  // If verification passed, update ALL remaining draft artifacts to pending_approval and exit
126
126
  if (verificationCycle.passed) {
127
127
  if (verbose) {
@@ -30,7 +30,7 @@ export declare function updateArtifactsToReady(userStoryIds: string[], testCaseI
30
30
  /**
31
31
  * Save analysis artifacts as draft and return their IDs
32
32
  */
33
- export declare function saveAnalysisArtifactsAsDraft(featureId: string, created_user_stories: Record<string, unknown>[], created_test_cases: Record<string, unknown>[], verbose?: boolean): Promise<{
33
+ export declare function saveAnalysisArtifactsAsDraft(featureId: string, createdUserStories: Record<string, unknown>[], createdTestCases: Record<string, unknown>[], verbose?: boolean): Promise<{
34
34
  userStoryIds: string[];
35
35
  testCaseIds: string[];
36
36
  }>;
@@ -163,18 +163,18 @@ export async function updateArtifactsToReady(userStoryIds, testCaseIds, verbose)
163
163
  /**
164
164
  * Save analysis artifacts as draft and return their IDs
165
165
  */
166
- export async function saveAnalysisArtifactsAsDraft(featureId, created_user_stories, created_test_cases, verbose) {
166
+ export async function saveAnalysisArtifactsAsDraft(featureId, createdUserStories, createdTestCases, verbose) {
167
167
  const userStoryIds = [];
168
168
  const testCaseIds = [];
169
169
  // Save user stories as draft
170
- if (created_user_stories && created_user_stories.length > 0) {
170
+ if (createdUserStories && createdUserStories.length > 0) {
171
171
  if (verbose) {
172
- logInfo(`Saving ${created_user_stories.length} user stories as draft...`);
172
+ logInfo(`Saving ${createdUserStories.length} user stories as draft...`);
173
173
  }
174
174
  try {
175
175
  const result = (await callMcpEndpoint('user_stories/create', {
176
176
  feature_id: featureId,
177
- user_stories: created_user_stories.map((story) => ({
177
+ user_stories: createdUserStories.map((story) => ({
178
178
  title: story.title,
179
179
  description: story.description,
180
180
  status: 'draft',
@@ -192,14 +192,14 @@ export async function saveAnalysisArtifactsAsDraft(featureId, created_user_stori
192
192
  }
193
193
  }
194
194
  // Save test cases as draft
195
- if (created_test_cases && created_test_cases.length > 0) {
195
+ if (createdTestCases && createdTestCases.length > 0) {
196
196
  if (verbose) {
197
- logInfo(`Saving ${created_test_cases.length} test cases as draft...`);
197
+ logInfo(`Saving ${createdTestCases.length} test cases as draft...`);
198
198
  }
199
199
  try {
200
200
  const result = (await callMcpEndpoint('test_cases/create', {
201
201
  feature_id: featureId,
202
- test_cases: created_test_cases.map((testCase) => ({
202
+ test_cases: createdTestCases.map((testCase) => ({
203
203
  name: testCase.name,
204
204
  description: testCase.description,
205
205
  is_critical: testCase.is_critical || false,
@@ -8,9 +8,9 @@ export async function performVerificationCycle(opts) {
8
8
  if (!checklistContext || checklistContext.checklists.length === 0) {
9
9
  return { passed: true, verificationResult: null };
10
10
  }
11
- const created_user_stories = (structuredAnalysisResult.created_user_stories ||
11
+ const createdUserStories = (structuredAnalysisResult.created_user_stories ||
12
12
  []);
13
- const created_test_cases = (structuredAnalysisResult.created_test_cases ||
13
+ const createdTestCases = (structuredAnalysisResult.created_test_cases ||
14
14
  []);
15
15
  if (verbose) {
16
16
  logInfo('🔍 Starting checklist verification...');
@@ -18,8 +18,8 @@ export async function performVerificationCycle(opts) {
18
18
  const verificationResult = await verifyChecklistCompliance({
19
19
  checklistContext,
20
20
  analysisContext: context,
21
- createdUserStories: created_user_stories || [],
22
- createdTestCases: created_test_cases || [],
21
+ createdUserStories: createdUserStories || [],
22
+ createdTestCases: createdTestCases || [],
23
23
  verbose,
24
24
  }, config);
25
25
  // Verification passed
@@ -81,8 +81,8 @@ export async function performVerificationCycle(opts) {
81
81
  }
82
82
  // Create improvement prompt for next iteration
83
83
  const nextPrompt = createImprovementPrompt(verificationResult, {
84
- created_user_stories: created_user_stories || [],
85
- created_test_cases: created_test_cases || [],
84
+ created_user_stories: createdUserStories || [],
85
+ created_test_cases: createdTestCases || [],
86
86
  });
87
87
  return { passed: false, verificationResult, nextPrompt };
88
88
  }
@@ -33,7 +33,9 @@ function userMessage(content) {
33
33
  }
34
34
  async function* prompt(testingPrompt) {
35
35
  yield userMessage(testingPrompt);
36
- await new Promise((res) => setTimeout(res, 10000));
36
+ await new Promise((res) => {
37
+ setTimeout(res, 10000);
38
+ });
37
39
  }
38
40
  /**
39
41
  * Extract JSON from a response using multiple strategies:
@@ -377,7 +379,7 @@ export const runFunctionalTesting = async (options, config, checklistContext
377
379
  const parsed = parseTestResult(responseText);
378
380
  if (parsed) {
379
381
  structuredTestResult = parsed.testResult;
380
- testStatus = parsed.testStatus;
382
+ ({ testStatus } = parsed);
381
383
  }
382
384
  else {
383
385
  structuredTestResult = {
@@ -10,7 +10,7 @@ export async function fetchFunctionalTestingContext(featureId, verbose) {
10
10
  logInfo(`Fetching complete functional testing context for feature: ${featureId}`);
11
11
  }
12
12
  // Fetch all required data in parallel for better performance
13
- const [feature, user_stories, test_cases] = await Promise.all([
13
+ const [feature, userStories, testCases] = await Promise.all([
14
14
  getFeature(featureId, verbose),
15
15
  getUserStories(featureId, verbose),
16
16
  getTestCases(featureId, verbose),
@@ -20,14 +20,14 @@ export async function fetchFunctionalTestingContext(featureId, verbose) {
20
20
  logInfo(`✅ Functional testing context fetched successfully:`);
21
21
  logInfo(` Feature: ${feature.name}`);
22
22
  logInfo(` Product: ${product.name}`);
23
- logInfo(` User Stories: ${user_stories.length}`);
24
- logInfo(` Test Cases: ${test_cases.length}`);
23
+ logInfo(` User Stories: ${userStories.length}`);
24
+ logInfo(` Test Cases: ${testCases.length}`);
25
25
  }
26
26
  return {
27
27
  feature,
28
28
  product,
29
- user_stories,
30
- test_cases,
29
+ user_stories: userStories,
30
+ test_cases: testCases,
31
31
  };
32
32
  }
33
33
  catch (error) {
@@ -119,7 +119,7 @@ export async function saveFunctionalTestResultsWithRetry(options, maxRetries = 3
119
119
  }
120
120
  return true;
121
121
  }
122
- else if (verbose) {
122
+ if (verbose) {
123
123
  logError(`❌ Save appeared successful but verification failed (attempt ${attempt})`);
124
124
  }
125
125
  }
@@ -128,7 +128,9 @@ export async function saveFunctionalTestResultsWithRetry(options, maxRetries = 3
128
128
  if (verbose) {
129
129
  logInfo(`⏳ Waiting ${delay}ms before retry...`);
130
130
  }
131
- await new Promise((resolve) => setTimeout(resolve, delay));
131
+ await new Promise((resolve) => {
132
+ setTimeout(resolve, delay);
133
+ });
132
134
  }
133
135
  }
134
136
  if (verbose) {
@@ -108,7 +108,7 @@ export const createFunctionalTestingMcpServer = () => {
108
108
  .optional()
109
109
  .default('testing')
110
110
  .describe('Environment name (testing, staging, production)'),
111
- }, async (args) => {
111
+ }, (args) => {
112
112
  // Get environment variables for testing configuration
113
113
  const testingConfig = {
114
114
  environment: args.environment || 'testing',
@@ -119,14 +119,14 @@ export const createFunctionalTestingMcpServer = () => {
119
119
  if (!testingConfig.login_username || !testingConfig.login_password) {
120
120
  throw new Error('Testing credentials not configured. Set TESTING_LOGIN_USERNAME and TESTING_LOGIN_PASSWORD environment variables.');
121
121
  }
122
- return {
122
+ return Promise.resolve({
123
123
  content: [
124
124
  {
125
125
  type: 'text',
126
126
  text: JSON.stringify(testingConfig, null, 2),
127
127
  },
128
128
  ],
129
- };
129
+ });
130
130
  }),
131
131
  ],
132
132
  });
@@ -20,9 +20,7 @@ function parseGrowthResult(responseText) {
20
20
  if (jsonResult && jsonResult.analysis) {
21
21
  return { analysis: jsonResult.analysis };
22
22
  }
23
- else {
24
- return { error: 'Invalid JSON structure' };
25
- }
23
+ return { error: 'Invalid JSON structure' };
26
24
  }
27
25
  catch (error) {
28
26
  return {
@@ -16,7 +16,9 @@ function userMessage(content) {
16
16
  }
17
17
  async function* prompt(executionPrompt) {
18
18
  yield userMessage(executionPrompt);
19
- await new Promise((res) => setTimeout(res, 10000));
19
+ await new Promise((res) => {
20
+ setTimeout(res, 10000);
21
+ });
20
22
  }
21
23
  /**
22
24
  * PR Execution Phase: Create git branches, push code, and generate compare URLs
@@ -81,7 +81,7 @@ export async function fetchPRSplittingContext(featureId, verbose, replaceExistin
81
81
  }
82
82
  const devBranchName = getDevBranchName(featureId);
83
83
  // Fetch database data and GitHub config in parallel (need token before remote branch check)
84
- const [feature, existing_branches, existing_pull_requests, githubConfig] = await Promise.all([
84
+ const [feature, existingBranches, existingPullRequests, githubConfig] = await Promise.all([
85
85
  getFeature(featureId, verbose),
86
86
  getBranches({ featureId, verbose }).catch(() => []),
87
87
  getPullRequests({ featureId, verbose }).catch(() => []),
@@ -128,7 +128,7 @@ export async function fetchPRSplittingContext(featureId, verbose, replaceExistin
128
128
  }
129
129
  // Determine diff range
130
130
  const devRef = localExists ? devBranchName : `origin/${devBranchName}`;
131
- const baseRef = determineDiffBaseRef(existing_pull_requests, replaceExisting);
131
+ const baseRef = determineDiffBaseRef(existingPullRequests, replaceExisting);
132
132
  const devBranchHeadSha = getBranchHeadSha(devRef);
133
133
  // Check if there are new changes since last sync
134
134
  if (baseRef !== 'main' && baseRef === devBranchHeadSha) {
@@ -147,15 +147,15 @@ export async function fetchPRSplittingContext(featureId, verbose, replaceExistin
147
147
  logInfo(` Dev Branch HEAD: ${devBranchHeadSha}`);
148
148
  logInfo(` Diff Base: ${baseRef}`);
149
149
  logInfo(` Changed Files: ${changedFiles.length}`);
150
- logInfo(` Existing Branches: ${existing_branches.length}`);
151
- logInfo(` Existing Pull Requests: ${existing_pull_requests.length}`);
150
+ logInfo(` Existing Branches: ${existingBranches.length}`);
151
+ logInfo(` Existing Pull Requests: ${existingPullRequests.length}`);
152
152
  logInfo(` GitHub: ${githubConfig.configured ? 'Configured' : 'Not configured'}`);
153
153
  }
154
154
  return {
155
155
  feature,
156
156
  product,
157
- existing_branches,
158
- existing_pull_requests,
157
+ existing_branches: existingBranches,
158
+ existing_pull_requests: existingPullRequests,
159
159
  diffStat,
160
160
  changedFiles,
161
161
  devBranchName,
@@ -15,7 +15,9 @@ function userMessage(content) {
15
15
  }
16
16
  async function* prompt(analysisPrompt) {
17
17
  yield userMessage(analysisPrompt);
18
- await new Promise((res) => setTimeout(res, 10000));
18
+ await new Promise((res) => {
19
+ setTimeout(res, 10000);
20
+ });
19
21
  }
20
22
  /**
21
23
  * PR Splitting Phase: Analyze diff and create PR split plan
@@ -85,8 +85,6 @@ export async function handlePullRequestCreation({ featureId, results, testingRes
85
85
  logDebug(`Pull request created${currentBranch ? ' and branch updated' : ''}`, verbose);
86
86
  return true;
87
87
  }
88
- else {
89
- logDebug(`Pull request creation failed: ${prResult.error}`, verbose);
90
- return false;
91
- }
88
+ logDebug(`Pull request creation failed: ${prResult.error}`, verbose);
89
+ return false;
92
90
  }