@link-assistant/hive-mind 0.46.1 → 0.47.1

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 (63) hide show
  1. package/CHANGELOG.md +20 -15
  2. package/README.md +42 -8
  3. package/package.json +16 -3
  4. package/src/agent.lib.mjs +49 -70
  5. package/src/agent.prompts.lib.mjs +6 -20
  6. package/src/buildUserMention.lib.mjs +4 -17
  7. package/src/claude-limits.lib.mjs +15 -15
  8. package/src/claude.lib.mjs +617 -626
  9. package/src/claude.prompts.lib.mjs +7 -22
  10. package/src/codex.lib.mjs +39 -71
  11. package/src/codex.prompts.lib.mjs +6 -20
  12. package/src/config.lib.mjs +3 -16
  13. package/src/contributing-guidelines.lib.mjs +5 -18
  14. package/src/exit-handler.lib.mjs +4 -4
  15. package/src/git.lib.mjs +7 -7
  16. package/src/github-issue-creator.lib.mjs +17 -17
  17. package/src/github-linking.lib.mjs +8 -33
  18. package/src/github.batch.lib.mjs +20 -16
  19. package/src/github.graphql.lib.mjs +18 -18
  20. package/src/github.lib.mjs +89 -91
  21. package/src/hive.config.lib.mjs +50 -50
  22. package/src/hive.mjs +1293 -1296
  23. package/src/instrument.mjs +7 -11
  24. package/src/interactive-mode.lib.mjs +112 -138
  25. package/src/lenv-reader.lib.mjs +1 -6
  26. package/src/lib.mjs +36 -45
  27. package/src/lino.lib.mjs +2 -2
  28. package/src/local-ci-checks.lib.mjs +15 -14
  29. package/src/memory-check.mjs +52 -60
  30. package/src/model-mapping.lib.mjs +25 -32
  31. package/src/model-validation.lib.mjs +31 -31
  32. package/src/opencode.lib.mjs +37 -62
  33. package/src/opencode.prompts.lib.mjs +7 -21
  34. package/src/protect-branch.mjs +14 -15
  35. package/src/review.mjs +28 -27
  36. package/src/reviewers-hive.mjs +64 -69
  37. package/src/sentry.lib.mjs +13 -10
  38. package/src/solve.auto-continue.lib.mjs +48 -38
  39. package/src/solve.auto-pr.lib.mjs +111 -69
  40. package/src/solve.branch-errors.lib.mjs +17 -46
  41. package/src/solve.branch.lib.mjs +16 -23
  42. package/src/solve.config.lib.mjs +263 -261
  43. package/src/solve.error-handlers.lib.mjs +21 -79
  44. package/src/solve.execution.lib.mjs +10 -18
  45. package/src/solve.feedback.lib.mjs +25 -46
  46. package/src/solve.mjs +59 -60
  47. package/src/solve.preparation.lib.mjs +10 -36
  48. package/src/solve.repo-setup.lib.mjs +4 -19
  49. package/src/solve.repository.lib.mjs +37 -37
  50. package/src/solve.results.lib.mjs +32 -46
  51. package/src/solve.session.lib.mjs +7 -22
  52. package/src/solve.validation.lib.mjs +19 -17
  53. package/src/solve.watch.lib.mjs +20 -33
  54. package/src/start-screen.mjs +24 -24
  55. package/src/task.mjs +38 -44
  56. package/src/telegram-bot.mjs +125 -121
  57. package/src/telegram-top-command.lib.mjs +32 -48
  58. package/src/usage-limit.lib.mjs +9 -13
  59. package/src/version-info.lib.mjs +1 -1
  60. package/src/version.lib.mjs +1 -1
  61. package/src/youtrack/solve.youtrack.lib.mjs +3 -8
  62. package/src/youtrack/youtrack-sync.mjs +8 -14
  63. package/src/youtrack/youtrack.lib.mjs +26 -28
package/src/solve.mjs CHANGED
@@ -133,7 +133,7 @@ if (argv.sentry) {
133
133
  await initializeSentry({
134
134
  noSentry: !argv.sentry,
135
135
  debug: argv.verbose,
136
- version: process.env.npm_package_version || '0.12.0'
136
+ version: process.env.npm_package_version || '0.12.0',
137
137
  });
138
138
  // Add breadcrumb for solve operation
139
139
  addBreadcrumb({
@@ -142,8 +142,8 @@ if (argv.sentry) {
142
142
  level: 'info',
143
143
  data: {
144
144
  model: argv.model,
145
- issueUrl: argv['issue-url'] || argv._?.[0] || 'not-set-yet'
146
- }
145
+ issueUrl: argv['issue-url'] || argv._?.[0] || 'not-set-yet',
146
+ },
147
147
  });
148
148
  }
149
149
  // Create a cleanup wrapper that will be populated with context later
@@ -186,11 +186,11 @@ const errorHandlerOptions = {
186
186
  argv,
187
187
  global,
188
188
  owner: null, // Will be set later when parsed
189
- repo: null, // Will be set later when parsed
189
+ repo: null, // Will be set later when parsed
190
190
  getLogFile,
191
191
  attachLogToGitHub,
192
192
  sanitizeLogContent,
193
- $
193
+ $,
194
194
  };
195
195
  process.on('uncaughtException', createUncaughtExceptionHandler(errorHandlerOptions));
196
196
  process.on('unhandledRejection', createUnhandledRejectionHandler(errorHandlerOptions));
@@ -247,12 +247,14 @@ if (argv.autoFork && !argv.fork) {
247
247
  if (!isPublic) {
248
248
  // Private repository without write access - cannot fork
249
249
  await log('');
250
- await log('❌ --auto-fork failed: Repository is private and you don\'t have write access', { level: 'error' });
250
+ await log("❌ --auto-fork failed: Repository is private and you don't have write access", { level: 'error' });
251
251
  await log('');
252
252
  await log(' 🔍 What happened:', { level: 'error' });
253
253
  await log(` Repository ${owner}/${repo} is private`, { level: 'error' });
254
- await log(' You don\'t have write access to this repository', { level: 'error' });
255
- await log(' --auto-fork cannot create a fork of a private repository you cannot access', { level: 'error' });
254
+ await log(" You don't have write access to this repository", { level: 'error' });
255
+ await log(' --auto-fork cannot create a fork of a private repository you cannot access', {
256
+ level: 'error',
257
+ });
256
258
  await log('');
257
259
  await log(' 💡 Solution:', { level: 'error' });
258
260
  await log(' • Request collaborator access from the repository owner', { level: 'error' });
@@ -284,7 +286,7 @@ if (argv.autoFork && !argv.fork) {
284
286
  await log('');
285
287
  await log(' 💡 Solutions:', { level: 'error' });
286
288
  await log(' • Check your GitHub CLI authentication: gh auth status', { level: 'error' });
287
- await log(' • Request collaborator access if you don\'t have it yet', { level: 'error' });
289
+ await log(" • Request collaborator access if you don't have it yet", { level: 'error' });
288
290
  await log(` https://github.com/${owner}/${repo}/settings/access`, { level: 'error' });
289
291
  await log('');
290
292
  await safeExit(1, 'Auto-fork failed - cannot verify private repository permissions');
@@ -301,7 +303,7 @@ if (argv.autoFork && !argv.fork) {
301
303
  const { checkRepositoryWritePermission } = githubLib;
302
304
  const hasWriteAccess = await checkRepositoryWritePermission(owner, repo, {
303
305
  useFork: argv.fork,
304
- issueUrl: issueUrl
306
+ issueUrl: issueUrl,
305
307
  });
306
308
 
307
309
  if (!hasWriteAccess) {
@@ -318,7 +320,9 @@ if (argv.autoCleanup === undefined) {
318
320
  // For private repos: clean up temp directories (default true)
319
321
  argv.autoCleanup = !isPublic;
320
322
  if (argv.verbose) {
321
- await log(` Auto-cleanup default: ${argv.autoCleanup} (repository is ${isPublic ? 'public' : 'private'})`, { verbose: true });
323
+ await log(` Auto-cleanup default: ${argv.autoCleanup} (repository is ${isPublic ? 'public' : 'private'})`, {
324
+ verbose: true,
325
+ });
322
326
  }
323
327
  }
324
328
  // Determine mode and get issue details
@@ -358,7 +362,7 @@ if (autoContinueResult.isContinueMode) {
358
362
  if (prCheckData.headRepositoryOwner && prCheckData.headRepositoryOwner.login !== owner) {
359
363
  forkOwner = prCheckData.headRepositoryOwner.login;
360
364
  // Get actual fork repository name (may be prefixed)
361
- const forkRepoName = (prCheckData.headRepository && prCheckData.headRepository.name) ? prCheckData.headRepository.name : repo;
365
+ const forkRepoName = prCheckData.headRepository && prCheckData.headRepository.name ? prCheckData.headRepository.name : repo;
362
366
  await log(`🍴 Detected fork PR from ${forkOwner}/${forkRepoName}`);
363
367
  if (argv.verbose) {
364
368
  await log(` Fork owner: ${forkOwner}`, { verbose: true });
@@ -372,10 +376,12 @@ if (autoContinueResult.isContinueMode) {
372
376
 
373
377
  if (canModify) {
374
378
  await log('✅ Maintainer can push to fork: Enabled by contributor');
375
- await log(' Will push changes directly to contributor\'s fork instead of creating own fork');
379
+ await log(" Will push changes directly to contributor's fork instead of creating own fork");
376
380
  // Don't disable fork mode, but we'll use the contributor's fork
377
381
  } else {
378
- await log('⚠️ Maintainer cannot push to fork: "Allow edits by maintainers" is not enabled', { level: 'warning' });
382
+ await log('⚠️ Maintainer cannot push to fork: "Allow edits by maintainers" is not enabled', {
383
+ level: 'warning',
384
+ });
379
385
  await log(' Posting comment to request access...', { level: 'warning' });
380
386
  await requestMaintainerAccess(owner, repo, prNumber);
381
387
  await log(' Comment posted. Proceeding with own fork instead.', { level: 'warning' });
@@ -392,7 +398,9 @@ if (autoContinueResult.isContinueMode) {
392
398
  // We have a branch but no PR - we'll use the existing branch and create a PR later
393
399
  await log(`🔄 Using existing branch: ${prBranch} (no PR yet - will create one)`);
394
400
  if (argv.verbose) {
395
- await log(' Branch will be checked out and PR will be created during auto-PR creation phase', { verbose: true });
401
+ await log(' Branch will be checked out and PR will be created during auto-PR creation phase', {
402
+ verbose: true,
403
+ });
396
404
  }
397
405
  }
398
406
  } else if (isIssueUrl) {
@@ -415,7 +423,7 @@ if (isPrUrl) {
415
423
  prNumber,
416
424
  owner,
417
425
  repo,
418
- jsonFields: 'headRefName,body,number,mergeStateStatus,state,headRepositoryOwner,headRepository'
426
+ jsonFields: 'headRefName,body,number,mergeStateStatus,state,headRepositoryOwner,headRepository',
419
427
  });
420
428
  if (prResult.code !== 0 || !prResult.data) {
421
429
  await log('Error: Failed to get PR details', { level: 'error' });
@@ -434,7 +442,7 @@ if (isPrUrl) {
434
442
  if (prData.headRepositoryOwner && prData.headRepositoryOwner.login !== owner) {
435
443
  forkOwner = prData.headRepositoryOwner.login;
436
444
  // Get actual fork repository name (may be prefixed)
437
- const forkRepoName = (prData.headRepository && prData.headRepository.name) ? prData.headRepository.name : repo;
445
+ const forkRepoName = prData.headRepository && prData.headRepository.name ? prData.headRepository.name : repo;
438
446
  await log(`🍴 Detected fork PR from ${forkOwner}/${forkRepoName}`);
439
447
  if (argv.verbose) {
440
448
  await log(` Fork owner: ${forkOwner}`, { verbose: true });
@@ -448,10 +456,12 @@ if (isPrUrl) {
448
456
 
449
457
  if (canModify) {
450
458
  await log('✅ Maintainer can push to fork: Enabled by contributor');
451
- await log(' Will push changes directly to contributor\'s fork instead of creating own fork');
459
+ await log(" Will push changes directly to contributor's fork instead of creating own fork");
452
460
  // Don't disable fork mode, but we'll use the contributor's fork
453
461
  } else {
454
- await log('⚠️ Maintainer cannot push to fork: "Allow edits by maintainers" is not enabled', { level: 'warning' });
462
+ await log('⚠️ Maintainer cannot push to fork: "Allow edits by maintainers" is not enabled', {
463
+ level: 'warning',
464
+ });
455
465
  await log(' Posting comment to request access...', { level: 'warning' });
456
466
  await requestMaintainerAccess(owner, repo, prNumber);
457
467
  await log(' Comment posted. Proceeding with own fork instead.', { level: 'warning' });
@@ -477,7 +487,7 @@ if (isPrUrl) {
477
487
  reportError(error, {
478
488
  context: 'pr_processing',
479
489
  prNumber,
480
- operation: 'process_pull_request'
490
+ operation: 'process_pull_request',
481
491
  });
482
492
  await log(`Error: Failed to process PR: ${cleanErrorMessage(error)}`, { level: 'error' });
483
493
  await safeExit(1, 'Failed to process PR');
@@ -506,7 +516,7 @@ try {
506
516
  issueUrl,
507
517
  log,
508
518
  formatAligned,
509
- $
519
+ $,
510
520
  });
511
521
 
512
522
  // Verify default branch and status using the new module
@@ -514,7 +524,7 @@ try {
514
524
  tempDir,
515
525
  log,
516
526
  formatAligned,
517
- $
527
+ $,
518
528
  });
519
529
  // Create or checkout branch using the new module
520
530
  const branchName = await createOrCheckoutBranch({
@@ -527,7 +537,7 @@ try {
527
537
  log,
528
538
  formatAligned,
529
539
  $,
530
- crypto
540
+ crypto,
531
541
  });
532
542
 
533
543
  // Auto-merge default branch to pull request branch if enabled
@@ -593,7 +603,7 @@ try {
593
603
  $,
594
604
  reportError,
595
605
  path,
596
- fs
606
+ fs,
597
607
  });
598
608
 
599
609
  let claudeCommitHash = null;
@@ -653,7 +663,7 @@ try {
653
663
  await log(`\n${formatAligned('⏭️', 'Auto PR creation:', 'DISABLED')}`);
654
664
  await log(formatAligned('', 'Workflow:', 'AI will create the PR', 2));
655
665
  }
656
-
666
+
657
667
  // Don't build the prompt yet - we'll build it after we have all the information
658
668
  // This includes PR URL (if created) and comment info (if in continue mode)
659
669
 
@@ -664,7 +674,7 @@ try {
664
674
  argv,
665
675
  log,
666
676
  formatAligned,
667
- $
677
+ $,
668
678
  });
669
679
 
670
680
  // Prepare feedback and timestamps using the new module
@@ -681,7 +691,7 @@ try {
681
691
  log,
682
692
  formatAligned,
683
693
  cleanErrorMessage,
684
- $
694
+ $,
685
695
  });
686
696
 
687
697
  // Initialize feedback lines
@@ -708,7 +718,7 @@ try {
708
718
  tempDir,
709
719
  argv,
710
720
  log,
711
- $
721
+ $,
712
722
  });
713
723
  if (uncommittedFeedbackLines && uncommittedFeedbackLines.length > 0) {
714
724
  if (!feedbackLines) {
@@ -724,7 +734,7 @@ try {
724
734
  branchName,
725
735
  log,
726
736
  formatAligned,
727
- $
737
+ $,
728
738
  });
729
739
 
730
740
  // Execute tool command with all prompts and settings
@@ -755,7 +765,7 @@ try {
755
765
  formatAligned,
756
766
  getResourceSnapshot,
757
767
  opencodePath,
758
- $
768
+ $,
759
769
  });
760
770
  } else if (argv.tool === 'codex') {
761
771
  const codexLib = await import('./codex.lib.mjs');
@@ -783,7 +793,7 @@ try {
783
793
  formatAligned,
784
794
  getResourceSnapshot,
785
795
  codexPath,
786
- $
796
+ $,
787
797
  });
788
798
  } else if (argv.tool === 'agent') {
789
799
  const agentLib = await import('./agent.lib.mjs');
@@ -811,7 +821,7 @@ try {
811
821
  formatAligned,
812
822
  getResourceSnapshot,
813
823
  agentPath,
814
- $
824
+ $,
815
825
  });
816
826
  } else {
817
827
  // Default to Claude
@@ -848,7 +858,7 @@ try {
848
858
  formatAligned,
849
859
  getResourceSnapshot,
850
860
  claudePath,
851
- $
861
+ $,
852
862
  });
853
863
  toolResult = claudeResult;
854
864
  }
@@ -856,8 +866,8 @@ try {
856
866
  const { success } = toolResult;
857
867
  let sessionId = toolResult.sessionId;
858
868
  let anthropicTotalCostUSD = toolResult.anthropicTotalCostUSD;
859
- let publicPricingEstimate = toolResult.publicPricingEstimate; // Used by agent tool
860
- let pricingInfo = toolResult.pricingInfo; // Used by agent tool for detailed pricing
869
+ let publicPricingEstimate = toolResult.publicPricingEstimate; // Used by agent tool
870
+ let pricingInfo = toolResult.pricingInfo; // Used by agent tool for detailed pricing
861
871
  limitReached = toolResult.limitReached;
862
872
  cleanupContext.limitReached = limitReached;
863
873
 
@@ -893,12 +903,9 @@ try {
893
903
  // Mark this as a usage limit case for proper formatting
894
904
  isUsageLimit: true,
895
905
  limitResetTime: global.limitResetTime,
896
- toolName: (argv.tool || 'AI tool').toString().toLowerCase() === 'claude' ? 'Claude' :
897
- (argv.tool || 'AI tool').toString().toLowerCase() === 'codex' ? 'Codex' :
898
- (argv.tool || 'AI tool').toString().toLowerCase() === 'opencode' ? 'OpenCode' :
899
- (argv.tool || 'AI tool').toString().toLowerCase() === 'agent' ? 'Agent' : 'AI tool',
906
+ toolName: (argv.tool || 'AI tool').toString().toLowerCase() === 'claude' ? 'Claude' : (argv.tool || 'AI tool').toString().toLowerCase() === 'codex' ? 'Codex' : (argv.tool || 'AI tool').toString().toLowerCase() === 'opencode' ? 'OpenCode' : (argv.tool || 'AI tool').toString().toLowerCase() === 'agent' ? 'Agent' : 'AI tool',
900
907
  resumeCommand,
901
- sessionId
908
+ sessionId,
902
909
  });
903
910
 
904
911
  if (logUploadSuccess) {
@@ -913,9 +920,7 @@ try {
913
920
  // Fallback: Post simple failure comment if logs are not attached
914
921
  try {
915
922
  const resetTime = global.limitResetTime;
916
- const failureComment = resetTime
917
- ? `❌ **Usage Limit Reached**\n\nThe AI tool has reached its usage limit. The limit will reset at: **${resetTime}**\n\nThis session has failed because \`--auto-continue-on-limit-reset\` was not enabled.\n\nTo automatically wait for the limit to reset and continue, use:\n\`\`\`bash\n./solve.mjs "${issueUrl}" --resume ${sessionId} --auto-continue-on-limit-reset\n\`\`\``
918
- : `❌ **Usage Limit Reached**\n\nThe AI tool has reached its usage limit. Please wait for the limit to reset.\n\nThis session has failed because \`--auto-continue-on-limit-reset\` was not enabled.\n\nTo resume after the limit resets, use:\n\`\`\`bash\n./solve.mjs "${issueUrl}" --resume ${sessionId}\n\`\`\``;
923
+ const failureComment = resetTime ? `❌ **Usage Limit Reached**\n\nThe AI tool has reached its usage limit. The limit will reset at: **${resetTime}**\n\nThis session has failed because \`--auto-continue-on-limit-reset\` was not enabled.\n\nTo automatically wait for the limit to reset and continue, use:\n\`\`\`bash\n./solve.mjs "${issueUrl}" --resume ${sessionId} --auto-continue-on-limit-reset\n\`\`\`` : `❌ **Usage Limit Reached**\n\nThe AI tool has reached its usage limit. Please wait for the limit to reset.\n\nThis session has failed because \`--auto-continue-on-limit-reset\` was not enabled.\n\nTo resume after the limit resets, use:\n\`\`\`bash\n./solve.mjs "${issueUrl}" --resume ${sessionId}\n\`\`\``;
919
924
 
920
925
  const commentResult = await $`gh pr comment ${prNumber} --repo ${owner}/${repo} --body ${failureComment}`;
921
926
  if (commentResult.code === 0) {
@@ -948,12 +953,9 @@ try {
948
953
  // Mark this as a usage limit case for proper formatting
949
954
  isUsageLimit: true,
950
955
  limitResetTime: global.limitResetTime,
951
- toolName: (argv.tool || 'AI tool').toString().toLowerCase() === 'claude' ? 'Claude' :
952
- (argv.tool || 'AI tool').toString().toLowerCase() === 'codex' ? 'Codex' :
953
- (argv.tool || 'AI tool').toString().toLowerCase() === 'opencode' ? 'OpenCode' :
954
- (argv.tool || 'AI tool').toString().toLowerCase() === 'agent' ? 'Agent' : 'AI tool',
956
+ toolName: (argv.tool || 'AI tool').toString().toLowerCase() === 'claude' ? 'Claude' : (argv.tool || 'AI tool').toString().toLowerCase() === 'codex' ? 'Codex' : (argv.tool || 'AI tool').toString().toLowerCase() === 'opencode' ? 'OpenCode' : (argv.tool || 'AI tool').toString().toLowerCase() === 'agent' ? 'Agent' : 'AI tool',
955
957
  resumeCommand,
956
- sessionId
958
+ sessionId,
957
959
  });
958
960
 
959
961
  if (logUploadSuccess) {
@@ -972,7 +974,7 @@ try {
972
974
  const { calculateWaitTime } = validation;
973
975
  const waitMs = calculateWaitTime(global.limitResetTime);
974
976
 
975
- const formatWaitTime = (ms) => {
977
+ const formatWaitTime = ms => {
976
978
  const seconds = Math.floor(ms / 1000);
977
979
  const minutes = Math.floor(seconds / 60);
978
980
  const hours = Math.floor(minutes / 60);
@@ -1016,15 +1018,12 @@ try {
1016
1018
  // For usage limit, use a dedicated comment format to make it clear and actionable
1017
1019
  isUsageLimit: !!limitReached,
1018
1020
  limitResetTime: limitReached ? toolResult.limitResetTime : null,
1019
- toolName: (argv.tool || 'AI tool').toString().toLowerCase() === 'claude' ? 'Claude' :
1020
- (argv.tool || 'AI tool').toString().toLowerCase() === 'codex' ? 'Codex' :
1021
- (argv.tool || 'AI tool').toString().toLowerCase() === 'opencode' ? 'OpenCode' :
1022
- (argv.tool || 'AI tool').toString().toLowerCase() === 'agent' ? 'Agent' : 'AI tool',
1021
+ toolName: (argv.tool || 'AI tool').toString().toLowerCase() === 'claude' ? 'Claude' : (argv.tool || 'AI tool').toString().toLowerCase() === 'codex' ? 'Codex' : (argv.tool || 'AI tool').toString().toLowerCase() === 'opencode' ? 'OpenCode' : (argv.tool || 'AI tool').toString().toLowerCase() === 'agent' ? 'Agent' : 'AI tool',
1023
1022
  resumeCommand,
1024
1023
  // Include sessionId so the PR comment can present it
1025
1024
  sessionId,
1026
1025
  // If not a usage limit case, fall back to generic failure format
1027
- errorMessage: limitReached ? undefined : `${argv.tool.toUpperCase()} execution failed`
1026
+ errorMessage: limitReached ? undefined : `${argv.tool.toUpperCase()} execution failed`,
1028
1027
  });
1029
1028
 
1030
1029
  if (logUploadSuccess) {
@@ -1093,8 +1092,8 @@ try {
1093
1092
  argv: {
1094
1093
  ...argv,
1095
1094
  watch: argv.watch || shouldRestart, // Enable watch if uncommitted changes
1096
- temporaryWatch: temporaryWatchMode // Flag to indicate temporary watch mode
1097
- }
1095
+ temporaryWatch: temporaryWatchMode, // Flag to indicate temporary watch mode
1096
+ },
1098
1097
  });
1099
1098
 
1100
1099
  // Update session data with latest from watch mode for accurate pricing
@@ -1157,7 +1156,7 @@ try {
1157
1156
  verbose: argv.verbose,
1158
1157
  sessionId,
1159
1158
  tempDir,
1160
- anthropicTotalCostUSD
1159
+ anthropicTotalCostUSD,
1161
1160
  });
1162
1161
 
1163
1162
  if (logUploadSuccess) {
@@ -1180,14 +1179,14 @@ try {
1180
1179
  log,
1181
1180
  formatAligned,
1182
1181
  $,
1183
- logsAttached
1182
+ logsAttached,
1184
1183
  });
1185
1184
  } catch (error) {
1186
1185
  // Don't report authentication errors to Sentry as they are user configuration issues
1187
1186
  if (!error.isAuthError) {
1188
1187
  reportError(error, {
1189
1188
  context: 'solve_main',
1190
- operation: 'main_execution'
1189
+ operation: 'main_execution',
1191
1190
  });
1192
1191
  }
1193
1192
  await handleMainExecutionError({
@@ -1203,7 +1202,7 @@ try {
1203
1202
  getLogFile,
1204
1203
  attachLogToGitHub,
1205
1204
  sanitizeLogContent,
1206
- $
1205
+ $,
1207
1206
  });
1208
1207
  } finally {
1209
1208
  // Clean up temporary directory using repository module
@@ -7,23 +7,7 @@
7
7
  const feedback = await import('./solve.feedback.lib.mjs');
8
8
  const { detectAndCountFeedback } = feedback;
9
9
 
10
-
11
-
12
- export async function prepareFeedbackAndTimestamps({
13
- prNumber,
14
- branchName: _branchName,
15
- owner,
16
- repo,
17
- issueNumber,
18
- isContinueMode: _isContinueMode,
19
- mergeStateStatus: _mergeStateStatus,
20
- prState: _prState,
21
- argv: _argv,
22
- log,
23
- formatAligned,
24
- cleanErrorMessage: _cleanErrorMessage,
25
- $
26
- }) {
10
+ export async function prepareFeedbackAndTimestamps({ prNumber, branchName: _branchName, owner, repo, issueNumber, isContinueMode: _isContinueMode, mergeStateStatus: _mergeStateStatus, prState: _prState, argv: _argv, log, formatAligned, cleanErrorMessage: _cleanErrorMessage, $ }) {
27
11
  // Count new comments and detect feedback
28
12
  let { feedbackLines } = await detectAndCountFeedback({
29
13
  prNumber,
@@ -39,7 +23,7 @@ export async function prepareFeedbackAndTimestamps({
39
23
  log,
40
24
  formatAligned,
41
25
  cleanErrorMessage: _cleanErrorMessage,
42
- $
26
+ $,
43
27
  });
44
28
 
45
29
  // Get timestamps from GitHub servers before executing the command
@@ -77,7 +61,9 @@ export async function prepareFeedbackAndTimestamps({
77
61
  const prsResult = await $`gh pr list --repo ${owner}/${repo} --limit 1 --json createdAt`;
78
62
 
79
63
  if (prsResult.code !== 0) {
80
- await log(`Warning: Failed to get PRs: ${prsResult.stderr ? prsResult.stderr.toString() : 'Unknown error'}`, { level: 'warning' });
64
+ await log(`Warning: Failed to get PRs: ${prsResult.stderr ? prsResult.stderr.toString() : 'Unknown error'}`, {
65
+ level: 'warning',
66
+ });
81
67
  // Continue anyway, PRs are optional for timestamp calculation
82
68
  }
83
69
 
@@ -106,7 +92,7 @@ export async function prepareFeedbackAndTimestamps({
106
92
  context: 'get_reference_timestamp',
107
93
  prNumber,
108
94
  issueNumber,
109
- operation: 'fetch_github_timestamps'
95
+ operation: 'fetch_github_timestamps',
110
96
  });
111
97
  await log('Warning: Could not get GitHub timestamps, using current time as reference', { level: 'warning' });
112
98
  await log(` Error: ${timestampError.message}`);
@@ -117,12 +103,7 @@ export async function prepareFeedbackAndTimestamps({
117
103
  return { feedbackLines, referenceTime };
118
104
  }
119
105
 
120
- export async function checkUncommittedChanges({
121
- tempDir,
122
- argv,
123
- log,
124
- $
125
- }) {
106
+ export async function checkUncommittedChanges({ tempDir, argv, log, $ }) {
126
107
  // Check for uncommitted changes before running Claude
127
108
  // Only add to feedback if auto-commit is disabled
128
109
  if (!argv['auto-commit-uncommitted-changes']) {
@@ -163,7 +144,7 @@ export async function checkUncommittedChanges({
163
144
  reportError(gitError, {
164
145
  context: 'check_uncommitted_changes',
165
146
  tempDir,
166
- operation: 'git_status'
147
+ operation: 'git_status',
167
148
  });
168
149
  await log(`⚠️ Warning: Could not check git status: ${gitError.message}`, { level: 'warning' });
169
150
  }
@@ -171,14 +152,7 @@ export async function checkUncommittedChanges({
171
152
  return [];
172
153
  }
173
154
 
174
- export async function checkForkActions({
175
- argv,
176
- forkedRepo,
177
- branchName,
178
- log,
179
- formatAligned,
180
- $
181
- }) {
155
+ export async function checkForkActions({ argv, forkedRepo, branchName, log, formatAligned, $ }) {
182
156
  // Check for GitHub Actions on fork repository if applicable
183
157
  let forkActionsUrl = null;
184
158
  if (argv.fork && forkedRepo) {
@@ -207,4 +181,4 @@ export async function checkForkActions({
207
181
  }
208
182
 
209
183
  return forkActionsUrl;
210
- }
184
+ }
@@ -3,17 +3,7 @@
3
3
  * Handles repository cloning, forking, and remote setup
4
4
  */
5
5
 
6
- export async function setupRepositoryAndClone({
7
- argv,
8
- owner,
9
- repo,
10
- forkOwner,
11
- tempDir,
12
- isContinueMode,
13
- issueUrl,
14
- log,
15
- $
16
- }) {
6
+ export async function setupRepositoryAndClone({ argv, owner, repo, forkOwner, tempDir, isContinueMode, issueUrl, log, $ }) {
17
7
  // Set up repository and handle forking
18
8
  const { repoToClone, forkedRepo, upstreamRemote, prForkOwner } = await setupRepository(argv, owner, repo, forkOwner, issueUrl);
19
9
 
@@ -57,12 +47,7 @@ async function setupPrForkRemote(tempDir, argv, prForkOwner, repo, isContinueMod
57
47
  return await setupPrForkFn(tempDir, argv, prForkOwner, repo, isContinueMode, owner);
58
48
  }
59
49
 
60
- export async function verifyDefaultBranchAndStatus({
61
- tempDir,
62
- log,
63
- formatAligned,
64
- $
65
- }) {
50
+ export async function verifyDefaultBranchAndStatus({ tempDir, log, formatAligned, $ }) {
66
51
  // Verify we're on the default branch and get its name
67
52
  const defaultBranchResult = await $({ cwd: tempDir })`git branch --show-current`;
68
53
 
@@ -78,7 +63,7 @@ export async function verifyDefaultBranchAndStatus({
78
63
  await log(`${formatAligned('❌', 'DEFAULT BRANCH DETECTION FAILED', '')}`, { level: 'error' });
79
64
  await log('');
80
65
  await log(' 🔍 What happened:');
81
- await log(' Unable to determine the repository\'s default branch.');
66
+ await log(" Unable to determine the repository's default branch.");
82
67
  await log('');
83
68
  await log(' 💡 This might mean:');
84
69
  await log(' • Repository is empty (no commits)');
@@ -111,4 +96,4 @@ export async function verifyDefaultBranchAndStatus({
111
96
  }
112
97
 
113
98
  return defaultBranch;
114
- }
99
+ }