@yemi33/minions 0.1.782 → 0.1.784

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
  # Changelog
2
2
 
3
+ ## 0.1.784 (2026-04-10)
4
+
5
+ ### Features
6
+ - cap review→fix cycles at evalMaxIterations (default 3)
7
+
8
+ ### Fixes
9
+ - don't overwrite approval with 'waiting' when platform API lags
10
+
3
11
  ## 0.1.782 (2026-04-10)
4
12
 
5
13
  ### Features
package/engine/ado.js CHANGED
@@ -341,6 +341,10 @@ async function pollPrStatus(config) {
341
341
  });
342
342
  } catch (err) { log('warn', `Metrics update: ${err.message}`); }
343
343
  }
344
+ if (newReviewStatus === 'approved') {
345
+ delete pr._reviewFixCycles;
346
+ delete pr._evalEscalated;
347
+ }
344
348
  }
345
349
  }
346
350
 
package/engine/github.js CHANGED
@@ -363,6 +363,11 @@ async function pollPrStatus(config) {
363
363
  } catch (err) { log('warn', `Metrics update: ${err.message}`); }
364
364
  }
365
365
  }
366
+ // Reset review→fix cycle counter on approval (loop succeeded)
367
+ if (newReviewStatus === 'approved') {
368
+ delete pr._reviewFixCycles;
369
+ delete pr._evalEscalated;
370
+ }
366
371
  }
367
372
  }
368
373
 
@@ -730,7 +730,10 @@ async function updatePrAfterReview(agentId, pr, project, config, resultSummary)
730
730
  const completedEntry = (dispatch.completed || []).find(d => d.agent === agentId && d.type === 'review');
731
731
 
732
732
  // Check actual review status from the platform (agent may have approved or requested changes)
733
- let postReviewStatus = 'waiting';
733
+ // Default to 'pending' (not 'waiting') — if platform hasn't propagated the vote yet,
734
+ // 'pending' lets the next poll cycle pick it up. 'waiting' would trigger the awaitingReReview
735
+ // gate and block the PR until the fix→re-review flow runs.
736
+ let postReviewStatus = 'pending';
734
737
  try {
735
738
  const projectObj = project || shared.getProjects(config)[0];
736
739
  if (projectObj) {
@@ -739,7 +742,6 @@ async function updatePrAfterReview(agentId, pr, project, config, resultSummary)
739
742
  ? require('./github').checkLiveReviewStatus
740
743
  : require('./ado').checkLiveReviewStatus;
741
744
  const liveStatus = await checkFn(pr, projectObj);
742
- // Use live status only if it's a decisive verdict (not 'pending' — review may not have propagated yet)
743
745
  if (liveStatus && liveStatus !== 'pending') postReviewStatus = liveStatus;
744
746
  }
745
747
  } catch (e) { log('warn', `Post-review status check for ${pr.id}: ${e.message}`); }
package/engine.js CHANGED
@@ -1576,9 +1576,26 @@ async function discoverFromPrs(config, project) {
1576
1576
  // The poller holds reviewStatus at 'waiting' until the reviewer acts on the new code.
1577
1577
  const awaitingReReview = reviewStatus === 'waiting' && !!pr.minionsReview?.fixedAt;
1578
1578
 
1579
+ // Review→fix cycle cap — stop after N iterations, alert human
1580
+ const evalMax = config.engine?.evalMaxIterations ?? DEFAULTS.evalMaxIterations;
1581
+ const evalCycles = pr._reviewFixCycles || 0;
1582
+ if (evalCycles >= evalMax && !pr._evalEscalated) {
1583
+ writeInboxAlert(`eval-escalated-${pr.agent || 'unassigned'}-${pr.id}`,
1584
+ `# Review Loop Escalation\n\n**PR ${pr.id}** on branch \`${pr.branch || 'unknown'}\` has gone through **${evalCycles}** review→fix cycles without approval.\n\n` +
1585
+ `Last review: ${pr.minionsReview?.note ? pr.minionsReview.note.slice(0, 200) : 'See PR thread'}\n\n` +
1586
+ `Auto-dispatch of reviews and fixes has been suspended. Please review the PR manually.`);
1587
+ try {
1588
+ mutatePullRequests(projectPrPath(project), prs => {
1589
+ const target = prs.find(p => p.id === pr.id);
1590
+ if (target) target._evalEscalated = true;
1591
+ });
1592
+ } catch (e) { log('warn', 'mark eval escalated: ' + e.message); }
1593
+ log('warn', `PR ${pr.id}: review→fix escalated after ${evalCycles} cycles — suspending auto-dispatch`);
1594
+ continue;
1595
+ }
1596
+
1579
1597
  // PRs needing review: pending review status and not already reviewed without new commits
1580
1598
  const autoReview = config.engine?.autoReview !== false;
1581
- // Skip re-dispatch if already reviewed and no new commits pushed since last review
1582
1599
  const alreadyReviewed = pr.lastReviewedAt && (!pr.lastPushedAt || pr.lastPushedAt <= pr.lastReviewedAt);
1583
1600
  const needsReview = autoReview && reviewStatus === 'pending' && !alreadyReviewed;
1584
1601
  if (needsReview) {
@@ -1627,7 +1644,16 @@ async function discoverFromPrs(config, project) {
1627
1644
  pr_id: pr.id, pr_branch: pr.branch || '',
1628
1645
  review_note: pr.minionsReview?.note || pr.reviewNote || 'See PR thread comments',
1629
1646
  }, `Fix PR ${pr.id} review feedback`, { dispatchKey: key, source: 'pr', pr, branch: pr.branch, project: projMeta });
1630
- if (item) { newWork.push(item); setCooldown(key); fixDispatched = true; }
1647
+ if (item) {
1648
+ newWork.push(item); setCooldown(key); fixDispatched = true;
1649
+ // Increment review→fix cycle counter
1650
+ try {
1651
+ mutatePullRequests(projectPrPath(project), prs => {
1652
+ const target = prs.find(p => p.id === pr.id);
1653
+ if (target) target._reviewFixCycles = (target._reviewFixCycles || 0) + 1;
1654
+ });
1655
+ } catch (e) { log('warn', 'increment review-fix cycles: ' + e.message); }
1656
+ }
1631
1657
  }
1632
1658
 
1633
1659
  // PRs with pending human feedback (skip if review-fix already dispatched above)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yemi33/minions",
3
- "version": "0.1.782",
3
+ "version": "0.1.784",
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"