@yemi33/minions 0.1.676 → 0.1.678
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 +6 -0
- package/dashboard/js/render-pipelines.js +12 -1
- package/dashboard/js/render-plans.js +28 -11
- package/engine/lifecycle.js +1 -12
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -374,7 +374,18 @@ async function _abortPipeline(id, btn) {
|
|
|
374
374
|
if (res.ok) {
|
|
375
375
|
var d = await res.json().catch(function() { return {}; });
|
|
376
376
|
showToast('cmd-toast', 'Pipeline aborted — ' + (d.cancelledWorkItems || 0) + ' work items cancelled', true);
|
|
377
|
-
|
|
377
|
+
// Replace abort button with Run Now
|
|
378
|
+
if (btn) {
|
|
379
|
+
btn.textContent = 'Run Now';
|
|
380
|
+
btn.style.color = 'var(--green)';
|
|
381
|
+
btn.style.borderColor = 'var(--green)';
|
|
382
|
+
btn.style.pointerEvents = '';
|
|
383
|
+
btn.style.opacity = '';
|
|
384
|
+
btn.onclick = function() { _triggerPipeline(id, btn); };
|
|
385
|
+
// Remove the retrigger button next to it (no longer needed)
|
|
386
|
+
var next = btn.nextElementSibling;
|
|
387
|
+
if (next && next.textContent.trim() === 'Retrigger') next.remove();
|
|
388
|
+
}
|
|
378
389
|
refresh();
|
|
379
390
|
openPipelineDetail(id);
|
|
380
391
|
} else { var d = await res.json().catch(function() { return {}; }); alert('Abort failed: ' + (d.error || 'unknown')); if (btn) { btn.textContent = 'Abort'; btn.style.pointerEvents = ''; btn.style.opacity = ''; } }
|
|
@@ -207,10 +207,10 @@ function renderPlans(plans) {
|
|
|
207
207
|
|
|
208
208
|
let actions = '';
|
|
209
209
|
if (needsAction) {
|
|
210
|
-
// Approve/Reject target the PRD .json file (not the .md plan) since the API parses it as JSON
|
|
211
210
|
const actionTarget = prdFile || p.file;
|
|
211
|
+
const actionLabel = effectiveStatus === 'paused' ? 'Resume' : 'Approve';
|
|
212
212
|
actions = '<div class="plan-card-actions" onclick="event.stopPropagation()">' +
|
|
213
|
-
'<button class="plan-btn approve" onclick="planApprove(\'' + escHtml(actionTarget) + '\')">
|
|
213
|
+
'<button class="plan-btn approve" onclick="planApprove(\'' + escHtml(actionTarget) + '\')">' + actionLabel + '</button>' +
|
|
214
214
|
'<button class="plan-btn reject" onclick="planReject(\'' + escHtml(actionTarget) + '\')">Reject</button>' +
|
|
215
215
|
'</div>';
|
|
216
216
|
} else if (isRevision) {
|
|
@@ -220,7 +220,8 @@ function renderPlans(plans) {
|
|
|
220
220
|
const executeBtn = isDraft && (effectiveStatus === 'active' || effectiveStatus === 'draft') && !isArchived && !prdFile ? '<button class="pr-pager-btn" style="font-size:9px;padding:2px 8px;color:var(--green);font-weight:600" ' +
|
|
221
221
|
'onclick="event.stopPropagation();planExecute(\'' + escHtml(p.file) + '\',\'' + escHtml(p.project) + '\',this)">Execute</button>' : '';
|
|
222
222
|
const showPause = effectiveStatus === 'dispatched' && prdFile && !isArchived;
|
|
223
|
-
|
|
223
|
+
// Resume pill not needed — paused state is handled by the actions block above
|
|
224
|
+
const showResume = false;
|
|
224
225
|
const verifyWi = allWi.find(w => w.itemType === 'verify' && w.sourcePlan === prdFile);
|
|
225
226
|
const hasVerifyWi = !!verifyWi;
|
|
226
227
|
const showVerify = effectiveStatus === 'completed' && prdFile && !isArchived && !hasVerifyWi;
|
|
@@ -228,7 +229,7 @@ function renderPlans(plans) {
|
|
|
228
229
|
'onclick="event.stopPropagation();planPause(\'' + escHtml(prdFile) + '\',this)">Pause</button>' : '';
|
|
229
230
|
const resumeBtn = showResume
|
|
230
231
|
? '<button class="pr-pager-btn" style="font-size:9px;padding:2px 8px;color:var(--green)" ' +
|
|
231
|
-
'onclick="event.stopPropagation();planApprove(\'' + escHtml(prdFile) + '\',this)">
|
|
232
|
+
'onclick="event.stopPropagation();planApprove(\'' + escHtml(prdFile) + '\',this)">Resume</button>'
|
|
232
233
|
: '';
|
|
233
234
|
const verifyBtn = showVerify ? '<button class="pr-pager-btn" style="font-size:9px;padding:2px 8px;color:var(--green)" ' +
|
|
234
235
|
'onclick="event.stopPropagation();triggerVerify(\'' + escHtml(prdFile) + '\',this)">Verify</button>' : '';
|
|
@@ -433,18 +434,29 @@ function _renderPlanModal(normalizedFile, raw, lastMod) {
|
|
|
433
434
|
(w.planFile === normalizedFile || w.sourcePlan === normalizedFile ||
|
|
434
435
|
(linkedPrdFile && w.sourcePlan === linkedPrdFile))
|
|
435
436
|
);
|
|
436
|
-
const
|
|
437
|
-
const
|
|
438
|
-
const
|
|
437
|
+
const prdConversion = wi.find(w => w.type === 'plan-to-prd' && w.status === 'done' && w.planFile === normalizedFile);
|
|
438
|
+
const linkedPrd = (window._lastStatus?.plans || []).find(p => p.sourcePlan === normalizedFile && p.format === 'prd');
|
|
439
|
+
const hasPrd = !!linkedPrd;
|
|
440
|
+
// Plan-to-prd conversion done is not "completed" — the PRD still needs approval and execution
|
|
441
|
+
const prdCompleted = prdConversion && linkedPrd && linkedPrd.status === 'completed';
|
|
442
|
+
const linkedPrdAwaiting = linkedPrd && (linkedPrd.status === 'awaiting-approval' || linkedPrd.status === 'paused');
|
|
443
|
+
const modalShowResume = isPaused || linkedPrdAwaiting;
|
|
439
444
|
const modalExecuteBtn = isMdPlan && !modalShowResume && !hasActiveWork && !prdCompleted && !hasPrd ? '<button class="pr-pager-btn" style="font-size:10px;padding:2px 10px;color:var(--green);font-weight:600" ' +
|
|
440
445
|
'onclick="planExecute(\'' + escHtml(normalizedFile) + '\',\'\',this)">Execute</button>' : '';
|
|
441
446
|
const modalCompletedLabel = prdCompleted && !hasActiveWork ? '<span style="font-size:10px;color:var(--green);font-weight:600">Completed</span>' : '';
|
|
447
|
+
const modalAwaitingLabel = linkedPrdAwaiting && !hasActiveWork && !prdCompleted ? '<span style="font-size:10px;color:var(--yellow);font-weight:600">Awaiting Approval</span>' : '';
|
|
442
448
|
const modalInProgressLabel = hasActiveWork ? '<span style="font-size:10px;color:var(--blue)">In Progress</span>' : '';
|
|
443
449
|
const isModalCompleted = planStatus === 'completed';
|
|
444
450
|
const modalPauseBtn = isActive && !isMdPlan && !isModalCompleted ? '<button class="pr-pager-btn" style="font-size:10px;padding:2px 10px;color:var(--yellow)" ' +
|
|
445
451
|
'onclick="planPause(\'' + escHtml(normalizedFile) + '\',this)">Pause</button>' : '';
|
|
446
|
-
const
|
|
447
|
-
|
|
452
|
+
const modalApproveTarget = linkedPrdAwaiting ? linkedPrd.file : normalizedFile;
|
|
453
|
+
const isActuallyPaused = planStatus === 'paused' || linkedPrd?.status === 'paused';
|
|
454
|
+
const modalApproveLabel = isActuallyPaused ? 'Resume' : 'Approve';
|
|
455
|
+
const showRejectInModal = linkedPrdAwaiting || planStatus === 'awaiting-approval';
|
|
456
|
+
const modalResumeBtn = modalShowResume ? '<button class="pr-pager-btn" style="font-size:10px;padding:2px 10px;color:var(--green)" ' +
|
|
457
|
+
'onclick="planApprove(\'' + escHtml(modalApproveTarget) + '\',this)">' + modalApproveLabel + '</button>' +
|
|
458
|
+
(showRejectInModal ? ' <button class="pr-pager-btn" style="font-size:10px;padding:2px 10px;color:var(--red)" ' +
|
|
459
|
+
'onclick="planReject(\'' + escHtml(modalApproveTarget) + '\')">Reject</button>' : '') : '';
|
|
448
460
|
const modalVerifyWi = (window._lastWorkItems || []).find(w => w.itemType === 'verify' && w.sourcePlan === normalizedFile);
|
|
449
461
|
const modalVerifyBtn = isModalCompleted && !modalVerifyWi ? '<button class="pr-pager-btn" style="font-size:10px;padding:2px 10px;color:var(--green)" ' +
|
|
450
462
|
'onclick="triggerVerify(\'' + escHtml(normalizedFile) + '\',this)">Verify</button>' : '';
|
|
@@ -453,7 +465,7 @@ function _renderPlanModal(normalizedFile, raw, lastMod) {
|
|
|
453
465
|
'onclick="planArchive(\'' + escHtml(normalizedFile) + '\')">Archive</button>';
|
|
454
466
|
const lastModLabel = lastMod ? '<div style="font-size:10px;color:var(--muted);font-weight:400;margin-top:2px">Last updated: ' + new Date(lastMod).toLocaleString() + '</div>' : '';
|
|
455
467
|
const actionBtns = '<div style="display:flex;gap:4px;flex-wrap:wrap;margin-top:4px">' +
|
|
456
|
-
(modalCompletedLabel || '') + (modalInProgressLabel || '') + (modalExecuteBtn || '') + (modalPauseBtn || '') + (modalResumeBtn || '') + (modalVerifyBtn || '') + (modalVerifyInfo || '') +
|
|
468
|
+
(modalCompletedLabel || '') + (modalAwaitingLabel || '') + (modalInProgressLabel || '') + (modalExecuteBtn || '') + (modalPauseBtn || '') + (modalResumeBtn || '') + (modalVerifyBtn || '') + (modalVerifyInfo || '') +
|
|
457
469
|
' ' + modalArchiveBtn +
|
|
458
470
|
' <button class="pr-pager-btn" style="font-size:10px;padding:2px 10px;color:var(--red)" ' +
|
|
459
471
|
'onclick="planDelete(\'' + escHtml(normalizedFile) + '\')">Delete</button>' +
|
|
@@ -549,10 +561,15 @@ async function planDelete(file) {
|
|
|
549
561
|
}
|
|
550
562
|
|
|
551
563
|
async function planArchive(file, btn) {
|
|
564
|
+
var isPrd = file.endsWith('.json');
|
|
565
|
+
var confirmMsg = isPrd
|
|
566
|
+
? 'Archive this PRD? The linked source plan will also be archived.'
|
|
567
|
+
: 'Archive this plan?';
|
|
568
|
+
if (!confirm(confirmMsg)) return;
|
|
552
569
|
_stopPlanPoll();
|
|
553
570
|
markDeleted('plan:' + file);
|
|
554
571
|
try { closeModal(); } catch { /* may not be open */ }
|
|
555
|
-
showToast('cmd-toast', '
|
|
572
|
+
showToast('cmd-toast', 'Archiving...', true);
|
|
556
573
|
try {
|
|
557
574
|
const res = await fetch('/api/plans/archive', {
|
|
558
575
|
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
package/engine/lifecycle.js
CHANGED
|
@@ -1245,18 +1245,7 @@ async function runPostCompletionHooks(dispatchItem, agentId, code, stdout, confi
|
|
|
1245
1245
|
// Plan chaining removed — user must explicitly execute plan-to-prd after reviewing the plan
|
|
1246
1246
|
if (effectiveSuccess && meta?.item?.sourcePlan) checkPlanCompletion(meta, config);
|
|
1247
1247
|
|
|
1248
|
-
//
|
|
1249
|
-
if (effectiveSuccess && meta?.item?.itemType === 'verify' && meta?.item?.sourcePlan) {
|
|
1250
|
-
try {
|
|
1251
|
-
const vPlanFile = meta.item.sourcePlan;
|
|
1252
|
-
const vPlanPath = path.join(PRD_DIR, vPlanFile);
|
|
1253
|
-
const vPlan = safeJson(vPlanPath);
|
|
1254
|
-
if (vPlan) {
|
|
1255
|
-
const vProjects = shared.getProjects(config);
|
|
1256
|
-
archivePlan(vPlanFile, vPlan, vProjects, config);
|
|
1257
|
-
}
|
|
1258
|
-
} catch (err) { log('warn', `Verify archive: ${err.message}`); }
|
|
1259
|
-
}
|
|
1248
|
+
// Archive is manual — user archives plans from the dashboard when ready
|
|
1260
1249
|
|
|
1261
1250
|
// Clean up worktree for non-shared-branch tasks after completion
|
|
1262
1251
|
if (meta?.branch && meta?.branchStrategy !== 'shared-branch') {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.678",
|
|
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"
|