@link-assistant/hive-mind 1.11.4 → 1.11.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 CHANGED
@@ -1,5 +1,13 @@
1
1
  # @link-assistant/hive-mind
2
2
 
3
+ ## 1.11.5
4
+
5
+ ### Patch Changes
6
+
7
+ - 7d3387c: Fix duplicate Solution Draft Log comments on GitHub PRs
8
+
9
+ When a Claude session ends with uncommitted changes and --attach-logs is enabled, the solution draft log was being uploaded twice - once by verifyResults() during normal completion, and again after temporary watch mode completes. This fix tracks whether logs were already uploaded and skips the duplicate upload.
10
+
3
11
  ## 1.11.4
4
12
 
5
13
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@link-assistant/hive-mind",
3
- "version": "1.11.4",
3
+ "version": "1.11.5",
4
4
  "description": "AI-powered issue solver and hive mind for collaborative problem solving",
5
5
  "main": "src/hive.mjs",
6
6
  "type": "module",
@@ -194,7 +194,7 @@ export const cacheTtl = {
194
194
  api: parseIntWithDefault('HIVE_MIND_API_CACHE_TTL_MS', 3 * 60 * 1000), // 3 minutes
195
195
  // Claude Usage API cache TTL - must be at least 20 minutes to avoid rate limiting
196
196
  // The API returns null values when called too frequently
197
- usageApi: parseIntWithDefault('HIVE_MIND_USAGE_API_CACHE_TTL_MS', 20 * 60 * 1000), // 20 minutes
197
+ usageApi: parseIntWithDefault('HIVE_MIND_USAGE_API_CACHE_TTL_MS', 10 * 60 * 1000), // 10 minutes
198
198
  // System metrics cache TTL (RAM, CPU, disk)
199
199
  system: parseIntWithDefault('HIVE_MIND_SYSTEM_CACHE_TTL_MS', 2 * 60 * 1000), // 2 minutes
200
200
  };
package/src/solve.mjs CHANGED
@@ -1159,7 +1159,9 @@ try {
1159
1159
  // Pass shouldRestart to prevent early exit when auto-restart is needed
1160
1160
  // Include agent tool pricing data when available (publicPricingEstimate, pricingInfo)
1161
1161
  // Issue #1088: Pass errorDuringExecution for "Finished with errors" state
1162
- await verifyResults(owner, repo, branchName, issueNumber, prNumber, prUrl, referenceTime, argv, shouldAttachLogs, shouldRestart, sessionId, tempDir, anthropicTotalCostUSD, publicPricingEstimate, pricingInfo, errorDuringExecution);
1162
+ // Issue #1154: Track if logs were already uploaded to prevent duplicates
1163
+ const verifyResult = await verifyResults(owner, repo, branchName, issueNumber, prNumber, prUrl, referenceTime, argv, shouldAttachLogs, shouldRestart, sessionId, tempDir, anthropicTotalCostUSD, publicPricingEstimate, pricingInfo, errorDuringExecution);
1164
+ const logsAlreadyUploaded = verifyResult?.logUploadSuccess || false;
1163
1165
 
1164
1166
  // Start watch mode if enabled OR if we need to handle uncommitted changes
1165
1167
  if (argv.verbose) {
@@ -1246,7 +1248,8 @@ try {
1246
1248
  }
1247
1249
 
1248
1250
  // Attach updated logs to PR after auto-restart completes
1249
- if (shouldAttachLogs && prNumber) {
1251
+ // Issue #1154: Skip if logs were already uploaded by verifyResults() to prevent duplicates
1252
+ if (shouldAttachLogs && prNumber && !logsAlreadyUploaded) {
1250
1253
  await log('📎 Uploading working session logs to Pull Request...');
1251
1254
  try {
1252
1255
  const logUploadSuccess = await attachLogToGitHub({
@@ -1273,6 +1276,9 @@ try {
1273
1276
  } catch (uploadError) {
1274
1277
  await log(`⚠️ Error uploading logs: ${uploadError.message}`, { level: 'warning' });
1275
1278
  }
1279
+ } else if (logsAlreadyUploaded) {
1280
+ await log('ℹ️ Logs already uploaded by verifyResults, skipping duplicate upload', { verbose: true });
1281
+ logsAttached = true;
1276
1282
  }
1277
1283
  }
1278
1284
 
@@ -564,7 +564,8 @@ export const verifyResults = async (owner, repo, branchName, issueNumber, prNumb
564
564
  if (!argv.watch && !shouldRestart) {
565
565
  await safeExit(0, 'Process completed successfully');
566
566
  }
567
- return; // Return normally for watch mode or auto-restart
567
+ // Issue #1154: Return logUploadSuccess to prevent duplicate log uploads
568
+ return { logUploadSuccess }; // Return for watch mode or auto-restart
568
569
  } else {
569
570
  await log(` ℹ️ Found pull request #${pr.number} but it appears to be from a different session`);
570
571
  }
@@ -627,7 +628,8 @@ export const verifyResults = async (owner, repo, branchName, issueNumber, prNumb
627
628
  if (!argv.watch && !shouldRestart) {
628
629
  await safeExit(0, 'Process completed successfully');
629
630
  }
630
- return; // Return normally for watch mode or auto-restart
631
+ // Issue #1154: Return logUploadSuccess to prevent duplicate log uploads
632
+ return { logUploadSuccess: true }; // Return for watch mode or auto-restart
631
633
  } else if (allComments.length > 0) {
632
634
  await log(` ℹ️ Issue has ${allComments.length} existing comment(s)`);
633
635
  } else {
@@ -645,7 +647,8 @@ export const verifyResults = async (owner, repo, branchName, issueNumber, prNumb
645
647
  if (!argv.watch) {
646
648
  await safeExit(0, 'Process completed successfully');
647
649
  }
648
- return; // Return normally for watch mode
650
+ // Issue #1154: Return logUploadSuccess to prevent duplicate log uploads
651
+ return { logUploadSuccess: false }; // Return for watch mode
649
652
  } catch (searchError) {
650
653
  reportError(searchError, {
651
654
  context: 'verify_pr_creation',
@@ -661,7 +664,8 @@ export const verifyResults = async (owner, repo, branchName, issueNumber, prNumb
661
664
  if (!argv.watch) {
662
665
  await safeExit(0, 'Process completed successfully');
663
666
  }
664
- return; // Return normally for watch mode
667
+ // Issue #1154: Return logUploadSuccess to prevent duplicate log uploads
668
+ return { logUploadSuccess: false }; // Return for watch mode
665
669
  }
666
670
  };
667
671
 
@@ -41,9 +41,9 @@ export const QUEUE_CONFIG = {
41
41
 
42
42
  // API limit thresholds (usage ratios: 0.0 - 1.0)
43
43
  // All thresholds use >= comparison (inclusive)
44
- CLAUDE_5_HOUR_SESSION_THRESHOLD: 0.85, // One-at-a-time if 5-hour limit >= 85%
45
- CLAUDE_WEEKLY_THRESHOLD: 0.98, // One-at-a-time if weekly limit >= 98%
46
- GITHUB_API_THRESHOLD: 0.8, // Enqueue if GitHub >= 80% with parallel claude
44
+ CLAUDE_5_HOUR_SESSION_THRESHOLD: 0.75, // One-at-a-time if 5-hour limit >= 75%
45
+ CLAUDE_WEEKLY_THRESHOLD: 0.97, // One-at-a-time if weekly limit >= 97%
46
+ GITHUB_API_THRESHOLD: 0.75, // Enqueue if GitHub >= 75% with parallel claude
47
47
 
48
48
  // Timing
49
49
  // MIN_START_INTERVAL_MS: Time to allow solve command to start actual claude process