@yemi33/minions 0.1.84 → 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 +10 -0
- package/dashboard/js/render-prd.js +50 -29
- package/dashboard.js +3 -3
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -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
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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
|
|
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;
|
|
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">' +
|
|
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">📄 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/dashboard.js
CHANGED
|
@@ -259,7 +259,7 @@ setInterval(() => {
|
|
|
259
259
|
// ── Command Center: session state + helpers ─────────────────────────────────
|
|
260
260
|
|
|
261
261
|
const CC_SESSION_EXPIRY_MS = 2 * 60 * 60 * 1000; // 2 hours
|
|
262
|
-
const CC_SESSION_MAX_TURNS =
|
|
262
|
+
const CC_SESSION_MAX_TURNS = Infinity;
|
|
263
263
|
let ccSession = { sessionId: null, createdAt: null, lastActiveAt: null, turnCount: 0 };
|
|
264
264
|
let ccInFlight = false;
|
|
265
265
|
let ccInFlightSince = 0; // timestamp — auto-release stuck guard
|
|
@@ -538,7 +538,7 @@ function updateSession(store, key, sessionId, existing) {
|
|
|
538
538
|
* @param {number} opts.maxTurns - Max tool-use turns
|
|
539
539
|
* @param {string} opts.allowedTools - Comma-separated tool list
|
|
540
540
|
*/
|
|
541
|
-
async function ccCall(message, { store = 'cc', sessionKey, extraContext, label = 'command-center', timeout = 900000, maxTurns =
|
|
541
|
+
async function ccCall(message, { store = 'cc', sessionKey, extraContext, label = 'command-center', timeout = 900000, maxTurns = 50, allowedTools = 'Bash,Read,Write,Edit,Glob,Grep,WebFetch,WebSearch', skipStatePreamble = false, model = 'sonnet' } = {}) {
|
|
542
542
|
const existing = resolveSession(store, sessionKey);
|
|
543
543
|
let sessionId = existing ? existing.sessionId : null;
|
|
544
544
|
|
|
@@ -623,7 +623,7 @@ async function ccDocCall({ message, document, title, filePath, selection, canEdi
|
|
|
623
623
|
store: 'doc', sessionKey: filePath || title,
|
|
624
624
|
extraContext: docContext, label: 'doc-chat',
|
|
625
625
|
timeout: isRich ? 300000 : 60000,
|
|
626
|
-
maxTurns: isRich ?
|
|
626
|
+
maxTurns: isRich ? 50 : 1,
|
|
627
627
|
model: isRich ? 'sonnet' : 'haiku',
|
|
628
628
|
allowedTools: isRich ? 'Read,Glob,Grep' : '',
|
|
629
629
|
skipStatePreamble: !isRich,
|
package/package.json
CHANGED