@link-assistant/hive-mind 1.50.0 → 1.50.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 +10 -0
- package/package.json +1 -1
- package/src/agent.lib.mjs +2 -2
- package/src/claude.lib.mjs +2 -2
- package/src/codex.lib.mjs +2 -2
- package/src/lib.mjs +6 -1
- package/src/opencode.lib.mjs +2 -2
- package/src/solve.auto-ensure.lib.mjs +8 -0
- package/src/solve.auto-merge.lib.mjs +10 -0
- package/src/solve.mjs +4 -4
- package/src/solve.repository.lib.mjs +3 -3
- package/src/solve.results.lib.mjs +9 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# @link-assistant/hive-mind
|
|
2
2
|
|
|
3
|
+
## 1.50.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 494989e: Add paths filter to CI/CD workflow trigger to skip unnecessary runs for non-code file changes (#1582)
|
|
8
|
+
- c4fadea: fix: prevent push failures in auto-restart and cleanup by syncing with remote (#1572)
|
|
9
|
+
- Add `git pull` before restart sessions and cleanup push to prevent stale local state
|
|
10
|
+
- Add `2>&1` to all `git push` commands so stderr is captured for proper error handling
|
|
11
|
+
- Fix multi-line log message formatting to include timestamps on each line
|
|
12
|
+
|
|
3
13
|
## 1.50.0
|
|
4
14
|
|
|
5
15
|
### Minor Changes
|
package/package.json
CHANGED
package/src/agent.lib.mjs
CHANGED
|
@@ -1082,12 +1082,12 @@ export const checkForUncommittedChanges = async (tempDir, owner, repo, branchNam
|
|
|
1082
1082
|
if (commitResult.code === 0) {
|
|
1083
1083
|
await log('✅ Changes committed successfully');
|
|
1084
1084
|
|
|
1085
|
-
const pushResult = await $({ cwd: tempDir })`git push origin ${branchName}`;
|
|
1085
|
+
const pushResult = await $({ cwd: tempDir })`git push origin ${branchName} 2>&1`;
|
|
1086
1086
|
|
|
1087
1087
|
if (pushResult.code === 0) {
|
|
1088
1088
|
await log('✅ Changes pushed successfully');
|
|
1089
1089
|
} else {
|
|
1090
|
-
await log(`⚠️ Warning: Could not push changes: ${pushResult.stderr?.toString().trim()}`, {
|
|
1090
|
+
await log(`⚠️ Warning: Could not push changes: ${pushResult.stderr?.toString().trim() || pushResult.stdout?.toString().trim()}`, {
|
|
1091
1091
|
level: 'warning',
|
|
1092
1092
|
});
|
|
1093
1093
|
}
|
package/src/claude.lib.mjs
CHANGED
|
@@ -1449,11 +1449,11 @@ export const checkForUncommittedChanges = async (tempDir, owner, repo, branchNam
|
|
|
1449
1449
|
if (commitResult.code === 0) {
|
|
1450
1450
|
await log('✅ Changes committed successfully');
|
|
1451
1451
|
await log('📤 Pushing changes to remote...');
|
|
1452
|
-
const pushResult = await $({ cwd: tempDir })`git push origin ${branchName}`;
|
|
1452
|
+
const pushResult = await $({ cwd: tempDir })`git push origin ${branchName} 2>&1`;
|
|
1453
1453
|
if (pushResult.code === 0) {
|
|
1454
1454
|
await log('✅ Changes pushed successfully');
|
|
1455
1455
|
} else {
|
|
1456
|
-
await log(`⚠️ Warning: Could not push changes: ${pushResult.stderr?.toString().trim()}`, {
|
|
1456
|
+
await log(`⚠️ Warning: Could not push changes: ${pushResult.stderr?.toString().trim() || pushResult.stdout?.toString().trim()}`, {
|
|
1457
1457
|
level: 'warning',
|
|
1458
1458
|
});
|
|
1459
1459
|
}
|
package/src/codex.lib.mjs
CHANGED
|
@@ -492,12 +492,12 @@ export const checkForUncommittedChanges = async (tempDir, owner, repo, branchNam
|
|
|
492
492
|
if (commitResult.code === 0) {
|
|
493
493
|
await log('✅ Changes committed successfully');
|
|
494
494
|
|
|
495
|
-
const pushResult = await $({ cwd: tempDir })`git push origin ${branchName}`;
|
|
495
|
+
const pushResult = await $({ cwd: tempDir })`git push origin ${branchName} 2>&1`;
|
|
496
496
|
|
|
497
497
|
if (pushResult.code === 0) {
|
|
498
498
|
await log('✅ Changes pushed successfully');
|
|
499
499
|
} else {
|
|
500
|
-
await log(`⚠️ Warning: Could not push changes: ${pushResult.stderr?.toString().trim()}`, {
|
|
500
|
+
await log(`⚠️ Warning: Could not push changes: ${pushResult.stderr?.toString().trim() || pushResult.stdout?.toString().trim()}`, {
|
|
501
501
|
level: 'warning',
|
|
502
502
|
});
|
|
503
503
|
}
|
package/src/lib.mjs
CHANGED
|
@@ -83,8 +83,13 @@ export const log = async (message, options = {}) => {
|
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
// Write to file if log file is set
|
|
86
|
+
// Issue #1572: Handle multi-line messages by timestamping each line,
|
|
87
|
+
// so continuation lines don't appear without timestamps in the log file
|
|
86
88
|
if (logFile) {
|
|
87
|
-
const
|
|
89
|
+
const timestamp = new Date().toISOString();
|
|
90
|
+
const prefix = `[${timestamp}] [${level.toUpperCase()}]`;
|
|
91
|
+
const lines = String(message).split('\n');
|
|
92
|
+
const logMessage = lines.map(line => `${prefix} ${line}`).join('\n');
|
|
88
93
|
await fs.appendFile(logFile, logMessage + '\n').catch(error => {
|
|
89
94
|
// Silent fail for file append errors to avoid infinite loop
|
|
90
95
|
// but report to Sentry in verbose mode
|
package/src/opencode.lib.mjs
CHANGED
|
@@ -546,12 +546,12 @@ export const checkForUncommittedChanges = async (tempDir, owner, repo, branchNam
|
|
|
546
546
|
if (commitResult.code === 0) {
|
|
547
547
|
await log('✅ Changes committed successfully');
|
|
548
548
|
|
|
549
|
-
const pushResult = await $({ cwd: tempDir })`git push origin ${branchName}`;
|
|
549
|
+
const pushResult = await $({ cwd: tempDir })`git push origin ${branchName} 2>&1`;
|
|
550
550
|
|
|
551
551
|
if (pushResult.code === 0) {
|
|
552
552
|
await log('✅ Changes pushed successfully');
|
|
553
553
|
} else {
|
|
554
|
-
await log(`⚠️ Warning: Could not push changes: ${pushResult.stderr?.toString().trim()}`, {
|
|
554
|
+
await log(`⚠️ Warning: Could not push changes: ${pushResult.stderr?.toString().trim() || pushResult.stdout?.toString().trim()}`, {
|
|
555
555
|
level: 'warning',
|
|
556
556
|
});
|
|
557
557
|
}
|
|
@@ -76,6 +76,14 @@ export const runAutoEnsureRequirements = async ({ issueUrl, owner, repo, issueNu
|
|
|
76
76
|
for (let ensureIteration = 1; ensureIteration <= finalizeCount; ensureIteration++) {
|
|
77
77
|
await log(`🔄 FINALIZE iteration ${ensureIteration}/${finalizeCount}: Restarting to verify requirements...`);
|
|
78
78
|
|
|
79
|
+
// Issue #1572: Sync local branch with remote before each finalize iteration
|
|
80
|
+
const pullResult = await $({ cwd: tempDir })`git pull origin ${branchName} 2>&1`;
|
|
81
|
+
if (pullResult.code === 0) {
|
|
82
|
+
await log(` Synced local branch ${branchName} from remote`, { verbose: true });
|
|
83
|
+
} else {
|
|
84
|
+
throw new Error(`git pull failed (code ${pullResult.code}): ${pullResult.stdout || pullResult.stderr || 'no output'}`);
|
|
85
|
+
}
|
|
86
|
+
|
|
79
87
|
const ensureFeedbackLines = ['', '='.repeat(60), '🔍 FINALIZE REQUIREMENTS CHECK:', '='.repeat(60), '', 'We need to ensure all changes are correct, consistent, validated, tested, logged and fully meet all discussed requirements (check issue description and all comments in issue and in pull request). Ensure all CI/CD checks pass.', ''];
|
|
80
88
|
|
|
81
89
|
const ensureResult = await executeToolIteration({
|
|
@@ -976,6 +976,16 @@ Once the billing issue is resolved, you can re-run the CI checks or push a new c
|
|
|
976
976
|
const prStateResult = await $`gh api repos/${owner}/${repo}/pulls/${prNumber} --jq '.mergeStateStatus'`;
|
|
977
977
|
const mergeStateStatus = prStateResult.code === 0 ? prStateResult.stdout.toString().trim() : null;
|
|
978
978
|
|
|
979
|
+
// Issue #1572: Sync local branch with remote before restarting to avoid push failures.
|
|
980
|
+
// Without this, the restarted session works on stale local state and can't push.
|
|
981
|
+
const effectiveBranch = prBranch || branchName;
|
|
982
|
+
const pullResult = await $({ cwd: tempDir })`git pull origin ${effectiveBranch} 2>&1`;
|
|
983
|
+
if (pullResult.code === 0) {
|
|
984
|
+
await log(formatAligned('🔄', 'Synced:', `Local branch ${effectiveBranch} updated from remote`));
|
|
985
|
+
} else {
|
|
986
|
+
throw new Error(`git pull failed (code ${pullResult.code}): ${pullResult.stdout || pullResult.stderr || 'no output'}`);
|
|
987
|
+
}
|
|
988
|
+
|
|
979
989
|
// Execute the AI tool using shared utility
|
|
980
990
|
await log(formatAligned('🔄', 'Restarting:', `Running ${argv.tool.toUpperCase()} to address issues...`));
|
|
981
991
|
|
package/src/solve.mjs
CHANGED
|
@@ -573,12 +573,12 @@ try {
|
|
|
573
573
|
const mergeResult = await $({ cwd: tempDir })`git merge ${defaultBranch} --no-edit`;
|
|
574
574
|
if (mergeResult.code === 0) {
|
|
575
575
|
await log(`${formatAligned('✅', 'Merge successful:', 'Pushing merged branch...')}`);
|
|
576
|
-
const pushResult = await $({ cwd: tempDir })`git push origin ${branchName}`;
|
|
576
|
+
const pushResult = await $({ cwd: tempDir })`git push origin ${branchName} 2>&1`;
|
|
577
577
|
if (pushResult.code === 0) {
|
|
578
578
|
await log(`${formatAligned('✅', 'Push successful:', 'Branch updated with latest changes')}`);
|
|
579
579
|
} else {
|
|
580
580
|
await log(`${formatAligned('⚠️', 'Push failed:', 'Merge completed but push failed')}`, { level: 'warning' });
|
|
581
|
-
await log(` Error: ${pushResult.stderr?.toString() || 'Unknown error'}`, { level: 'warning' });
|
|
581
|
+
await log(` Error: ${pushResult.stderr?.toString() || pushResult.stdout?.toString() || 'Unknown error'}`, { level: 'warning' });
|
|
582
582
|
}
|
|
583
583
|
} else {
|
|
584
584
|
// Merge failed - likely due to conflicts
|
|
@@ -1343,13 +1343,13 @@ try {
|
|
|
1343
1343
|
await log('');
|
|
1344
1344
|
|
|
1345
1345
|
try {
|
|
1346
|
-
const pushResult = await $({ cwd: tempDir })`git push origin ${branchName}`;
|
|
1346
|
+
const pushResult = await $({ cwd: tempDir })`git push origin ${branchName} 2>&1`;
|
|
1347
1347
|
if (pushResult.code === 0) {
|
|
1348
1348
|
await log('✅ Changes pushed successfully to remote branch');
|
|
1349
1349
|
await log(` Branch: ${branchName}`);
|
|
1350
1350
|
await log('');
|
|
1351
1351
|
} else {
|
|
1352
|
-
const errorMsg = pushResult.stderr?.toString() || 'Unknown error';
|
|
1352
|
+
const errorMsg = pushResult.stderr?.toString() || pushResult.stdout?.toString() || 'Unknown error';
|
|
1353
1353
|
await log('⚠️ Push failed:', { level: 'error' });
|
|
1354
1354
|
await log(` ${errorMsg.trim()}`, { level: 'error' });
|
|
1355
1355
|
await log(' Please push manually:', { level: 'error' });
|
|
@@ -1113,12 +1113,12 @@ export const setupUpstreamAndSync = async (tempDir, forkedRepo, upstreamRemote,
|
|
|
1113
1113
|
|
|
1114
1114
|
// Step 3: Push the updated default branch to fork to keep it in sync
|
|
1115
1115
|
await log(`${formatAligned('🔄', 'Pushing to fork:', `${upstreamDefaultBranch} branch`)}`);
|
|
1116
|
-
const pushResult = await $({ cwd: tempDir })`git push origin ${upstreamDefaultBranch}`;
|
|
1116
|
+
const pushResult = await $({ cwd: tempDir })`git push origin ${upstreamDefaultBranch} 2>&1`;
|
|
1117
1117
|
if (pushResult.code === 0) {
|
|
1118
1118
|
await log(`${formatAligned('✅', 'Fork updated:', 'Default branch pushed to fork')}`);
|
|
1119
1119
|
} else {
|
|
1120
1120
|
// Check if it's a non-fast-forward error (fork has diverged from upstream)
|
|
1121
|
-
const errorMsg = pushResult.stderr ? pushResult.stderr.toString().trim() : '';
|
|
1121
|
+
const errorMsg = (pushResult.stderr ? pushResult.stderr.toString().trim() : '') || (pushResult.stdout ? pushResult.stdout.toString().trim() : '');
|
|
1122
1122
|
const isNonFastForward = errorMsg.includes('non-fast-forward') || errorMsg.includes('rejected') || errorMsg.includes('tip of your current branch is behind');
|
|
1123
1123
|
|
|
1124
1124
|
if (isNonFastForward) {
|
|
@@ -1147,7 +1147,7 @@ export const setupUpstreamAndSync = async (tempDir, forkedRepo, upstreamRemote,
|
|
|
1147
1147
|
await log(`${formatAligned('🔄', 'Force pushing:', 'Syncing fork with upstream (--force-with-lease)')}`);
|
|
1148
1148
|
const forcePushResult = await $({
|
|
1149
1149
|
cwd: tempDir,
|
|
1150
|
-
})`git push --force-with-lease origin ${upstreamDefaultBranch}`;
|
|
1150
|
+
})`git push --force-with-lease origin ${upstreamDefaultBranch} 2>&1`;
|
|
1151
1151
|
|
|
1152
1152
|
if (forcePushResult.code === 0) {
|
|
1153
1153
|
await log(`${formatAligned('✅', 'Fork synced:', 'Successfully force-pushed to align with upstream')}`);
|
|
@@ -269,6 +269,15 @@ export const cleanupClaudeFile = async (tempDir, branchName, claudeCommitHash =
|
|
|
269
269
|
await log(formatAligned('🔄', 'Cleanup:', `Reverting ${fileName} commit`));
|
|
270
270
|
await log(` Using saved commit hash: ${claudeCommitHash.substring(0, 7)}...`, { verbose: true });
|
|
271
271
|
|
|
272
|
+
// Issue #1572: Sync local branch with remote before cleanup to prevent push failures.
|
|
273
|
+
// After auto-restart sessions, the local branch may be behind the remote.
|
|
274
|
+
const pullResult = await $({ cwd: tempDir })`git pull origin ${branchName} 2>&1`;
|
|
275
|
+
if (pullResult.code === 0) {
|
|
276
|
+
await log(` Synced local branch before cleanup`, { verbose: true });
|
|
277
|
+
} else {
|
|
278
|
+
throw new Error(`git pull failed (code ${pullResult.code}): ${pullResult.stdout || pullResult.stderr || 'no output'}`);
|
|
279
|
+
}
|
|
280
|
+
|
|
272
281
|
const commitToRevert = claudeCommitHash;
|
|
273
282
|
|
|
274
283
|
// APPROACH 3: Check for modifications before reverting (proactive detection)
|