@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.
- package/CHANGELOG.md +20 -15
- package/README.md +42 -8
- package/package.json +16 -3
- package/src/agent.lib.mjs +49 -70
- package/src/agent.prompts.lib.mjs +6 -20
- package/src/buildUserMention.lib.mjs +4 -17
- package/src/claude-limits.lib.mjs +15 -15
- package/src/claude.lib.mjs +617 -626
- package/src/claude.prompts.lib.mjs +7 -22
- package/src/codex.lib.mjs +39 -71
- package/src/codex.prompts.lib.mjs +6 -20
- package/src/config.lib.mjs +3 -16
- package/src/contributing-guidelines.lib.mjs +5 -18
- package/src/exit-handler.lib.mjs +4 -4
- package/src/git.lib.mjs +7 -7
- package/src/github-issue-creator.lib.mjs +17 -17
- package/src/github-linking.lib.mjs +8 -33
- package/src/github.batch.lib.mjs +20 -16
- package/src/github.graphql.lib.mjs +18 -18
- package/src/github.lib.mjs +89 -91
- package/src/hive.config.lib.mjs +50 -50
- package/src/hive.mjs +1293 -1296
- package/src/instrument.mjs +7 -11
- package/src/interactive-mode.lib.mjs +112 -138
- package/src/lenv-reader.lib.mjs +1 -6
- package/src/lib.mjs +36 -45
- package/src/lino.lib.mjs +2 -2
- package/src/local-ci-checks.lib.mjs +15 -14
- package/src/memory-check.mjs +52 -60
- package/src/model-mapping.lib.mjs +25 -32
- package/src/model-validation.lib.mjs +31 -31
- package/src/opencode.lib.mjs +37 -62
- package/src/opencode.prompts.lib.mjs +7 -21
- package/src/protect-branch.mjs +14 -15
- package/src/review.mjs +28 -27
- package/src/reviewers-hive.mjs +64 -69
- package/src/sentry.lib.mjs +13 -10
- package/src/solve.auto-continue.lib.mjs +48 -38
- package/src/solve.auto-pr.lib.mjs +111 -69
- package/src/solve.branch-errors.lib.mjs +17 -46
- package/src/solve.branch.lib.mjs +16 -23
- package/src/solve.config.lib.mjs +263 -261
- package/src/solve.error-handlers.lib.mjs +21 -79
- package/src/solve.execution.lib.mjs +10 -18
- package/src/solve.feedback.lib.mjs +25 -46
- package/src/solve.mjs +59 -60
- package/src/solve.preparation.lib.mjs +10 -36
- package/src/solve.repo-setup.lib.mjs +4 -19
- package/src/solve.repository.lib.mjs +37 -37
- package/src/solve.results.lib.mjs +32 -46
- package/src/solve.session.lib.mjs +7 -22
- package/src/solve.validation.lib.mjs +19 -17
- package/src/solve.watch.lib.mjs +20 -33
- package/src/start-screen.mjs +24 -24
- package/src/task.mjs +38 -44
- package/src/telegram-bot.mjs +125 -121
- package/src/telegram-top-command.lib.mjs +32 -48
- package/src/usage-limit.lib.mjs +9 -13
- package/src/version-info.lib.mjs +1 -1
- package/src/version.lib.mjs +1 -1
- package/src/youtrack/solve.youtrack.lib.mjs +3 -8
- package/src/youtrack/youtrack-sync.mjs +8 -14
- 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
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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)}`, {
|
|
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)}`, {
|
|
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
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
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
|
+
};
|