@yemi33/minions 0.1.85 → 0.1.86

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.86 (2026-03-31)
4
+
5
+ ### Dashboard
6
+ - dashboard/js/render-prd.js
7
+
3
8
  ## 0.1.85 (2026-03-31)
4
9
 
5
10
  ### Dashboard
@@ -13,37 +13,54 @@ function renderPrd(prd, prog) {
13
13
  return;
14
14
  }
15
15
 
16
- // Derive status from work items
17
- const allWi = window._lastWorkItems || [];
18
- const prdItems = (prog?.items || []).filter(i => !i._archived);
19
- const implementItems = allWi.filter(w => prdItems.some(pi => pi.id === w.id));
20
- const allDone = implementItems.length > 0 && implementItems.every(w => w.status === 'done' || w.status === 'in-pr' || w.status === 'implemented' || w.status === 'complete');
21
- const hasActive = implementItems.some(w => w.status === 'pending' || w.status === 'dispatched');
22
-
23
- // Find the active PRD file for action buttons
24
- const prdFile = prd.existing?.[0]?.file || '';
25
- const prdStatus = prd.existing?.[0]?.status || '';
26
- const effectiveStatus = allDone && !hasActive ? 'completed' : hasActive ? 'in-progress' : prdStatus || 'active';
27
-
28
16
  const statusColors = { 'completed': 'var(--green)', 'in-progress': 'var(--blue)', 'awaiting-approval': 'var(--yellow)', 'paused': 'var(--muted)', 'approved': 'var(--green)' };
29
17
  const statusLabels = { 'completed': 'Completed', 'in-progress': 'In Progress', 'awaiting-approval': 'Awaiting Approval', 'paused': 'Paused', 'approved': 'Approved' };
30
18
 
31
- let actions = '';
32
- if (prdFile) {
33
- if (effectiveStatus === 'awaiting-approval') {
34
- actions = ' <button class="pr-pager-btn" style="font-size:9px;padding:1px 6px;color:var(--green);border-color:var(--green);margin-left:4px" onclick="planApprove(\'' + escHtml(prdFile) + '\',this)">Approve</button>';
35
- } else if (effectiveStatus === 'completed') {
36
- actions = ' <button class="pr-pager-btn" style="font-size:9px;padding:1px 6px;color:var(--green);border-color:var(--green);margin-left:4px" onclick="triggerVerify(\'' + escHtml(prdFile) + '\',this)">Verify</button>' +
37
- ' <button class="pr-pager-btn" style="font-size:9px;padding:1px 6px;color:var(--muted);border-color:var(--border);margin-left:4px" onclick="planDelete(\'' + escHtml(prdFile) + '\')">Archive</button>';
38
- } else if (effectiveStatus === 'in-progress') {
39
- actions = ' <button class="pr-pager-btn" style="font-size:9px;padding:1px 6px;color:var(--yellow);border-color:var(--yellow);margin-left:4px" onclick="planPause(\'' + escHtml(prdFile) + '\',this)">Pause</button>';
40
- } else if (effectiveStatus === 'paused') {
41
- actions = ' <button class="pr-pager-btn" style="font-size:9px;padding:1px 6px;color:var(--green);border-color:var(--green);margin-left:4px" onclick="planApprove(\'' + escHtml(prdFile) + '\',this)">Resume</button>';
19
+ // Show per-PRD status summary in header when multiple PRDs exist
20
+ const existing = prd.existing || [];
21
+ const allWi = window._lastWorkItems || [];
22
+ const prdItems = (prog?.items || []).filter(i => !i._archived);
23
+
24
+ if (existing.length <= 1) {
25
+ // Single PRD show status + actions in header
26
+ const implementItems = allWi.filter(w => prdItems.some(pi => pi.id === w.id));
27
+ const allDone = implementItems.length > 0 && implementItems.every(w => w.status === 'done' || w.status === 'in-pr' || w.status === 'implemented' || w.status === 'complete');
28
+ const hasActive = implementItems.some(w => w.status === 'pending' || w.status === 'dispatched');
29
+ const prdFile = existing[0]?.file || '';
30
+ const prdStatus = existing[0]?.status || '';
31
+ const effectiveStatus = allDone && !hasActive ? 'completed' : hasActive ? 'in-progress' : prdStatus || 'active';
32
+
33
+ let actions = '';
34
+ if (prdFile) {
35
+ if (effectiveStatus === 'awaiting-approval') {
36
+ actions = ' <button class="pr-pager-btn" style="font-size:9px;padding:1px 6px;color:var(--green);border-color:var(--green);margin-left:4px" onclick="planApprove(\'' + escHtml(prdFile) + '\',this)">Approve</button>';
37
+ } else if (effectiveStatus === 'completed') {
38
+ actions = ' <button class="pr-pager-btn" style="font-size:9px;padding:1px 6px;color:var(--green);border-color:var(--green);margin-left:4px" onclick="triggerVerify(\'' + escHtml(prdFile) + '\',this)">Verify</button>' +
39
+ ' <button class="pr-pager-btn" style="font-size:9px;padding:1px 6px;color:var(--muted);border-color:var(--border);margin-left:4px" onclick="planDelete(\'' + escHtml(prdFile) + '\')">Archive</button>';
40
+ } else if (effectiveStatus === 'in-progress') {
41
+ actions = ' <button class="pr-pager-btn" style="font-size:9px;padding:1px 6px;color:var(--yellow);border-color:var(--yellow);margin-left:4px" onclick="planPause(\'' + escHtml(prdFile) + '\',this)">Pause</button>';
42
+ } else if (effectiveStatus === 'paused') {
43
+ actions = ' <button class="pr-pager-btn" style="font-size:9px;padding:1px 6px;color:var(--green);border-color:var(--green);margin-left:4px" onclick="planApprove(\'' + escHtml(prdFile) + '\',this)">Resume</button>';
44
+ }
45
+ }
46
+ badge.innerHTML = '<span style="font-weight:600;font-size:11px;color:' + (statusColors[effectiveStatus] || 'var(--muted)') + '">' + (statusLabels[effectiveStatus] || effectiveStatus) + '</span>' +
47
+ ' <span style="color:var(--muted);font-size:10px">' + (prd.age || '') + '</span>' + actions;
48
+ } else {
49
+ // Multiple PRDs — show count summary, per-PRD details are in renderPrdProgress groups
50
+ const counts = { completed: 0, 'in-progress': 0, 'awaiting-approval': 0, paused: 0 };
51
+ for (const p of existing) {
52
+ const items = prdItems.filter(i => i.source === p.file);
53
+ const wiForPrd = allWi.filter(w => items.some(pi => pi.id === w.id));
54
+ const allDone = wiForPrd.length > 0 && wiForPrd.every(w => w.status === 'done' || w.status === 'in-pr' || w.status === 'implemented' || w.status === 'complete');
55
+ const hasActive = wiForPrd.some(w => w.status === 'pending' || w.status === 'dispatched');
56
+ const s = allDone && !hasActive ? 'completed' : hasActive ? 'in-progress' : p.status || 'active';
57
+ counts[s] = (counts[s] || 0) + 1;
42
58
  }
59
+ const parts = Object.entries(counts).filter(([, n]) => n > 0).map(([s, n]) =>
60
+ '<span style="font-size:10px;color:' + (statusColors[s] || 'var(--muted)') + '">' + n + ' ' + (statusLabels[s] || s).toLowerCase() + '</span>'
61
+ );
62
+ badge.innerHTML = '<span style="font-weight:600;font-size:11px;color:var(--text)">' + existing.length + ' PRDs</span> ' + parts.join(' · ');
43
63
  }
44
-
45
- badge.innerHTML = '<span style="font-weight:600;font-size:11px;color:' + (statusColors[effectiveStatus] || 'var(--muted)') + '">' + (statusLabels[effectiveStatus] || effectiveStatus) + '</span>' +
46
- ' <span style="color:var(--muted);font-size:10px">' + (prd.age || '') + '</span>' + actions;
47
64
  section.innerHTML = '';
48
65
  }
49
66
 
@@ -52,10 +69,10 @@ function renderPrdProgress(prog) {
52
69
  const countEl = document.getElementById('prd-progress-count');
53
70
  if (!prog) { el.innerHTML = ''; countEl.textContent = '—'; return; }
54
71
 
55
- // Compute progress from active (non-archived) items only
72
+ // Compute overall progress from active (non-archived) items
56
73
  const activeItems = (prog.items || []).filter(i => !i._archived);
57
74
  if (activeItems.length > 0) {
58
- const activeDone = activeItems.filter(i => i.status === 'done' || i.status === 'implemented' || i.status === 'in-pr').length; // in-pr counted as done for backward compat
75
+ const activeDone = activeItems.filter(i => i.status === 'done' || i.status === 'implemented' || i.status === 'in-pr').length;
59
76
  countEl.textContent = Math.round((activeDone / activeItems.length) * 100) + '%';
60
77
  } else {
61
78
  countEl.textContent = '—';
@@ -159,7 +176,7 @@ function renderPrdProgress(prog) {
159
176
  (prLinks ? '<span>' + prLinks + '</span>' : '') +
160
177
  '<span class="prd-item-priority ' + (i.priority || '') + '">' + escHtml(i.priority || '') + '</span>' +
161
178
  '<span onclick="event.stopPropagation();prdItemRemove(\'' + src + '\',\'' + iid + '\')" style="color:var(--red);cursor:pointer;font-size:10px;padding:0 4px" title="Remove item">x</span>' +
162
- (i.description ? '<div style="width:100%;font-size:11px;color:var(--muted);padding:2px 0 2px 42px;line-height:1.4">' + escHtml(i.description) + '</div>' : '') +
179
+ (i.description ? '<div style="width:100%;font-size:11px;color:var(--muted);padding:2px 0 2px 42px;line-height:1.4">' + renderMd(i.description) + '</div>' : '') +
163
180
  '</div>';
164
181
  };
165
182
 
@@ -220,6 +237,9 @@ function renderPrdProgress(prog) {
220
237
  : isCompleted
221
238
  ? '<span onclick="event.stopPropagation();triggerVerify(\'' + escHtml(g.file) + '\',this)" style="color:var(--green);cursor:pointer;font-size:9px;padding:1px 6px;background:rgba(63,185,80,0.1);border:1px solid rgba(63,185,80,0.3);border-radius:3px">Verify</span>'
222
239
  : '<span onclick="event.stopPropagation();planPause(\'' + escHtml(g.file) + '\',this)" style="color:var(--yellow);cursor:pointer;font-size:9px;padding:1px 6px;background:rgba(210,153,34,0.1);border:1px solid rgba(210,153,34,0.3);border-radius:3px">Pause</span>';
240
+ const archiveBtn = isCompleted
241
+ ? '<span onclick="event.stopPropagation();planDelete(\'' + escHtml(g.file) + '\')" style="color:var(--muted);cursor:pointer;font-size:9px;padding:1px 6px;background:var(--surface);border:1px solid var(--border);border-radius:3px">Archive</span>'
242
+ : '';
223
243
  const deleteBtn = '<span onclick="event.stopPropagation();planDelete(\'' + escHtml(g.file) + '\')" style="color:var(--red);cursor:pointer;font-size:9px;padding:1px 6px;background:rgba(248,81,73,0.1);border:1px solid rgba(248,81,73,0.3);border-radius:3px">Delete</span>';
224
244
  const sourcePlanLink = g.sourcePlan
225
245
  ? '<span onclick="event.stopPropagation();planView(\'' + escHtml(g.sourcePlan) + '\')" style="color:var(--blue);cursor:pointer;font-size:9px;padding:1px 6px;background:rgba(56,139,253,0.1);border:1px solid rgba(56,139,253,0.3);border-radius:3px" title="View source plan">&#x1F4C4; Plan</span>'
@@ -244,6 +264,7 @@ function renderPrdProgress(prog) {
244
264
  : '<span style="color:var(--muted);font-weight:400;font-size:10px;margin-left:auto;display:flex;align-items:center;gap:6px">' +
245
265
  sourcePlanLink +
246
266
  pauseResumeBtn +
267
+ archiveBtn +
247
268
  deleteBtn +
248
269
  '</span>') +
249
270
  staleRecovery +
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yemi33/minions",
3
- "version": "0.1.85",
3
+ "version": "0.1.86",
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"