@yemi33/minions 0.1.2310 → 0.1.2312
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/dashboard/js/refresh.js +1 -1
- package/dashboard/js/render-pipelines.js +11 -4
- package/dashboard.js +13 -0
- package/engine/ado.js +40 -6
- package/engine/github.js +26 -6
- package/package.json +1 -1
package/dashboard/js/refresh.js
CHANGED
|
@@ -352,6 +352,11 @@ function renderPipelines(pipelines, opts) {
|
|
|
352
352
|
'<span style="color:' + statusColor + ';font-size:var(--text-base);font-weight:600">' + escHtml(statusLabel) + '</span>' +
|
|
353
353
|
(p.stopWhen ? '<span style="font-size:var(--text-xs);color:var(--yellow)" title="Auto-stops when condition met: ' + escHtml(typeof p.stopWhen === 'string' ? p.stopWhen : (p.stopWhen.check || 'condition')) + '">STOP-WHEN</span>' : '') +
|
|
354
354
|
(p.enabled === false ? '<span style="font-size:var(--text-xs);color:var(--red)"' + (p._stopReason ? ' title="' + escHtml(p._stopReason) + '"' : '') + '>' + (p._stoppedBy ? 'AUTO-STOPPED' : 'DISABLED') + '</span>' : '') +
|
|
355
|
+
(p.enabled !== false
|
|
356
|
+
? (activeRun
|
|
357
|
+
? '<button class="pr-pager-btn" style="font-size:var(--text-xs);padding:2px 8px;color:var(--yellow);border-color:var(--yellow)" onclick="event.stopPropagation();_retriggerPipeline(\'' + escHtml(p.id) + '\',this)">Retrigger</button>'
|
|
358
|
+
: '<button class="btn-action btn-action-md" onclick="event.stopPropagation();_triggerPipeline(\'' + escHtml(p.id) + '\',this)">Run Now</button>')
|
|
359
|
+
: '') +
|
|
355
360
|
'</div>' +
|
|
356
361
|
'</div>' +
|
|
357
362
|
resourcesHtml +
|
|
@@ -403,10 +408,12 @@ function openPipelineDetail(id) {
|
|
|
403
408
|
html += '<div style="display:flex;justify-content:space-between;align-items:center">' +
|
|
404
409
|
'<span style="font-size:var(--text-sm);color:var(--muted)">' + _renderPipelineTriggerLabel(p.trigger?.cron) + ' · ' + escHtml(_getPipelineStageLabel(p)) + '</span>' +
|
|
405
410
|
'<div style="display:flex;gap:6px">' +
|
|
406
|
-
(activeRun
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
411
|
+
(activeRun ? '<button class="btn-destructive btn-destructive-md" onclick="_abortPipeline(\'' + escHtml(id) + '\',this)">Abort</button>' : '') +
|
|
412
|
+
(p.enabled !== false
|
|
413
|
+
? (activeRun
|
|
414
|
+
? '<button class="pr-pager-btn" style="font-size:var(--text-xs);padding:2px 8px;color:var(--yellow);border-color:var(--yellow)" onclick="_retriggerPipeline(\'' + escHtml(id) + '\',this)">Retrigger</button>'
|
|
415
|
+
: '<button class="btn-action btn-action-md" onclick="_triggerPipeline(\'' + escHtml(id) + '\',this)">Run Now</button>')
|
|
416
|
+
: '') +
|
|
410
417
|
'<button class="pr-pager-btn" style="font-size:var(--text-xs);padding:2px 8px;color:var(--blue);border-color:var(--blue)" onclick="openEditPipelineModal(\'' + escHtml(id) + '\')">Edit</button>' +
|
|
411
418
|
'<button class="pr-pager-btn' + (_pipelineToggleInFlight.has(id) ? ' disabled' : '') + '" style="font-size:var(--text-xs);padding:2px 8px" onclick="_togglePipelineEnabled(\'' + escHtml(id) + '\',' + !p.enabled + ',this)">' + (p.enabled !== false ? 'Disable' : 'Enable') + '</button>' +
|
|
412
419
|
'<button class="btn-destructive btn-destructive-md" onclick="_deletePipelineConfirm(\'' + escHtml(id) + '\')">Delete</button>' +
|
package/dashboard.js
CHANGED
|
@@ -447,6 +447,19 @@ function mergeSettingsConfigUpdate(current, candidate, body, patch = {}) {
|
|
|
447
447
|
} else {
|
|
448
448
|
delete currentProject.liveCheckoutAutoStash;
|
|
449
449
|
}
|
|
450
|
+
// W-mr2pum3k000443c0 (checkout-mode pill snap-back) — mirror liveValidation
|
|
451
|
+
// the same way. handleSettingsUpdate validates + assigns liveValidation on
|
|
452
|
+
// `candidate` (and defensively deletes it there when the project moves off
|
|
453
|
+
// checkoutMode:'live'), but without this branch that value never reaches
|
|
454
|
+
// `current` before it's written to disk, so the hybrid pill flips back on
|
|
455
|
+
// the next status poll. Presence-of-own-property mirrors candidate's final
|
|
456
|
+
// state (set or delete) regardless of whether the request body even
|
|
457
|
+
// included the key, so the defensive-cleanup delete above also persists.
|
|
458
|
+
if (Object.prototype.hasOwnProperty.call(candidateProject, 'liveValidation')) {
|
|
459
|
+
currentProject.liveValidation = candidateProject.liveValidation;
|
|
460
|
+
} else {
|
|
461
|
+
delete currentProject.liveValidation;
|
|
462
|
+
}
|
|
450
463
|
// W-mqiaw974 (issue #241): the field was renamed from the legacy
|
|
451
464
|
// `worktreeMode`. Drop any stale legacy key on every settings save so a
|
|
452
465
|
// migrated project never carries both fields.
|
package/engine/ado.js
CHANGED
|
@@ -527,6 +527,35 @@ function votesToReviewStatus(votes) {
|
|
|
527
527
|
return REVIEW_STATUS.PENDING;
|
|
528
528
|
}
|
|
529
529
|
|
|
530
|
+
/**
|
|
531
|
+
* Issue #633 — ADO never clears a reviewer's numeric vote when new commits
|
|
532
|
+
* land on a PR, so a hard-reject -10 vote stays live forever unless the
|
|
533
|
+
* reviewer explicitly re-votes. Without this check, `reviewStatus` gets
|
|
534
|
+
* permanently stuck at 'changes-requested' after a fix is pushed, and the
|
|
535
|
+
* auto re-review-after-fix flow (engine.js needsReReview, which only fires on
|
|
536
|
+
* reviewStatus === 'waiting') can never dispatch again for that PR.
|
|
537
|
+
*
|
|
538
|
+
* Treat a live -10 vote as stale/superseded — i.e. resolve to 'waiting'
|
|
539
|
+
* instead of 'changes-requested' — once a fix has completed after the vote
|
|
540
|
+
* was (most recently) cast AND no further push has landed since that fix:
|
|
541
|
+
* - `pr.minionsReview.fixedAt` is set (a fix dispatch completed), and
|
|
542
|
+
* - the fix happened after the last minions review that produced the
|
|
543
|
+
* rejection (`!pr.lastReviewedAt || fixedAt > pr.lastReviewedAt` —
|
|
544
|
+
* mirrors the `fixedAfterReview` gate in engine.js needsReReview), and
|
|
545
|
+
* - no push has landed since that fix completed
|
|
546
|
+
* (`!pr.lastPushedAt || pr.lastPushedAt <= fixedAt`).
|
|
547
|
+
* If a new push lands after the fix without a following fix completion, or
|
|
548
|
+
* the last review (and its -10) postdates the recorded fix, the reject is
|
|
549
|
+
* still live/fresh and reviewStatus correctly stays 'changes-requested'.
|
|
550
|
+
*/
|
|
551
|
+
function isStaleAdoRejectVote(pr) {
|
|
552
|
+
const fixedAt = pr?.minionsReview?.fixedAt;
|
|
553
|
+
if (!fixedAt) return false;
|
|
554
|
+
const fixedAfterReview = !pr.lastReviewedAt || fixedAt > pr.lastReviewedAt;
|
|
555
|
+
const noPushSinceFix = !pr.lastPushedAt || pr.lastPushedAt <= fixedAt;
|
|
556
|
+
return fixedAfterReview && noPushSinceFix;
|
|
557
|
+
}
|
|
558
|
+
|
|
530
559
|
// ─── Reviewer Vote Snapshots (W-mpg58wv3) ────────────────────────────────────
|
|
531
560
|
//
|
|
532
561
|
// ADO's reviewer API does NOT include the source commit at which a reviewer
|
|
@@ -1569,11 +1598,7 @@ async function pollPrStatus(config) {
|
|
|
1569
1598
|
}
|
|
1570
1599
|
} else if (votes.length > 0) {
|
|
1571
1600
|
if (votes.some(v => v === -10)) {
|
|
1572
|
-
|
|
1573
|
-
newReviewStatus = REVIEW_STATUS.WAITING;
|
|
1574
|
-
} else {
|
|
1575
|
-
newReviewStatus = REVIEW_STATUS.CHANGES_REQUESTED;
|
|
1576
|
-
}
|
|
1601
|
+
newReviewStatus = isStaleAdoRejectVote(pr) ? REVIEW_STATUS.WAITING : REVIEW_STATUS.CHANGES_REQUESTED;
|
|
1577
1602
|
}
|
|
1578
1603
|
else if (votes.some(v => v >= 5)) newReviewStatus = REVIEW_STATUS.APPROVED;
|
|
1579
1604
|
else if (votes.some(v => v === -5)) newReviewStatus = REVIEW_STATUS.WAITING;
|
|
@@ -2346,7 +2371,16 @@ async function checkLiveReviewStatus(pr, project) {
|
|
|
2346
2371
|
if (!prData) return null;
|
|
2347
2372
|
const votes = (prData.reviewers || []).map(r => r.vote).filter(v => v !== undefined);
|
|
2348
2373
|
if (votes.length === 0) return 'pending';
|
|
2349
|
-
|
|
2374
|
+
const liveStatus = votesToReviewStatus(votes);
|
|
2375
|
+
// Issue #633: the live vote check is the pre-dispatch gate for
|
|
2376
|
+
// engine.js needsReReview — it must apply the same stale-reject-vote
|
|
2377
|
+
// override as pollPrStatus, or a cached 'waiting' status set below by
|
|
2378
|
+
// the poller gets immediately reverted back to 'changes-requested' here
|
|
2379
|
+
// before a re-review can ever be dispatched.
|
|
2380
|
+
if (liveStatus === REVIEW_STATUS.CHANGES_REQUESTED && isStaleAdoRejectVote(pr)) {
|
|
2381
|
+
return REVIEW_STATUS.WAITING;
|
|
2382
|
+
}
|
|
2383
|
+
return liveStatus;
|
|
2350
2384
|
} catch (e) {
|
|
2351
2385
|
log('warn', `Live review check for ${pr.id}: ${e.message}`);
|
|
2352
2386
|
return null;
|
package/engine/github.js
CHANGED
|
@@ -705,6 +705,24 @@ async function forEachActiveGhPr(config, callback) {
|
|
|
705
705
|
return totalUpdated;
|
|
706
706
|
}
|
|
707
707
|
|
|
708
|
+
/**
|
|
709
|
+
* Issue #633 (mirror of engine/ado.js isStaleAdoRejectVote) — GitHub reviews
|
|
710
|
+
* generally get dismissed/replaced when a reviewer re-reviews, but a stale
|
|
711
|
+
* CHANGES_REQUESTED review from a login that never re-reviews after a fix can
|
|
712
|
+
* still pin `reviewStatus` at 'changes-requested' forever (the reviewer's
|
|
713
|
+
* review state persists until dismissed). Mirror the ADO fix so the same
|
|
714
|
+
* fixedAfterReview + no-push-since-fix override applies here: treat a live
|
|
715
|
+
* CHANGES_REQUESTED review as stale/superseded once a fix has completed after
|
|
716
|
+
* the review that produced it and no further push has landed since that fix.
|
|
717
|
+
*/
|
|
718
|
+
function isStaleGithubChangesRequested(pr) {
|
|
719
|
+
const fixedAt = pr?.minionsReview?.fixedAt;
|
|
720
|
+
if (!fixedAt) return false;
|
|
721
|
+
const fixedAfterReview = !pr.lastReviewedAt || fixedAt > pr.lastReviewedAt;
|
|
722
|
+
const noPushSinceFix = !pr.lastPushedAt || pr.lastPushedAt <= fixedAt;
|
|
723
|
+
return fixedAfterReview && noPushSinceFix;
|
|
724
|
+
}
|
|
725
|
+
|
|
708
726
|
// ─── PR Status Polling ──────────────────────────────────────────────────────
|
|
709
727
|
|
|
710
728
|
async function pollPrStatus(config) {
|
|
@@ -999,11 +1017,7 @@ async function pollPrStatus(config) {
|
|
|
999
1017
|
if (pr.reviewStatus === REVIEW_STATUS.APPROVED) {
|
|
1000
1018
|
newReviewStatus = REVIEW_STATUS.APPROVED;
|
|
1001
1019
|
} else if (states.some(s => s === 'CHANGES_REQUESTED')) {
|
|
1002
|
-
|
|
1003
|
-
newReviewStatus = REVIEW_STATUS.WAITING;
|
|
1004
|
-
} else {
|
|
1005
|
-
newReviewStatus = REVIEW_STATUS.CHANGES_REQUESTED;
|
|
1006
|
-
}
|
|
1020
|
+
newReviewStatus = isStaleGithubChangesRequested(pr) ? REVIEW_STATUS.WAITING : REVIEW_STATUS.CHANGES_REQUESTED;
|
|
1007
1021
|
}
|
|
1008
1022
|
else if (states.some(s => s === 'APPROVED')) newReviewStatus = REVIEW_STATUS.APPROVED;
|
|
1009
1023
|
else if (states.length > 0) newReviewStatus = REVIEW_STATUS.PENDING;
|
|
@@ -1575,7 +1589,13 @@ async function checkLiveReviewStatus(pr, project) {
|
|
|
1575
1589
|
latestByUser.set(r.user?.login || '', r.state);
|
|
1576
1590
|
}
|
|
1577
1591
|
const states = [...latestByUser.values()];
|
|
1578
|
-
|
|
1592
|
+
// Issue #633: mirror the pollPrStatus stale-reject override here — this
|
|
1593
|
+
// live check is the pre-dispatch gate for engine.js needsReReview, and
|
|
1594
|
+
// without the override it immediately reverts a cached 'waiting' status
|
|
1595
|
+
// back to 'changes-requested' before a re-review can ever be dispatched.
|
|
1596
|
+
if (states.some(s => s === 'CHANGES_REQUESTED')) {
|
|
1597
|
+
return isStaleGithubChangesRequested(pr) ? REVIEW_STATUS.WAITING : REVIEW_STATUS.CHANGES_REQUESTED;
|
|
1598
|
+
}
|
|
1579
1599
|
if (states.some(s => s === 'APPROVED')) return REVIEW_STATUS.APPROVED;
|
|
1580
1600
|
if (states.length > 0) return REVIEW_STATUS.PENDING;
|
|
1581
1601
|
return REVIEW_STATUS.PENDING;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2312",
|
|
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"
|