@yemi33/minions 0.1.2110 → 0.1.2111
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/command-center.js +36 -36
- package/dashboard/js/detail-panel.js +12 -12
- package/dashboard/js/fre.js +9 -9
- package/dashboard/js/live-stream.js +2 -2
- package/dashboard/js/modal-qa.js +17 -17
- package/dashboard/js/qa.js +3 -3
- package/dashboard/js/refresh.js +8 -8
- package/dashboard/js/render-agents.js +12 -12
- package/dashboard/js/render-dispatch.js +8 -8
- package/dashboard/js/render-inbox.js +5 -5
- package/dashboard/js/render-managed.js +16 -16
- package/dashboard/js/render-meetings.js +36 -36
- package/dashboard/js/render-other.js +23 -23
- package/dashboard/js/render-pinned.js +1 -1
- package/dashboard/js/render-pipelines.js +36 -36
- package/dashboard/js/render-plans.js +23 -23
- package/dashboard/js/render-prd.js +100 -100
- package/dashboard/js/render-prs.js +10 -10
- package/dashboard/js/render-schedules.js +23 -23
- package/dashboard/js/render-skills.js +7 -7
- package/dashboard/js/render-utils.js +22 -22
- package/dashboard/js/render-watches.js +37 -37
- package/dashboard/js/render-work-items.js +34 -34
- package/dashboard/js/utils.js +8 -8
- package/dashboard/layout.html +20 -20
- package/dashboard/pages/engine.html +4 -4
- package/dashboard/pages/home.html +4 -4
- package/dashboard/pages/inbox.html +3 -3
- package/dashboard/pages/meetings.html +2 -2
- package/dashboard/pages/pipelines.html +2 -2
- package/dashboard/pages/plans.html +3 -3
- package/dashboard/pages/prs.html +2 -2
- package/dashboard/pages/schedule.html +2 -2
- package/dashboard/pages/tools.html +1 -1
- package/dashboard/pages/watches.html +2 -2
- package/dashboard/pages/work.html +3 -3
- package/dashboard/styles.css +38 -38
- package/package.json +1 -1
|
@@ -45,7 +45,7 @@ async function _savePrdDesc(source, itemId) {
|
|
|
45
45
|
if (res.ok) {
|
|
46
46
|
_prdDescRawCache = newDesc;
|
|
47
47
|
// eslint-disable-next-line no-unsanitized/property -- reason: renderMd() escapes all user-controlled fields before assembling HTML (see dashboard/js/utils.js)
|
|
48
|
-
view.innerHTML = newDesc ? renderMd(newDesc) : '<span style="color:var(--muted);font-size:
|
|
48
|
+
view.innerHTML = newDesc ? renderMd(newDesc) : '<span style="color:var(--muted);font-size:var(--text-base)">No description</span>';
|
|
49
49
|
view.style.display = '';
|
|
50
50
|
editor.style.display = 'none';
|
|
51
51
|
document.getElementById('prd-desc-edit-btn').style.display = '';
|
|
@@ -105,21 +105,21 @@ function renderPrd(prd, prog) {
|
|
|
105
105
|
let actions = '';
|
|
106
106
|
if (prdFile && !headerStale) {
|
|
107
107
|
if (effectiveStatus === 'awaiting-approval') {
|
|
108
|
-
actions = ' <button class="pr-pager-btn" style="font-size:
|
|
108
|
+
actions = ' <button class="pr-pager-btn" style="font-size:var(--text-xs);padding:1px 6px;color:var(--green);border-color:var(--green);margin-left:4px" onclick="planApprove(\'' + escHtml(prdFile) + '\',this)">Approve</button>';
|
|
109
109
|
} else if (effectiveStatus === 'completed') {
|
|
110
110
|
const hasVerifyWi = allWi.some(w => w.itemType === 'verify' && w.sourcePlan === prdFile);
|
|
111
|
-
actions = (hasVerifyWi ? '' : ' <button class="pr-pager-btn" style="font-size:
|
|
112
|
-
' <button class="pr-pager-btn" style="font-size:
|
|
111
|
+
actions = (hasVerifyWi ? '' : ' <button class="pr-pager-btn" style="font-size:var(--text-xs);padding:1px 6px;color:var(--green);border-color:var(--green);margin-left:4px" onclick="triggerVerify(\'' + escHtml(prdFile) + '\',this)">Verify</button>') +
|
|
112
|
+
' <button class="pr-pager-btn" style="font-size:var(--text-xs);padding:1px 6px;margin-left:4px" onclick="planArchive(\'' + escHtml(prdFile) + '\',this)">Archive</button>';
|
|
113
113
|
} else if (effectiveStatus === 'dispatched') {
|
|
114
|
-
actions = ' <button class="pr-pager-btn" style="font-size:
|
|
114
|
+
actions = ' <button class="pr-pager-btn" style="font-size:var(--text-xs);padding:1px 6px;color:var(--yellow);border-color:var(--yellow);margin-left:4px" onclick="planPause(\'' + escHtml(prdFile) + '\',this)">Pause</button>';
|
|
115
115
|
} else if (effectiveStatus === 'paused') {
|
|
116
|
-
actions = ' <button class="pr-pager-btn" style="font-size:
|
|
117
|
-
' <button class="pr-pager-btn" style="font-size:
|
|
116
|
+
actions = ' <button class="pr-pager-btn" style="font-size:var(--text-xs);padding:1px 6px;color:var(--green);border-color:var(--green);margin-left:4px" onclick="planApprove(\'' + escHtml(prdFile) + '\',this)">Resume</button>' +
|
|
117
|
+
' <button class="pr-pager-btn" style="font-size:var(--text-xs);padding:1px 6px;margin-left:4px" onclick="planArchive(\'' + escHtml(prdFile) + '\',this)">Archive</button>';
|
|
118
118
|
}
|
|
119
119
|
}
|
|
120
120
|
// eslint-disable-next-line no-unsanitized/property -- reason: structural HTML is a string literal; all user data wrapped in escHtml() (fields: PRD file; status label/color and age text are derived UI state)
|
|
121
|
-
badge.innerHTML = '<span style="font-weight:600;font-size:
|
|
122
|
-
' <span style="color:var(--muted);font-size:
|
|
121
|
+
badge.innerHTML = '<span style="font-weight:600;font-size:var(--text-base);color:' + (statusColors[effectiveStatus] || 'var(--muted)') + '">' + (statusLabels[effectiveStatus] || effectiveStatus) + '</span>' +
|
|
122
|
+
' <span style="color:var(--muted);font-size:var(--text-sm)">' + (prd.age || '') + '</span>' + actions;
|
|
123
123
|
} else {
|
|
124
124
|
// Multiple PRDs — show count summary, per-PRD details are in renderPrdProgress groups
|
|
125
125
|
const counts = { completed: 0, 'dispatched': 0, 'awaiting-approval': 0, paused: 0 };
|
|
@@ -134,10 +134,10 @@ function renderPrd(prd, prog) {
|
|
|
134
134
|
counts[s] = (counts[s] || 0) + 1;
|
|
135
135
|
}
|
|
136
136
|
const parts = Object.entries(counts).filter(([, n]) => n > 0).map(([s, n]) =>
|
|
137
|
-
'<span style="font-size:
|
|
137
|
+
'<span style="font-size:var(--text-sm);color:' + (statusColors[s] || 'var(--muted)') + '">' + n + ' ' + (statusLabels[s] || s).toLowerCase() + '</span>'
|
|
138
138
|
);
|
|
139
139
|
// eslint-disable-next-line no-unsanitized/property -- reason: composed from compile-time constants (no user data flows in)
|
|
140
|
-
badge.innerHTML = '<span style="font-weight:600;font-size:
|
|
140
|
+
badge.innerHTML = '<span style="font-weight:600;font-size:var(--text-base);color:var(--text)">' + existing.length + ' PRDs</span> ' + parts.join(' · ');
|
|
141
141
|
}
|
|
142
142
|
section.innerHTML = '';
|
|
143
143
|
}
|
|
@@ -224,7 +224,7 @@ function renderPrdProgress(prog) {
|
|
|
224
224
|
const labels = { 'done': 'DONE', 'in-progress': 'WIP', 'failed': 'FAIL', 'paused': 'PAUSED', 'missing': '\u2014', 'updated': 'REDO' };
|
|
225
225
|
const style = styles[s] || 'background:var(--surface);color:var(--muted)';
|
|
226
226
|
const label = labels[s] || '—';
|
|
227
|
-
return '<span style="font-size:
|
|
227
|
+
return '<span style="font-size:var(--text-xs);font-weight:700;padding:2px 6px;border-radius:3px;letter-spacing:0.5px;white-space:nowrap;' + style + '">' + label + '</span>';
|
|
228
228
|
};
|
|
229
229
|
|
|
230
230
|
// Build work item lookup by actual work item ID.
|
|
@@ -258,13 +258,13 @@ function renderPrdProgress(prog) {
|
|
|
258
258
|
const wi = wiById[workItemId] || wiById[i.id];
|
|
259
259
|
const wiAgent = wi?.dispatched_to ? (agentData.find(a => a.id === wi.dispatched_to) || {}) : null;
|
|
260
260
|
const wiLabel = _renderPrdWorkItemIdBadge(wi ? wi.id : workItemId, i.id);
|
|
261
|
-
const agentLabel = wiAgent ? '<span style="font-size:
|
|
261
|
+
const agentLabel = wiAgent ? '<span style="font-size:var(--text-xs);color:var(--muted)" title="' + escHtml(wiAgent.name || wi.dispatched_to) + '">' +
|
|
262
262
|
(wiAgent.emoji || '') + ' ' + escHtml(wiAgent.name || wi.dispatched_to) + '</span>' : '';
|
|
263
263
|
|
|
264
264
|
// Branch label — show the target branch for this item
|
|
265
265
|
const wiBranch = wi ? (wi.branch || wi.featureBranch || (wi._artifacts && wi._artifacts.branch) || '') : '';
|
|
266
266
|
const branchLabel = wiBranch
|
|
267
|
-
? '<span style="font-size:
|
|
267
|
+
? '<span style="font-size:var(--text-xs);color:var(--muted);background:var(--surface);padding:1px 5px;border-radius:3px;border:1px solid var(--border);font-family:monospace;max-width:180px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:inline-block;vertical-align:middle" title="Branch: ' + escHtml(wiBranch) + '">🌿 ' + escHtml(wiBranch) + '</span>'
|
|
268
268
|
: '';
|
|
269
269
|
|
|
270
270
|
// Requeue button for failed items or PRD items with no work item (orphaned/deleted)
|
|
@@ -273,19 +273,19 @@ function renderPrdProgress(prog) {
|
|
|
273
273
|
const requeueState = getPrdRequeueState(wi ? wi.id : i.id);
|
|
274
274
|
let requeueBtn = '';
|
|
275
275
|
if (requeueState && requeueState.status === 'pending') {
|
|
276
|
-
requeueBtn = '<span style="color:var(--yellow);cursor:wait;font-size:
|
|
276
|
+
requeueBtn = '<span style="color:var(--yellow);cursor:wait;font-size:var(--text-xs);padding:1px 5px;background:rgba(210,153,34,0.1);border:1px solid rgba(210,153,34,0.35);border-radius:3px" title="Retry request in progress">requeuing…</span>';
|
|
277
277
|
} else if (requeueState && requeueState.status === 'queued') {
|
|
278
|
-
requeueBtn = '<span style="color:var(--green);cursor:default;font-size:
|
|
278
|
+
requeueBtn = '<span style="color:var(--green);cursor:default;font-size:var(--text-xs);padding:1px 5px;background:rgba(63,185,80,0.1);border:1px solid rgba(63,185,80,0.35);border-radius:3px" title="Successfully requeued">requeued</span>';
|
|
279
279
|
} else if (requeueState && requeueState.status === 'error') {
|
|
280
|
-
requeueBtn = '<span style="color:var(--red);cursor:default;font-size:
|
|
280
|
+
requeueBtn = '<span style="color:var(--red);cursor:default;font-size:var(--text-xs);padding:1px 5px;background:rgba(248,81,73,0.1);border:1px solid rgba(248,81,73,0.35);border-radius:3px" title="' + escHtml(requeueState.message || 'Retry failed') + '">retry failed</span>';
|
|
281
281
|
} else if (canRequeue) {
|
|
282
|
-
requeueBtn = '<span onclick="event.stopPropagation();prdItemRequeue(\'' + escHtml(wi ? wi.id : i.id) + '\',\'' + escHtml(wi ? (wi._source || '') : '') + '\',\'' + escHtml(i.source || '') + '\')" style="color:var(--green);cursor:pointer;font-size:
|
|
282
|
+
requeueBtn = '<span onclick="event.stopPropagation();prdItemRequeue(\'' + escHtml(wi ? wi.id : i.id) + '\',\'' + escHtml(wi ? (wi._source || '') : '') + '\',\'' + escHtml(i.source || '') + '\')" style="color:var(--green);cursor:pointer;font-size:var(--text-xs);padding:1px 5px;background:rgba(63,185,80,0.1);border:1px solid rgba(63,185,80,0.3);border-radius:3px" title="Requeue this work item">retry</span>';
|
|
283
283
|
}
|
|
284
284
|
|
|
285
285
|
// Re-open button for done items — sets PRD item to "updated" so engine re-dispatches
|
|
286
286
|
const isDone = i.status === 'done' || (wi && wi.status === 'done');
|
|
287
287
|
const reopenBtn = isDone
|
|
288
|
-
? '<span onclick="event.stopPropagation();prdItemReopen(\'' + escHtml(i.source || '') + '\',\'' + escHtml(i.id) + '\')" style="color:var(--blue);cursor:pointer;font-size:
|
|
288
|
+
? '<span onclick="event.stopPropagation();prdItemReopen(\'' + escHtml(i.source || '') + '\',\'' + escHtml(i.id) + '\')" style="color:var(--blue);cursor:pointer;font-size:var(--text-xs);padding:1px 5px;background:rgba(56,139,253,0.1);border:1px solid rgba(56,139,253,0.3);border-radius:3px" title="Re-open: set to updated so engine re-dispatches on existing branch">re-open</span>'
|
|
289
289
|
: '';
|
|
290
290
|
|
|
291
291
|
return '<div class="prd-item-row st-' + (i.status || 'missing') + '" style="flex-wrap:wrap;cursor:pointer" onclick="if(shouldIgnoreSelectionClick(event))return;prdItemEdit(\'' + src + '\',\'' + iid + '\')">' +
|
|
@@ -300,8 +300,8 @@ function renderPrdProgress(prog) {
|
|
|
300
300
|
(prLinks ? '<span>' + prLinks + '</span>' : '') +
|
|
301
301
|
branchLabel +
|
|
302
302
|
'<span class="prd-item-priority ' + (i.priority || '') + '">' + escHtml(i.priority || '') + '</span>' +
|
|
303
|
-
'<span onclick="event.stopPropagation();prdItemRemove(\'' + src + '\',\'' + iid + '\')" style="color:var(--red);cursor:pointer;font-size:
|
|
304
|
-
(i.description ? '<div style="width:100%;font-size:
|
|
303
|
+
'<span onclick="event.stopPropagation();prdItemRemove(\'' + src + '\',\'' + iid + '\')" style="color:var(--red);cursor:pointer;font-size:var(--text-sm);padding:0 4px" title="Remove item">x</span>' +
|
|
304
|
+
(i.description ? '<div style="width:100%;font-size:var(--text-base);color:var(--muted);padding:2px 0 2px 42px;line-height:1.4">' + renderMd(i.description) + '</div>' : '') +
|
|
305
305
|
// Show decomposed children inline
|
|
306
306
|
(i.status === 'decomposed' ? (function() {
|
|
307
307
|
const children = (window._lastWorkItems || []).filter(w => w.parent_id === i.id);
|
|
@@ -309,11 +309,11 @@ function renderPrdProgress(prog) {
|
|
|
309
309
|
return '<div style="width:100%;padding:4px 0 4px 42px;display:flex;flex-direction:column;gap:2px">' +
|
|
310
310
|
children.map(c => {
|
|
311
311
|
const childAgent = c.dispatched_to ? (agentData.find(a => a.id === c.dispatched_to) || {}) : null;
|
|
312
|
-
return '<div style="font-size:
|
|
312
|
+
return '<div style="font-size:var(--text-sm);display:flex;align-items:center;gap:6px;color:var(--text);padding:2px 6px;background:var(--surface);border-radius:4px;border:1px solid var(--border)">' +
|
|
313
313
|
statusBadge(c.status) +
|
|
314
|
-
'<span style="color:var(--muted);font-size:
|
|
314
|
+
'<span style="color:var(--muted);font-size:var(--text-xs)">' + escHtml(c.id) + '</span>' +
|
|
315
315
|
'<span style="flex:1">' + escHtml((c.title || '').replace('Implement: ', '').slice(0, 60)) + '</span>' +
|
|
316
|
-
(childAgent ? '<span style="font-size:
|
|
316
|
+
(childAgent ? '<span style="font-size:var(--text-xs);color:var(--muted)">' + (childAgent.emoji || '') + ' ' + escHtml(childAgent.name || c.dispatched_to) + '</span>' : '') +
|
|
317
317
|
'</div>';
|
|
318
318
|
}).join('') +
|
|
319
319
|
'</div>';
|
|
@@ -351,64 +351,64 @@ function renderPrdProgress(prog) {
|
|
|
351
351
|
const end = t.allDone && t.lastCompleted ? t.lastCompleted : isBlocked ? (t.lastCompleted || t.firstDispatched) : Date.now();
|
|
352
352
|
const elapsed = end - t.firstDispatched;
|
|
353
353
|
const icon = t.allDone ? '✓' : isBlocked ? '⏸' : '⏱';
|
|
354
|
-
runtimeLabel = '<span style="color:' + (t.allDone ? 'var(--green)' : isBlocked ? 'var(--muted)' : 'var(--yellow)') + ';font-weight:400;font-size:
|
|
354
|
+
runtimeLabel = '<span style="color:' + (t.allDone ? 'var(--green)' : isBlocked ? 'var(--muted)' : 'var(--yellow)') + ';font-weight:400;font-size:var(--text-sm)">' +
|
|
355
355
|
icon + ' ' + formatDuration(elapsed) + (t.allDone ? '' : isAwaitingApproval ? ' (awaiting approval)' : isPaused ? ' (paused)' : ' elapsed') + '</span>';
|
|
356
356
|
}
|
|
357
357
|
|
|
358
358
|
const pausedLabel = isAwaitingApproval
|
|
359
|
-
? '<span style="color:var(--yellow);font-weight:600;font-size:
|
|
359
|
+
? '<span style="color:var(--yellow);font-weight:600;font-size:var(--text-sm);padding:1px 6px;border:1px solid var(--yellow);border-radius:3px">AWAITING APPROVAL</span>'
|
|
360
360
|
: isPaused
|
|
361
|
-
? '<span style="color:var(--muted);font-weight:600;font-size:
|
|
361
|
+
? '<span style="color:var(--muted);font-weight:600;font-size:var(--text-sm);padding:1px 6px;border:1px solid var(--muted);border-radius:3px">PAUSED</span>'
|
|
362
362
|
: '';
|
|
363
363
|
const showStale = (!isBlocked || isPaused) && g.planStale;
|
|
364
364
|
const staleLabel = showStale
|
|
365
|
-
? '<span style="color:var(--orange);font-weight:700;font-size:
|
|
365
|
+
? '<span style="color:var(--orange);font-weight:700;font-size:var(--text-sm);padding:1px 6px;border:1px solid var(--orange);border-radius:3px;background:rgba(210,153,34,0.12)" title="Source plan changed after this PRD was generated">STALE</span>'
|
|
366
366
|
: '';
|
|
367
367
|
const staleRecovery = showStale
|
|
368
368
|
? '<div style="width:100%;margin-top:4px;padding:6px 8px;border:1px solid rgba(210,153,34,0.35);border-radius:4px;background:rgba(210,153,34,0.08);display:flex;align-items:center;gap:8px;flex-wrap:wrap">' +
|
|
369
|
-
'<span style="color:var(--orange);font-size:
|
|
370
|
-
'<span onclick="event.stopPropagation();prdRegenerate(\'' + escHtml(g.file) + '\')" style="color:var(--green);cursor:pointer;font-size:
|
|
371
|
-
'<span onclick="event.stopPropagation();prdResumeWithoutRegen(\'' + escHtml(g.file) + '\')" style="color:var(--muted);cursor:pointer;font-size:
|
|
372
|
-
'<span onclick="event.stopPropagation();planView(\'' + escHtml(g.sourcePlan || g.file) + '\')" style="color:var(--blue);cursor:pointer;font-size:
|
|
369
|
+
'<span style="color:var(--orange);font-size:var(--text-sm);font-weight:600">⚠️ Source plan was revised. This PRD may be outdated.</span>' +
|
|
370
|
+
'<span onclick="event.stopPropagation();prdRegenerate(\'' + escHtml(g.file) + '\')" style="color:var(--green);cursor:pointer;font-size:var(--text-sm);font-weight:700;padding:2px 8px;background:rgba(63,185,80,0.12);border:1px solid rgba(63,185,80,0.35);border-radius:4px" title="Compare revised plan against existing PRD and update items">Regenerate PRD</span>' +
|
|
371
|
+
'<span onclick="event.stopPropagation();prdResumeWithoutRegen(\'' + escHtml(g.file) + '\')" style="color:var(--muted);cursor:pointer;font-size:var(--text-sm);padding:2px 8px;background:var(--surface);border:1px solid var(--border);border-radius:4px" title="Resume without regenerating — use current PRD as-is">Resume as-is</span>' +
|
|
372
|
+
'<span onclick="event.stopPropagation();planView(\'' + escHtml(g.sourcePlan || g.file) + '\')" style="color:var(--blue);cursor:pointer;font-size:var(--text-sm);padding:2px 8px;background:rgba(56,139,253,0.1);border:1px solid rgba(56,139,253,0.3);border-radius:4px" title="Review latest plan changes">Review plan</span>' +
|
|
373
373
|
'</div>'
|
|
374
374
|
: '';
|
|
375
375
|
const isCompleted = done > 0 && done === g.items.length;
|
|
376
376
|
// Hide regular action buttons when stale banner is showing — stale banner has its own actions
|
|
377
377
|
const isStale = showStale;
|
|
378
378
|
const pauseResumeBtn = isStale ? '' : isAwaitingApproval
|
|
379
|
-
? '<span onclick="event.stopPropagation();planApprove(\'' + escHtml(g.file) + '\',this)" style="color:var(--green);cursor:pointer;font-size:
|
|
379
|
+
? '<span onclick="event.stopPropagation();planApprove(\'' + escHtml(g.file) + '\',this)" style="color:var(--green);cursor:pointer;font-size:var(--text-xs);padding:1px 6px;background:rgba(63,185,80,0.1);border:1px solid rgba(63,185,80,0.3);border-radius:3px">Approve</span>'
|
|
380
380
|
: isPaused
|
|
381
|
-
? '<span onclick="event.stopPropagation();planApprove(\'' + escHtml(g.file) + '\',this)" style="color:var(--green);cursor:pointer;font-size:
|
|
381
|
+
? '<span onclick="event.stopPropagation();planApprove(\'' + escHtml(g.file) + '\',this)" style="color:var(--green);cursor:pointer;font-size:var(--text-xs);padding:1px 6px;background:rgba(63,185,80,0.1);border:1px solid rgba(63,185,80,0.3);border-radius:3px">Resume</span>'
|
|
382
382
|
: isCompleted && !(window._lastWorkItems || []).some(w => w.itemType === 'verify' && w.sourcePlan === g.file)
|
|
383
|
-
? '<span onclick="event.stopPropagation();triggerVerify(\'' + escHtml(g.file) + '\',this)" style="color:var(--green);cursor:pointer;font-size:
|
|
384
|
-
: isCompleted ? '' : '<span onclick="event.stopPropagation();planPause(\'' + escHtml(g.file) + '\',this)" style="color:var(--yellow);cursor:pointer;font-size:
|
|
385
|
-
const archiveBtn = (!isStale && (isCompleted || isPaused)) ? '<span onclick="event.stopPropagation();planArchive(\'' + escHtml(g.file) + '\',this)" style="color:var(--muted);cursor:pointer;font-size:
|
|
386
|
-
const deleteBtn = '<span onclick="event.stopPropagation();planDelete(\'' + escHtml(g.file) + '\')" style="color:var(--red);cursor:pointer;font-size:
|
|
383
|
+
? '<span onclick="event.stopPropagation();triggerVerify(\'' + escHtml(g.file) + '\',this)" style="color:var(--green);cursor:pointer;font-size:var(--text-xs);padding:1px 6px;background:rgba(63,185,80,0.1);border:1px solid rgba(63,185,80,0.3);border-radius:3px">Verify</span>'
|
|
384
|
+
: isCompleted ? '' : '<span onclick="event.stopPropagation();planPause(\'' + escHtml(g.file) + '\',this)" style="color:var(--yellow);cursor:pointer;font-size:var(--text-xs);padding:1px 6px;background:rgba(210,153,34,0.1);border:1px solid rgba(210,153,34,0.3);border-radius:3px">Pause</span>';
|
|
385
|
+
const archiveBtn = (!isStale && (isCompleted || isPaused)) ? '<span onclick="event.stopPropagation();planArchive(\'' + escHtml(g.file) + '\',this)" style="color:var(--muted);cursor:pointer;font-size:var(--text-xs);padding:1px 6px;background:rgba(139,148,158,0.1);border:1px solid rgba(139,148,158,0.3);border-radius:3px">Archive</span>' : '';
|
|
386
|
+
const deleteBtn = '<span onclick="event.stopPropagation();planDelete(\'' + escHtml(g.file) + '\')" style="color:var(--red);cursor:pointer;font-size:var(--text-xs);padding:1px 6px;background:rgba(248,81,73,0.1);border:1px solid rgba(248,81,73,0.3);border-radius:3px">Delete</span>';
|
|
387
387
|
const sourcePlanLink = g.sourcePlan
|
|
388
|
-
? '<span onclick="event.stopPropagation();planView(\'' + escHtml(g.sourcePlan) + '\')" style="color:var(--blue);cursor:pointer;font-size:
|
|
388
|
+
? '<span onclick="event.stopPropagation();planView(\'' + escHtml(g.sourcePlan) + '\')" style="color:var(--blue);cursor:pointer;font-size:var(--text-xs);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>'
|
|
389
389
|
: '';
|
|
390
390
|
|
|
391
|
-
return '<div style="font-size:
|
|
391
|
+
return '<div style="font-size:var(--text-base);font-weight:600;color:var(--blue);margin-bottom:4px;padding:6px 8px;background:var(--surface2);border-radius:4px;display:flex;align-items:center;gap:8px;flex-wrap:wrap">' +
|
|
392
392
|
(g._projects.length > 0 ? g._projects.map(function(p) { return '<span class="prd-project-badge">' + escHtml(p) + '</span>'; }).join(' ') : '') +
|
|
393
393
|
'<span style="color:var(--text)">' + escHtml(summary || g.file) + '</span>' +
|
|
394
394
|
(g.branchStrategy === 'shared-branch'
|
|
395
|
-
? '<span style="font-size:
|
|
396
|
-
: '<span style="font-size:
|
|
395
|
+
? '<span style="font-size:var(--text-xs);padding:1px 5px;border-radius:3px;background:rgba(210,153,34,0.15);color:var(--yellow);font-weight:400" title="All items commit to a single shared feature branch">🌳 shared branch</span>'
|
|
396
|
+
: '<span style="font-size:var(--text-xs);padding:1px 5px;border-radius:3px;background:rgba(56,139,253,0.12);color:var(--blue);font-weight:400" title="Each item gets its own branch (work/P-xxx) and PR">🔀 parallel branches</span>') +
|
|
397
397
|
pausedLabel +
|
|
398
398
|
staleLabel +
|
|
399
|
-
'<span style="font-weight:700;font-size:
|
|
400
|
-
'<span style="color:var(--muted);font-weight:400;font-size:
|
|
399
|
+
'<span style="font-weight:700;font-size:var(--text-base);color:' + (done === g.items.length && g.items.length > 0 ? 'var(--green)' : 'var(--text)') + '">' + (g.items.length > 0 ? Math.round((done / g.items.length) * 100) : 0) + '%</span>' +
|
|
400
|
+
'<span style="color:var(--muted);font-weight:400;font-size:var(--text-sm)">' + g.items.length + ' items' +
|
|
401
401
|
(done ? ' · ' + done + ' done' : '') + (wip ? ' · ' + wip + ' active' : '') +
|
|
402
402
|
'</span>' +
|
|
403
|
-
(g.prdUpdatedAt ? '<span style="color:var(--muted);font-weight:400;font-size:
|
|
403
|
+
(g.prdUpdatedAt ? '<span style="color:var(--muted);font-weight:400;font-size:var(--text-sm)" title="PRD last updated: ' + g.prdUpdatedAt + '">PRD updated ' + timeAgo(g.prdUpdatedAt) + '</span>' : '') +
|
|
404
404
|
runtimeLabel +
|
|
405
405
|
(g.archived
|
|
406
|
-
? '<span style="color:var(--muted);font-weight:400;font-size:
|
|
406
|
+
? '<span style="color:var(--muted);font-weight:400;font-size:var(--text-sm);margin-left:auto;display:flex;align-items:center;gap:6px">' +
|
|
407
407
|
(g.sourcePlan
|
|
408
|
-
? '<span onclick="event.stopPropagation();planView(\'' + escHtml(g.sourcePlan) + '\')" style="color:var(--blue);cursor:pointer;font-size:
|
|
408
|
+
? '<span onclick="event.stopPropagation();planView(\'' + escHtml(g.sourcePlan) + '\')" style="color:var(--blue);cursor:pointer;font-size:var(--text-sm);text-decoration:underline" title="View source plan">📄 ' + escHtml(g.sourcePlan) + '</span>'
|
|
409
409
|
: '<span>' + escHtml(g.file) + '</span>') +
|
|
410
410
|
'</span>'
|
|
411
|
-
: '<span style="color:var(--muted);font-weight:400;font-size:
|
|
411
|
+
: '<span style="color:var(--muted);font-weight:400;font-size:var(--text-sm);margin-left:auto;display:flex;align-items:center;gap:6px">' +
|
|
412
412
|
sourcePlanLink +
|
|
413
413
|
pauseResumeBtn +
|
|
414
414
|
archiveBtn +
|
|
@@ -470,7 +470,7 @@ function renderPrdProgress(prog) {
|
|
|
470
470
|
const col = columns[d] || [];
|
|
471
471
|
const colLabel = d === 0 ? 'Root' : 'Wave ' + d;
|
|
472
472
|
html += '<div style="flex:1;min-width:0">' +
|
|
473
|
-
'<div style="font-size:
|
|
473
|
+
'<div style="font-size:var(--text-xs);color:var(--muted);text-transform:uppercase;letter-spacing:0.5px;margin-bottom:6px;text-align:center">' + colLabel + '</div>';
|
|
474
474
|
for (const i of col) {
|
|
475
475
|
const borderColor = statusColor(i.status, i.id);
|
|
476
476
|
const src = escHtml(i.source || '');
|
|
@@ -485,49 +485,49 @@ function renderPrdProgress(prog) {
|
|
|
485
485
|
const wiIdBadge = _renderPrdWorkItemIdBadge(wiForCard ? wiForCard.id : workItemId, i.id, '8px', '1px 4px');
|
|
486
486
|
const isDoneCard = i.status === 'done' || (wiForCard && wiForCard.status === 'done');
|
|
487
487
|
const reopenBtnGraph = isDoneCard
|
|
488
|
-
? '<span onclick="event.stopPropagation();prdItemReopen(\'' + src + '\',\'' + iid + '\')" style="font-size:
|
|
488
|
+
? '<span onclick="event.stopPropagation();prdItemReopen(\'' + src + '\',\'' + iid + '\')" style="font-size:var(--text-xs);color:var(--blue);cursor:pointer;padding:1px 4px;background:rgba(56,139,253,0.1);border:1px solid rgba(56,139,253,0.3);border-radius:3px" title="Re-open: set to updated so engine re-dispatches on existing branch">re-open</span>'
|
|
489
489
|
: '';
|
|
490
490
|
const cardTitle = i.description ? escHtml(i.name + ' — ' + i.description) : escHtml(i.name || '');
|
|
491
491
|
html += '<div onclick="prdItemEdit(\'' + src + '\',\'' + iid + '\')" ' +
|
|
492
492
|
'title="' + cardTitle + '" ' +
|
|
493
493
|
'style="background:var(--surface2);border:1px solid var(--border);border-left:3px solid ' + borderColor + ';' + wipAnim +
|
|
494
|
-
'border-radius:4px;padding:6px 8px;margin-bottom:6px;cursor:pointer;font-size:
|
|
494
|
+
'border-radius:4px;padding:6px 8px;margin-bottom:6px;cursor:pointer;font-size:var(--text-base)">' +
|
|
495
495
|
'<div style="display:flex;align-items:center;gap:4px;margin-bottom:2px">' +
|
|
496
496
|
statusBadge(i.status, i.id) +
|
|
497
497
|
'<span style="font-weight:600;color:var(--text)">' + escHtml(i.id) + '</span>' +
|
|
498
498
|
wiIdBadge +
|
|
499
|
-
'<span onclick="event.stopPropagation();prdItemRemove(\'' + src + '\',\'' + iid + '\')" style="margin-left:auto;color:var(--red);cursor:pointer;font-size:
|
|
499
|
+
'<span onclick="event.stopPropagation();prdItemRemove(\'' + src + '\',\'' + iid + '\')" style="margin-left:auto;color:var(--red);cursor:pointer;font-size:var(--text-sm);padding:0 4px;line-height:1" title="Remove item">x</span>' +
|
|
500
500
|
'</div>' +
|
|
501
|
-
'<div style="color:var(--text);font-size:
|
|
501
|
+
'<div style="color:var(--text);font-size:var(--text-base);line-height:1.3;margin-bottom:3px;overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical">' + escHtml(i.name) + '</div>' +
|
|
502
502
|
'<div style="display:flex;gap:4px;flex-wrap:wrap;align-items:center">' +
|
|
503
|
-
'<span class="prd-item-priority ' + (i.priority || '') + '" style="font-size:
|
|
504
|
-
(agentDisplay ? '<span style="font-size:
|
|
503
|
+
'<span class="prd-item-priority ' + (i.priority || '') + '" style="font-size:var(--text-xs);padding:1px 4px">' + escHtml(i.priority || '') + '</span>' +
|
|
504
|
+
(agentDisplay ? '<span style="font-size:var(--text-xs);color:var(--muted)">' + agentDisplay + '</span>' : '') +
|
|
505
505
|
(function() {
|
|
506
506
|
const w = wi[i.id];
|
|
507
507
|
const rqId = w ? w.id : i.id;
|
|
508
508
|
const rq = getPrdRequeueState(rqId);
|
|
509
509
|
if (rq && rq.status === 'pending') {
|
|
510
|
-
return '<span style="font-size:
|
|
510
|
+
return '<span style="font-size:var(--text-xs);color:var(--yellow);cursor:wait;padding:1px 4px;background:rgba(210,153,34,0.1);border:1px solid rgba(210,153,34,0.35);border-radius:3px">requeuing…</span>';
|
|
511
511
|
}
|
|
512
512
|
if (rq && rq.status === 'queued') {
|
|
513
|
-
return '<span style="font-size:
|
|
513
|
+
return '<span style="font-size:var(--text-xs);color:var(--green);cursor:default;padding:1px 4px;background:rgba(63,185,80,0.1);border:1px solid rgba(63,185,80,0.35);border-radius:3px">requeued</span>';
|
|
514
514
|
}
|
|
515
515
|
if (rq && rq.status === 'error') {
|
|
516
|
-
return '<span style="font-size:
|
|
516
|
+
return '<span style="font-size:var(--text-xs);color:var(--red);cursor:default;padding:1px 4px;background:rgba(248,81,73,0.1);border:1px solid rgba(248,81,73,0.35);border-radius:3px" title="' + escHtml(rq.message || 'Retry failed') + '">failed</span>';
|
|
517
517
|
}
|
|
518
518
|
// Show retry for failed items, or PRD items with no work item (orphaned/deleted)
|
|
519
519
|
const canRetry = (w && i.status === 'failed') ||
|
|
520
520
|
(!w && i.status && i.status !== 'missing' && i.status !== 'done' && i.status !== 'planned');
|
|
521
521
|
if (!canRetry) return '';
|
|
522
|
-
return '<span onclick="event.stopPropagation();prdItemRequeue(\'' + escHtml(rqId) + '\',\'' + escHtml(w ? (w._source || '') : '') + '\',\'' + escHtml(i.source || '') + '\')" style="font-size:
|
|
522
|
+
return '<span onclick="event.stopPropagation();prdItemRequeue(\'' + escHtml(rqId) + '\',\'' + escHtml(w ? (w._source || '') : '') + '\',\'' + escHtml(i.source || '') + '\')" style="font-size:var(--text-xs);color:var(--green);cursor:pointer;padding:1px 4px;background:rgba(63,185,80,0.1);border:1px solid rgba(63,185,80,0.3);border-radius:3px">retry</span>';
|
|
523
523
|
})() +
|
|
524
524
|
reopenBtnGraph +
|
|
525
|
-
(deps ? '<span style="font-size:
|
|
525
|
+
(deps ? '<span style="font-size:var(--text-xs);color:var(--muted)" title="Depends on: ' + escHtml(deps) + '">deps: ' + escHtml(deps) + '</span>' : '') +
|
|
526
526
|
(function() {
|
|
527
527
|
var w = wi[i.id];
|
|
528
528
|
var b = w ? (w.branch || w.featureBranch || (w._artifacts && w._artifacts.branch) || '') : '';
|
|
529
529
|
if (!b) return '';
|
|
530
|
-
return '<span style="font-size:
|
|
530
|
+
return '<span style="font-size:var(--text-xs);color:var(--muted);font-family:monospace;max-width:120px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:inline-block;vertical-align:middle" title="Branch: ' + escHtml(b) + '">🌿 ' + escHtml(b) + '</span>';
|
|
531
531
|
})() +
|
|
532
532
|
'</div>' +
|
|
533
533
|
((i.prs || []).length ? '<div style="margin-top:3px">' + (i.prs || []).map(function(pr) { return _renderPrLink(pr, { size: '9px' }); }).join(' ') + '</div>' : '') +
|
|
@@ -537,10 +537,10 @@ function renderPrdProgress(prog) {
|
|
|
537
537
|
return '<div style="margin-top:4px;border-top:1px solid var(--border);padding-top:4px">' +
|
|
538
538
|
children.map(function(c) {
|
|
539
539
|
var cAgent = c.dispatched_to ? (agentData.find(function(a) { return a.id === c.dispatched_to; }) || {}) : null;
|
|
540
|
-
return '<div style="font-size:
|
|
540
|
+
return '<div style="font-size:var(--text-xs);display:flex;align-items:center;gap:4px;padding:1px 0">' +
|
|
541
541
|
statusBadge(c.status) +
|
|
542
542
|
'<span style="flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap">' + escHtml((c.title || '').replace('Implement: ', '').slice(0, 40)) + '</span>' +
|
|
543
|
-
(cAgent ? '<span style="font-size:
|
|
543
|
+
(cAgent ? '<span style="font-size:var(--text-xs);color:var(--muted)">' + (cAgent.emoji || '') + '</span>' : '') +
|
|
544
544
|
'</div>';
|
|
545
545
|
}).join('') +
|
|
546
546
|
'</div>';
|
|
@@ -548,7 +548,7 @@ function renderPrdProgress(prog) {
|
|
|
548
548
|
'</div>';
|
|
549
549
|
}
|
|
550
550
|
html += '</div>';
|
|
551
|
-
if (d < maxDepth) html += '<div style="display:flex;align-items:center;color:var(--border);font-size:
|
|
551
|
+
if (d < maxDepth) html += '<div style="display:flex;align-items:center;color:var(--border);font-size:var(--text-xl);padding:0 2px">→</div>';
|
|
552
552
|
}
|
|
553
553
|
html += '</div>';
|
|
554
554
|
return html;
|
|
@@ -560,8 +560,8 @@ function renderPrdProgress(prog) {
|
|
|
560
560
|
const renderViewToggle = () => {
|
|
561
561
|
const isGraph = window._prdViewMode === 'graph';
|
|
562
562
|
return '<div style="display:flex;gap:4px;margin-bottom:8px;padding:0 8px">' +
|
|
563
|
-
'<button class="pr-pager-btn" style="font-size:
|
|
564
|
-
'<button class="pr-pager-btn" style="font-size:
|
|
563
|
+
'<button class="pr-pager-btn" style="font-size:var(--text-xs);padding:2px 8px;' + (isGraph ? 'background:var(--blue);color:#fff;border-color:var(--blue)' : '') + '" onclick="window._prdViewMode=\'graph\';rerenderPrdFromCache()">Graph</button>' +
|
|
564
|
+
'<button class="pr-pager-btn" style="font-size:var(--text-xs);padding:2px 8px;' + (!isGraph ? 'background:var(--blue);color:#fff;border-color:var(--blue)' : '') + '" onclick="window._prdViewMode=\'list\';rerenderPrdFromCache()">List</button>' +
|
|
565
565
|
'</div>';
|
|
566
566
|
};
|
|
567
567
|
|
|
@@ -597,22 +597,22 @@ function renderPrdProgress(prog) {
|
|
|
597
597
|
if (prs.length === 0 && !guide) return '';
|
|
598
598
|
let html = '<div style="margin:6px 0 10px;padding:6px 10px;background:rgba(56,139,253,0.08);border:1px solid rgba(56,139,253,0.25);border-radius:4px">';
|
|
599
599
|
if (prs.length > 0) {
|
|
600
|
-
html += '<div style="font-size:
|
|
600
|
+
html += '<div style="font-size:var(--text-sm);font-weight:600;color:var(--blue);margin-bottom:4px">E2E Aggregate PRs</div>';
|
|
601
601
|
html += prs.map(pr => {
|
|
602
602
|
const statusColor = pr.status === 'active' ? 'var(--green)' : pr.status === 'merged' ? 'var(--purple)' : 'var(--muted)';
|
|
603
|
-
return '<div style="display:flex;align-items:center;gap:6px;padding:2px 0;font-size:
|
|
604
|
-
'<span style="color:' + statusColor + ';font-size:
|
|
603
|
+
return '<div style="display:flex;align-items:center;gap:6px;padding:2px 0;font-size:var(--text-base)">' +
|
|
604
|
+
'<span style="color:' + statusColor + ';font-size:var(--text-xs);font-weight:600;padding:1px 4px;border:1px solid;border-radius:3px">' + escHtml(pr.status || 'active') + '</span>' +
|
|
605
605
|
'<a href="' + escHtml(pr.url || '#') + '" target="_blank" rel="noopener" style="color:var(--blue);text-decoration:underline;font-weight:500">' + escHtml(pr.id) + '</a>' +
|
|
606
606
|
'<span style="color:var(--text);flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap">' + escHtml(pr.title || '') + '</span>' +
|
|
607
|
-
'<span style="color:var(--muted);font-size:
|
|
607
|
+
'<span style="color:var(--muted);font-size:var(--text-xs)">' + escHtml(pr._project || '') + '</span>' +
|
|
608
608
|
'</div>';
|
|
609
609
|
}).join('');
|
|
610
610
|
}
|
|
611
611
|
if (guide) {
|
|
612
|
-
html += '<div style="display:flex;align-items:center;gap:6px;padding:' + (prs.length ? '4px' : '0') + ' 0 0;font-size:
|
|
613
|
-
'<span style="font-size:
|
|
612
|
+
html += '<div style="display:flex;align-items:center;gap:6px;padding:' + (prs.length ? '4px' : '0') + ' 0 0;font-size:var(--text-base)">' +
|
|
613
|
+
'<span style="font-size:var(--text-xs);color:var(--green);font-weight:600;padding:1px 4px;border:1px solid var(--green);border-radius:3px">GUIDE</span>' +
|
|
614
614
|
'<span onclick="openVerifyGuide(\'' + escHtml(guide.file) + '\')" style="color:var(--blue);cursor:pointer;text-decoration:underline;font-weight:500">Manual Testing Guide</span>' +
|
|
615
|
-
'<span style="color:var(--muted);font-size:
|
|
615
|
+
'<span style="color:var(--muted);font-size:var(--text-xs)">Build instructions, test steps, known issues</span>' +
|
|
616
616
|
'</div>';
|
|
617
617
|
}
|
|
618
618
|
html += '</div>';
|
|
@@ -647,7 +647,7 @@ function renderPrdProgress(prog) {
|
|
|
647
647
|
window._archivedPrdRenderGroupStats = renderGroupStats;
|
|
648
648
|
window._archivedPrdRenderE2eSection = renderE2eSection;
|
|
649
649
|
html += '<div style="margin-top:8px;text-align:right;position:relative" data-file="prd-archives">' +
|
|
650
|
-
'<button class="pr-pager-btn" style="font-size:
|
|
650
|
+
'<button class="pr-pager-btn" style="font-size:var(--text-sm);padding:3px 10px;color:var(--muted)" onclick="openArchivedPrdModal()">' +
|
|
651
651
|
'View Archives (' + archivedKeys.length + ')' +
|
|
652
652
|
'</button>' +
|
|
653
653
|
'</div>';
|
|
@@ -678,13 +678,13 @@ function openArchivedPrdModal() {
|
|
|
678
678
|
return;
|
|
679
679
|
} else {
|
|
680
680
|
// Picker: list archived plans, click to expand
|
|
681
|
-
html = '<div style="margin-bottom:12px;font-size:
|
|
681
|
+
html = '<div style="margin-bottom:12px;font-size:var(--text-md);color:var(--muted)">Select an archived PRD to view:</div>';
|
|
682
682
|
html += groups.map((g, i) => {
|
|
683
683
|
const done = g.items.filter(it => it.status === 'done').length;
|
|
684
684
|
const failed = g.items.filter(it => it.status === 'failed').length;
|
|
685
685
|
const completed = g.completedAt ? formatLocalDate(g.completedAt) : '';
|
|
686
686
|
return '<div class="plan-card" style="cursor:pointer;margin-bottom:8px" onclick="if(shouldIgnoreSelectionClick(event))return;showArchivedPrdDetail(\'' + escHtml(g.file) + '\')">' +
|
|
687
|
-
'<div class="plan-card-title" style="font-size:
|
|
687
|
+
'<div class="plan-card-title" style="font-size:var(--text-lg)">' + escHtml(g.summary || g.file) + '</div>' +
|
|
688
688
|
'<div class="plan-card-meta">' +
|
|
689
689
|
(g._projects.length > 0 ? g._projects.map(function(p) { return '<span>' + escHtml(p) + '</span>'; }).join(' ') : '') +
|
|
690
690
|
'<span>' + g.items.length + ' items</span>' +
|
|
@@ -713,11 +713,11 @@ function showArchivedPrdDetail(idxOrFile) {
|
|
|
713
713
|
// View mode toggle for archived
|
|
714
714
|
const isGraph = window._archivedPrdViewMode !== 'list';
|
|
715
715
|
const toggleHtml = '<div style="display:flex;gap:4px;margin-bottom:8px">' +
|
|
716
|
-
'<button class="pr-pager-btn" style="font-size:
|
|
717
|
-
'<button class="pr-pager-btn" style="font-size:
|
|
718
|
-
'<button class="pr-pager-btn" style="font-size:
|
|
719
|
-
'<button class="pr-pager-btn" style="font-size:
|
|
720
|
-
'<button class="pr-pager-btn" style="font-size:
|
|
716
|
+
'<button class="pr-pager-btn" style="font-size:var(--text-xs);padding:2px 8px;' + (isGraph ? 'background:var(--blue);color:#fff;border-color:var(--blue)' : '') + '" onclick="window._archivedPrdViewMode=\'graph\';showArchivedPrdDetail(\'' + escHtml(g.file) + '\')">Graph</button>' +
|
|
717
|
+
'<button class="pr-pager-btn" style="font-size:var(--text-xs);padding:2px 8px;' + (!isGraph ? 'background:var(--blue);color:#fff;border-color:var(--blue)' : '') + '" onclick="window._archivedPrdViewMode=\'list\';showArchivedPrdDetail(\'' + escHtml(g.file) + '\')">List</button>' +
|
|
718
|
+
'<button class="pr-pager-btn" style="font-size:var(--text-xs);padding:2px 8px;color:var(--green);margin-left:auto" onclick="triggerVerify(\'' + escHtml(g.file) + '\')">Trigger Verify</button>' +
|
|
719
|
+
'<button class="pr-pager-btn" style="font-size:var(--text-xs);padding:2px 8px" onclick="planUnarchive(\'' + escHtml(g.file) + '\',this)">Unarchive</button>' +
|
|
720
|
+
'<button class="pr-pager-btn" style="font-size:var(--text-xs);padding:2px 8px" onclick="openArchivedPrdModal()">Back</button>' +
|
|
721
721
|
'</div>';
|
|
722
722
|
|
|
723
723
|
// Render directly from the archived group data (not from stale renderGroup closure)
|
|
@@ -777,7 +777,7 @@ async function prdItemEdit(source, itemId) {
|
|
|
777
777
|
}
|
|
778
778
|
typeValue = (typeValue || '').toString().toLowerCase();
|
|
779
779
|
const typePillHtml = typeValue
|
|
780
|
-
? '<span style="font-size:
|
|
780
|
+
? '<span style="font-size:var(--text-sm);font-weight:600;padding:2px 6px;border-radius:3px;background:var(--surface-alt,var(--surface));border:1px solid var(--border);color:var(--muted);text-transform:lowercase">' + escHtml(typeValue) + '</span>'
|
|
781
781
|
: '';
|
|
782
782
|
|
|
783
783
|
// Build completion summary section
|
|
@@ -799,14 +799,14 @@ async function prdItemEdit(source, itemId) {
|
|
|
799
799
|
|
|
800
800
|
completionHtml = '<div style="background:var(--surface);border:1px solid var(--border);border-left:3px solid ' + statusColor + ';border-radius:4px;padding:10px 12px;margin-bottom:12px">' +
|
|
801
801
|
'<div style="display:flex;align-items:center;gap:8px;margin-bottom:6px">' +
|
|
802
|
-
(wi ? '<a href="#" onclick="event.preventDefault();event.stopPropagation();openWorkItemDetail(\'' + escHtml(wi.id) + '\')" title="Open ' + escHtml(wi.id) + ' detail" style="font-size:
|
|
802
|
+
(wi ? '<a href="#" onclick="event.preventDefault();event.stopPropagation();openWorkItemDetail(\'' + escHtml(wi.id) + '\')" title="Open ' + escHtml(wi.id) + ' detail" style="font-size:var(--text-base);font-weight:700;color:' + statusColor + ';text-decoration:none;cursor:pointer" onmouseover="this.style.textDecoration=\'underline\'" onmouseout="this.style.textDecoration=\'none\'">' + statusLabel + ' →</a>' : '<span style="font-size:var(--text-base);font-weight:700;color:' + statusColor + '">' + statusLabel + '</span>') +
|
|
803
803
|
typePillHtml +
|
|
804
|
-
(agent ? '<span style="font-size:
|
|
805
|
-
(completedAt ? '<span style="font-size:
|
|
804
|
+
(agent ? '<span style="font-size:var(--text-base);color:var(--muted)">by ' + escHtml(agent) + '</span>' : '') +
|
|
805
|
+
(completedAt ? '<span style="font-size:var(--text-sm);color:var(--muted)">' + escHtml(completedAt.slice(0, 16).replace('T', ' ')) + '</span>' : '') +
|
|
806
806
|
'</div>' +
|
|
807
|
-
(prLinks ? '<div style="font-size:
|
|
808
|
-
(summary ? '<div style="font-size:
|
|
809
|
-
(isFailed && completedEntry?.reason ? '<div style="font-size:
|
|
807
|
+
(prLinks ? '<div style="font-size:var(--text-base);margin-bottom:6px">PR: ' + prLinks + '</div>' : '') +
|
|
808
|
+
(summary ? '<div style="font-size:var(--text-md);color:var(--text);line-height:1.5;white-space:pre-wrap;max-height:300px;overflow-y:auto">' + escHtml(summary) + '</div>' : '') +
|
|
809
|
+
(isFailed && completedEntry?.reason ? '<div style="font-size:var(--text-base);color:var(--red);margin-top:4px">' + escHtml(completedEntry.reason) + '</div>' : '') +
|
|
810
810
|
'</div>';
|
|
811
811
|
}
|
|
812
812
|
|
|
@@ -817,26 +817,26 @@ async function prdItemEdit(source, itemId) {
|
|
|
817
817
|
const html = '<div style="padding:8px 0">' +
|
|
818
818
|
completionHtml +
|
|
819
819
|
standaloneTypePillHtml +
|
|
820
|
-
'<label style="font-size:
|
|
821
|
-
'<input id="prd-edit-name" value="' + escHtml(item.name || '') + '" style="width:100%;padding:6px 10px;background:var(--surface);border:1px solid var(--border);border-radius:4px;color:var(--text);font-size:
|
|
820
|
+
'<label style="font-size:var(--text-base);color:var(--muted);display:block;margin-bottom:4px">Name</label>' +
|
|
821
|
+
'<input id="prd-edit-name" value="' + escHtml(item.name || '') + '" style="width:100%;padding:6px 10px;background:var(--surface);border:1px solid var(--border);border-radius:4px;color:var(--text);font-size:var(--text-lg);margin-bottom:10px">' +
|
|
822
822
|
'<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:4px">' +
|
|
823
|
-
'<label style="font-size:
|
|
823
|
+
'<label style="font-size:var(--text-base);color:var(--muted)">Description</label>' +
|
|
824
824
|
'<div style="display:flex;gap:6px">' +
|
|
825
|
-
'<button id="prd-desc-edit-btn" type="button" class="pr-pager-btn" aria-label="Edit description" style="font-size:
|
|
826
|
-
'<button id="prd-desc-save-btn" type="button" class="pr-pager-btn" aria-label="Save description" style="font-size:
|
|
827
|
-
'<button id="prd-desc-cancel-btn" type="button" class="pr-pager-btn" aria-label="Cancel description edit" style="font-size:
|
|
825
|
+
'<button id="prd-desc-edit-btn" type="button" class="pr-pager-btn" aria-label="Edit description" style="font-size:var(--text-sm);padding:2px 10px" onclick="_togglePrdDescEdit()">Edit</button>' +
|
|
826
|
+
'<button id="prd-desc-save-btn" type="button" class="pr-pager-btn" aria-label="Save description" style="font-size:var(--text-sm);padding:2px 10px;color:var(--green);border-color:var(--green);display:none" onclick="_savePrdDesc(\'' + escHtml(source) + '\',\'' + escHtml(itemId) + '\')">Save</button>' +
|
|
827
|
+
'<button id="prd-desc-cancel-btn" type="button" class="pr-pager-btn" aria-label="Cancel description edit" style="font-size:var(--text-sm);padding:2px 10px;display:none" onclick="_cancelPrdDescEdit()">Cancel</button>' +
|
|
828
828
|
'</div>' +
|
|
829
829
|
'</div>' +
|
|
830
|
-
'<div id="prd-desc-view" style="margin-bottom:10px;padding:8px 10px;background:var(--surface);border:1px solid var(--border);border-radius:4px;min-height:32px">' + (item.description ? renderMd(item.description) : '<span style="color:var(--muted);font-size:
|
|
831
|
-
'<textarea id="prd-edit-desc" rows="4" style="display:none;width:100%;padding:6px 10px;background:var(--surface);border:1px solid var(--border);border-radius:4px;color:var(--text);font-size:
|
|
830
|
+
'<div id="prd-desc-view" style="margin-bottom:10px;padding:8px 10px;background:var(--surface);border:1px solid var(--border);border-radius:4px;min-height:32px">' + (item.description ? renderMd(item.description) : '<span style="color:var(--muted);font-size:var(--text-base)">No description</span>') + '</div>' +
|
|
831
|
+
'<textarea id="prd-edit-desc" rows="4" style="display:none;width:100%;padding:6px 10px;background:var(--surface);border:1px solid var(--border);border-radius:4px;color:var(--text);font-size:var(--text-md);resize:vertical;margin-bottom:10px">' + escHtml(item.description || '') + '</textarea>' +
|
|
832
832
|
'<div style="display:flex;gap:12px;margin-bottom:12px">' +
|
|
833
|
-
'<div><label style="font-size:
|
|
833
|
+
'<div><label style="font-size:var(--text-base);color:var(--muted);display:block;margin-bottom:4px">Priority</label>' +
|
|
834
834
|
'<select id="prd-edit-priority" style="padding:4px 8px;background:var(--surface);border:1px solid var(--border);border-radius:4px;color:var(--text)">' +
|
|
835
835
|
'<option value="high"' + (item.priority === 'high' ? ' selected' : '') + '>High</option>' +
|
|
836
836
|
'<option value="medium"' + (item.priority === 'medium' ? ' selected' : '') + '>Medium</option>' +
|
|
837
837
|
'<option value="low"' + (item.priority === 'low' ? ' selected' : '') + '>Low</option>' +
|
|
838
838
|
'</select></div>' +
|
|
839
|
-
'<div><label style="font-size:
|
|
839
|
+
'<div><label style="font-size:var(--text-base);color:var(--muted);display:block;margin-bottom:4px">Complexity</label>' +
|
|
840
840
|
'<select id="prd-edit-complexity" style="padding:4px 8px;background:var(--surface);border:1px solid var(--border);border-radius:4px;color:var(--text)">' +
|
|
841
841
|
'<option value="small"' + ((item.estimated_complexity || item.complexity) === 'small' ? ' selected' : '') + '>Small</option>' +
|
|
842
842
|
'<option value="medium"' + ((item.estimated_complexity || item.complexity) === 'medium' ? ' selected' : '') + '>Medium</option>' +
|
|
@@ -983,7 +983,7 @@ function openArchive(i) {
|
|
|
983
983
|
|
|
984
984
|
// Summary
|
|
985
985
|
if (a.summary) {
|
|
986
|
-
html += '<div class="archive-detail-section"><h4>Summary</h4><p style="font-size:
|
|
986
|
+
html += '<div class="archive-detail-section"><h4>Summary</h4><p style="font-size:var(--text-md);color:var(--muted);line-height:1.6">' + escHtml(a.summary) + '</p></div>';
|
|
987
987
|
}
|
|
988
988
|
|
|
989
989
|
// Existing features
|
|
@@ -1011,7 +1011,7 @@ function openArchive(i) {
|
|
|
1011
1011
|
html += '<div class="archive-feature">' +
|
|
1012
1012
|
'<span class="feat-id">' + escHtml(f.id) + '</span> ' +
|
|
1013
1013
|
'<span class="prd-item-priority ' + pClass + '">' + escHtml(f.priority || '') + '</span>' +
|
|
1014
|
-
(f.status ? ' <span class="pr-badge ' + (f.status === 'done' ? 'approved' : 'draft') + '" style="font-size:
|
|
1014
|
+
(f.status ? ' <span class="pr-badge ' + (f.status === 'done' ? 'approved' : 'draft') + '" style="font-size:var(--text-xs)">' + escHtml(f.status) + '</span>' : '') +
|
|
1015
1015
|
'<div class="feat-name">' + escHtml(f.name) + '</div>' +
|
|
1016
1016
|
'<div class="feat-desc">' + escHtml(f.description || '') + '</div>' +
|
|
1017
1017
|
(f.rationale ? '<div class="feat-desc" style="margin-top:4px;color:var(--yellow)">Rationale: ' + escHtml(f.rationale) + '</div>' : '') +
|