@link-assistant/hive-mind 0.46.0 → 0.47.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 (63) hide show
  1. package/CHANGELOG.md +26 -13
  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
@@ -14,22 +14,8 @@ import { handleErrorWithIssueCreation } from './github-issue-creator.lib.mjs';
14
14
  /**
15
15
  * Handles log attachment and PR closing on failure
16
16
  */
17
- export const handleFailure = async (options) => {
18
- const {
19
- error,
20
- errorType,
21
- shouldAttachLogs,
22
- argv,
23
- global,
24
- owner,
25
- repo,
26
- log,
27
- getLogFile,
28
- attachLogToGitHub,
29
- cleanErrorMessage,
30
- sanitizeLogContent,
31
- $
32
- } = options;
17
+ export const handleFailure = async options => {
18
+ const { error, errorType, shouldAttachLogs, argv, global, owner, repo, log, getLogFile, attachLogToGitHub, cleanErrorMessage, sanitizeLogContent, $ } = options;
33
19
 
34
20
  // Offer to create GitHub issue for the error
35
21
  try {
@@ -41,14 +27,14 @@ export const handleFailure = async (options) => {
41
27
  owner: global.owner || owner,
42
28
  repo: global.repo || repo,
43
29
  prNumber: global.createdPR?.number,
44
- errorType
30
+ errorType,
45
31
  },
46
- skipPrompt: !process.stdin.isTTY || argv.noIssueCreation
32
+ skipPrompt: !process.stdin.isTTY || argv.noIssueCreation,
47
33
  });
48
34
  } catch (issueError) {
49
35
  reportError(issueError, {
50
36
  context: 'automatic_issue_creation',
51
- operation: 'handle_error_with_issue_creation'
37
+ operation: 'handle_error_with_issue_creation',
52
38
  });
53
39
  await log(`⚠️ Could not create issue: ${issueError.message}`, { level: 'warning' });
54
40
  }
@@ -67,7 +53,7 @@ export const handleFailure = async (options) => {
67
53
  log,
68
54
  sanitizeLogContent,
69
55
  verbose: argv.verbose,
70
- errorMessage: cleanErrorMessage(error)
56
+ errorMessage: cleanErrorMessage(error),
71
57
  });
72
58
  if (logUploadSuccess) {
73
59
  await log('📎 Failure log attached to Pull Request');
@@ -77,7 +63,7 @@ export const handleFailure = async (options) => {
77
63
  context: 'attach_failure_log',
78
64
  prNumber: global.createdPR?.number,
79
65
  errorType,
80
- operation: 'attach_log_to_pr'
66
+ operation: 'attach_log_to_pr',
81
67
  });
82
68
  await log(`⚠️ Could not attach failure log: ${attachError.message}`, { level: 'warning' });
83
69
  }
@@ -87,11 +73,7 @@ export const handleFailure = async (options) => {
87
73
  if (argv.autoClosePullRequestOnFail && global.createdPR && global.createdPR.number) {
88
74
  await log('\n🔒 Auto-closing pull request due to failure...');
89
75
  try {
90
- const closeMessage = errorType === 'uncaughtException'
91
- ? 'Auto-closed due to uncaught exception. Logs have been attached for debugging.'
92
- : errorType === 'unhandledRejection'
93
- ? 'Auto-closed due to unhandled rejection. Logs have been attached for debugging.'
94
- : 'Auto-closed due to execution failure. Logs have been attached for debugging.';
76
+ const closeMessage = errorType === 'uncaughtException' ? 'Auto-closed due to uncaught exception. Logs have been attached for debugging.' : errorType === 'unhandledRejection' ? 'Auto-closed due to unhandled rejection. Logs have been attached for debugging.' : 'Auto-closed due to execution failure. Logs have been attached for debugging.';
95
77
 
96
78
  const result = await $`gh pr close ${global.createdPR.number} --repo ${global.owner || owner}/${global.repo || repo} --comment ${closeMessage}`;
97
79
  if (result.exitCode === 0) {
@@ -103,7 +85,7 @@ export const handleFailure = async (options) => {
103
85
  prNumber: global.createdPR?.number,
104
86
  owner,
105
87
  repo,
106
- operation: 'close_pull_request'
88
+ operation: 'close_pull_request',
107
89
  });
108
90
  await log(`⚠️ Could not close pull request: ${closeError.message}`, { level: 'warning' });
109
91
  }
@@ -113,23 +95,10 @@ export const handleFailure = async (options) => {
113
95
  /**
114
96
  * Creates an uncaught exception handler
115
97
  */
116
- export const createUncaughtExceptionHandler = (options) => {
117
- const {
118
- log,
119
- cleanErrorMessage,
120
- absoluteLogPath,
121
- shouldAttachLogs,
122
- argv,
123
- global,
124
- owner,
125
- repo,
126
- getLogFile,
127
- attachLogToGitHub,
128
- sanitizeLogContent,
129
- $
130
- } = options;
98
+ export const createUncaughtExceptionHandler = options => {
99
+ const { log, cleanErrorMessage, absoluteLogPath, shouldAttachLogs, argv, global, owner, repo, getLogFile, attachLogToGitHub, sanitizeLogContent, $ } = options;
131
100
 
132
- return async (error) => {
101
+ return async error => {
133
102
  await log(`\n❌ Uncaught Exception: ${cleanErrorMessage(error)}`, { level: 'error' });
134
103
  await log(` 📁 Full log file: ${absoluteLogPath}`, { level: 'error' });
135
104
 
@@ -146,7 +115,7 @@ export const createUncaughtExceptionHandler = (options) => {
146
115
  attachLogToGitHub,
147
116
  cleanErrorMessage,
148
117
  sanitizeLogContent,
149
- $
118
+ $,
150
119
  });
151
120
 
152
121
  await safeExit(1, 'Error occurred');
@@ -156,23 +125,10 @@ export const createUncaughtExceptionHandler = (options) => {
156
125
  /**
157
126
  * Creates an unhandled rejection handler
158
127
  */
159
- export const createUnhandledRejectionHandler = (options) => {
160
- const {
161
- log,
162
- cleanErrorMessage,
163
- absoluteLogPath,
164
- shouldAttachLogs,
165
- argv,
166
- global,
167
- owner,
168
- repo,
169
- getLogFile,
170
- attachLogToGitHub,
171
- sanitizeLogContent,
172
- $
173
- } = options;
128
+ export const createUnhandledRejectionHandler = options => {
129
+ const { log, cleanErrorMessage, absoluteLogPath, shouldAttachLogs, argv, global, owner, repo, getLogFile, attachLogToGitHub, sanitizeLogContent, $ } = options;
174
130
 
175
- return async (reason) => {
131
+ return async reason => {
176
132
  await log(`\n❌ Unhandled Rejection: ${cleanErrorMessage(reason)}`, { level: 'error' });
177
133
  await log(` 📁 Full log file: ${absoluteLogPath}`, { level: 'error' });
178
134
 
@@ -189,7 +145,7 @@ export const createUnhandledRejectionHandler = (options) => {
189
145
  attachLogToGitHub,
190
146
  cleanErrorMessage,
191
147
  sanitizeLogContent,
192
- $
148
+ $,
193
149
  });
194
150
 
195
151
  await safeExit(1, 'Error occurred');
@@ -199,22 +155,8 @@ export const createUnhandledRejectionHandler = (options) => {
199
155
  /**
200
156
  * Handles execution errors in the main catch block
201
157
  */
202
- export const handleMainExecutionError = async (options) => {
203
- const {
204
- error,
205
- log,
206
- cleanErrorMessage,
207
- absoluteLogPath,
208
- shouldAttachLogs,
209
- argv,
210
- global,
211
- owner,
212
- repo,
213
- getLogFile,
214
- attachLogToGitHub,
215
- sanitizeLogContent,
216
- $
217
- } = options;
158
+ export const handleMainExecutionError = async options => {
159
+ const { error, log, cleanErrorMessage, absoluteLogPath, shouldAttachLogs, argv, global, owner, repo, getLogFile, attachLogToGitHub, sanitizeLogContent, $ } = options;
218
160
 
219
161
  // Special handling for authentication errors
220
162
  if (error.isAuthError) {
@@ -249,8 +191,8 @@ export const handleMainExecutionError = async (options) => {
249
191
  attachLogToGitHub,
250
192
  cleanErrorMessage,
251
193
  sanitizeLogContent,
252
- $
194
+ $,
253
195
  });
254
196
 
255
197
  await safeExit(1, 'Error occurred');
256
- };
198
+ };
@@ -24,12 +24,7 @@ const memoryCheck = await import('./memory-check.mjs');
24
24
 
25
25
  // Import shared library functions
26
26
  const lib = await import('./lib.mjs');
27
- const {
28
- log,
29
- getLogFile,
30
- cleanErrorMessage,
31
- formatAligned
32
- } = lib;
27
+ const { log, getLogFile, cleanErrorMessage, formatAligned } = lib;
33
28
 
34
29
  // Import GitHub-related functions
35
30
  const githubLib = await import('./github.lib.mjs');
@@ -37,13 +32,10 @@ const githubLib = await import('./github.lib.mjs');
37
32
  const sentryLib = await import('./sentry.lib.mjs');
38
33
  const { reportError } = sentryLib;
39
34
 
40
- const {
41
- sanitizeLogContent,
42
- attachLogToGitHub
43
- } = githubLib;
35
+ const { sanitizeLogContent, attachLogToGitHub } = githubLib;
44
36
 
45
37
  // Create or find temporary directory for cloning the repository
46
- export const setupTempDirectory = async (argv) => {
38
+ export const setupTempDirectory = async argv => {
47
39
  let tempDir;
48
40
  let isResuming = argv.resume;
49
41
 
@@ -65,7 +57,7 @@ export const setupTempDirectory = async (argv) => {
65
57
  reportError(err, {
66
58
  context: 'resume_session_setup',
67
59
  sessionId: argv.resume,
68
- operation: 'find_session_log'
60
+ operation: 'find_session_log',
69
61
  });
70
62
  await log(`Warning: Session log for ${argv.resume} not found, but continuing with resume attempt`);
71
63
  tempDir = path.join(os.tmpdir(), `gh-issue-solver-resume-${argv.resume}-${Date.now()}`);
@@ -146,7 +138,7 @@ export const setupRepository = async (argv, owner, repo) => {
146
138
 
147
139
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
148
140
  const delay = baseDelay * Math.pow(2, attempt - 1); // 2s, 4s, 8s, 16s, 32s
149
- await log(`${formatAligned('⏳', 'Verifying fork:', `Attempt ${attempt}/${maxRetries} (waiting ${delay/1000}s)...`)}`);
141
+ await log(`${formatAligned('⏳', 'Verifying fork:', `Attempt ${attempt}/${maxRetries} (waiting ${delay / 1000}s)...`)}`);
150
142
  await new Promise(resolve => setTimeout(resolve, delay));
151
143
 
152
144
  const reCheckResult = await $`gh repo view ${forkFullName} --json name 2>/dev/null`;
@@ -201,7 +193,7 @@ export const handleExecutionError = async (error, shouldAttachLogs, owner, repo,
201
193
  log,
202
194
  sanitizeLogContent,
203
195
  verbose: argv.verbose || false,
204
- errorMessage: cleanErrorMessage(error)
196
+ errorMessage: cleanErrorMessage(error),
205
197
  });
206
198
 
207
199
  if (logUploadSuccess) {
@@ -211,7 +203,7 @@ export const handleExecutionError = async (error, shouldAttachLogs, owner, repo,
211
203
  reportError(attachError, {
212
204
  context: 'attach_error_log',
213
205
  prNumber: global.createdPR?.number,
214
- operation: 'attach_log_to_pr'
206
+ operation: 'attach_log_to_pr',
215
207
  });
216
208
  await log(`⚠️ Could not attach failure log: ${attachError.message}`, { level: 'warning' });
217
209
  }
@@ -232,7 +224,7 @@ export const handleExecutionError = async (error, shouldAttachLogs, owner, repo,
232
224
  reportError(closeError, {
233
225
  context: 'close_pr_on_error',
234
226
  prNumber: global.createdPR?.number,
235
- operation: 'close_pull_request'
227
+ operation: 'close_pull_request',
236
228
  });
237
229
  await log(`⚠️ Could not close pull request: ${closeError.message}`, { level: 'warning' });
238
230
  }
@@ -253,7 +245,7 @@ export const cleanupTempDirectory = async (tempDir, argv, limitReached) => {
253
245
  reportError(cleanupError, {
254
246
  context: 'cleanup_temp_directory',
255
247
  tempDir,
256
- operation: 'remove_temp_dir'
248
+ operation: 'remove_temp_dir',
257
249
  });
258
250
  await log(' ⚠️ (failed)');
259
251
  }
@@ -288,4 +280,4 @@ export const executeMainSolveLogic = async (tempDir, repoToClone) => {
288
280
  };
289
281
 
290
282
  // Use getResourceSnapshot from memory-check module
291
- export const getResourceSnapshot = memoryCheck.getResourceSnapshot;
283
+ export const getResourceSnapshot = memoryCheck.getResourceSnapshot;
@@ -6,23 +6,8 @@
6
6
  // Import Sentry integration
7
7
  import { reportError } from './sentry.lib.mjs';
8
8
 
9
- export const detectAndCountFeedback = async (params) => {
10
- const {
11
- prNumber,
12
- branchName,
13
- owner,
14
- repo,
15
- issueNumber,
16
- isContinueMode,
17
- argv,
18
- mergeStateStatus,
19
- prState,
20
- workStartTime,
21
- log,
22
- formatAligned,
23
- cleanErrorMessage,
24
- $
25
- } = params;
9
+ export const detectAndCountFeedback = async params => {
10
+ const { prNumber, branchName, owner, repo, issueNumber, isContinueMode, argv, mergeStateStatus, prState, workStartTime, log, formatAligned, cleanErrorMessage, $ } = params;
26
11
 
27
12
  let newPrComments = 0;
28
13
  let newIssueComments = 0;
@@ -40,7 +25,7 @@ export const detectAndCountFeedback = async (params) => {
40
25
  } catch (error) {
41
26
  reportError(error, {
42
27
  context: 'get_current_user',
43
- operation: 'gh_api_user'
28
+ operation: 'gh_api_user',
44
29
  });
45
30
  await log('Warning: Could not get current GitHub user', { level: 'warning' });
46
31
  }
@@ -91,7 +76,7 @@ export const detectAndCountFeedback = async (params) => {
91
76
  reportError(error, {
92
77
  context: 'get_last_commit_time',
93
78
  prNumber,
94
- operation: 'fetch_commit_timestamp'
79
+ operation: 'fetch_commit_timestamp',
95
80
  });
96
81
  await log(`Warning: Could not get last commit time: ${cleanErrorMessage(error)}`, { level: 'warning' });
97
82
  }
@@ -99,14 +84,8 @@ export const detectAndCountFeedback = async (params) => {
99
84
 
100
85
  // Only proceed if we have a last commit time
101
86
  if (lastCommitTime) {
102
-
103
87
  // Define log patterns to filter out comments containing logs from solve.mjs
104
- const logPatterns = [
105
- /📊.*Log file|solution\s+draft.*log/i,
106
- /🔗.*Link:|💻.*Session:/i,
107
- /Generated with.*solve\.mjs/i,
108
- /Session ID:|Log file available:/i
109
- ];
88
+ const logPatterns = [/📊.*Log file|solution\s+draft.*log/i, /🔗.*Link:|💻.*Session:/i, /Generated with.*solve\.mjs/i, /Session ID:|Log file available:/i];
110
89
 
111
90
  // Count new PR comments after last commit (both code review comments and conversation comments)
112
91
  let prReviewComments = [];
@@ -271,10 +250,12 @@ export const detectAndCountFeedback = async (params) => {
271
250
  reportError(error, {
272
251
  context: 'check_description_edits',
273
252
  prNumber,
274
- operation: 'fetch_pr_timeline'
253
+ operation: 'fetch_pr_timeline',
275
254
  });
276
255
  if (argv.verbose) {
277
- await log(`Warning: Could not check description edit times: ${cleanErrorMessage(error)}`, { level: 'warning' });
256
+ await log(`Warning: Could not check description edit times: ${cleanErrorMessage(error)}`, {
257
+ level: 'warning',
258
+ });
278
259
  }
279
260
  }
280
261
 
@@ -299,10 +280,12 @@ export const detectAndCountFeedback = async (params) => {
299
280
  reportError(error, {
300
281
  context: 'check_branch_commits',
301
282
  branchName,
302
- operation: 'fetch_commit_messages'
283
+ operation: 'fetch_commit_messages',
303
284
  });
304
285
  if (argv.verbose) {
305
- await log(`Warning: Could not check default branch commits: ${cleanErrorMessage(error)}`, { level: 'warning' });
286
+ await log(`Warning: Could not check default branch commits: ${cleanErrorMessage(error)}`, {
287
+ level: 'warning',
288
+ });
306
289
  }
307
290
  }
308
291
 
@@ -316,12 +299,12 @@ export const detectAndCountFeedback = async (params) => {
316
299
  // 5. Check merge status (non-clean indicates issues with merging)
317
300
  if (mergeStateStatus && mergeStateStatus !== 'CLEAN') {
318
301
  const statusDescriptions = {
319
- 'DIRTY': 'Merge status is DIRTY (conflicts detected)',
320
- 'UNSTABLE': 'Merge status is UNSTABLE (non-passing commit status)',
321
- 'BLOCKED': 'Merge status is BLOCKED',
322
- 'BEHIND': 'Merge status is BEHIND (head ref is out of date)',
323
- 'HAS_HOOKS': 'Merge status is HAS_HOOKS (has pre-receive hooks)',
324
- 'UNKNOWN': 'Merge status is UNKNOWN'
302
+ DIRTY: 'Merge status is DIRTY (conflicts detected)',
303
+ UNSTABLE: 'Merge status is UNSTABLE (non-passing commit status)',
304
+ BLOCKED: 'Merge status is BLOCKED',
305
+ BEHIND: 'Merge status is BEHIND (head ref is out of date)',
306
+ HAS_HOOKS: 'Merge status is HAS_HOOKS (has pre-receive hooks)',
307
+ UNKNOWN: 'Merge status is UNKNOWN',
325
308
  };
326
309
  const description = statusDescriptions[mergeStateStatus] || `Merge status is ${mergeStateStatus}`;
327
310
  feedbackLines.push(description);
@@ -334,9 +317,7 @@ export const detectAndCountFeedback = async (params) => {
334
317
  const checksResult = await $`gh api repos/${owner}/${repo}/commits/$(gh api repos/${owner}/${repo}/pulls/${prNumber} --jq '.head.sha')/check-runs`;
335
318
  if (checksResult.code === 0) {
336
319
  const checksData = JSON.parse(checksResult.stdout.toString());
337
- const failedChecks = checksData.check_runs?.filter(check =>
338
- check.conclusion === 'failure' && new Date(check.completed_at) > lastCommitTime
339
- ) || [];
320
+ const failedChecks = checksData.check_runs?.filter(check => check.conclusion === 'failure' && new Date(check.completed_at) > lastCommitTime) || [];
340
321
 
341
322
  if (failedChecks.length > 0) {
342
323
  feedbackLines.push(`Failed pull request checks: ${failedChecks.length}`);
@@ -348,7 +329,7 @@ export const detectAndCountFeedback = async (params) => {
348
329
  reportError(error, {
349
330
  context: 'check_pr_status_checks',
350
331
  prNumber,
351
- operation: 'fetch_status_checks'
332
+ operation: 'fetch_status_checks',
352
333
  });
353
334
  if (argv.verbose) {
354
335
  await log(`Warning: Could not check PR status checks: ${cleanErrorMessage(error)}`, { level: 'warning' });
@@ -360,9 +341,7 @@ export const detectAndCountFeedback = async (params) => {
360
341
  const reviewsResult = await $`gh api repos/${owner}/${repo}/pulls/${prNumber}/reviews`;
361
342
  if (reviewsResult.code === 0) {
362
343
  const reviews = JSON.parse(reviewsResult.stdout.toString());
363
- const changesRequestedReviews = reviews.filter(review =>
364
- review.state === 'CHANGES_REQUESTED' && new Date(review.submitted_at) > lastCommitTime
365
- );
344
+ const changesRequestedReviews = reviews.filter(review => review.state === 'CHANGES_REQUESTED' && new Date(review.submitted_at) > lastCommitTime);
366
345
 
367
346
  if (changesRequestedReviews.length > 0) {
368
347
  feedbackLines.push(`Changes requested in reviews: ${changesRequestedReviews.length}`);
@@ -374,7 +353,7 @@ export const detectAndCountFeedback = async (params) => {
374
353
  reportError(error, {
375
354
  context: 'check_pr_reviews',
376
355
  prNumber,
377
- operation: 'fetch_pr_reviews'
356
+ operation: 'fetch_pr_reviews',
378
357
  });
379
358
  if (argv.verbose) {
380
359
  await log(`Warning: Could not check PR reviews: ${cleanErrorMessage(error)}`, { level: 'warning' });
@@ -419,7 +398,7 @@ export const detectAndCountFeedback = async (params) => {
419
398
  reportError(error, {
420
399
  context: 'count_new_comments',
421
400
  prNumber,
422
- operation: 'detect_and_count_feedback'
401
+ operation: 'detect_and_count_feedback',
423
402
  });
424
403
  await log(`Warning: Could not count new comments: ${cleanErrorMessage(error)}`, { level: 'warning' });
425
404
  }
@@ -433,4 +412,4 @@ export const detectAndCountFeedback = async (params) => {
433
412
  }
434
413
 
435
414
  return { newPrComments, newIssueComments, commentInfo, feedbackLines };
436
- };
415
+ };