@yemi33/minions 0.1.1641 → 0.1.1642

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,10 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.1642 (2026-04-30)
4
+
5
+ ### Features
6
+ - fix PR comment auto-fix loop
7
+
3
8
  ## 0.1.1641 (2026-04-30)
4
9
 
5
10
  ### Features
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "runtime": "copilot",
3
3
  "models": null,
4
- "cachedAt": "2026-04-30T17:23:35.113Z"
4
+ "cachedAt": "2026-04-30T20:24:03.227Z"
5
5
  }
package/engine.js CHANGED
@@ -2195,12 +2195,55 @@ async function discoverFromPrs(config, project) {
2195
2195
  if (item) { newWork.push(item); }
2196
2196
  }
2197
2197
 
2198
+ let fixDispatched = false;
2199
+
2200
+ // Fresh reviewer comments are actionable fixes, even while the PR is otherwise
2201
+ // awaiting a stale-vote re-review or has build-fix retries escalated.
2202
+ const humanFixKey = `human-fix-${project?.name || 'default'}-${prDisplayId}`;
2203
+ const hasCoalescedFeedback = (dispatchCooldowns.get(humanFixKey)?.pendingContexts || []).length > 0;
2204
+ if ((pr.humanFeedback?.pendingFix || hasCoalescedFeedback) && !fixDispatched) {
2205
+ const key = humanFixKey;
2206
+ let staleCoalesced = [];
2207
+ const alreadyDispatched = isAlreadyDispatched(key);
2208
+ const blockedByCooldown = isOnCooldown(key, cooldownMs);
2209
+ if (blockedByCooldown && !alreadyDispatched) {
2210
+ staleCoalesced = getCoalescedContexts(key);
2211
+ clearCooldown(key);
2212
+ log('info', `Cleared stale cooldown for ${key} — no matching dispatch history`);
2213
+ }
2214
+ if (alreadyDispatched || isOnCooldown(key, cooldownMs)) {
2215
+ // Coalesce: save feedback for next dispatch
2216
+ if (pr.humanFeedback?.feedbackContent) {
2217
+ setCooldownWithContext(key, { feedbackContent: pr.humanFeedback.feedbackContent, timestamp: ts() });
2218
+ }
2219
+ continue;
2220
+ }
2221
+ const agentId = resolveAgent('fix', config, { authorAgent: pr.agent });
2222
+ if (!agentId) continue;
2223
+ const prBranch = ensurePrBranchForDispatch(project, pr, 'human-feedback fix');
2224
+ if (!prBranch) continue;
2225
+
2226
+ const coalesced = [...staleCoalesced, ...getCoalescedContexts(key)];
2227
+ let reviewNote = pr.humanFeedback.feedbackContent || 'See PR thread comments';
2228
+ if (coalesced.length > 0) {
2229
+ const earlier = coalesced.map(c => c.feedbackContent).filter(Boolean).join('\n\n---\n\n');
2230
+ if (earlier) reviewNote = earlier + '\n\n---\n\n' + reviewNote;
2231
+ }
2232
+
2233
+ const item = buildPrDispatch(agentId, config, project, pr, 'fix', {
2234
+ pr_id: pr.id, pr_number: prNumber, pr_title: pr.title || '', pr_branch: prBranch,
2235
+ reviewer: 'Human Reviewer',
2236
+ review_note: reviewNote,
2237
+ }, `Fix ${pr.id}: ${pr.title || ''} — human feedback`, { dispatchKey: key, source: 'pr-human-feedback', pr, branch: prBranch, project: projMeta });
2238
+ if (item) { newWork.push(item); fixDispatched = true; }
2239
+ }
2240
+
2198
2241
  // Re-review after fix: trigger when a fix was pushed after the last minions review,
2199
2242
  // or when no minions review has completed yet (e.g. human-feedback-only fix path).
2200
2243
  const fixedAfterReview = !!(pr.minionsReview?.fixedAt &&
2201
2244
  (!pr.lastReviewedAt || pr.minionsReview.fixedAt > pr.lastReviewedAt));
2202
2245
  const needsReReview = reviewEnabled && reviewStatus === 'waiting' &&
2203
- fixedAfterReview && !evalEscalated;
2246
+ fixedAfterReview && !evalEscalated && !fixDispatched;
2204
2247
  if (needsReReview) {
2205
2248
  const key = `rereview-${project?.name || 'default'}-${prDisplayId}`;
2206
2249
  // Skip isAlreadyDispatched — fixedAfterReview/lastReviewedAt already dedupe; the 1hr
@@ -2240,8 +2283,7 @@ async function discoverFromPrs(config, project) {
2240
2283
 
2241
2284
  // PRs with changes requested → route back to author for fix
2242
2285
  // Gate on evalLoopEnabled — the review→fix cycle is the eval loop
2243
- let fixDispatched = false;
2244
- if (evalLoopEnabled && reviewStatus === 'changes-requested' && !awaitingReReview && !evalEscalated) {
2286
+ if (evalLoopEnabled && reviewStatus === 'changes-requested' && !awaitingReReview && !evalEscalated && !fixDispatched) {
2245
2287
  const key = `fix-${project?.name || 'default'}-${prDisplayId}`;
2246
2288
  if (isAlreadyDispatched(key) || isOnCooldown(key, cooldownMs)) continue;
2247
2289
  const agentId = resolveAgent('fix', config, { authorAgent: pr.agent });
@@ -2265,46 +2307,6 @@ async function discoverFromPrs(config, project) {
2265
2307
  }
2266
2308
  }
2267
2309
 
2268
- // PRs with pending human feedback (skip if review-fix already dispatched above)
2269
- const humanFixKey = `human-fix-${project?.name || 'default'}-${prDisplayId}`;
2270
- const hasCoalescedFeedback = (dispatchCooldowns.get(humanFixKey)?.pendingContexts || []).length > 0;
2271
- if ((pr.humanFeedback?.pendingFix || hasCoalescedFeedback) && !awaitingReReview && !fixDispatched) {
2272
- const key = humanFixKey;
2273
- let staleCoalesced = [];
2274
- const alreadyDispatched = isAlreadyDispatched(key);
2275
- const blockedByCooldown = isOnCooldown(key, cooldownMs);
2276
- if (blockedByCooldown && !alreadyDispatched) {
2277
- staleCoalesced = getCoalescedContexts(key);
2278
- clearCooldown(key);
2279
- log('info', `Cleared stale cooldown for ${key} — no matching dispatch history`);
2280
- }
2281
- if (alreadyDispatched || isOnCooldown(key, cooldownMs)) {
2282
- // Coalesce: save feedback for next dispatch
2283
- if (pr.humanFeedback?.feedbackContent) {
2284
- setCooldownWithContext(key, { feedbackContent: pr.humanFeedback.feedbackContent, timestamp: ts() });
2285
- }
2286
- continue;
2287
- }
2288
- const agentId = resolveAgent('fix', config, { authorAgent: pr.agent });
2289
- if (!agentId) continue;
2290
- const prBranch = ensurePrBranchForDispatch(project, pr, 'human-feedback fix');
2291
- if (!prBranch) continue;
2292
-
2293
- const coalesced = [...staleCoalesced, ...getCoalescedContexts(key)];
2294
- let reviewNote = pr.humanFeedback.feedbackContent || 'See PR thread comments';
2295
- if (coalesced.length > 0) {
2296
- const earlier = coalesced.map(c => c.feedbackContent).filter(Boolean).join('\n\n---\n\n');
2297
- if (earlier) reviewNote = earlier + '\n\n---\n\n' + reviewNote;
2298
- }
2299
-
2300
- const item = buildPrDispatch(agentId, config, project, pr, 'fix', {
2301
- pr_id: pr.id, pr_number: prNumber, pr_title: pr.title || '', pr_branch: prBranch,
2302
- reviewer: 'Human Reviewer',
2303
- review_note: reviewNote,
2304
- }, `Fix ${pr.id}: ${pr.title || ''} — human feedback`, { dispatchKey: key, source: 'pr-human-feedback', pr, branch: prBranch, project: projMeta });
2305
- if (item) { newWork.push(item); fixDispatched = true; }
2306
- }
2307
-
2308
2310
  // PRs with build failures — route to author (has session context from implementing)
2309
2311
  // Grace period: after a build fix push, wait for CI to run before re-dispatching
2310
2312
  // Skip if build hasn't transitioned since last fix (still showing the old failure)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yemi33/minions",
3
- "version": "0.1.1641",
3
+ "version": "0.1.1642",
4
4
  "description": "Multi-agent AI dev team that runs from ~/.minions/ — five autonomous agents share a single engine, dashboard, and knowledge base",
5
5
  "bin": {
6
6
  "minions": "bin/minions.js"