@yemi33/minions 0.1.370 → 0.1.372
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 +3 -1
- package/engine/github.js +10 -0
- package/engine/lifecycle.js +9 -1
- package/engine.js +4 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 0.1.
|
|
3
|
+
## 0.1.372 (2026-04-06)
|
|
4
4
|
|
|
5
5
|
### Features
|
|
6
|
+
- Fix review re-dispatch infinite loop (#226)
|
|
6
7
|
- Add subagent guidance and health check preamble to playbooks (#225)
|
|
7
8
|
- Fix 2 failing source-pattern test assertions (#224)
|
|
8
9
|
|
|
9
10
|
### Fixes
|
|
11
|
+
- restore dispatched_to on work items when marking done after retry
|
|
10
12
|
- copy button preserves markdown formatting
|
|
11
13
|
|
|
12
14
|
## 0.1.368 (2026-04-06)
|
package/engine/github.js
CHANGED
|
@@ -141,6 +141,13 @@ async function pollPrStatus(config) {
|
|
|
141
141
|
else if (prData.state === 'closed') newStatus = PR_STATUS.ABANDONED;
|
|
142
142
|
else if (prData.state === 'open') newStatus = PR_STATUS.ACTIVE;
|
|
143
143
|
|
|
144
|
+
// Track head SHA changes to detect new pushes (used for review re-dispatch gating)
|
|
145
|
+
if (prData.head?.sha && pr.headSha !== prData.head.sha) {
|
|
146
|
+
pr.headSha = prData.head.sha;
|
|
147
|
+
pr.lastPushedAt = new Date().toISOString();
|
|
148
|
+
updated = true;
|
|
149
|
+
}
|
|
150
|
+
|
|
144
151
|
if (pr.status !== newStatus) {
|
|
145
152
|
log('info', `PR ${pr.id} status: ${pr.status} → ${newStatus}`);
|
|
146
153
|
pr.status = newStatus;
|
|
@@ -191,6 +198,9 @@ async function pollPrStatus(config) {
|
|
|
191
198
|
if (states.some(s => s === 'CHANGES_REQUESTED')) newReviewStatus = 'changes-requested';
|
|
192
199
|
else if (states.some(s => s === 'APPROVED')) newReviewStatus = 'approved';
|
|
193
200
|
else if (states.length > 0) newReviewStatus = 'pending';
|
|
201
|
+
// If all reviews were COMMENTED (filtered out), states is empty but reviews exist.
|
|
202
|
+
// Set to 'waiting' instead of leaving as 'pending' to prevent infinite review re-dispatch.
|
|
203
|
+
else if (states.length === 0 && reviews.length > 0 && newReviewStatus === 'pending') newReviewStatus = 'waiting';
|
|
194
204
|
|
|
195
205
|
if (pr.reviewStatus !== newReviewStatus) {
|
|
196
206
|
log('info', `PR ${pr.id} reviewStatus: ${pr.reviewStatus} → ${newReviewStatus}`);
|
package/engine/lifecycle.js
CHANGED
|
@@ -546,6 +546,8 @@ function updateWorkItemStatus(meta, status, reason) {
|
|
|
546
546
|
delete target.failReason;
|
|
547
547
|
delete target.failedAt;
|
|
548
548
|
target.completedAt = ts();
|
|
549
|
+
// Restore agent info from dispatch metadata (cleared on retry reset)
|
|
550
|
+
if (meta._agentId && !target.dispatched_to) target.dispatched_to = meta._agentId;
|
|
549
551
|
} else if (status === WI_STATUS.FAILED) {
|
|
550
552
|
if (reason) target.failReason = reason;
|
|
551
553
|
target.failedAt = ts();
|
|
@@ -727,6 +729,9 @@ function updatePrAfterReview(agentId, pr, project) {
|
|
|
727
729
|
|
|
728
730
|
// Set reviewStatus to 'waiting' (single source of truth — synced from ADO/GitHub votes on next poll)
|
|
729
731
|
target.reviewStatus = 'waiting';
|
|
732
|
+
// Track when this PR was last reviewed — used by engine.js to prevent re-dispatch
|
|
733
|
+
// until new commits are pushed (lastPushedAt > lastReviewedAt)
|
|
734
|
+
target.lastReviewedAt = ts();
|
|
730
735
|
target.minionsReview = {
|
|
731
736
|
reviewer: reviewerName,
|
|
732
737
|
reviewedAt: ts(),
|
|
@@ -1160,7 +1165,10 @@ function runPostCompletionHooks(dispatchItem, agentId, code, stdout, config) {
|
|
|
1160
1165
|
// If decomposition produced nothing, fall through to mark parent as done
|
|
1161
1166
|
}
|
|
1162
1167
|
|
|
1163
|
-
if (isSuccess && meta?.item?.id && !skipDoneStatus)
|
|
1168
|
+
if (isSuccess && meta?.item?.id && !skipDoneStatus) {
|
|
1169
|
+
meta._agentId = agentId;
|
|
1170
|
+
updateWorkItemStatus(meta, WI_STATUS.DONE, '');
|
|
1171
|
+
}
|
|
1164
1172
|
if (!isSuccess && meta?.item?.id) {
|
|
1165
1173
|
// Auto-retry: read fresh _retryCount from file (not stale dispatch-time snapshot)
|
|
1166
1174
|
let retries = (meta.item._retryCount || 0);
|
package/engine.js
CHANGED
|
@@ -1268,9 +1268,11 @@ function discoverFromPrs(config, project) {
|
|
|
1268
1268
|
// minionsReview tracks metadata (reviewer, note) but not the authoritative status
|
|
1269
1269
|
const reviewStatus = pr.reviewStatus || 'pending';
|
|
1270
1270
|
|
|
1271
|
-
// PRs needing review: pending
|
|
1271
|
+
// PRs needing review: pending review status and not already reviewed without new commits
|
|
1272
1272
|
const autoReview = config.engine?.autoReview !== false;
|
|
1273
|
-
|
|
1273
|
+
// Skip re-dispatch if already reviewed and no new commits pushed since last review
|
|
1274
|
+
const alreadyReviewed = pr.lastReviewedAt && (!pr.lastPushedAt || pr.lastPushedAt <= pr.lastReviewedAt);
|
|
1275
|
+
const needsReview = autoReview && reviewStatus === 'pending' && !alreadyReviewed;
|
|
1274
1276
|
if (needsReview) {
|
|
1275
1277
|
const key = `review-${project?.name || 'default'}-${pr.id}`;
|
|
1276
1278
|
if (isAlreadyDispatched(key) || isOnCooldown(key, cooldownMs)) continue;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.372",
|
|
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"
|