@link-assistant/hive-mind 2.11.7 → 2.11.9
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 +36 -0
- package/package.json +1 -1
- package/src/bidirectional-interactive.lib.mjs +6 -2
- package/src/child-exit.lib.mjs +107 -0
- package/src/contributing-guidelines.lib.mjs +19 -6
- package/src/development-log.lib.mjs +82 -5
- package/src/fix.ci-cd-issue.lib.mjs +5 -3
- package/src/fix.mjs +5 -2
- package/src/github-entity-validation.lib.mjs +4 -1
- package/src/github.lib.mjs +3 -3
- package/src/hive.mjs +15 -21
- package/src/isolation-runner.lib.mjs +5 -2
- package/src/lib.mjs +21 -0
- package/src/locales/en.lino +10 -0
- package/src/locales/hi.lino +10 -0
- package/src/locales/ru.lino +10 -0
- package/src/locales/zh.lino +10 -0
- package/src/log-growth.lib.mjs +94 -0
- package/src/option-suggestions.lib.mjs +2 -0
- package/src/pull-request-changes.lib.mjs +94 -24
- package/src/review.mjs +12 -3
- package/src/session-kill-diagnostics.lib.mjs +388 -0
- package/src/session-kill-policy.lib.mjs +96 -0
- package/src/session-kill-recovery.lib.mjs +256 -0
- package/src/session-kill-resume.lib.mjs +175 -0
- package/src/session-monitor.kill-sections.lib.mjs +198 -0
- package/src/session-monitor.lib.mjs +97 -2
- package/src/session-monitor.oom.lib.mjs +148 -0
- package/src/session-monitor.stale-executing.lib.mjs +6 -27
- package/src/session-resume.lib.mjs +28 -2
- package/src/solve.auto-continue.lib.mjs +6 -2
- package/src/solve.auto-merge.lib.mjs +1 -1
- package/src/solve.config.lib.mjs +14 -0
- package/src/solve.keep-working.lib.mjs +7 -2
- package/src/solve.minimal-restart-prompt.lib.mjs +11 -3
- package/src/solve.preparation.lib.mjs +5 -1
- package/src/solve.progress-monitoring.lib.mjs +5 -1
- package/src/solve.repository.lib.mjs +5 -2
- package/src/solve.results.lib.mjs +13 -8
- package/src/task.mjs +5 -3
- package/src/telegram-bot.mjs +3 -1
- package/src/telegram-command-execution.lib.mjs +5 -2
|
@@ -407,7 +407,9 @@ export const cleanupClaudeFile = async (tempDir, branchName, claudeCommitHash =
|
|
|
407
407
|
// APPROACH 3: Check for modifications before reverting (proactive detection)
|
|
408
408
|
// This is the main strategy - detect if the file was modified after initial commit
|
|
409
409
|
await log(` Checking if ${fileName} was modified since initial commit...`, { verbose: true });
|
|
410
|
-
|
|
410
|
+
// Issue #2135: `mirror: false`. Only "is it non-empty" is asked here, and
|
|
411
|
+
// the answer is a file's whole diff.
|
|
412
|
+
const diffResult = await $({ cwd: tempDir, ...QUIET_PROBE })`git diff ${commitToRevert} HEAD -- ${fileName} 2>&1`;
|
|
411
413
|
|
|
412
414
|
if (diffResult.stdout && diffResult.stdout.trim()) {
|
|
413
415
|
// File was modified after initial commit - use manual approach to avoid conflicts
|
|
@@ -746,7 +748,8 @@ export const verifyResults = async (owner, repo, branchName, issueNumber, prNumb
|
|
|
746
748
|
// First, get all PRs from our branch
|
|
747
749
|
// IMPORTANT: Use --state all to find PRs that may have been merged during the session (Issue #1008)
|
|
748
750
|
// Without --state all, gh pr list only returns OPEN PRs, missing merged ones
|
|
749
|
-
|
|
751
|
+
// Issue #2135: `mirror: false` - the pull requests found are named below.
|
|
752
|
+
const allBranchPrsResult = await $(QUIET_PROBE)`gh pr list --repo ${owner}/${repo} --head ${branchName} --state all --json number,url,createdAt,headRefName,title,state,updatedAt,isDraft`;
|
|
750
753
|
|
|
751
754
|
if (allBranchPrsResult.code !== 0) {
|
|
752
755
|
await log(' ⚠️ Failed to check pull requests');
|
|
@@ -819,7 +822,7 @@ export const verifyResults = async (owner, repo, branchName, issueNumber, prNumb
|
|
|
819
822
|
// "1 file(s) modified, 1 line(s) added" for a pull request that
|
|
820
823
|
// changed nothing, because the stats were never checked for being
|
|
821
824
|
// empty.
|
|
822
|
-
const changeStats = await getPullRequestChangeStats({ owner, repo, prNumber: pr.number,
|
|
825
|
+
const changeStats = await getPullRequestChangeStats({ owner, repo, prNumber: pr.number, $, log });
|
|
823
826
|
if (!changeStats.hasChanges) {
|
|
824
827
|
await log(` ⚠️ PR #${pr.number} has an empty diff - the description will say so instead of claiming changes`, { level: 'warning' });
|
|
825
828
|
}
|
|
@@ -948,7 +951,9 @@ Fixes ${issueRef}
|
|
|
948
951
|
|
|
949
952
|
// Get all comments and filter them
|
|
950
953
|
// Use --paginate to get all comments - GitHub API returns max 30 per page by default
|
|
951
|
-
|
|
954
|
+
// Issue #2135: `mirror: false` - the counts below are the report; the raw
|
|
955
|
+
// answer is every comment body on the issue.
|
|
956
|
+
const allCommentsResult = await $(QUIET_PROBE)`gh api repos/${owner}/${repo}/issues/${issueNumber}/comments --paginate`;
|
|
952
957
|
|
|
953
958
|
if (allCommentsResult.code !== 0) {
|
|
954
959
|
await log(' ⚠️ Failed to check comments');
|
|
@@ -1209,7 +1214,7 @@ export const checkForAiCreatedComments = async (sessionStartTime, owner, repo, p
|
|
|
1209
1214
|
// Check comments on the PR first (if we have a PR)
|
|
1210
1215
|
if (prNumber) {
|
|
1211
1216
|
// Check PR conversation comments
|
|
1212
|
-
const prCommentsResult = await
|
|
1217
|
+
const prCommentsResult = await $(QUIET_PROBE)`gh api repos/${owner}/${repo}/issues/${prNumber}/comments --paginate`;
|
|
1213
1218
|
if (prCommentsResult.code === 0) {
|
|
1214
1219
|
const prComments = JSON.parse(prCommentsResult.stdout.toString().trim() || '[]');
|
|
1215
1220
|
const newPrComments = filterNewAiComments(prComments, 'pr');
|
|
@@ -1220,7 +1225,7 @@ export const checkForAiCreatedComments = async (sessionStartTime, owner, repo, p
|
|
|
1220
1225
|
}
|
|
1221
1226
|
|
|
1222
1227
|
// Check PR review comments (inline code comments)
|
|
1223
|
-
const reviewCommentsResult = await
|
|
1228
|
+
const reviewCommentsResult = await $(QUIET_PROBE)`gh api repos/${owner}/${repo}/pulls/${prNumber}/comments --paginate`;
|
|
1224
1229
|
if (reviewCommentsResult.code === 0) {
|
|
1225
1230
|
const reviewComments = JSON.parse(reviewCommentsResult.stdout.toString().trim() || '[]');
|
|
1226
1231
|
const newReviewComments = filterNewAiComments(reviewComments, 'review');
|
|
@@ -1233,7 +1238,7 @@ export const checkForAiCreatedComments = async (sessionStartTime, owner, repo, p
|
|
|
1233
1238
|
|
|
1234
1239
|
// Check issue comments (if different from PR number or no PR)
|
|
1235
1240
|
if (issueNumber && issueNumber !== prNumber) {
|
|
1236
|
-
const issueCommentsResult = await
|
|
1241
|
+
const issueCommentsResult = await $(QUIET_PROBE)`gh api repos/${owner}/${repo}/issues/${issueNumber}/comments --paginate`;
|
|
1237
1242
|
if (issueCommentsResult.code === 0) {
|
|
1238
1243
|
const issueComments = JSON.parse(issueCommentsResult.stdout.toString().trim() || '[]');
|
|
1239
1244
|
const newIssueComments = filterNewAiComments(issueComments, 'issue');
|
|
@@ -1413,7 +1418,7 @@ export const maybeAttachWorkingSessionSummary = async ({ argv, resultSummary, wo
|
|
|
1413
1418
|
: null);
|
|
1414
1419
|
// Issue #2119: a summary posted on a pull request that changed nothing must
|
|
1415
1420
|
// say so, instead of reading as a report of completed work.
|
|
1416
|
-
const changeStats = prNumber ? await getPullRequestChangeStats({ owner, repo, prNumber,
|
|
1421
|
+
const changeStats = prNumber ? await getPullRequestChangeStats({ owner, repo, prNumber, $, log }) : null;
|
|
1417
1422
|
|
|
1418
1423
|
// Issue #2132: the summary carries no cost/budget block. `resolvedBudgetStatsData`
|
|
1419
1424
|
// is computed only so the caller can reuse it for this session's log comment.
|
package/src/task.mjs
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import crypto from 'crypto';
|
|
4
4
|
import path from 'path';
|
|
5
5
|
import { spawn } from 'child_process';
|
|
6
|
+
import { describeChildExit } from './child-exit.lib.mjs';
|
|
6
7
|
import { promises as fs } from 'fs';
|
|
7
8
|
import { buildStartAgentArgs, resolveStartAgentCommand } from './task.agent-command.lib.mjs';
|
|
8
9
|
import { getDefaultTaskModel, parseTaskArguments } from './task.config.lib.mjs';
|
|
@@ -112,8 +113,8 @@ function runCommand(command, args, options = {}) {
|
|
|
112
113
|
child.on('error', error => {
|
|
113
114
|
resolve({ code: 1, stdout, stderr: stderr || error.message });
|
|
114
115
|
});
|
|
115
|
-
child.on('close', code => {
|
|
116
|
-
resolve({ code, stdout, stderr });
|
|
116
|
+
child.on('close', (code, signal) => {
|
|
117
|
+
resolve({ code, stdout, stderr, signal });
|
|
117
118
|
});
|
|
118
119
|
});
|
|
119
120
|
}
|
|
@@ -122,7 +123,8 @@ async function commandOutput(command, args, options = {}) {
|
|
|
122
123
|
const result = await runCommand(command, args, options);
|
|
123
124
|
if (result.code !== 0) {
|
|
124
125
|
const output = `${result.stderr || ''}${result.stdout || ''}`.trim();
|
|
125
|
-
|
|
126
|
+
// Issue #2135: `describeChildExit` names a signal instead of "code null".
|
|
127
|
+
throw new Error(output || describeChildExit({ command, code: result.code, signal: result.signal }));
|
|
126
128
|
}
|
|
127
129
|
return result.stdout.trim();
|
|
128
130
|
}
|
package/src/telegram-bot.mjs
CHANGED
|
@@ -1248,7 +1248,9 @@ let launchAnnouncementShown = false;
|
|
|
1248
1248
|
|
|
1249
1249
|
function startSessionMonitoringOnce() {
|
|
1250
1250
|
if (sessionMonitoringTimer) return;
|
|
1251
|
-
|
|
1251
|
+
// Issue #2134: the monitor needs the isolation runner to start a recovery
|
|
1252
|
+
// working session when `--on-session-kill=resume` is in effect.
|
|
1253
|
+
sessionMonitoringTimer = startSessionMonitoring(bot, VERBOSE, 30000, { isolationRunner });
|
|
1252
1254
|
}
|
|
1253
1255
|
|
|
1254
1256
|
// Issue #1927 (requirements #3/#4): a periodic timestamped heartbeat so the "last
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { spawn } from 'child_process';
|
|
2
|
+
import { describeChildExit } from './child-exit.lib.mjs';
|
|
2
3
|
import { promisify } from 'util';
|
|
3
4
|
import { exec as execCallback } from 'child_process';
|
|
4
5
|
import { t } from './i18n.lib.mjs';
|
|
@@ -57,7 +58,7 @@ function executeWithCommand(startScreenCmd, command, args, verbose = false) {
|
|
|
57
58
|
});
|
|
58
59
|
});
|
|
59
60
|
|
|
60
|
-
child.on('close', code => {
|
|
61
|
+
child.on('close', (code, signal) => {
|
|
61
62
|
if (code === 0) {
|
|
62
63
|
resolve({
|
|
63
64
|
success: true,
|
|
@@ -67,7 +68,9 @@ function executeWithCommand(startScreenCmd, command, args, verbose = false) {
|
|
|
67
68
|
resolve({
|
|
68
69
|
success: false,
|
|
69
70
|
output: stdout,
|
|
70
|
-
|
|
71
|
+
// Issue #2135: name the signal, so an out-of-memory abort is not
|
|
72
|
+
// reported as "code null".
|
|
73
|
+
error: stderr || describeChildExit({ command: 'Command', code, signal }),
|
|
71
74
|
});
|
|
72
75
|
}
|
|
73
76
|
});
|