@link-assistant/hive-mind 1.50.4 → 1.50.5
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 +9 -0
- package/package.json +1 -1
- package/src/solve.auto-continue.lib.mjs +10 -2
- package/src/solve.auto-merge.lib.mjs +8 -37
- package/src/solve.mjs +10 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# @link-assistant/hive-mind
|
|
2
2
|
|
|
3
|
+
## 1.50.5
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 61b2a32: fix: prevent solution draft log and ready to merge comments from appearing between limit reached and auto resume (#1571)
|
|
8
|
+
- `autoContinueWhenLimitResets()` now awaits child process exit instead of returning immediately after spawn
|
|
9
|
+
- Added defense-in-depth guard in solve.mjs to skip post-processing when limit was reached with auto-continue enabled
|
|
10
|
+
- This ensures the correct comment ordering: Limit Reached → Auto Resume → Solution Draft Log → Ready to merge
|
|
11
|
+
|
|
3
12
|
## 1.50.4
|
|
4
13
|
|
|
5
14
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -182,8 +182,16 @@ export const autoContinueWhenLimitResets = async (issueUrl, sessionId, argv, sho
|
|
|
182
182
|
env: process.env,
|
|
183
183
|
});
|
|
184
184
|
|
|
185
|
-
child
|
|
186
|
-
|
|
185
|
+
// Issue #1571: Await child process exit to prevent parent from continuing
|
|
186
|
+
// to post "Solution Draft Log" and "Ready to merge" comments before the
|
|
187
|
+
// resumed session starts. Without this await, the parent process would
|
|
188
|
+
// return from this function and continue executing verifyResults() and
|
|
189
|
+
// startAutoRestartUntilMergeable(), causing confusing comment ordering.
|
|
190
|
+
await new Promise(resolve => {
|
|
191
|
+
child.on('close', code => {
|
|
192
|
+
process.exit(code);
|
|
193
|
+
resolve(); // Won't be reached due to process.exit, but included for completeness
|
|
194
|
+
});
|
|
187
195
|
});
|
|
188
196
|
} catch (error) {
|
|
189
197
|
reportError(error, {
|
|
@@ -62,10 +62,7 @@ export const watchUntilMergeable = async params => {
|
|
|
62
62
|
const { issueUrl, owner, repo, issueNumber, prNumber, prBranch, branchName, tempDir, argv } = params;
|
|
63
63
|
|
|
64
64
|
const rawWatchInterval = argv.watchInterval || 60; // seconds
|
|
65
|
-
// Issue #
|
|
66
|
-
// Issue #1567: Reduced from 5 minutes (300s) to 2 minutes (120s) to decrease wait times
|
|
67
|
-
// between working session finish and "Ready to merge" / next action detection.
|
|
68
|
-
// This also applies uniformly whether CI/CD is configured or not.
|
|
65
|
+
// Issue #1567: Minimum 120s interval to conserve API rate limits while keeping responsiveness
|
|
69
66
|
const MIN_CI_CHECK_INTERVAL_SECONDS = 120;
|
|
70
67
|
const watchInterval = Math.max(rawWatchInterval, MIN_CI_CHECK_INTERVAL_SECONDS);
|
|
71
68
|
const isAutoMerge = argv.autoMerge || false;
|
|
@@ -76,39 +73,19 @@ export const watchUntilMergeable = async params => {
|
|
|
76
73
|
let latestSessionId = null;
|
|
77
74
|
let latestAnthropicCost = null;
|
|
78
75
|
|
|
79
|
-
// Issue #1323: Track actual
|
|
80
|
-
// `iteration` counts check cycles (how many times we check for blockers)
|
|
81
|
-
// `restartCount` counts actual AI tool executions (when we actually restart the AI)
|
|
76
|
+
// Issue #1323: Track actual AI restarts separately from check cycle iterations
|
|
82
77
|
let restartCount = 0;
|
|
83
78
|
|
|
84
|
-
// Issue #1371:
|
|
85
|
-
// This replaces the all-time history check (checkForExistingComment) which incorrectly
|
|
86
|
-
// suppressed new notifications when a previous solve run had already posted one.
|
|
87
|
-
// In-memory deduplication correctly handles the case where multiple check cycles in
|
|
88
|
-
// the same run detect mergeability simultaneously, without blocking fresh runs.
|
|
79
|
+
// Issue #1371: In-memory dedup for "Ready to merge" comment (per-session, not all-time)
|
|
89
80
|
let readyToMergeCommentPosted = false;
|
|
90
81
|
|
|
91
82
|
let currentBackoffSeconds = watchInterval;
|
|
92
83
|
|
|
93
|
-
// Issue #1503: Track consecutive "no workflow runs" checks per-SHA
|
|
94
|
-
// The `checkCount` parameter in getMergeBlockers is a safety valve that triggers after
|
|
95
|
-
// MAX_NO_RUNS_CHECKS (5) consecutive checks with zero workflow runs, concluding CI was
|
|
96
|
-
// genuinely not triggered (paths-ignore, fork PRs, etc.). Previously, `iteration` (total
|
|
97
|
-
// loop count) was passed as `checkCount`, which meant after 5 iterations (regardless of
|
|
98
|
-
// CI state), any new push would immediately trigger the safety valve because checkCount
|
|
99
|
-
// was already >= 5. This caused false positive "Ready to merge" when a new commit was
|
|
100
|
-
// pushed and CI hadn't registered yet.
|
|
101
|
-
//
|
|
102
|
-
// Fix: Track the HEAD SHA and reset the counter when it changes (new push detected).
|
|
84
|
+
// Issue #1503: Track consecutive "no workflow runs" checks per-SHA (reset on new push)
|
|
103
85
|
let consecutiveNoRunsChecks = 0;
|
|
104
86
|
let lastKnownHeadSha = null;
|
|
105
87
|
|
|
106
|
-
// Issue #1567: Initial cooldown
|
|
107
|
-
// Wait at least MIN_CI_CHECK_INTERVAL_SECONDS after working session finishes before
|
|
108
|
-
// starting to check. This ensures:
|
|
109
|
-
// 1. Solution Draft Log is fully posted before any "Ready to merge" can appear
|
|
110
|
-
// 2. CI/CD checks have time to register with GitHub (avoids false "no CI" detection)
|
|
111
|
-
// 3. Consistent behavior whether CI/CD is configured or not
|
|
88
|
+
// Issue #1567: Initial cooldown to let CI register and solution logs post
|
|
112
89
|
const INITIAL_COOLDOWN_SECONDS = MIN_CI_CHECK_INTERVAL_SECONDS;
|
|
113
90
|
|
|
114
91
|
await log('');
|
|
@@ -161,9 +138,7 @@ export const watchUntilMergeable = async params => {
|
|
|
161
138
|
await log(formatAligned('🔍', `Check #${iteration}:`, currentTime.toLocaleTimeString()));
|
|
162
139
|
|
|
163
140
|
try {
|
|
164
|
-
// Issue #1503: Get
|
|
165
|
-
// consecutive no-runs counter. This prevents false positives where the counter
|
|
166
|
-
// from a previous commit's checks carries over to a new commit.
|
|
141
|
+
// Issue #1503: Get current HEAD SHA to detect new pushes and reset no-runs counter
|
|
167
142
|
let currentHeadSha = null;
|
|
168
143
|
try {
|
|
169
144
|
const shaResult = await $`gh pr view ${prNumber} --repo ${owner}/${repo} --json headRefOid --jq .headRefOid`;
|
|
@@ -184,17 +159,13 @@ export const watchUntilMergeable = async params => {
|
|
|
184
159
|
readyToMergeCommentPosted = false;
|
|
185
160
|
}
|
|
186
161
|
|
|
187
|
-
// Issue #1503: Increment counter; getMergeBlockers
|
|
188
|
-
// If getMergeBlockers sees no workflow runs on this check, the counter stays incremented.
|
|
189
|
-
// If it sees workflow runs or checks, the counter is irrelevant (different code paths).
|
|
162
|
+
// Issue #1503: Increment counter; getMergeBlockers uses it as a safety valve
|
|
190
163
|
consecutiveNoRunsChecks++;
|
|
191
164
|
|
|
192
165
|
// Get merge blockers
|
|
193
166
|
const { blockers, noCiConfigured, noCiTriggered, workflowRunConclusions, ciStatus } = await getMergeBlockers(owner, repo, prNumber, argv.verbose, consecutiveNoRunsChecks, prBranch);
|
|
194
167
|
|
|
195
|
-
// Issue #1503: Reset
|
|
196
|
-
// This ensures the safety valve only fires after truly consecutive "no runs" checks,
|
|
197
|
-
// not after interleaved pending/success/failure states that happened to reach the count.
|
|
168
|
+
// Issue #1503: Reset counter when CI checks exist (safety valve only for consecutive "no runs")
|
|
198
169
|
if (ciStatus && ciStatus.status !== 'no_checks') {
|
|
199
170
|
// CI checks exist (pending, success, failure, etc.) — the "no runs" counter is irrelevant
|
|
200
171
|
consecutiveNoRunsChecks = 0;
|
package/src/solve.mjs
CHANGED
|
@@ -1077,13 +1077,10 @@ try {
|
|
|
1077
1077
|
}
|
|
1078
1078
|
}
|
|
1079
1079
|
|
|
1080
|
-
//
|
|
1081
|
-
// This allows the code to continue to showSessionSummary() where autoContinueWhenLimitResets() is called
|
|
1080
|
+
// Skip failure exit if limit reached with auto-resume (continues to showSessionSummary/autoContinueWhenLimitResets)
|
|
1082
1081
|
const shouldSkipFailureExitForAutoLimitContinue = limitReached && argv.autoResumeOnLimitReset;
|
|
1083
|
-
|
|
1084
1082
|
if (!success && !shouldSkipFailureExitForAutoLimitContinue) {
|
|
1085
1083
|
// Show claude resume command only for --tool claude (or default) on failure
|
|
1086
|
-
// Uses the (cd ... && claude --resume ...) pattern for a fully copyable, executable command
|
|
1087
1084
|
const toolForFailure = argv.tool || 'claude';
|
|
1088
1085
|
if (sessionId && toolForFailure === 'claude') {
|
|
1089
1086
|
const claudeResumeCmd = buildClaudeResumeCommand({ tempDir, sessionId, model: argv.model });
|
|
@@ -1094,9 +1091,7 @@ try {
|
|
|
1094
1091
|
await log('');
|
|
1095
1092
|
}
|
|
1096
1093
|
|
|
1097
|
-
//
|
|
1098
|
-
// Note: sessionId is not required - logs should be uploaded even if agent failed before establishing a session
|
|
1099
|
-
// Issues #1212, #1462: Fall back to uploading logs to the issue if PR is not available
|
|
1094
|
+
// Attach failure logs before exiting (Issues #1212, #1462: fall back to issue if no PR)
|
|
1100
1095
|
const hasPR = global.createdPR && global.createdPR.number;
|
|
1101
1096
|
const hasIssue = global.issueNumber;
|
|
1102
1097
|
const logTargetType = hasPR ? 'pr' : hasIssue ? 'issue' : null;
|
|
@@ -1148,8 +1143,7 @@ try {
|
|
|
1148
1143
|
await safeExit(1, `${argv.tool.toUpperCase()} execution failed`);
|
|
1149
1144
|
}
|
|
1150
1145
|
|
|
1151
|
-
// Clean up .playwright-mcp/
|
|
1152
|
-
// This prevents browser automation artifacts from triggering auto-restart (Issue #1124)
|
|
1146
|
+
// Clean up .playwright-mcp/ to prevent browser artifacts from triggering auto-restart (Issue #1124)
|
|
1153
1147
|
if (argv.playwrightMcpAutoCleanup !== false) {
|
|
1154
1148
|
const playwrightMcpDir = path.join(tempDir, '.playwright-mcp');
|
|
1155
1149
|
try {
|
|
@@ -1179,6 +1173,13 @@ try {
|
|
|
1179
1173
|
// Show summary of session and log file
|
|
1180
1174
|
await showSessionSummary(sessionId, limitReached, argv, issueUrl, tempDir, shouldAttachLogs);
|
|
1181
1175
|
|
|
1176
|
+
// Issue #1571: Defense-in-depth guard. autoContinueWhenLimitResets() awaits child exit
|
|
1177
|
+
// and calls process.exit(), so this should not be reached. Skip post-processing to
|
|
1178
|
+
// prevent "Solution Draft Log" / "Ready to merge" comments before "Auto Resume".
|
|
1179
|
+
if (limitReached && (argv.autoResumeOnLimitReset || argv.autoRestartOnLimitReset) && global.limitResetTime) {
|
|
1180
|
+
await safeExit(0, 'Auto-continue child process will handle post-processing');
|
|
1181
|
+
}
|
|
1182
|
+
|
|
1182
1183
|
// Issue #1263: Handle solution summary attachment
|
|
1183
1184
|
// --attach-solution-summary: Always attach if result summary is available
|
|
1184
1185
|
// --auto-attach-solution-summary: Only attach if AI didn't create any comments during session
|