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
@@ -89,14 +89,12 @@ export async function checkApprovalBeforePhaseExecution(featureId, verbose = fal
89
89
  message: `Approval request created for status: ${currentStatus}`,
90
90
  };
91
91
  }
92
- else {
93
- logError('Failed to create approval request');
94
- return {
95
- canProceed: false,
96
- requiresApproval: true,
97
- message: `Failed to create approval request for status: ${currentStatus}`,
98
- };
99
- }
92
+ logError('Failed to create approval request');
93
+ return {
94
+ canProceed: false,
95
+ requiresApproval: true,
96
+ message: `Failed to create approval request for status: ${currentStatus}`,
97
+ };
100
98
  }
101
99
  catch (error) {
102
100
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -115,7 +115,8 @@ function stopPolling() {
115
115
  // Event Handlers
116
116
  // ============================================================
117
117
  async function handleInit(msg) {
118
- config = msg.config;
118
+ ;
119
+ ({ config } = msg);
119
120
  verbose = msg.verbose ?? false;
120
121
  log('info', `Chat worker initialized (id: ${WORKER_ID})`);
121
122
  // Load existing channels before starting the poll loop
@@ -27,7 +27,9 @@ import { calculateStats, createCompletedState, createFailedState, createInitialS
27
27
  */
28
28
  export const MAX_CONCURRENCY = 10;
29
29
  /** Path to the compiled worker entry points */
30
+ // eslint-disable-next-line @typescript-eslint/naming-convention -- ESM __filename/__dirname polyfill
30
31
  const __filename = fileURLToPath(import.meta.url);
32
+ // eslint-disable-next-line @typescript-eslint/naming-convention -- ESM __filename/__dirname polyfill
31
33
  const __dirname = dirname(__filename);
32
34
  const WORKER_SCRIPT = join(__dirname, 'feature-worker.js');
33
35
  const CHAT_WORKER_SCRIPT = join(__dirname, 'chat-worker.js');
@@ -362,7 +364,7 @@ export class AgentWorkflowProcessor {
362
364
  }
363
365
  });
364
366
  // Set up worker timeout
365
- const workerTimeout = this.config.workflow.workerTimeout;
367
+ const { workerTimeout } = this.config.workflow;
366
368
  activeWorker.timeoutTimer = setTimeout(() => {
367
369
  logError(`Worker for ${feature.name} timed out after ${Math.round(workerTimeout / 1000)}s, killing...`);
368
370
  try {
@@ -22,13 +22,11 @@ export const runCodeReview = async (options) => {
22
22
  if (exitCode === 0) {
23
23
  logSuccess('Review completed successfully');
24
24
  }
25
- else {
26
- if (hasBlockingIssues) {
27
- logError('Review failed with blocking issues');
28
- }
29
- else if (hasWarnings) {
30
- logError('Review failed with warnings');
31
- }
25
+ else if (hasBlockingIssues) {
26
+ logError('Review failed with blocking issues');
27
+ }
28
+ else if (hasWarnings) {
29
+ logError('Review failed with warnings');
32
30
  }
33
31
  process.exit(exitCode);
34
32
  }
@@ -221,10 +221,8 @@ const runFromUserStoriesAnalysis = async (options, config) => {
221
221
  if (prCreated) {
222
222
  await continueWithCodeReviewAndRefine(options, config, results, verbose);
223
223
  }
224
- else {
225
- if (verbose) {
226
- logInfo('āš ļø Skipping code review and refine workflow: pull request creation failed');
227
- }
224
+ else if (verbose) {
225
+ logInfo('āš ļø Skipping code review and refine workflow: pull request creation failed');
228
226
  }
229
227
  }
230
228
  return finalizePipelineExecution(options, results, verbose);
@@ -274,10 +272,8 @@ const runFromTestCasesAnalysis = async (options, config) => {
274
272
  if (prCreated) {
275
273
  await continueWithCodeReviewAndRefine(options, config, results, verbose);
276
274
  }
277
- else {
278
- if (verbose) {
279
- logInfo('āš ļø Skipping code review and refine workflow: pull request creation failed');
280
- }
275
+ else if (verbose) {
276
+ logInfo('āš ļø Skipping code review and refine workflow: pull request creation failed');
281
277
  }
282
278
  }
283
279
  return finalizePipelineExecution(options, results, verbose);
@@ -378,10 +374,8 @@ const runFromPRSplitting = async (options, config) => {
378
374
  if (prCreated) {
379
375
  await continueWithCodeReviewAndRefine(options, config, results, verbose);
380
376
  }
381
- else {
382
- if (verbose) {
383
- logInfo('āš ļø Skipping code review and refine workflow: pull request creation failed');
384
- }
377
+ else if (verbose) {
378
+ logInfo('āš ļø Skipping code review and refine workflow: pull request creation failed');
385
379
  }
386
380
  }
387
381
  return finalizePipelineExecution(options, results, verbose);
@@ -430,10 +424,8 @@ const runFromPRExecution = async (options, config) => {
430
424
  if (prCreated) {
431
425
  await continueWithCodeReviewAndRefine(options, config, results, verbose);
432
426
  }
433
- else {
434
- if (verbose) {
435
- logInfo('āš ļø Skipping code review and refine workflow: pull request creation failed');
436
- }
427
+ else if (verbose) {
428
+ logInfo('āš ļø Skipping code review and refine workflow: pull request creation failed');
437
429
  }
438
430
  }
439
431
  return finalizePipelineExecution(options, results, verbose);
@@ -496,10 +488,8 @@ const runFromFeatureAnalysis = async (options, config) => {
496
488
  if (prCreated) {
497
489
  await continueWithCodeReviewAndRefine(options, config, results, verbose);
498
490
  }
499
- else {
500
- if (verbose) {
501
- logInfo('āš ļø Skipping code review and refine workflow: pull request creation failed');
502
- }
491
+ else if (verbose) {
492
+ logInfo('āš ļø Skipping code review and refine workflow: pull request creation failed');
503
493
  }
504
494
  }
505
495
  return finalizePipelineExecution(options, results, verbose);
@@ -545,10 +535,8 @@ const runFromTechnicalDesign = async (options, config) => {
545
535
  if (prCreated) {
546
536
  await continueWithCodeReviewAndRefine(options, config, results, verbose);
547
537
  }
548
- else {
549
- if (verbose) {
550
- logInfo('āš ļø Skipping code review and refine workflow: pull request creation failed');
551
- }
538
+ else if (verbose) {
539
+ logInfo('āš ļø Skipping code review and refine workflow: pull request creation failed');
552
540
  }
553
541
  }
554
542
  return finalizePipelineExecution(options, results, verbose);
@@ -588,10 +576,8 @@ const runFromCodeImplementation = async (options, config) => {
588
576
  if (prCreated) {
589
577
  await continueWithCodeReviewAndRefine(options, config, results, verbose);
590
578
  }
591
- else {
592
- if (verbose) {
593
- logInfo('āš ļø Skipping code review and refine workflow: pull request creation failed');
594
- }
579
+ else if (verbose) {
580
+ logInfo('āš ļø Skipping code review and refine workflow: pull request creation failed');
595
581
  }
596
582
  }
597
583
  return finalizePipelineExecution(options, results, verbose);
@@ -625,10 +611,8 @@ const runFromFunctionalTesting = async (options, config) => {
625
611
  if (prCreated) {
626
612
  await continueWithCodeReviewAndRefine(options, config, results, verbose);
627
613
  }
628
- else {
629
- if (verbose) {
630
- logInfo('āš ļø Skipping code review and refine workflow: pull request creation failed');
631
- }
614
+ else if (verbose) {
615
+ logInfo('āš ļø Skipping code review and refine workflow: pull request creation failed');
632
616
  }
633
617
  }
634
618
  return finalizePipelineExecution(options, results, verbose);
package/dist/constants.js CHANGED
@@ -16,7 +16,9 @@ export function getVersion() {
16
16
  return _cachedVersion;
17
17
  }
18
18
  try {
19
+ // eslint-disable-next-line @typescript-eslint/naming-convention -- ESM __filename/__dirname polyfill
19
20
  const __filename = fileURLToPath(import.meta.url);
21
+ // eslint-disable-next-line @typescript-eslint/naming-convention -- ESM __filename/__dirname polyfill
20
22
  const __dirname = dirname(__filename);
21
23
  const pkg = JSON.parse(readFileSync(join(__dirname, '../package.json'), 'utf-8'));
22
24
  _cachedVersion = pkg.version;
package/dist/index.js CHANGED
@@ -19,10 +19,12 @@ import { runTaskWorker } from './commands/task-worker/index.js';
19
19
  import { runWorkflow } from './commands/workflow/index.js';
20
20
  import { logError, logInfo } from './utils/logger.js';
21
21
  // Get package.json version dynamically
22
+ // eslint-disable-next-line @typescript-eslint/naming-convention -- ESM __filename/__dirname polyfill
22
23
  const __filename = fileURLToPath(import.meta.url);
24
+ // eslint-disable-next-line @typescript-eslint/naming-convention -- ESM __filename/__dirname polyfill
23
25
  const __dirname = dirname(__filename);
24
26
  const packageJson = JSON.parse(readFileSync(join(__dirname, '../package.json'), 'utf-8'));
25
- const version = packageJson.version;
27
+ const { version } = packageJson;
26
28
  // Load environment variables (each only sets vars not already defined):
27
29
  // 1. Real environment variables (highest priority - already in process.env)
28
30
  // 2. .env file in cwd (medium priority - loaded first)
@@ -18,9 +18,7 @@ function parseAppStoreResult(responseText) {
18
18
  if (jsonResult && jsonResult.app_store) {
19
19
  return { appStore: jsonResult.app_store };
20
20
  }
21
- else {
22
- return { error: 'Invalid JSON structure: missing app_store key' };
23
- }
21
+ return { error: 'Invalid JSON structure: missing app_store key' };
24
22
  }
25
23
  catch (error) {
26
24
  return {
@@ -91,8 +91,7 @@ function createCompositionHtml(framedScreenshotDataUrl, spec, targetWidth, targe
91
91
  </body>
92
92
  </html>`;
93
93
  }
94
- else {
95
- return `<!DOCTYPE html>
94
+ return `<!DOCTYPE html>
96
95
  <html>
97
96
  <head>
98
97
  <style>
@@ -152,7 +151,6 @@ function createCompositionHtml(framedScreenshotDataUrl, spec, targetWidth, targe
152
151
  </div>
153
152
  </body>
154
153
  </html>`;
155
- }
156
154
  }
157
155
  // ============================================================
158
156
  // escapeHtml tests
@@ -381,7 +379,7 @@ void describe('STORE_SCREENSHOT_SIZES - Orientation', () => {
381
379
  }
382
380
  });
383
381
  void it('should have Google phone in portrait (height > width)', () => {
384
- const phone = STORE_SCREENSHOT_SIZES.google.phone;
382
+ const { phone } = STORE_SCREENSHOT_SIZES.google;
385
383
  assert.ok(phone.height > phone.width, `Google phone should be portrait: ${phone.width}x${phone.height}`);
386
384
  });
387
385
  void it('should have Google tablet_7 in portrait (height > width)', () => {
@@ -20,9 +20,7 @@ function parseAppStoreResult(responseText) {
20
20
  if (jsonResult && jsonResult.app_store) {
21
21
  return { appStore: jsonResult.app_store };
22
22
  }
23
- else {
24
- return { error: 'Invalid JSON structure: missing app_store key' };
25
- }
23
+ return { error: 'Invalid JSON structure: missing app_store key' };
26
24
  }
27
25
  catch (error) {
28
26
  return {
@@ -5,7 +5,7 @@ import { cloneFeatureRepo, ensureWorkspaceDir, } from '../../workspace/workspace
5
5
  import { executeAppStoreQuery } from './agent.js';
6
6
  import { prepareAppStoreContext } from './context.js';
7
7
  import { createAppStoreSystemPrompt } from './prompts.js';
8
- import { generateStoreScreenshots } from './screenshot-composer.js';
8
+ import { generateStoreScreenshots, } from './screenshot-composer.js';
9
9
  import { uploadAppStoreScreenshots } from './uploader.js';
10
10
  export const generateAppStoreAssets = async (options, config
11
11
  // eslint-disable-next-line complexity -- orchestration function with sequential asset generation steps
@@ -17,7 +17,7 @@ export const generateAppStoreAssets = async (options, config
17
17
  }
18
18
  try {
19
19
  // Resolve locale: use explicit param, or fetch from Apple App Store Connect
20
- let locale = options.locale;
20
+ let { locale } = options;
21
21
  if (!locale) {
22
22
  logInfo('No locale specified, fetching primary locale from Apple App Store Connect...');
23
23
  const appleLocale = await getAppStorePrimaryLocale(productId, verbose);
@@ -53,7 +53,8 @@ export const generateAppStoreAssets = async (options, config
53
53
  if (!aiResult) {
54
54
  throw new Error('No results received from AI');
55
55
  }
56
- const listings = (aiResult.listings || {});
56
+ const listings = (aiResult.listings ||
57
+ {});
57
58
  const screenshotSpecs = (aiResult.screenshots || []);
58
59
  logInfo(`AI generated: ${Object.keys(listings).length} locale(s), ${screenshotSpecs.length} screenshot spec(s)`);
59
60
  // Ensure store configs exist
@@ -52,7 +52,7 @@ async function composeStoreScreenshot(opts) {
52
52
  }
53
53
  async function loadChromium() {
54
54
  try {
55
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
55
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, no-new-func -- dynamic import to avoid bundler resolution of optional peer dependency
56
56
  const pw = await Function('return import("playwright")')();
57
57
  return pw.chromium;
58
58
  }
@@ -144,9 +144,8 @@ function createCompositionHtml(framedScreenshotDataUrl, spec, targetWidth, targe
144
144
  </body>
145
145
  </html>`;
146
146
  }
147
- else {
148
- // Landscape: text on left, device on right
149
- return `<!DOCTYPE html>
147
+ // Landscape: text on left, device on right
148
+ return `<!DOCTYPE html>
150
149
  <html>
151
150
  <head>
152
151
  <style>
@@ -206,7 +205,6 @@ function createCompositionHtml(framedScreenshotDataUrl, spec, targetWidth, targe
206
205
  </div>
207
206
  </body>
208
207
  </html>`;
209
- }
210
208
  }
211
209
  function escapeHtml(str) {
212
210
  return str
@@ -48,7 +48,9 @@ function userMessage(content) {
48
48
  }
49
49
  async function* prompt(userPrompt) {
50
50
  yield userMessage(userPrompt);
51
- await new Promise((res) => setTimeout(res, 10000));
51
+ await new Promise((res) => {
52
+ setTimeout(res, 10000);
53
+ });
52
54
  }
53
55
  /**
54
56
  * Run a single autonomous iteration using Claude Code SDK
@@ -143,8 +145,7 @@ async function handleSuccessfulIteration(opts) {
143
145
  let prNumber;
144
146
  if (!prUrl) {
145
147
  const prInfo = await createAutonomousPR(githubConfig, devBranchName, currentBranch, verbose);
146
- prUrl = prInfo.prUrl;
147
- prNumber = prInfo.prNumber;
148
+ ({ prUrl, prNumber } = prInfo);
148
149
  }
149
150
  // Log iteration completion to audit logs
150
151
  await logFeaturePhaseEvent({
@@ -11,7 +11,7 @@ export async function fetchBranchPlanningContext(featureId, verbose) {
11
11
  logInfo(`Fetching branch planning context for feature: ${featureId}`);
12
12
  }
13
13
  // Fetch all required data in parallel for better performance
14
- const [feature, user_stories, test_cases, existing_branches] = await Promise.all([
14
+ const [feature, userStories, testCases, existingBranches] = await Promise.all([
15
15
  getFeature(featureId, verbose),
16
16
  getUserStories(featureId, verbose),
17
17
  getTestCases(featureId, verbose),
@@ -22,17 +22,17 @@ export async function fetchBranchPlanningContext(featureId, verbose) {
22
22
  logInfo(`āœ… Branch planning context fetched successfully:`);
23
23
  logInfo(` Feature: ${feature.name}`);
24
24
  logInfo(` Product: ${product.name}`);
25
- logInfo(` User Stories: ${user_stories.length}`);
26
- logInfo(` Test Cases: ${test_cases.length}`);
25
+ logInfo(` User Stories: ${userStories.length}`);
26
+ logInfo(` Test Cases: ${testCases.length}`);
27
27
  logInfo(` Technical Design: ${feature.technical_design ? 'Yes' : 'No'}`);
28
- logInfo(` Existing Branches: ${existing_branches.length}`);
28
+ logInfo(` Existing Branches: ${existingBranches.length}`);
29
29
  }
30
30
  return {
31
31
  feature,
32
32
  product,
33
- user_stories,
34
- test_cases,
35
- existing_branches,
33
+ user_stories: userStories,
34
+ test_cases: testCases,
35
+ existing_branches: existingBranches,
36
36
  };
37
37
  }
38
38
  catch (error) {
@@ -29,7 +29,9 @@ function userMessage(content) {
29
29
  }
30
30
  async function* prompt(analysisPrompt) {
31
31
  yield userMessage(analysisPrompt);
32
- await new Promise((res) => setTimeout(res, 10000));
32
+ await new Promise((res) => {
33
+ setTimeout(res, 10000);
34
+ });
33
35
  }
34
36
  /**
35
37
  * Fetch feedbacks for branch planning phase
@@ -81,8 +83,8 @@ async function buildUserPrompt(opts) {
81
83
  }
82
84
  const feedbacksInfo = await formatFeedbacksForContext(feedbacksContext);
83
85
  const currentPlanInfo = existingBranchesInfo || 'No existing branch plan documented.';
84
- const prompt = createImprovementPrompt(feedbacksInfo, currentPlanInfo);
85
- return `${prompt}\n\n## Feature Context\n\n${contextInfo}`;
86
+ const systemPrompt = createImprovementPrompt(feedbacksInfo, currentPlanInfo);
87
+ return `${systemPrompt}\n\n## Feature Context\n\n${contextInfo}`;
86
88
  }
87
89
  return createBranchPlanningPromptWithContext(featureId, contextInfo, existingBranchesInfo || '');
88
90
  }
@@ -27,7 +27,9 @@ function userMessage(content) {
27
27
  }
28
28
  async function* prompt(bugFixPrompt) {
29
29
  yield userMessage(bugFixPrompt);
30
- await new Promise((res) => setTimeout(res, 10000));
30
+ await new Promise((res) => {
31
+ setTimeout(res, 10000);
32
+ });
31
33
  }
32
34
  export const fixTestFailures = async (options, config
33
35
  // eslint-disable-next-line complexity -- orchestration function with agent setup, message processing, and result extraction
@@ -131,15 +133,13 @@ export const fixTestFailures = async (options, config
131
133
  attemptNumber,
132
134
  };
133
135
  }
134
- else {
135
- return {
136
- featureId,
137
- fixSummary: null,
138
- status: 'error',
139
- message: 'Bug fixing failed or incomplete',
140
- attemptNumber,
141
- };
142
- }
136
+ return {
137
+ featureId,
138
+ fixSummary: null,
139
+ status: 'error',
140
+ message: 'Bug fixing failed or incomplete',
141
+ attemptNumber,
142
+ };
143
143
  }
144
144
  catch (error) {
145
145
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -272,16 +272,16 @@ function parseBugFixResponse(response) {
272
272
  const summaryMatch = response.match(/## Fix Summary\n([\s\S]*?)(?=\n##|\n\n|$)/);
273
273
  const summary = summaryMatch ? summaryMatch[1].trim() : 'Bug fixes applied';
274
274
  const filesMatch = response.match(/## Files Fixed\n([\s\S]*?)(?=\n##|\n\n|$)/);
275
- let files_modified = [];
275
+ let filesModified = [];
276
276
  if (filesMatch) {
277
- files_modified = filesMatch[1]
277
+ filesModified = filesMatch[1]
278
278
  .split('\n')
279
279
  .filter((line) => line.trim().startsWith('-'))
280
280
  .map((line) => line.replace(/^-\s*/, '').trim());
281
281
  }
282
282
  return {
283
283
  summary,
284
- files_modified,
284
+ files_modified: filesModified,
285
285
  tests_passed: true,
286
286
  fixes_applied: [],
287
287
  };
@@ -10,13 +10,13 @@ export async function fetchBugFixingContext(featureId, verbose) {
10
10
  logInfo(`Fetching complete bug fixing 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),
17
17
  ]);
18
18
  // Get latest test report to understand what has been tested
19
- let latest_test_report = null;
19
+ let latestTestReport = null;
20
20
  try {
21
21
  if (verbose) {
22
22
  logInfo('Fetching latest test report...');
@@ -25,7 +25,7 @@ export async function fetchBugFixingContext(featureId, verbose) {
25
25
  feature_id: featureId,
26
26
  }));
27
27
  if (testReportResult.test_report) {
28
- latest_test_report = testReportResult.test_report;
28
+ latestTestReport = testReportResult.test_report;
29
29
  }
30
30
  }
31
31
  catch (error) {
@@ -36,16 +36,16 @@ export async function fetchBugFixingContext(featureId, verbose) {
36
36
  if (verbose) {
37
37
  logInfo(`āœ… Bug fixing context fetched successfully:`);
38
38
  logInfo(` Feature: ${feature.name}`);
39
- logInfo(` User Stories: ${user_stories.length}`);
40
- logInfo(` Test Cases: ${test_cases.length} (${test_cases.filter((tc) => tc.is_critical).length} critical)`);
39
+ logInfo(` User Stories: ${userStories.length}`);
40
+ logInfo(` Test Cases: ${testCases.length} (${testCases.filter((tc) => tc.is_critical).length} critical)`);
41
41
  logInfo(` Technical Design: ${feature.technical_design ? 'Available' : 'Not available'}`);
42
- logInfo(` Latest Test Report: ${latest_test_report ? 'Available' : 'Not available'}`);
42
+ logInfo(` Latest Test Report: ${latestTestReport ? 'Available' : 'Not available'}`);
43
43
  }
44
44
  return {
45
45
  feature,
46
- user_stories,
47
- test_cases,
48
- latest_test_report,
46
+ user_stories: userStories,
47
+ test_cases: testCases,
48
+ latest_test_report: latestTestReport,
49
49
  };
50
50
  }
51
51
  catch (error) {
@@ -58,23 +58,20 @@ export const createBugFixingMcpServer = () => {
58
58
  files_modified: z
59
59
  .array(z.string())
60
60
  .describe('List of files that were modified'),
61
- }, async (args) => {
62
- // This tool verifies the bug fix
63
- return {
64
- content: [
65
- {
66
- type: 'text',
67
- text: JSON.stringify({
68
- verified: true,
69
- feature_id: args.feature_id,
70
- summary: args.fix_summary,
71
- files_modified: args.files_modified,
72
- message: 'Bug fix verification complete',
73
- }, null, 2),
74
- },
75
- ],
76
- };
77
- }),
61
+ }, (args) => Promise.resolve({
62
+ content: [
63
+ {
64
+ type: 'text',
65
+ text: JSON.stringify({
66
+ verified: true,
67
+ feature_id: args.feature_id,
68
+ summary: args.fix_summary,
69
+ files_modified: args.files_modified,
70
+ message: 'Bug fix verification complete',
71
+ }, null, 2),
72
+ },
73
+ ],
74
+ })),
78
75
  ],
79
76
  });
80
77
  };
@@ -10,7 +10,7 @@ export async function fetchCodeImplementationContext(featureId, verbose) {
10
10
  logInfo(`Fetching complete code implementation 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,15 +20,15 @@ export async function fetchCodeImplementationContext(featureId, verbose) {
20
20
  logInfo(`āœ… Code implementation 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
  logInfo(` Technical Design: ${feature.technical_design ? 'Available' : 'Not available'}`);
26
26
  }
27
27
  return {
28
28
  feature,
29
29
  product,
30
- user_stories,
31
- test_cases,
30
+ user_stories: userStories,
31
+ test_cases: testCases,
32
32
  technical_design: feature.technical_design,
33
33
  };
34
34
  }
@@ -33,7 +33,9 @@ function userMessage(content) {
33
33
  }
34
34
  async function* prompt(implementationPrompt) {
35
35
  yield userMessage(implementationPrompt);
36
- await new Promise((res) => setTimeout(res, 10000));
36
+ await new Promise((res) => {
37
+ setTimeout(res, 10000);
38
+ });
37
39
  }
38
40
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
39
41
  function processAssistantContent(content, verbose) {
@@ -265,8 +267,7 @@ export const implementFeatureCode = async (options, config, checklistContext
265
267
  });
266
268
  const baseBranchInfo = getBaseBranchInfo(currentBranch, allBranches, baseBranch);
267
269
  actualBaseBranch = baseBranchInfo.baseBranch;
268
- rebaseTargetBranch = baseBranchInfo.rebaseTargetBranch;
269
- originalBaseBranch = baseBranchInfo.originalBaseBranch;
270
+ ({ rebaseTargetBranch, originalBaseBranch } = baseBranchInfo);
270
271
  baseBranchCompleted = baseBranchInfo.baseBranchCompleted || false;
271
272
  if (verbose) {
272
273
  logInfo(`šŸ”— Branch chaining detected:`);
@@ -525,7 +526,7 @@ export const implementFeatureCode = async (options, config, checklistContext
525
526
  maxIterations,
526
527
  verbose,
527
528
  });
528
- verificationResult = verificationCycle.verificationResult;
529
+ ({ verificationResult } = verificationCycle);
529
530
  // If verification passed, exit
530
531
  if (verificationCycle.passed) {
531
532
  if (verbose) {
@@ -10,7 +10,9 @@ function userMessage(content) {
10
10
  }
11
11
  async function* prompt(verificationPrompt) {
12
12
  yield userMessage(verificationPrompt);
13
- await new Promise((res) => setTimeout(res, 10000));
13
+ await new Promise((res) => {
14
+ setTimeout(res, 10000);
15
+ });
14
16
  }
15
17
  const FAILED_VERIFICATION = {
16
18
  overall_status: 'failed',
@@ -118,7 +118,7 @@ export async function fetchPRDataGraphQL(octokit, owner, repo, prNumber, verbose
118
118
  repo,
119
119
  prNumber,
120
120
  });
121
- const pullRequest = result.repository.pullRequest;
121
+ const { pullRequest } = result.repository;
122
122
  // Transform GraphQL reviews to our interface
123
123
  const reviews = (pullRequest.reviews.nodes || []).map(
124
124
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -9,8 +9,8 @@ import { getBaseBranchInfo, getBranches, updateBranch, } from '../../services/br
9
9
  import { getUncommittedFiles, hasUncommittedChanges, prepareCustomBranchGitEnvironmentAsync, preparePhaseGitEnvironmentAsync, syncFeatBranchWithMain, } from '../../utils/git-branch-manager.js';
10
10
  import { gitPushCurrentBranch } from '../../utils/git-push.js';
11
11
  import { logError, logInfo } from '../../utils/logger.js';
12
- import { fetchCodeRefineContext } from './context.js';
13
12
  import { verifyAndResolveComments, } from '../code-refine-verification/index.js';
13
+ import { fetchCodeRefineContext } from './context.js';
14
14
  import { executeRefineIteration } from './refine-iteration.js';
15
15
  /**
16
16
  * Log base branch info for verbose mode
@@ -295,7 +295,7 @@ Please ensure Claude Code commits all changes before completing the refine phase
295
295
  const verificationData = verificationResult.data;
296
296
  const suggestions = verificationData.suggestions || [];
297
297
  const unresolvedCommentDetails = verificationData.unresolvedCommentDetails || [];
298
- const unresolvedReviewDetails = verificationData.unresolvedReviewDetails;
298
+ const { unresolvedReviewDetails } = verificationData;
299
299
  verificationFailureContext = {
300
300
  attempt: currentIteration + 1,
301
301
  suggestions,
@@ -313,11 +313,9 @@ Please ensure Claude Code commits all changes before completing the refine phase
313
313
  logInfo(`\nšŸ”„ Will retry... (${MAX_REFINE_ITERATIONS - currentIteration} attempts remaining)`);
314
314
  }
315
315
  }
316
- else {
316
+ else if (verbose) {
317
317
  // Max iterations reached
318
- if (verbose) {
319
- logInfo(`\nāš ļø Maximum iterations (${MAX_REFINE_ITERATIONS}) reached. Verification still failing.`);
320
- }
318
+ logInfo(`\nāš ļø Maximum iterations (${MAX_REFINE_ITERATIONS}) reached. Verification still failing.`);
321
319
  }
322
320
  }
323
321
  // Return last verification result (which failed)