@ariso-ai/ivan 1.0.11 → 1.0.12

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 (32) hide show
  1. package/dist/services/address-task-executor.d.ts +1 -1
  2. package/dist/services/address-task-executor.d.ts.map +1 -1
  3. package/dist/services/address-task-executor.js +163 -84
  4. package/dist/services/address-task-executor.js.map +1 -1
  5. package/dist/services/claude-cli-executor.d.ts +1 -0
  6. package/dist/services/claude-cli-executor.d.ts.map +1 -1
  7. package/dist/services/claude-cli-executor.js +1 -0
  8. package/dist/services/claude-cli-executor.js.map +1 -1
  9. package/dist/services/claude-executor.d.ts +1 -0
  10. package/dist/services/claude-executor.d.ts.map +1 -1
  11. package/dist/services/claude-executor.js +26 -14
  12. package/dist/services/claude-executor.js.map +1 -1
  13. package/dist/services/executor-factory.d.ts +1 -0
  14. package/dist/services/executor-factory.d.ts.map +1 -1
  15. package/dist/services/executor-factory.js.map +1 -1
  16. package/dist/services/git-interfaces.d.ts +1 -0
  17. package/dist/services/git-interfaces.d.ts.map +1 -1
  18. package/dist/services/git-manager-cli.d.ts +1 -0
  19. package/dist/services/git-manager-cli.d.ts.map +1 -1
  20. package/dist/services/git-manager-cli.js +1 -0
  21. package/dist/services/git-manager-cli.js.map +1 -1
  22. package/dist/services/git-manager-pat.d.ts +1 -0
  23. package/dist/services/git-manager-pat.d.ts.map +1 -1
  24. package/dist/services/git-manager-pat.js +64 -32
  25. package/dist/services/git-manager-pat.js.map +1 -1
  26. package/dist/services/github-api-client.d.ts.map +1 -1
  27. package/dist/services/github-api-client.js +22 -5
  28. package/dist/services/github-api-client.js.map +1 -1
  29. package/dist/services/task-executor.d.ts.map +1 -1
  30. package/dist/services/task-executor.js +177 -145
  31. package/dist/services/task-executor.js.map +1 -1
  32. package/package.json +1 -1
@@ -236,31 +236,39 @@ export class TaskExecutor {
236
236
  }
237
237
  return addressTasks;
238
238
  }
239
- async executeTask(task) {
240
- console.log('');
241
- console.log(chalk.cyan.bold(`📝 Task: ${task.description}`));
242
- let spinner = ora('Updating task status...').start();
239
+ async executeTask(task, quiet = false) {
240
+ if (!quiet) {
241
+ console.log('');
242
+ console.log(chalk.cyan.bold(`📝 Task: ${task.description}`));
243
+ }
244
+ let spinner = quiet ? null : ora('Updating task status...').start();
243
245
  let worktreePath = null;
244
246
  let branchName = null;
245
247
  try {
246
248
  await this.jobManager.updateTaskStatus(task.uuid, 'active');
247
- spinner.succeed('Task marked as active');
248
- spinner = ora('Cleaning up and syncing with main branch...').start();
249
+ if (spinner)
250
+ spinner.succeed('Task marked as active');
251
+ if (!quiet)
252
+ spinner = ora('Cleaning up and syncing with main branch...').start();
249
253
  if (!this.gitManager) {
250
254
  throw new Error('GitManager not initialized');
251
255
  }
252
256
  await this.gitManager.cleanupAndSyncMain();
253
- spinner.succeed('Repository cleaned and synced with main');
257
+ if (spinner)
258
+ spinner.succeed('Repository cleaned and synced with main');
254
259
  if (!this.gitManager) {
255
260
  throw new Error('GitManager not initialized');
256
261
  }
257
262
  branchName = this.gitManager.generateBranchName(task.description);
258
- spinner = ora(`Creating worktree for branch: ${branchName}`).start();
263
+ if (!quiet)
264
+ spinner = ora(`Creating worktree for branch: ${branchName}`).start();
259
265
  worktreePath = await this.gitManager.createWorktree(branchName);
260
266
  this.gitManager.switchToWorktree(worktreePath);
261
- spinner.succeed(`Worktree created: ${worktreePath}`);
267
+ if (spinner)
268
+ spinner.succeed(`Worktree created: ${worktreePath}`);
262
269
  await this.jobManager.updateTaskBranch(task.uuid, branchName);
263
- spinner = ora('Executing task with Claude Code...').start();
270
+ if (!quiet)
271
+ spinner = ora('Executing task with Claude Code...').start();
264
272
  // Append repository-specific instructions to the task if they exist
265
273
  let taskWithInstructions = task.description;
266
274
  if (this.repoInstructions) {
@@ -269,16 +277,25 @@ export class TaskExecutor {
269
277
  // Use worktree path for Claude execution, falling back to workingDir if needed
270
278
  const executionPath = worktreePath || this.workingDir;
271
279
  const result = await this.getClaudeExecutor().executeTask(taskWithInstructions, executionPath);
272
- spinner.succeed('Claude Code execution completed');
273
- spinner = ora('Storing execution log...').start();
280
+ if (spinner) {
281
+ spinner.succeed('Claude Code execution completed');
282
+ }
283
+ else if (quiet) {
284
+ // In quiet mode, output the final message from Claude
285
+ console.log(result.lastMessage);
286
+ }
287
+ if (!quiet)
288
+ spinner = ora('Storing execution log...').start();
274
289
  await this.jobManager.updateTaskExecutionLog(task.uuid, result.log);
275
- spinner.succeed('Execution log stored');
290
+ if (spinner)
291
+ spinner.succeed('Execution log stored');
276
292
  if (!this.gitManager) {
277
293
  throw new Error('GitManager not initialized');
278
294
  }
279
295
  const changedFiles = this.gitManager.getChangedFiles();
280
296
  if (changedFiles.length === 0) {
281
- console.log(chalk.yellow('⚠️ No changes detected, skipping commit and PR creation'));
297
+ if (!quiet)
298
+ console.log(chalk.yellow('⚠️ No changes detected, skipping commit and PR creation'));
282
299
  await this.jobManager.updateTaskStatus(task.uuid, 'completed');
283
300
  return;
284
301
  }
@@ -286,10 +303,13 @@ export class TaskExecutor {
286
303
  throw new Error('GitManager not initialized');
287
304
  }
288
305
  const diff = this.gitManager.getDiff();
289
- spinner = ora('Generating commit message...').start();
306
+ if (!quiet)
307
+ spinner = ora('Generating commit message...').start();
290
308
  const commitMessage = await this.getOpenAIService().generateCommitMessage(diff, changedFiles);
291
- spinner.succeed(`Commit message generated: ${commitMessage}`);
292
- spinner = ora('Committing changes...').start();
309
+ if (spinner)
310
+ spinner.succeed(`Commit message generated: ${commitMessage}`);
311
+ if (!quiet)
312
+ spinner = ora('Committing changes...').start();
293
313
  if (!this.gitManager) {
294
314
  throw new Error('GitManager not initialized');
295
315
  }
@@ -301,11 +321,13 @@ export class TaskExecutor {
301
321
  try {
302
322
  await this.gitManager.commitChanges(commitMessage);
303
323
  // Only show success message if spinner is running (first attempt)
304
- if (commitAttempts === 0) {
305
- spinner.succeed('Changes committed');
306
- }
307
- else if (spinner.isSpinning) {
308
- spinner.succeed('Commit successful after retry');
324
+ if (spinner) {
325
+ if (commitAttempts === 0) {
326
+ spinner.succeed('Changes committed');
327
+ }
328
+ else if (spinner.isSpinning) {
329
+ spinner.succeed('Commit successful after retry');
330
+ }
309
331
  }
310
332
  commitSucceeded = true;
311
333
  }
@@ -314,26 +336,33 @@ export class TaskExecutor {
314
336
  const errorMessage = commitError instanceof Error ? commitError.message : String(commitError);
315
337
  // Check if this is a pre-commit hook failure
316
338
  if (errorMessage.includes('pre-commit') && commitAttempts < maxCommitAttempts) {
317
- spinner.fail(`Pre-commit hook failed (attempt ${commitAttempts}/${maxCommitAttempts})`);
318
- console.log(chalk.yellow('🔧 Running Claude to fix pre-commit errors...'));
339
+ if (spinner) {
340
+ spinner.fail(`Pre-commit hook failed (attempt ${commitAttempts}/${maxCommitAttempts})`);
341
+ console.log(chalk.yellow('🔧 Running Claude to fix pre-commit errors...'));
342
+ }
319
343
  // Extract the error details from the commit error
320
344
  const errorDetails = errorMessage;
321
345
  // Prepare prompt for Claude to fix the errors
322
346
  const fixPrompt = `Fix the following pre-commit hook errors:\n\n${errorDetails}\n\nPlease fix all TypeScript errors, linting issues, and any other problems preventing the commit.`;
323
- spinner = ora('Running Claude to fix pre-commit errors...').start();
347
+ if (!quiet)
348
+ spinner = ora('Running Claude to fix pre-commit errors...').start();
324
349
  try {
325
350
  // Run Claude to fix the errors
326
351
  const fixResult = await this.getClaudeExecutor().executeTask(fixPrompt, worktreePath || this.workingDir);
327
- spinner.succeed('Claude attempted to fix the errors');
352
+ if (spinner)
353
+ spinner.succeed('Claude attempted to fix the errors');
328
354
  // Update the execution log with the fix attempt
329
355
  const previousLog = await this.jobManager.getTaskExecutionLog(task.uuid);
330
356
  await this.jobManager.updateTaskExecutionLog(task.uuid, `${previousLog}\n\n--- Pre-commit Fix Attempt ${commitAttempts} ---\n${fixResult.log}`);
331
357
  // Try to commit again on the next iteration
332
- spinner = ora('Retrying commit...').start();
358
+ if (!quiet)
359
+ spinner = ora('Retrying commit...').start();
333
360
  }
334
361
  catch (fixError) {
335
- spinner.fail('Failed to run Claude to fix errors');
336
- console.error(chalk.red('Claude fix attempt failed:'), fixError);
362
+ if (spinner)
363
+ spinner.fail('Failed to run Claude to fix errors');
364
+ if (!quiet)
365
+ console.error(chalk.red('Claude fix attempt failed:'), fixError);
337
366
  throw commitError; // Re-throw the original error
338
367
  }
339
368
  }
@@ -346,40 +375,51 @@ export class TaskExecutor {
346
375
  if (!commitSucceeded) {
347
376
  throw new Error(`Failed to commit after ${maxCommitAttempts} attempts due to pre-commit hook failures`);
348
377
  }
349
- spinner = ora('Pushing branch...').start();
378
+ if (!quiet)
379
+ spinner = ora('Pushing branch...').start();
350
380
  if (!this.gitManager) {
351
381
  throw new Error('GitManager not initialized');
352
382
  }
353
383
  await this.gitManager.pushBranch(branchName);
354
- spinner.succeed('Branch pushed to origin');
355
- spinner = ora('Generating PR description...').start();
384
+ if (spinner)
385
+ spinner.succeed('Branch pushed to origin');
386
+ if (!quiet)
387
+ spinner = ora('Generating PR description...').start();
356
388
  const { title, body } = await this.getOpenAIService().generatePullRequestDescription(task.description, diff, changedFiles);
357
- spinner.succeed('PR description generated');
358
- spinner = ora('Creating pull request...').start();
389
+ if (spinner)
390
+ spinner.succeed('PR description generated');
391
+ if (!quiet)
392
+ spinner = ora('Creating pull request...').start();
359
393
  if (!this.gitManager) {
360
394
  throw new Error('GitManager not initialized');
361
395
  }
362
396
  const prUrl = await this.gitManager.createPullRequest(title, body);
363
- spinner.succeed(`Pull request created: ${prUrl}`);
397
+ if (spinner)
398
+ spinner.succeed(`Pull request created: ${prUrl}`);
364
399
  await this.jobManager.updateTaskPrLink(task.uuid, prUrl);
365
400
  await this.jobManager.updateTaskStatus(task.uuid, 'completed');
366
- console.log(chalk.green(`✅ Task completed: ${task.description}`));
367
- console.log(chalk.cyan(`🔗 PR: ${prUrl}`));
401
+ if (!quiet) {
402
+ console.log(chalk.green(`✅ Task completed: ${task.description}`));
403
+ console.log(chalk.cyan(`🔗 PR: ${prUrl}`));
404
+ }
368
405
  }
369
406
  catch (error) {
370
- if (spinner.isSpinning) {
407
+ if (spinner && spinner.isSpinning) {
371
408
  spinner.fail('Task execution failed');
372
409
  }
373
410
  // Store error log if execution failed
374
411
  try {
375
412
  const errorLog = error instanceof Error ? error.message : String(error);
376
413
  await this.jobManager.updateTaskExecutionLog(task.uuid, `ERROR: ${errorLog}`);
377
- console.log(chalk.gray('Error log stored to database'));
414
+ if (!quiet)
415
+ console.log(chalk.gray('Error log stored to database'));
378
416
  }
379
417
  catch (logError) {
380
- console.error(chalk.red('Failed to store error log:'), logError);
418
+ if (!quiet)
419
+ console.error(chalk.red('Failed to store error log:'), logError);
381
420
  }
382
- console.error(chalk.red(`❌ Failed to execute task: ${task.description}`), error);
421
+ if (!quiet)
422
+ console.error(chalk.red(`❌ Failed to execute task: ${task.description}`), error);
383
423
  throw error;
384
424
  }
385
425
  finally {
@@ -390,10 +430,12 @@ export class TaskExecutor {
390
430
  }
391
431
  }
392
432
  }
393
- async executeTasksWithSinglePR(tasks) {
394
- console.log('');
395
- console.log(chalk.blue('📦 Creating single branch for all tasks...'));
396
- let spinner = ora('Cleaning up and syncing with main branch...').start();
433
+ async executeTasksWithSinglePR(tasks, quiet = false) {
434
+ if (!quiet) {
435
+ console.log('');
436
+ console.log(chalk.blue('📦 Creating single branch for all tasks...'));
437
+ }
438
+ let spinner = quiet ? null : ora('Cleaning up and syncing with main branch...').start();
397
439
  let worktreePath = null;
398
440
  let branchName = null;
399
441
  let sessionId;
@@ -402,16 +444,19 @@ export class TaskExecutor {
402
444
  throw new Error('GitManager not initialized');
403
445
  }
404
446
  await this.gitManager.cleanupAndSyncMain();
405
- spinner.succeed('Repository cleaned and synced with main');
447
+ if (spinner)
448
+ spinner.succeed('Repository cleaned and synced with main');
406
449
  // Generate branch name based on all tasks
407
450
  const combinedDescription = tasks.length === 1
408
451
  ? tasks[0].description
409
452
  : `Multiple tasks: ${tasks.slice(0, 2).map(t => t.description).join(', ')}${tasks.length > 2 ? '...' : ''}`;
410
453
  branchName = this.gitManager.generateBranchName(combinedDescription);
411
- spinner = ora(`Creating worktree for branch: ${branchName}`).start();
454
+ if (!quiet)
455
+ spinner = ora(`Creating worktree for branch: ${branchName}`).start();
412
456
  worktreePath = await this.gitManager.createWorktree(branchName);
413
457
  this.gitManager.switchToWorktree(worktreePath);
414
- spinner.succeed(`Worktree created: ${worktreePath}`);
458
+ if (spinner)
459
+ spinner.succeed(`Worktree created: ${worktreePath}`);
415
460
  // Update all tasks with the same branch
416
461
  for (const task of tasks) {
417
462
  await this.jobManager.updateTaskBranch(task.uuid, branchName);
@@ -419,12 +464,17 @@ export class TaskExecutor {
419
464
  // Execute each task on the same branch
420
465
  for (let i = 0; i < tasks.length; i++) {
421
466
  const task = tasks[i];
422
- console.log('');
423
- console.log(chalk.cyan.bold(`📝 Task ${i + 1}/${tasks.length}: ${task.description}`));
424
- spinner = ora('Updating task status...').start();
467
+ if (!quiet) {
468
+ console.log('');
469
+ console.log(chalk.cyan.bold(`📝 Task ${i + 1}/${tasks.length}: ${task.description}`));
470
+ }
471
+ if (!quiet)
472
+ spinner = ora('Updating task status...').start();
425
473
  await this.jobManager.updateTaskStatus(task.uuid, 'active');
426
- spinner.succeed('Task marked as active');
427
- spinner = ora('Executing task with Claude Code...').start();
474
+ if (spinner)
475
+ spinner.succeed('Task marked as active');
476
+ if (!quiet)
477
+ spinner = ora('Executing task with Claude Code...').start();
428
478
  // Append repository-specific instructions to the task if they exist
429
479
  let taskWithInstructions = task.description;
430
480
  if (this.repoInstructions) {
@@ -436,10 +486,18 @@ export class TaskExecutor {
436
486
  const result = await this.getClaudeExecutor().executeTask(taskWithInstructions, executionPath, sessionId);
437
487
  // Store the session ID for the next task
438
488
  sessionId = result.sessionId;
439
- spinner.succeed('Claude Code execution completed');
440
- spinner = ora('Storing execution log...').start();
489
+ if (spinner) {
490
+ spinner.succeed('Claude Code execution completed');
491
+ }
492
+ else if (quiet) {
493
+ // In quiet mode, output the final message from Claude
494
+ console.log(result.lastMessage);
495
+ }
496
+ if (!quiet)
497
+ spinner = ora('Storing execution log...').start();
441
498
  await this.jobManager.updateTaskExecutionLog(task.uuid, result.log);
442
- spinner.succeed('Execution log stored');
499
+ if (spinner)
500
+ spinner.succeed('Execution log stored');
443
501
  // Commit changes after each task (but don't create PR yet)
444
502
  if (!this.gitManager) {
445
503
  throw new Error('GitManager not initialized');
@@ -447,10 +505,13 @@ export class TaskExecutor {
447
505
  const changedFiles = this.gitManager.getChangedFiles();
448
506
  if (changedFiles.length > 0) {
449
507
  const diff = this.gitManager.getDiff();
450
- spinner = ora('Generating commit message...').start();
508
+ if (!quiet)
509
+ spinner = ora('Generating commit message...').start();
451
510
  const commitMessage = await this.getOpenAIService().generateCommitMessage(diff, changedFiles);
452
- spinner.succeed(`Commit message generated: ${commitMessage}`);
453
- spinner = ora('Committing changes...').start();
511
+ if (spinner)
512
+ spinner.succeed(`Commit message generated: ${commitMessage}`);
513
+ if (!quiet)
514
+ spinner = ora('Committing changes...').start();
454
515
  // Try to commit, handling pre-commit hook failures
455
516
  let commitAttempts = 0;
456
517
  const maxCommitAttempts = 3;
@@ -459,11 +520,13 @@ export class TaskExecutor {
459
520
  try {
460
521
  await this.gitManager.commitChanges(commitMessage);
461
522
  // Only show success message if spinner is running (first attempt)
462
- if (commitAttempts === 0) {
463
- spinner.succeed('Changes committed');
464
- }
465
- else if (spinner.isSpinning) {
466
- spinner.succeed('Commit successful after retry');
523
+ if (spinner) {
524
+ if (commitAttempts === 0) {
525
+ spinner.succeed('Changes committed');
526
+ }
527
+ else if (spinner.isSpinning) {
528
+ spinner.succeed('Commit successful after retry');
529
+ }
467
530
  }
468
531
  commitSucceeded = true;
469
532
  }
@@ -472,28 +535,35 @@ export class TaskExecutor {
472
535
  const errorMessage = commitError instanceof Error ? commitError.message : String(commitError);
473
536
  // Check if this is a pre-commit hook failure
474
537
  if (errorMessage.includes('pre-commit') && commitAttempts < maxCommitAttempts) {
475
- spinner.fail(`Pre-commit hook failed (attempt ${commitAttempts}/${maxCommitAttempts})`);
476
- console.log(chalk.yellow('🔧 Running Claude to fix pre-commit errors...'));
538
+ if (spinner) {
539
+ spinner.fail(`Pre-commit hook failed (attempt ${commitAttempts}/${maxCommitAttempts})`);
540
+ console.log(chalk.yellow('🔧 Running Claude to fix pre-commit errors...'));
541
+ }
477
542
  // Extract the error details from the commit error
478
543
  const errorDetails = errorMessage;
479
544
  // Prepare prompt for Claude to fix the errors
480
545
  const fixPrompt = `Fix the following pre-commit hook errors:\n\n${errorDetails}\n\nPlease fix all TypeScript errors, linting issues, and any other problems preventing the commit.`;
481
- spinner = ora('Running Claude to fix pre-commit errors...').start();
546
+ if (!quiet)
547
+ spinner = ora('Running Claude to fix pre-commit errors...').start();
482
548
  try {
483
549
  // Run Claude to fix the errors (pass session ID to maintain context)
484
550
  const fixResult = await this.getClaudeExecutor().executeTask(fixPrompt, executionPath, sessionId);
485
551
  // Update session ID
486
552
  sessionId = fixResult.sessionId;
487
- spinner.succeed('Claude attempted to fix the errors');
553
+ if (spinner)
554
+ spinner.succeed('Claude attempted to fix the errors');
488
555
  // Update the execution log with the fix attempt
489
556
  const previousLog = await this.jobManager.getTaskExecutionLog(task.uuid);
490
557
  await this.jobManager.updateTaskExecutionLog(task.uuid, `${previousLog}\n\n--- Pre-commit Fix Attempt ${commitAttempts} ---\n${fixResult.log}`);
491
558
  // Try to commit again on the next iteration
492
- spinner = ora('Retrying commit...').start();
559
+ if (!quiet)
560
+ spinner = ora('Retrying commit...').start();
493
561
  }
494
562
  catch (fixError) {
495
- spinner.fail('Failed to run Claude to fix errors');
496
- console.error(chalk.red('Claude fix attempt failed:'), fixError);
563
+ if (spinner)
564
+ spinner.fail('Failed to run Claude to fix errors');
565
+ if (!quiet)
566
+ console.error(chalk.red('Claude fix attempt failed:'), fixError);
497
567
  throw commitError; // Re-throw the original error
498
568
  }
499
569
  }
@@ -508,43 +578,54 @@ export class TaskExecutor {
508
578
  }
509
579
  }
510
580
  else {
511
- console.log(chalk.yellow('⚠️ No changes detected for this task'));
581
+ if (!quiet)
582
+ console.log(chalk.yellow('⚠️ No changes detected for this task'));
512
583
  }
513
584
  await this.jobManager.updateTaskStatus(task.uuid, 'completed');
514
- console.log(chalk.green(`✅ Task ${i + 1}/${tasks.length} completed`));
585
+ if (!quiet)
586
+ console.log(chalk.green(`✅ Task ${i + 1}/${tasks.length} completed`));
515
587
  }
516
588
  // After all tasks are complete, create a single PR
517
- spinner = ora('Pushing branch...').start();
589
+ if (!quiet)
590
+ spinner = ora('Pushing branch...').start();
518
591
  if (!this.gitManager) {
519
592
  throw new Error('GitManager not initialized');
520
593
  }
521
594
  await this.gitManager.pushBranch(branchName);
522
- spinner.succeed('Branch pushed to origin');
595
+ if (spinner)
596
+ spinner.succeed('Branch pushed to origin');
523
597
  // Generate PR description based on all tasks
524
- spinner = ora('Generating pull request description...').start();
598
+ if (!quiet)
599
+ spinner = ora('Generating pull request description...').start();
525
600
  const allTaskDescriptions = tasks.map(t => `- ${t.description}`).join('\n');
526
601
  const prTaskDescription = `Completed ${tasks.length} tasks:\n\n${allTaskDescriptions}`;
527
602
  // Get combined diff for PR description
528
603
  const finalDiff = this.gitManager.getDiff('origin/main', 'HEAD');
529
604
  const allChangedFiles = this.gitManager.getChangedFiles('origin/main');
530
605
  const { title, body } = await this.getOpenAIService().generatePullRequestDescription(prTaskDescription, finalDiff, allChangedFiles);
531
- spinner.succeed('PR description generated');
532
- spinner = ora('Creating pull request...').start();
606
+ if (spinner)
607
+ spinner.succeed('PR description generated');
608
+ if (!quiet)
609
+ spinner = ora('Creating pull request...').start();
533
610
  const prUrl = await this.gitManager.createPullRequest(title, body);
534
- spinner.succeed(`Pull request created: ${prUrl}`);
611
+ if (spinner)
612
+ spinner.succeed(`Pull request created: ${prUrl}`);
535
613
  // Update all tasks with the same PR link
536
614
  for (const task of tasks) {
537
615
  await this.jobManager.updateTaskPrLink(task.uuid, prUrl);
538
616
  }
539
- console.log('');
540
- console.log(chalk.green.bold(`✅ All ${tasks.length} tasks completed in a single PR!`));
541
- console.log(chalk.cyan(`🔗 PR: ${prUrl}`));
617
+ if (!quiet) {
618
+ console.log('');
619
+ console.log(chalk.green.bold(`✅ All ${tasks.length} tasks completed in a single PR!`));
620
+ console.log(chalk.cyan(`🔗 PR: ${prUrl}`));
621
+ }
542
622
  }
543
623
  catch (error) {
544
624
  if (spinner && spinner.isSpinning) {
545
625
  spinner.fail('Batch task execution failed');
546
626
  }
547
- console.error(chalk.red('❌ Failed to execute tasks with single PR:'), error);
627
+ if (!quiet)
628
+ console.error(chalk.red('❌ Failed to execute tasks with single PR:'), error);
548
629
  throw error;
549
630
  }
550
631
  finally {
@@ -557,49 +638,28 @@ export class TaskExecutor {
557
638
  }
558
639
  async executeNonInteractiveWorkflow(config) {
559
640
  try {
560
- console.log(chalk.blue.bold('🚀 Starting non-interactive workflow'));
561
- console.log('');
562
- console.log(chalk.blue('🔍 Validating dependencies...'));
563
- await this.getClaudeExecutor().validateClaudeCodeInstallation();
564
- console.log(chalk.green('✅ Claude Code SDK configured'));
641
+ // Quiet mode: suppress all intermediate output
642
+ const executor = this.getClaudeExecutor();
643
+ executor.quietMode = true;
644
+ await executor.validateClaudeCodeInstallation();
565
645
  this.workingDir = await this.repositoryManager.getValidWorkingDirectory();
566
646
  this.gitManager = createGitManager(this.workingDir);
567
647
  if (!this.gitManager) {
568
648
  throw new Error('GitManager not initialized');
569
649
  }
650
+ this.gitManager.quietMode = true;
570
651
  this.gitManager.validateGitHubCliInstallation();
571
- const authType = this.configManager.getGithubAuthType();
572
- if (authType === 'gh-cli') {
573
- console.log(chalk.green('✅ GitHub CLI is installed'));
574
- }
575
- if (!this.gitManager) {
576
- throw new Error('GitManager not initialized');
577
- }
578
652
  this.gitManager.validateGitHubCliAuthentication();
579
- if (authType === 'gh-cli') {
580
- console.log(chalk.green('✅ GitHub CLI is authenticated'));
581
- }
582
- else {
583
- console.log(chalk.green('✅ GitHub PAT is configured'));
584
- }
585
- const repoInfo = this.repositoryManager.getRepositoryInfo(this.workingDir);
586
- console.log(chalk.blue(`📂 Working in: ${repoInfo.name} (${repoInfo.branch})`));
587
- console.log('');
588
653
  // Get or create repository in database
589
654
  const repository = await this.repositoryManager.getOrCreateRepository(this.workingDir);
590
655
  // Load repository-specific instructions
591
656
  this.repoInstructions = await this.configManager.getRepoInstructions(this.workingDir);
592
- if (this.repoInstructions) {
593
- console.log(chalk.green('✅ Repository-specific instructions loaded'));
594
- }
595
657
  // Process tasks based on config
596
658
  let finalTasks = config.tasks;
597
659
  const prStrategy = config.prStrategy || 'multiple';
598
660
  // If single task and generateSubtasks is true, break it down
599
661
  if (config.tasks.length === 1 && config.generateSubtasks) {
600
- console.log(chalk.blue('🔍 Generating subtasks...'));
601
662
  finalTasks = await this.jobManager.generateTaskBreakdownWithClaude(config.tasks[0], this.workingDir);
602
- console.log(chalk.green(`✅ Generated ${finalTasks.length} subtasks`));
603
663
  }
604
664
  // Create job and tasks
605
665
  const jobDescription = config.tasks.length === 1 ? config.tasks[0] : `Multiple tasks: ${config.tasks.slice(0, 2).join(', ')}${config.tasks.length > 2 ? '...' : ''}`;
@@ -612,20 +672,16 @@ export class TaskExecutor {
612
672
  tasks.push(task);
613
673
  }
614
674
  }
615
- console.log('');
616
- console.log(chalk.blue.bold(`📋 Executing ${tasks.length} task(s)...`));
617
675
  const shouldWaitForComments = config.waitForComments || false;
618
- // Execute tasks based on PR strategy
676
+ // Execute tasks based on PR strategy (quiet mode)
619
677
  if (prStrategy === 'single' && tasks.length > 1) {
620
- await this.executeTasksWithSinglePR(tasks);
678
+ await this.executeTasksWithSinglePR(tasks, true);
621
679
  }
622
680
  else {
623
681
  for (const task of tasks) {
624
- await this.executeTask(task);
682
+ await this.executeTask(task, true);
625
683
  }
626
684
  }
627
- console.log('');
628
- console.log(chalk.green.bold('🎉 All initial tasks completed successfully!'));
629
685
  // Collect PR URLs
630
686
  const createdPRUrls = [];
631
687
  for (const task of tasks) {
@@ -634,44 +690,20 @@ export class TaskExecutor {
634
690
  createdPRUrls.push(updatedTask.pr_link);
635
691
  }
636
692
  }
693
+ // Output final results
637
694
  if (createdPRUrls.length > 0) {
638
- console.log('');
639
- console.log(chalk.blue('📋 PRs created:'));
640
- createdPRUrls.forEach(url => console.log(chalk.cyan(` - ${url}`)));
695
+ createdPRUrls.forEach(url => console.log(url));
641
696
  if (shouldWaitForComments) {
642
- // Wait 30 minutes for reviewers to comment
643
- console.log('');
644
- console.log(chalk.blue('⏰ Waiting 30 minutes for PR reviews...'));
645
- console.log(chalk.gray('PRs being monitored:'));
646
- createdPRUrls.forEach(url => console.log(chalk.gray(` - ${url}`)));
647
- console.log('');
697
+ // Wait 30 minutes for reviewers to comment (silent wait)
648
698
  const waitTime = 30 * 60 * 1000; // 30 minutes in milliseconds
649
- const startTime = Date.now();
650
- const interval = setInterval(() => {
651
- const elapsed = Date.now() - startTime;
652
- const remaining = waitTime - elapsed;
653
- const minutes = Math.floor(remaining / 60000);
654
- const seconds = Math.floor((remaining % 60000) / 1000);
655
- process.stdout.write(`\r${chalk.blue('⏰')} Time remaining: ${minutes}:${seconds.toString().padStart(2, '0')} `);
656
- }, 1000);
657
699
  await new Promise(resolve => setTimeout(resolve, waitTime));
658
- clearInterval(interval);
659
- console.log('\n');
660
700
  // Check for unaddressed comments on created PRs
661
- console.log(chalk.blue('🔍 Checking for PR review comments...'));
662
701
  const prService = createPRService(this.workingDir);
663
702
  const addressTasks = await this.checkAndCreateAddressTasks(createdPRUrls, prService);
664
703
  if (addressTasks.length > 0) {
665
- console.log('');
666
- console.log(chalk.blue.bold(`📋 Found ${addressTasks.length} comments to address`));
667
- // Execute address tasks automatically
704
+ // Execute address tasks automatically (quiet mode)
668
705
  const addressExecutor = new AddressTaskExecutor();
669
- await addressExecutor.executeAddressTasks(addressTasks);
670
- console.log('');
671
- console.log(chalk.green.bold('🎉 All PR comments addressed successfully!'));
672
- }
673
- else {
674
- console.log(chalk.green('✨ No unaddressed comments found on PRs!'));
706
+ await addressExecutor.executeAddressTasks(addressTasks, true);
675
707
  }
676
708
  }
677
709
  }