@link-assistant/hive-mind 1.67.1 → 1.67.2

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,11 @@
1
1
  # @link-assistant/hive-mind
2
2
 
3
+ ## 1.67.2
4
+
5
+ ### Patch Changes
6
+
7
+ - 240231e: Verify the pull request still links to the issue after every work session inside `--watch`, `--auto-restart-until-mergeable`, and `--finalize`, so that an iteration that turns out to be the last one cannot leave the PR un-linked when the AI rewrote the description without a closing keyword.
8
+
3
9
  ## 1.67.1
4
10
 
5
11
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@link-assistant/hive-mind",
3
- "version": "1.67.1",
3
+ "version": "1.67.2",
4
4
  "description": "AI-powered issue solver and hive mind for collaborative problem solving",
5
5
  "main": "src/hive.mjs",
6
6
  "type": "module",
@@ -23,12 +23,21 @@ const { wrapDollarWithGhRetry } = await import('./github-rate-limit.lib.mjs');
23
23
  const $ = wrapDollarWithGhRetry(__rawDollar$);
24
24
  // Import shared library functions
25
25
  const lib = await import('./lib.mjs');
26
- const { log } = lib;
26
+ const { log, cleanErrorMessage } = lib;
27
27
 
28
28
  // Import shared restart utilities
29
29
  const restartShared = await import('./solve.restart-shared.lib.mjs');
30
30
  const { executeToolIteration } = restartShared;
31
31
 
32
+ // Issue #1763: Re-verify PR ↔ issue link after every finalize iteration so a
33
+ // PR body that the AI rewrote without a closing keyword does not survive past
34
+ // the last requirements-check.
35
+ const resultsLib = await import('./solve.results.lib.mjs');
36
+ const { ensurePullRequestIssueLink } = resultsLib;
37
+
38
+ const sentryLib = await import('./sentry.lib.mjs');
39
+ const { reportError } = sentryLib;
40
+
32
41
  /**
33
42
  * Runs finalize requirements-check iterations after the main solve.
34
43
  *
@@ -116,6 +125,34 @@ export const runAutoEnsureRequirements = async ({ issueUrl, owner, repo, issueNu
116
125
  if (ensureResult.pricingInfo) pricingInfo = ensureResult.pricingInfo;
117
126
  }
118
127
 
128
+ // Issue #1763: Re-verify the PR body contains a closing keyword for the
129
+ // issue after every finalize iteration. The AI agent can rewrite the PR
130
+ // description mid-session and any iteration may end up being the last
131
+ // one, so this check cannot be deferred to the top-level verifyResults
132
+ // path.
133
+ if (prNumber && issueNumber && owner && repo) {
134
+ try {
135
+ await log('🔗 Verifying PR issue link after finalize iteration...');
136
+ await ensurePullRequestIssueLink({
137
+ prNumber,
138
+ issueNumber,
139
+ owner,
140
+ repo,
141
+ argv,
142
+ });
143
+ } catch (issueLinkError) {
144
+ reportError(issueLinkError, {
145
+ context: 'ensure_pr_issue_link_finalize_iteration',
146
+ prNumber,
147
+ owner,
148
+ repo,
149
+ ensureIteration,
150
+ operation: 'ensure_pr_issue_link',
151
+ });
152
+ await log(`⚠️ PR issue link check error: ${cleanErrorMessage(issueLinkError)}`, { level: 'warning' });
153
+ }
154
+ }
155
+
119
156
  await log(`✅ FINALIZE iteration ${ensureIteration}/${finalizeCount} complete`);
120
157
  await log('');
121
158
  }
@@ -60,8 +60,10 @@ const toolComments = await import('./tool-comments.lib.mjs');
60
60
  const { READY_TO_MERGE_MARKER, AUTO_RESTART_MARKER, AUTO_MERGED_MARKER, postTrackedComment } = toolComments;
61
61
 
62
62
  // Issue #1728: Per-iteration working session summary attachment helper
63
+ // Issue #1763: Per-iteration PR ↔ issue link verification (so a clobbered
64
+ // PR body is restored before the next stop condition fires).
63
65
  const resultsLib = await import('./solve.results.lib.mjs');
64
- const { maybeAttachWorkingSessionSummary } = resultsLib;
66
+ const { maybeAttachWorkingSessionSummary, ensurePullRequestIssueLink } = resultsLib;
65
67
 
66
68
  // Issue #1574: Interruptible sleep so CTRL+C is never blocked by a lingering timer
67
69
  const { interruptibleSleep } = await import('./interruptible-sleep.lib.mjs');
@@ -942,6 +944,35 @@ No further AI sessions will be started automatically for this run. Please review
942
944
  }
943
945
  }
944
946
 
947
+ // Issue #1763: Re-verify the PR body contains a closing keyword for
948
+ // the issue after every auto-restart-until-mergeable iteration. The
949
+ // AI agent can rewrite the PR description mid-session and any
950
+ // iteration may end up being the last one (mergeable, max-iters,
951
+ // billing limit, etc.), so this check cannot be deferred to the
952
+ // top-level verifyResults path.
953
+ if (prNumber && issueNumber && owner && repo) {
954
+ try {
955
+ await log(formatAligned('🔗', 'Verifying PR issue link after iteration...', '', 2));
956
+ await ensurePullRequestIssueLink({
957
+ prNumber,
958
+ issueNumber,
959
+ owner,
960
+ repo,
961
+ argv,
962
+ });
963
+ } catch (issueLinkError) {
964
+ reportError(issueLinkError, {
965
+ context: 'ensure_pr_issue_link_auto_restart_iteration',
966
+ prNumber,
967
+ owner,
968
+ repo,
969
+ iteration,
970
+ operation: 'ensure_pr_issue_link',
971
+ });
972
+ await log(formatAligned('', `⚠️ PR issue link check error: ${cleanErrorMessage(issueLinkError)}`, '', 2));
973
+ }
974
+ }
975
+
945
976
  await log('');
946
977
  await log(formatAligned('✅', `${argv.tool.toUpperCase()} execution completed:`, 'Checking if PR is now mergeable...'));
947
978
  }
@@ -47,8 +47,11 @@ const toolComments = await import('./tool-comments.lib.mjs');
47
47
  const { AUTO_RESTART_MARKER, postTrackedComment } = toolComments;
48
48
 
49
49
  // Issue #1728: Per-iteration working session summary attachment helper
50
+ // Issue #1763: Per-iteration PR ↔ issue link verification (in case the AI
51
+ // agent overwrites the PR body without a closing keyword and the iteration
52
+ // ends up being the last one).
50
53
  const resultsLib = await import('./solve.results.lib.mjs');
51
- const { maybeAttachWorkingSessionSummary } = resultsLib;
54
+ const { maybeAttachWorkingSessionSummary, ensurePullRequestIssueLink } = resultsLib;
52
55
 
53
56
  /**
54
57
  * Monitor for feedback in a loop and trigger restart when detected
@@ -514,6 +517,34 @@ export const watchForFeedback = async params => {
514
517
  }
515
518
  }
516
519
 
520
+ // Issue #1763: Re-verify the PR body contains a closing keyword for
521
+ // the issue after every iteration. The AI agent can rewrite the PR
522
+ // description mid-session and any iteration may turn out to be the
523
+ // last one (interrupt, hit iteration cap, billing limit, etc.), so
524
+ // we cannot rely on a single end-of-run check.
525
+ if (prNumber && issueNumber && owner && repo) {
526
+ try {
527
+ await log(formatAligned('🔗', 'Verifying PR issue link after iteration...', '', 2));
528
+ await ensurePullRequestIssueLink({
529
+ prNumber,
530
+ issueNumber,
531
+ owner,
532
+ repo,
533
+ argv,
534
+ });
535
+ } catch (issueLinkError) {
536
+ reportError(issueLinkError, {
537
+ context: 'ensure_pr_issue_link_watch_iteration',
538
+ prNumber,
539
+ owner,
540
+ repo,
541
+ autoRestartCount,
542
+ operation: 'ensure_pr_issue_link',
543
+ });
544
+ await log(formatAligned('', `⚠️ PR issue link check error: ${cleanErrorMessage(issueLinkError)}`, '', 2));
545
+ }
546
+ }
547
+
517
548
  await log('');
518
549
  if (isTemporaryWatch) {
519
550
  await log(formatAligned('✅', `${argv.tool.toUpperCase()} execution completed:`, 'Checking for remaining changes...'));