@yemi33/minions 0.1.2109 → 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/docs/onboarding.md +2 -2
- package/engine.js +52 -6
- package/package.json +1 -1
|
@@ -172,25 +172,25 @@ function renderWatches(watchesData, opts) {
|
|
|
172
172
|
'<td><span class="pr-id">' + escHtml(w.id) + '</span></td>' +
|
|
173
173
|
'<td style="max-width:180px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap" title="' + escHtml(w.description || w.target) + '">' + escHtml(w.target) + '</td>' +
|
|
174
174
|
'<td><span class="dispatch-type explore">' + escHtml(targetLabel) + '</span></td>' +
|
|
175
|
-
'<td><span style="font-size:
|
|
176
|
-
'<td><span style="font-size:
|
|
177
|
-
'<td><span style="font-size:
|
|
175
|
+
'<td><span style="font-size:var(--text-base);color:var(--blue)">' + escHtml(condLabel) + '</span></td>' +
|
|
176
|
+
'<td><span style="font-size:var(--text-sm)">' + actionLabel + '</span></td>' +
|
|
177
|
+
'<td><span style="font-size:var(--text-sm);color:var(--muted)">' + escHtml(_intervalToHuman(w.interval)) + '</span></td>' +
|
|
178
178
|
'<td><span class="pr-agent">' + escHtml(w.owner || 'human') + '</span></td>' +
|
|
179
179
|
'<td>' + statusBadge + '</td>' +
|
|
180
|
-
'<td title="Last triggered: ' + escHtml(lastTriggered) + '"><span style="font-size:
|
|
180
|
+
'<td title="Last triggered: ' + escHtml(lastTriggered) + '"><span style="font-size:var(--text-base)">' + escHtml(triggerInfo) + '</span></td>' +
|
|
181
181
|
'<td><span class="pr-date">' + escHtml(lastChecked) + '</span></td>' +
|
|
182
182
|
'<td style="white-space:nowrap">';
|
|
183
183
|
|
|
184
184
|
// Pause/Resume button (F7: marks as `disabled` while POST in flight)
|
|
185
185
|
var pauseBusyCls = _watchToggleInFlight.has(w.id) ? ' disabled' : '';
|
|
186
186
|
if (w.status === 'active') {
|
|
187
|
-
html += '<button class="pr-pager-btn' + pauseBusyCls + '" style="font-size:
|
|
187
|
+
html += '<button class="pr-pager-btn' + pauseBusyCls + '" style="font-size:var(--text-xs);padding:1px 6px;color:var(--yellow);border-color:var(--yellow);margin-right:4px" onclick="event.stopPropagation();toggleWatchPause(\'' + escHtml(w.id) + '\',true)" title="Pause">⏸</button>';
|
|
188
188
|
} else if (w.status === 'paused') {
|
|
189
|
-
html += '<button class="pr-pager-btn' + pauseBusyCls + '" style="font-size:
|
|
189
|
+
html += '<button class="pr-pager-btn' + pauseBusyCls + '" style="font-size:var(--text-xs);padding:1px 6px;color:var(--green);border-color:var(--green);margin-right:4px" onclick="event.stopPropagation();toggleWatchPause(\'' + escHtml(w.id) + '\',false)" title="Resume">▶</button>';
|
|
190
190
|
}
|
|
191
191
|
|
|
192
192
|
// Delete button
|
|
193
|
-
html += '<button class="pr-pager-btn" style="font-size:
|
|
193
|
+
html += '<button class="pr-pager-btn" style="font-size:var(--text-xs);padding:1px 6px;color:var(--red);border-color:var(--red)" onclick="event.stopPropagation();deleteWatch(\'' + escHtml(w.id) + '\')" title="Delete">✕</button>';
|
|
194
194
|
html += '</td></tr>';
|
|
195
195
|
}
|
|
196
196
|
|
|
@@ -226,18 +226,18 @@ function _renderWatchActionDetail(action) {
|
|
|
226
226
|
if (action.length === 0) return '';
|
|
227
227
|
var stepHtml = action.map(function(step, i) {
|
|
228
228
|
return '<div style="margin-top:4px;padding:8px;background:var(--surface2);border-radius:4px">' +
|
|
229
|
-
'<div style="font-size:
|
|
230
|
-
'<div style="font-size:
|
|
231
|
-
(step && step.guard && step.guard.expr ? '<div style="font-size:
|
|
232
|
-
(step && step.params && Object.keys(step.params).length ? '<div style="margin-top:4px;font-size:
|
|
229
|
+
'<div style="font-size:var(--text-base);color:var(--muted)">Step ' + (i + 1) + '</div>' +
|
|
230
|
+
'<div style="font-size:var(--text-md)"><strong>Type:</strong> <span class="dispatch-type explore">' + escHtml(step && step.type ? step.type : '?') + '</span></div>' +
|
|
231
|
+
(step && step.guard && step.guard.expr ? '<div style="font-size:var(--text-base);margin-top:2px"><strong>Guard:</strong> <code>' + escHtml(step.guard.expr) + '</code></div>' : '') +
|
|
232
|
+
(step && step.params && Object.keys(step.params).length ? '<div style="margin-top:4px;font-size:var(--text-base);font-family:monospace;white-space:pre-wrap">' + escHtml(JSON.stringify(step.params, null, 2)) + '</div>' : '') +
|
|
233
233
|
'</div>';
|
|
234
234
|
}).join('');
|
|
235
235
|
return '<div><strong style="color:var(--muted)">Follow-up Action Chain (' + action.length + ' step' + (action.length === 1 ? '' : 's') + '):</strong>' + stepHtml + '</div>';
|
|
236
236
|
}
|
|
237
237
|
if (action.type) {
|
|
238
238
|
return '<div><strong style="color:var(--muted)">Follow-up Action:</strong> <span class="dispatch-type explore">' + escHtml(action.type) + '</span>' +
|
|
239
|
-
(action.guard && action.guard.expr ? '<div style="font-size:
|
|
240
|
-
(action.params && Object.keys(action.params).length ? '<div style="margin-top:4px;padding:8px;background:var(--surface2);border-radius:4px;font-size:
|
|
239
|
+
(action.guard && action.guard.expr ? '<div style="font-size:var(--text-base);margin-top:2px"><strong>Guard:</strong> <code>' + escHtml(action.guard.expr) + '</code></div>' : '') +
|
|
240
|
+
(action.params && Object.keys(action.params).length ? '<div style="margin-top:4px;padding:8px;background:var(--surface2);border-radius:4px;font-size:var(--text-base);font-family:monospace;white-space:pre-wrap">' + escHtml(JSON.stringify(action.params, null, 2)) + '</div>' : '') +
|
|
241
241
|
'</div>';
|
|
242
242
|
}
|
|
243
243
|
return '';
|
|
@@ -248,7 +248,7 @@ function _renderWatchActionDetail(action) {
|
|
|
248
248
|
function _renderWatchRequiresDetail(requires) {
|
|
249
249
|
if (!Array.isArray(requires) || requires.length === 0) return '';
|
|
250
250
|
var rows = requires.map(function(r, i) {
|
|
251
|
-
return '<div style="margin-top:4px;padding:6px 8px;background:var(--surface2);border-radius:4px;font-size:
|
|
251
|
+
return '<div style="margin-top:4px;padding:6px 8px;background:var(--surface2);border-radius:4px;font-size:var(--text-base)">' +
|
|
252
252
|
'<span style="color:var(--muted)">[' + (i + 1) + ']</span> ' +
|
|
253
253
|
escHtml(r && r.target ? r.target : '?') +
|
|
254
254
|
' <span class="dispatch-type explore">' + escHtml(r && r.targetType ? r.targetType : '?') + '</span>' +
|
|
@@ -267,7 +267,7 @@ function _renderWatchRequiresDetail(requires) {
|
|
|
267
267
|
// watches that were created before Phase 6.2 don't show a half-empty table.
|
|
268
268
|
function _renderWatchHistoryDetail(history) {
|
|
269
269
|
if (!Array.isArray(history) || history.length === 0) {
|
|
270
|
-
return '<div style="color:var(--muted);font-style:italic;font-size:
|
|
270
|
+
return '<div style="color:var(--muted);font-style:italic;font-size:var(--text-base)">no history yet — watch has not been checked, or pre-dates the history feature</div>';
|
|
271
271
|
}
|
|
272
272
|
// Render newest-first for readability — the engine stores oldest-first.
|
|
273
273
|
var entries = history.slice().reverse();
|
|
@@ -285,7 +285,7 @@ function _renderWatchHistoryDetail(history) {
|
|
|
285
285
|
'</tr>';
|
|
286
286
|
}).join('');
|
|
287
287
|
return '<div><strong style="color:var(--muted)">Evaluation History (' + history.length + ' check' + (history.length === 1 ? '' : 's') + ', newest first):</strong>' +
|
|
288
|
-
'<table style="margin-top:4px;font-size:
|
|
288
|
+
'<table style="margin-top:4px;font-size:var(--text-base);border-collapse:collapse;width:100%"><tbody>' + rows + '</tbody></table>' +
|
|
289
289
|
'</div>';
|
|
290
290
|
}
|
|
291
291
|
|
|
@@ -302,12 +302,12 @@ function openWatchDetail(id) {
|
|
|
302
302
|
// eslint-disable-next-line no-unsanitized/property -- reason: structural HTML is a string literal; all user data wrapped in escHtml() (fields: watch description/target/id)
|
|
303
303
|
document.getElementById('modal-title').innerHTML = escHtml(w.description || w.target) +
|
|
304
304
|
' <div style="display:flex;gap:4px;margin-top:4px">' +
|
|
305
|
-
(w.status === 'active' ? '<button class="pr-pager-btn" style="font-size:
|
|
306
|
-
(w.status === 'paused' ? '<button class="pr-pager-btn" style="font-size:
|
|
307
|
-
'<button class="pr-pager-btn" style="font-size:
|
|
305
|
+
(w.status === 'active' ? '<button class="pr-pager-btn" style="font-size:var(--text-sm);padding:2px 10px;color:var(--yellow)" onclick="toggleWatchPause(\'' + escHtml(w.id) + '\',true);closeModal()">Pause</button>' : '') +
|
|
306
|
+
(w.status === 'paused' ? '<button class="pr-pager-btn" style="font-size:var(--text-sm);padding:2px 10px;color:var(--green)" onclick="toggleWatchPause(\'' + escHtml(w.id) + '\',false);closeModal()">Resume</button>' : '') +
|
|
307
|
+
'<button class="pr-pager-btn" style="font-size:var(--text-sm);padding:2px 10px;color:var(--red)" onclick="deleteWatch(\'' + escHtml(w.id) + '\');closeModal()">Delete</button>' +
|
|
308
308
|
'</div>';
|
|
309
309
|
|
|
310
|
-
var body = '<div style="display:flex;flex-direction:column;gap:10px;font-size:
|
|
310
|
+
var body = '<div style="display:flex;flex-direction:column;gap:10px;font-size:var(--text-md);line-height:1.6">' +
|
|
311
311
|
'<div><strong style="color:var(--muted)">ID:</strong> ' + escHtml(w.id) + '</div>' +
|
|
312
312
|
'<div><strong style="color:var(--muted)">Target:</strong> ' + escHtml(w.target) + '</div>' +
|
|
313
313
|
'<div><strong style="color:var(--muted)">Target Type:</strong> <span class="dispatch-type explore">' + escHtml(targetLabel) + '</span></div>' +
|
|
@@ -330,14 +330,14 @@ function openWatchDetail(id) {
|
|
|
330
330
|
'<div><strong style="color:var(--muted)">Created:</strong> ' + escHtml(createdAt) + '</div>' +
|
|
331
331
|
'<div><strong style="color:var(--muted)">Last Checked:</strong> ' + escHtml(lastChecked) + '</div>' +
|
|
332
332
|
'<div><strong style="color:var(--muted)">Last Triggered:</strong> ' + escHtml(lastTriggered) + '</div>' +
|
|
333
|
-
(w._lastTriggerMessage ? '<div><strong style="color:var(--muted)">Last Trigger Message:</strong><div style="margin-top:4px;padding:8px;background:var(--surface2);border-radius:4px;font-size:
|
|
333
|
+
(w._lastTriggerMessage ? '<div><strong style="color:var(--muted)">Last Trigger Message:</strong><div style="margin-top:4px;padding:8px;background:var(--surface2);border-radius:4px;font-size:var(--text-base)">' + escHtml(w._lastTriggerMessage) + '</div></div>' : '') +
|
|
334
334
|
(w.project ? '<div><strong style="color:var(--muted)">Project:</strong> ' + escHtml(w.project) + '</div>' : '') +
|
|
335
335
|
(w.description ? '<div><strong style="color:var(--muted)">Description:</strong> ' + escHtml(w.description) + '</div>' : '') +
|
|
336
336
|
// P-w15f1d4b — Phase 7.2: reserve a placeholder for the lazily-fetched
|
|
337
337
|
// evaluation history table. The fetch below populates it once
|
|
338
338
|
// /api/watches/:id/history resolves; failures fall back to the inline
|
|
339
339
|
// _history copy from /api/watches (best-effort) or a "no history" hint.
|
|
340
|
-
'<div id="watch-history-' + escHtml(w.id) + '"><div style="color:var(--muted);font-style:italic;font-size:
|
|
340
|
+
'<div id="watch-history-' + escHtml(w.id) + '"><div style="color:var(--muted);font-style:italic;font-size:var(--text-base)">Loading history…</div></div>' +
|
|
341
341
|
'</div>';
|
|
342
342
|
|
|
343
343
|
// eslint-disable-next-line no-unsanitized/property -- reason: structural HTML is a string literal; all user data wrapped in escHtml() by watch detail renderers (fields: watch id/target/owner/description/action params/requires/history/result messages)
|
|
@@ -459,29 +459,29 @@ function _watchFormHtml() {
|
|
|
459
459
|
var projOpts = '<option value="">Any</option>' + (cmdProjects || []).map(function(p) { return '<option value="' + escHtml(p.name) + '">' + escHtml(p.name) + '</option>'; }).join('');
|
|
460
460
|
|
|
461
461
|
return '<div style="display:flex;flex-direction:column;gap:12px;font-family:inherit">' +
|
|
462
|
-
'<div id="watch-form-error" style="display:none;color:var(--red);font-size:
|
|
462
|
+
'<div id="watch-form-error" style="display:none;color:var(--red);font-size:var(--text-md);padding:6px 10px;background:rgba(255,50,50,0.1);border-radius:var(--radius-sm)"></div>' +
|
|
463
463
|
'<label style="color:var(--text);font-size:var(--text-md)">Target (e.g. PR number, work item ID, meeting/plan/schedule/pipeline/dispatch/agent ID)<input id="watch-edit-target" placeholder="e.g. 1057, W-abc123, M-xyz, schedule-42" style="' + inputStyle + '"></label>' +
|
|
464
464
|
'<label style="color:var(--text);font-size:var(--text-md)">Target Type<select id="watch-edit-target-type" style="' + inputStyle + '" onchange="_updateWatchConditionOptions()">' + ttOpts + '</select></label>' +
|
|
465
465
|
'<label style="color:var(--text);font-size:var(--text-md)">Condition<select id="watch-edit-condition" style="' + inputStyle + '">' + condOpts + '</select></label>' +
|
|
466
|
-
'<label style="color:var(--text);font-size:var(--text-md)">Check Interval <span style="font-size:
|
|
466
|
+
'<label style="color:var(--text);font-size:var(--text-md)">Check Interval <span style="font-size:var(--text-sm);color:var(--muted)">(e.g. 5m, 15m, 1h — default 5m)</span><input id="watch-edit-interval" placeholder="5m" style="' + inputStyle + '"></label>' +
|
|
467
467
|
'<label style="color:var(--text);font-size:var(--text-md)">Owner (who gets notified)<select id="watch-edit-owner" style="' + inputStyle + '">' + agentOpts + '</select></label>' +
|
|
468
468
|
'<label style="color:var(--text);font-size:var(--text-md)">Project<select id="watch-edit-project" style="' + inputStyle + '">' + projOpts + '</select></label>' +
|
|
469
469
|
'<label style="color:var(--text);font-size:var(--text-md)">Description<input id="watch-edit-desc" placeholder="Optional description" style="' + inputStyle + '"></label>' +
|
|
470
|
-
'<label style="color:var(--text);font-size:var(--text-md)">Stop After N Triggers <span style="font-size:
|
|
470
|
+
'<label style="color:var(--text);font-size:var(--text-md)">Stop After N Triggers <span style="font-size:var(--text-sm);color:var(--muted)">(0 = run forever, 1 = expire on first match)</span><input id="watch-edit-stop-after" type="number" value="0" min="0" style="' + inputStyle + '"></label>' +
|
|
471
471
|
'<label style="color:var(--text);font-size:var(--text-md)">On Each Poll (if condition not met)<select id="watch-edit-on-not-met" style="' + inputStyle + '"><option value="">None — do nothing</option><option value="notify">Notify — write to inbox each poll</option></select></label>' +
|
|
472
472
|
// P-w14e7a8c — Phase 7.1: action chain editor (step list + add/remove)
|
|
473
473
|
'<div style="border:1px solid var(--border);border-radius:var(--radius-sm);padding:10px;display:flex;flex-direction:column;gap:8px">' +
|
|
474
474
|
'<div style="color:var(--text);font-size:var(--text-md);display:flex;align-items:center;justify-content:space-between">' +
|
|
475
|
-
'<span>Follow-up Action(s) <span style="font-size:
|
|
476
|
-
'<button type="button" class="pr-pager-btn" style="font-size:
|
|
475
|
+
'<span>Follow-up Action(s) <span style="font-size:var(--text-sm);color:var(--muted)">(runs after the inbox notification when the watch fires; 1 step = single, 2+ = chain)</span></span>' +
|
|
476
|
+
'<button type="button" class="pr-pager-btn" style="font-size:var(--text-sm);padding:2px 8px;color:var(--green);border-color:var(--green)" onclick="_addWatchStepRow()">+ Add step</button>' +
|
|
477
477
|
'</div>' +
|
|
478
478
|
'<div id="watch-edit-steps"></div>' +
|
|
479
479
|
'</div>' +
|
|
480
480
|
// P-w14e7a8c — Phase 7.1: requires editor (cross-target AND-join rows)
|
|
481
481
|
'<div style="border:1px solid var(--border);border-radius:var(--radius-sm);padding:10px;display:flex;flex-direction:column;gap:8px">' +
|
|
482
482
|
'<div style="color:var(--text);font-size:var(--text-md);display:flex;align-items:center;justify-content:space-between">' +
|
|
483
|
-
'<span>Requires <span style="font-size:
|
|
484
|
-
'<button type="button" class="pr-pager-btn" style="font-size:
|
|
483
|
+
'<span>Requires <span style="font-size:var(--text-sm);color:var(--muted)">(cross-target AND-join — every requirement must also be true to fire)</span></span>' +
|
|
484
|
+
'<button type="button" class="pr-pager-btn" style="font-size:var(--text-sm);padding:2px 8px;color:var(--green);border-color:var(--green)" onclick="_addRequireRow()">+ Add requirement</button>' +
|
|
485
485
|
'</div>' +
|
|
486
486
|
'<div id="watch-edit-requires"></div>' +
|
|
487
487
|
'</div>' +
|
|
@@ -518,12 +518,12 @@ function _addWatchStepRow(initial) {
|
|
|
518
518
|
row.innerHTML =
|
|
519
519
|
'<div style="display:flex;align-items:center;justify-content:space-between;gap:8px">' +
|
|
520
520
|
'<select id="watch-step-' + idx + '-type" style="' + inputStyle + ';margin-top:0;flex:1" onchange="_updateWatchStepParamsHint(' + idx + ')">' + actionOpts + '</select>' +
|
|
521
|
-
'<button type="button" class="pr-pager-btn" style="font-size:
|
|
521
|
+
'<button type="button" class="pr-pager-btn" style="font-size:var(--text-sm);padding:2px 8px;color:var(--red);border-color:var(--red)" onclick="_removeWatchStepRow(' + idx + ')">Remove</button>' +
|
|
522
522
|
'</div>' +
|
|
523
|
-
'<label style="color:var(--text);font-size:
|
|
523
|
+
'<label style="color:var(--text);font-size:var(--text-base)">Params (JSON) <span style="font-size:var(--text-sm);color:var(--muted)" id="watch-step-' + idx + '-params-hint"></span>' +
|
|
524
524
|
'<textarea id="watch-step-' + idx + '-params" rows="3" placeholder=\'{"title": "Re-check {{target}} after merge"}\' style="' + inputStyle + ';font-family:monospace"></textarea>' +
|
|
525
525
|
'</label>' +
|
|
526
|
-
'<label style="color:var(--text);font-size:
|
|
526
|
+
'<label style="color:var(--text);font-size:var(--text-base)">Guard expression <span style="font-size:var(--text-sm);color:var(--muted)">(optional — skip step if expr is false; e.g. <code>newState.mergeable === true</code>)</span>' +
|
|
527
527
|
'<input id="watch-step-' + idx + '-guard" placeholder="" style="' + inputStyle + ';font-family:monospace">' +
|
|
528
528
|
'</label>';
|
|
529
529
|
container.appendChild(row);
|
|
@@ -579,10 +579,10 @@ function _addRequireRow(initial) {
|
|
|
579
579
|
row.style.cssText = 'display:grid;grid-template-columns:1fr 1fr 1fr auto;gap:6px;align-items:end';
|
|
580
580
|
// eslint-disable-next-line no-unsanitized/property -- reason: structural HTML is a string literal; all user data wrapped in escHtml() (fields: target type registry values/labels)
|
|
581
581
|
row.innerHTML =
|
|
582
|
-
'<label style="color:var(--text);font-size:
|
|
583
|
-
'<label style="color:var(--text);font-size:
|
|
584
|
-
'<label style="color:var(--text);font-size:
|
|
585
|
-
'<button type="button" class="pr-pager-btn" style="font-size:
|
|
582
|
+
'<label style="color:var(--text);font-size:var(--text-base);margin:0">Target<input id="watch-require-' + idx + '-target" placeholder="e.g. PR-123, pipeline-X" style="' + inputStyle + '"></label>' +
|
|
583
|
+
'<label style="color:var(--text);font-size:var(--text-base);margin:0">Target Type<select id="watch-require-' + idx + '-target-type" style="' + inputStyle + '" onchange="_updateRequireConditionOptions(' + idx + ')">' + ttOpts + '</select></label>' +
|
|
584
|
+
'<label style="color:var(--text);font-size:var(--text-base);margin:0">Condition<select id="watch-require-' + idx + '-condition" style="' + inputStyle + '"></select></label>' +
|
|
585
|
+
'<button type="button" class="pr-pager-btn" style="font-size:var(--text-sm);padding:6px 8px;color:var(--red);border-color:var(--red)" onclick="_removeRequireRow(' + idx + ')">Remove</button>';
|
|
586
586
|
container.appendChild(row);
|
|
587
587
|
if (initTarget) document.getElementById('watch-require-' + idx + '-target').value = initTarget;
|
|
588
588
|
if (initTT) document.getElementById('watch-require-' + idx + '-target-type').value = initTT;
|
|
@@ -625,7 +625,7 @@ function _updateWatchConditionOptions() {
|
|
|
625
625
|
|
|
626
626
|
function _renderCreateWatchModal() {
|
|
627
627
|
document.getElementById('modal-title').innerHTML = 'Create Watch' +
|
|
628
|
-
' <button class="pr-pager-btn" style="font-size:
|
|
628
|
+
' <button class="pr-pager-btn" style="font-size:var(--text-sm);padding:2px 12px;color:var(--green);border-color:var(--green);margin-left:8px" onclick="submitWatch()">Create</button>';
|
|
629
629
|
// eslint-disable-next-line no-unsanitized/property -- reason: structural HTML is a string literal; all user data wrapped in escHtml() by _watchFormHtml() (fields: target/action registries, project names, agent ids/names)
|
|
630
630
|
document.getElementById('modal-body').innerHTML = _watchFormHtml();
|
|
631
631
|
document.getElementById('modal-body').style.whiteSpace = 'normal';
|
|
@@ -87,15 +87,15 @@ function getWiRetryState(id) {
|
|
|
87
87
|
function wiRetryBtn(item) {
|
|
88
88
|
const rs = getWiRetryState(item.id);
|
|
89
89
|
if (rs && rs.status === 'pending') {
|
|
90
|
-
return '<span style="font-size:
|
|
90
|
+
return '<span style="font-size:var(--text-xs);padding:1px 6px;color:var(--yellow);border:1px solid rgba(210,153,34,0.35);background:rgba(210,153,34,0.1);border-radius:3px;cursor:wait;margin-left:4px">Retrying\u2026</span>';
|
|
91
91
|
}
|
|
92
92
|
if (rs && rs.status === 'done') {
|
|
93
|
-
return '<span style="font-size:
|
|
93
|
+
return '<span style="font-size:var(--text-xs);padding:1px 6px;color:var(--green);border:1px solid rgba(63,185,80,0.35);background:rgba(63,185,80,0.1);border-radius:3px;margin-left:4px">Requeued</span>';
|
|
94
94
|
}
|
|
95
95
|
if (rs && rs.status === 'error') {
|
|
96
|
-
return '<span style="font-size:
|
|
96
|
+
return '<span style="font-size:var(--text-xs);padding:1px 6px;color:var(--red);border:1px solid rgba(248,81,73,0.35);background:rgba(248,81,73,0.1);border-radius:3px;margin-left:4px;cursor:pointer" title="' + escapeHtml(rs.message || 'Retry failed') + ' — click to try again" onclick="event.stopPropagation();retryWorkItem(\'' + escapeHtml(item.id) + '\',\'' + escapeHtml(item._source || '') + '\')">Retry failed</span>';
|
|
97
97
|
}
|
|
98
|
-
return '<button class="pr-pager-btn" style="font-size:
|
|
98
|
+
return '<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="event.stopPropagation();retryWorkItem(\'' + escapeHtml(item.id) + '\',\'' + escapeHtml(item._source || '') + '\')">Retry</button>';
|
|
99
99
|
}
|
|
100
100
|
|
|
101
101
|
function wiRow(item) {
|
|
@@ -106,9 +106,9 @@ function wiRow(item) {
|
|
|
106
106
|
const typeBadge = (t) => '<span class="dispatch-type ' + (t || 'implement') + '">' + escapeHtml(t || 'implement') + '</span>';
|
|
107
107
|
const priBadge = (p) => '<span class="prd-item-priority ' + (p || '') + '">' + escapeHtml(p || 'medium') + '</span>';
|
|
108
108
|
const prLink = item._pr
|
|
109
|
-
? '<a class="pr-title" href="' + escapeHtml(item._prUrl || '#') + '" target="_blank" style="font-size:
|
|
109
|
+
? '<a class="pr-title" href="' + escapeHtml(item._prUrl || '#') + '" target="_blank" style="font-size:var(--text-sm)">' + escapeHtml(item._pr) + '</a>'
|
|
110
110
|
: (item.branchStrategy === 'shared-branch' && item.status === 'done')
|
|
111
|
-
? '<span style="font-size:
|
|
111
|
+
? '<span style="font-size:var(--text-xs);color:var(--muted)" title="Part of shared branch — aggregate PR created at verify stage">shared branch</span>'
|
|
112
112
|
: '<span style="color:var(--muted)">—</span>';
|
|
113
113
|
// PR follow-up chip (W-mpej3cox00099466) — surfaced when the WI was spun
|
|
114
114
|
// off from a PR comment via meta.pr_followup. Links to the parent PR.
|
|
@@ -118,21 +118,21 @@ function wiRow(item) {
|
|
|
118
118
|
var prRef = prFollowup.parent_pr_id || prFollowup.parent_pr_url;
|
|
119
119
|
var prNumMatch = String(prRef).match(/(\d+)(?!.*\d)/);
|
|
120
120
|
var prLabel = prNumMatch ? ('PR #' + prNumMatch[1]) : 'parent PR';
|
|
121
|
-
followupChip = ' <a class="pr-badge draft" style="font-size:
|
|
121
|
+
followupChip = ' <a class="pr-badge draft" style="font-size:var(--text-xs);text-decoration:none" target="_blank" rel="noopener" href="' + escapeHtml(prFollowup.parent_pr_url) + '" title="Follow-up dispatched from ' + escapeHtml(prRef) + (prFollowup.parent_comment_author ? ' by ' + escapeHtml(prFollowup.parent_comment_author) : '') + '" onclick="event.stopPropagation()">↩ from ' + escapeHtml(prLabel) + '</a>';
|
|
122
122
|
}
|
|
123
123
|
return '<tr data-wi-id="' + escapeHtml(item.id) + '" style="cursor:pointer" onclick="if(shouldIgnoreSelectionClick(event))return;openWorkItemDetail(\'' + escapeHtml(item.id) + '\')">' +
|
|
124
124
|
'<td><span class="pr-id">' + escapeHtml(item.id || '') + '</span></td>' +
|
|
125
125
|
'<td style="max-width:220px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap" title="' + escapeHtml((item.title || '').slice(0, 200)) + '">' + escapeHtml(item.title || '') + followupChip + '</td>' +
|
|
126
|
-
'<td><span style="font-size:
|
|
127
|
-
(item.scope === 'fan-out' ? ' <span class="pr-badge ' + (item.status === 'done' || item.status === 'failed' ? 'draft' : 'building') + '" style="font-size:
|
|
126
|
+
'<td><span style="font-size:var(--text-sm);color:var(--muted)">' + escapeHtml(item._source || '') + '</span>' +
|
|
127
|
+
(item.scope === 'fan-out' ? ' <span class="pr-badge ' + (item.status === 'done' || item.status === 'failed' ? 'draft' : 'building') + '" style="font-size:var(--text-xs)">fan-out</span>' : '') + '</td>' +
|
|
128
128
|
'<td>' + typeBadge(item.type) + '</td>' +
|
|
129
129
|
'<td>' + priBadge(item.priority) + '</td>' +
|
|
130
130
|
'<td>' + statusBadge(item.status || 'pending') +
|
|
131
|
-
(item._reopened ? ' <span style="font-size:
|
|
132
|
-
(item._pendingReason && item.status === 'pending' && item._pendingReason !== 'already_dispatched' ? ' <span style="font-size:
|
|
133
|
-
(item._pendingReason === 'already_dispatched' && item.status === 'pending' ? ' <span style="font-size:
|
|
131
|
+
(item._reopened ? ' <span style="font-size:var(--text-xs);color:var(--purple);margin-left:4px" title="This item was reopened from a previously completed state">reopened</span>' : '') +
|
|
132
|
+
(item._pendingReason && item.status === 'pending' && item._pendingReason !== 'already_dispatched' ? ' <span style="font-size:var(--text-xs);color:var(--muted);margin-left:4px" title="Pending reason: ' + escapeHtml(item._pendingReason) + '">' + escapeHtml(item._pendingReason.replace(/_/g, ' ')) + '</span>' : '') +
|
|
133
|
+
(item._pendingReason === 'already_dispatched' && item.status === 'pending' ? ' <span style="font-size:var(--text-xs);color:var(--blue);margin-left:4px" title="In dispatch queue, waiting to be assigned">queued</span>' : '') +
|
|
134
134
|
(item._managedSpawnPartial && Array.isArray(item._managedSpawnPartial.failed) && item._managedSpawnPartial.failed.length
|
|
135
|
-
? ' <span style="font-size:
|
|
135
|
+
? ' <span style="font-size:var(--text-xs);color:var(--yellow);margin-left:4px;border:1px solid var(--yellow);padding:0 4px;border-radius:6px" title="managed-spawn: '
|
|
136
136
|
+ escapeHtml(((item._managedSpawnPartial.healthy || []).length) + '/' + (((item._managedSpawnPartial.healthy || []).length) + item._managedSpawnPartial.failed.length))
|
|
137
137
|
+ ' healthy — failed: '
|
|
138
138
|
+ escapeHtml(item._managedSpawnPartial.failed.map(function(f){ return (f && f.name) || '?'; }).join(', '))
|
|
@@ -140,18 +140,18 @@ function wiRow(item) {
|
|
|
140
140
|
+ escapeHtml(((item._managedSpawnPartial.healthy || []).length) + '/' + (((item._managedSpawnPartial.healthy || []).length) + item._managedSpawnPartial.failed.length))
|
|
141
141
|
+ ' healthy</span>'
|
|
142
142
|
: '') +
|
|
143
|
-
(item._skipReason && item.status === 'pending' ? ' <span style="font-size:
|
|
143
|
+
(item._skipReason && item.status === 'pending' ? ' <span style="font-size:var(--text-xs);color:var(--yellow);margin-left:4px" title="Dispatch blocked: ' + escapeHtml(item._skipReason) + (item._blockedBy ? ' (by ' + escapeHtml(item._blockedBy) + ')' : '') + '">' + escapeHtml(item._skipReason.replace(/_/g, ' ')) + (item._blockedBy ? ' <span style="color:var(--muted)">(' + escapeHtml(item._blockedBy) + ')</span>' : '') + '</span>' : '') +
|
|
144
144
|
(item.status === 'failed' ? ' ' + wiRetryBtn(item) : '') +
|
|
145
145
|
'</td>' +
|
|
146
146
|
'<td>' +
|
|
147
147
|
(item.completedAgents && item.completedAgents.length > 0
|
|
148
148
|
? '<span class="pr-agent">' + escapeHtml(item.completedAgents.join(', ')) + '</span>'
|
|
149
149
|
: '<span class="pr-agent">' + escapeHtml(item.dispatched_to || item.agent || '—') + '</span>') +
|
|
150
|
-
(item.failReason ? '<span style="display:block;font-size:
|
|
150
|
+
(item.failReason ? '<span style="display:block;font-size:var(--text-xs);color:var(--red)" title="' + escapeHtml(item.failReason) + '">' + escapeHtml(item.failReason.slice(0, 30)) + '</span>' : '') +
|
|
151
151
|
'</td>' +
|
|
152
152
|
'<td>' + prLink + '</td>' +
|
|
153
153
|
'<td><span class="pr-date">' + escapeHtml((item.created || '').slice(0, 16).replace('T', ' ')) + '</span></td>' +
|
|
154
|
-
'<td style="white-space:nowrap;font-size:
|
|
154
|
+
'<td style="white-space:nowrap;font-size:var(--text-xs);color:var(--muted)">' +
|
|
155
155
|
(function() {
|
|
156
156
|
// /api/status slims the full arrays into integer counts
|
|
157
157
|
// (dashboard.js:1796-1797: referencesCount / acceptanceCriteriaCount).
|
|
@@ -168,11 +168,11 @@ function wiRow(item) {
|
|
|
168
168
|
})() +
|
|
169
169
|
'</td>' +
|
|
170
170
|
'<td style="white-space:nowrap">' +
|
|
171
|
-
((item.status === 'pending' || item.status === 'failed') ? '<button class="pr-pager-btn" style="font-size:
|
|
172
|
-
((item.status === 'done' || item.status === 'failed') ? '<button class="pr-pager-btn" style="font-size:
|
|
173
|
-
((item.status === 'done' || item.status === 'failed') && !item._humanFeedback ? '<button class="pr-pager-btn" style="font-size:
|
|
174
|
-
((item.status === 'pending' || item.status === 'dispatched' || item.status === 'queued' || item.status === 'failed') ? '<button class="pr-pager-btn" style="font-size:
|
|
175
|
-
'<button class="pr-pager-btn" style="font-size:
|
|
171
|
+
((item.status === 'pending' || item.status === 'failed') ? '<button class="pr-pager-btn" style="font-size:var(--text-xs);padding:1px 6px;color:var(--blue);border-color:var(--blue);margin-right:4px" onclick="event.stopPropagation();editWorkItem(\'' + escapeHtml(item.id) + '\',\'' + escapeHtml(item._source || '') + '\')" title="Edit work item">✎</button>' : '') +
|
|
172
|
+
((item.status === 'done' || item.status === 'failed') ? '<button class="pr-pager-btn" style="font-size:var(--text-xs);padding:1px 6px;color:var(--muted);border-color:var(--border);margin-right:4px" onclick="event.stopPropagation();archiveWorkItem(\'' + escapeHtml(item.id) + '\',\'' + escapeHtml(item._source || '') + '\')" title="Archive work item">📦</button>' : '') +
|
|
173
|
+
((item.status === 'done' || item.status === 'failed') && !item._humanFeedback ? '<button class="pr-pager-btn" style="font-size:var(--text-xs);padding:1px 6px;color:var(--green);border-color:var(--green);margin-right:4px" onclick="event.stopPropagation();feedbackWorkItem(\'' + escapeHtml(item.id) + '\',\'' + escapeHtml(item._source || '') + '\')" title="Give feedback">👍👎</button>' : (item._humanFeedback ? '<span style="font-size:var(--text-xs)" title="Feedback given">' + (item._humanFeedback.rating === 'up' ? '👍' : '👎') + '</span> ' : '')) +
|
|
174
|
+
((item.status === 'pending' || item.status === 'dispatched' || item.status === 'queued' || item.status === 'failed') ? '<button class="pr-pager-btn" style="font-size:var(--text-xs);padding:1px 6px;color:var(--orange);border-color:var(--orange);margin-right:4px" onclick="event.stopPropagation();cancelWorkItem(\'' + escapeHtml(item.id) + '\',\'' + escapeHtml(item._source || '') + '\')" title="Cancel work item and kill agent">🚫</button>' : '') +
|
|
175
|
+
'<button class="pr-pager-btn" style="font-size:var(--text-xs);padding:1px 6px;color:var(--red);border-color:var(--red)" onclick="event.stopPropagation();deleteWorkItem(\'' + escapeHtml(item.id) + '\',\'' + escapeHtml(item._source || '') + '\')" title="Delete work item and kill agent">✕</button>' +
|
|
176
176
|
'</td>' +
|
|
177
177
|
'</tr>';
|
|
178
178
|
}
|
|
@@ -393,7 +393,7 @@ async function toggleWorkItemArchive() {
|
|
|
393
393
|
const items = await fetch('/api/work-items/archive').then(r => r.json());
|
|
394
394
|
if (!items.length) { el.innerHTML = '<p class="empty">No archived work items.</p>'; return; }
|
|
395
395
|
// eslint-disable-next-line no-unsanitized/property -- reason: structural HTML is a string literal; all user data wrapped in escapeHtml() (fields: archived work item id/title/type/status/agent)
|
|
396
|
-
el.innerHTML = '<div style="font-size:
|
|
396
|
+
el.innerHTML = '<div style="font-size:var(--text-sm);color:var(--muted);margin-bottom:6px;font-weight:600;text-transform:uppercase;letter-spacing:0.5px">Archived (' + items.length + ')</div>' +
|
|
397
397
|
'<div class="pr-table-wrap"><table class="pr-table"><thead><tr><th>ID</th><th>Title</th><th>Type</th><th>Status</th><th>Agent</th><th>Archived</th></tr></thead><tbody>' +
|
|
398
398
|
items.map(function(i) {
|
|
399
399
|
return '<tr style="opacity:0.6">' +
|
|
@@ -447,8 +447,8 @@ function feedbackWorkItem(id, source) {
|
|
|
447
447
|
document.getElementById('modal-body').innerHTML =
|
|
448
448
|
'<div style="display:flex;flex-direction:column;gap:16px">' +
|
|
449
449
|
'<div style="display:flex;gap:16px;justify-content:center">' +
|
|
450
|
-
'<button id="fb-up" onclick="_selectRating(\'up\')" style="font-size:
|
|
451
|
-
'<button id="fb-down" onclick="_selectRating(\'down\')" style="font-size:
|
|
450
|
+
'<button id="fb-up" onclick="_selectRating(\'up\')" style="font-size:var(--text-display);background:none;border:2px solid var(--border);border-radius:12px;padding:12px 20px;cursor:pointer;transition:all 0.2s">👍</button>' +
|
|
451
|
+
'<button id="fb-down" onclick="_selectRating(\'down\')" style="font-size:var(--text-display);background:none;border:2px solid var(--border);border-radius:12px;padding:12px 20px;cursor:pointer;transition:all 0.2s">👎</button>' +
|
|
452
452
|
'</div>' +
|
|
453
453
|
'<textarea id="feedback-comment" rows="3" style="width:100%;padding:8px;background:var(--bg);border:1px solid var(--border);border-radius:var(--radius-sm);color:var(--text);font-family:inherit;resize:vertical" placeholder="What was good or needs improvement?"></textarea>' +
|
|
454
454
|
'<div style="display:flex;justify-content:flex-end;gap:8px">' +
|
|
@@ -587,14 +587,14 @@ async function _submitCreateWorkItem(e) {
|
|
|
587
587
|
}
|
|
588
588
|
|
|
589
589
|
function _wiRenderDetail(item) {
|
|
590
|
-
const field = (label, value) => value ? '<div style="margin-bottom:8px"><span style="color:var(--muted);font-size:
|
|
590
|
+
const field = (label, value) => value ? '<div style="margin-bottom:8px"><span style="color:var(--muted);font-size:var(--text-sm);text-transform:uppercase;letter-spacing:0.5px">' + label + '</span><div style="margin-top:2px">' + value + '</div></div>' : '';
|
|
591
591
|
const badge = (cls, text) => '<span class="pr-badge ' + cls + '">' + escapeHtml(text) + '</span>';
|
|
592
592
|
const statusCls = item.status === 'failed' ? 'rejected' : item.status === 'dispatched' ? 'building' : item.status === 'done' ? 'approved' : 'active';
|
|
593
593
|
|
|
594
|
-
let html = '<div style="display:flex;flex-direction:column;gap:4px;font-size:
|
|
594
|
+
let html = '<div style="display:flex;flex-direction:column;gap:4px;font-size:var(--text-lg)">';
|
|
595
595
|
html += '<div style="display:flex;gap:8px;align-items:center;margin-bottom:8px">' +
|
|
596
596
|
badge(statusCls, item.status || 'pending') +
|
|
597
|
-
(item._reopened ? ' <span style="font-size:
|
|
597
|
+
(item._reopened ? ' <span style="font-size:var(--text-xs);color:var(--purple);margin-left:4px" title="This item was reopened from a previously completed state">reopened</span>' : '') + ' ' +
|
|
598
598
|
'<span class="dispatch-type ' + (item.type || 'implement') + '">' + escapeHtml(item.type || 'implement') + '</span>' +
|
|
599
599
|
'<span class="prd-item-priority ' + (item.priority || '') + '">' + escapeHtml(item.priority || 'medium') + '</span>' +
|
|
600
600
|
'</div>';
|
|
@@ -611,7 +611,7 @@ function _wiRenderDetail(item) {
|
|
|
611
611
|
} else {
|
|
612
612
|
_descHtml = escapeHtml(item.title || '—');
|
|
613
613
|
}
|
|
614
|
-
html += field('Description', '<div id="wi-detail-desc" style="font-size:
|
|
614
|
+
html += field('Description', '<div id="wi-detail-desc" style="font-size:var(--text-md);max-height:320px;overflow-y:auto;padding:8px 10px;background:var(--surface2);border:1px solid var(--border);border-radius:var(--radius-sm)">' + _descHtml + '</div>');
|
|
615
615
|
html += field('Agent', escapeHtml(item.dispatched_to || item.agent || 'Auto'));
|
|
616
616
|
html += field('Source', escapeHtml(item._source || 'central'));
|
|
617
617
|
if (item.created) html += field('Created', escapeHtml(formatLocalDateTime(item.created)));
|
|
@@ -623,7 +623,7 @@ function _wiRenderDetail(item) {
|
|
|
623
623
|
var _msp = item._managedSpawnPartial;
|
|
624
624
|
var _mspHealthy = Array.isArray(_msp.healthy) ? _msp.healthy : [];
|
|
625
625
|
var _mspTotal = _mspHealthy.length + _msp.failed.length;
|
|
626
|
-
var _mspBody = '<div style="color:var(--yellow);font-size:
|
|
626
|
+
var _mspBody = '<div style="color:var(--yellow);font-size:var(--text-base);margin-bottom:6px">'
|
|
627
627
|
+ escapeHtml(_mspHealthy.length + '/' + _mspTotal) + ' specs healthy. Failed: '
|
|
628
628
|
+ escapeHtml(_msp.failed.map(function(f){ return (f && f.name) || '?'; }).join(', '))
|
|
629
629
|
+ (_msp.evaluated_at ? ' <span style="color:var(--muted)">(evaluated ' + escapeHtml(_msp.evaluated_at) + ')</span>' : '')
|
|
@@ -632,8 +632,8 @@ function _wiRenderDetail(item) {
|
|
|
632
632
|
var name = escapeHtml((f && f.name) || '?');
|
|
633
633
|
var reason = escapeHtml((f && f.reason) || 'unknown');
|
|
634
634
|
var tail = (f && f.log_tail) || '';
|
|
635
|
-
return '<details style="margin-bottom:6px"><summary style="cursor:pointer;font-size:
|
|
636
|
-
+ '<pre style="font-size:
|
|
635
|
+
return '<details style="margin-bottom:6px"><summary style="cursor:pointer;font-size:var(--text-base)"><strong>' + name + '</strong> — ' + reason + '</summary>'
|
|
636
|
+
+ '<pre style="font-size:var(--text-sm);max-height:240px;overflow:auto;padding:6px;background:var(--surface2);border:1px solid var(--border);border-radius:var(--radius-sm);margin:4px 0 0 0">'
|
|
637
637
|
+ escapeHtml(tail || '(no log tail captured)')
|
|
638
638
|
+ '</pre></details>';
|
|
639
639
|
}).join('');
|
|
@@ -659,7 +659,7 @@ function _wiRenderDetail(item) {
|
|
|
659
659
|
}
|
|
660
660
|
var refs = Array.isArray(item.references) ? item.references.filter(r => r && typeof r === 'object' && r.url) : [];
|
|
661
661
|
if (refs.length) {
|
|
662
|
-
html += field('References', refs.map(r => '<a href="' + escapeHtml(r.url) + '" target="_blank" style="color:var(--blue)">' + escapeHtml(r.title || r.url) + '</a>' + (r.type ? ' <span style="color:var(--muted);font-size:
|
|
662
|
+
html += field('References', refs.map(r => '<a href="' + escapeHtml(r.url) + '" target="_blank" style="color:var(--blue)">' + escapeHtml(r.title || r.url) + '</a>' + (r.type ? ' <span style="color:var(--muted);font-size:var(--text-sm)">(' + escapeHtml(r.type) + ')</span>' : '')).join('<br>'));
|
|
663
663
|
} else if (item.referencesCount > 0) {
|
|
664
664
|
html += field('References', '<span style="color:var(--muted)">' + item.referencesCount + ' reference(s) — loading…</span>');
|
|
665
665
|
}
|
|
@@ -669,7 +669,7 @@ function _wiRenderDetail(item) {
|
|
|
669
669
|
// Artifacts — output log, branch, skills, etc.
|
|
670
670
|
var arts = item._artifacts || {};
|
|
671
671
|
var artPills = '';
|
|
672
|
-
var pillStyle = 'display:inline-flex;align-items:center;gap:3px;padding:2px 8px;border-radius:10px;font-size:
|
|
672
|
+
var pillStyle = 'display:inline-flex;align-items:center;gap:3px;padding:2px 8px;border-radius:10px;font-size:var(--text-sm);cursor:pointer;background:var(--surface2);border:1px solid var(--border);color:var(--text)';
|
|
673
673
|
// Output log pill removed — raw stream-json output is not human-readable
|
|
674
674
|
var artBackFn = "pushModalBack(function(){openWorkItemDetail('" + escapeHtml(item.id) + "')});";
|
|
675
675
|
if (arts.branch) artPills += '<span style="' + pillStyle + ';cursor:default">🌿 ' + escapeHtml(arts.branch) + '</span> ';
|
|
@@ -687,7 +687,7 @@ function _wiRenderDetail(item) {
|
|
|
687
687
|
artPills += '<span onclick="' + artBackFn + 'kbOpenItem(\'' + escapeHtml(kbCat) + '\',\'' + escapeHtml(kbFile) + '\')" style="' + pillStyle + '">📚 ' + escapeHtml(kbLabel) + '</span> ';
|
|
688
688
|
} else if (noteFile.startsWith('archive:')) {
|
|
689
689
|
var archLabel = noteFile.slice(8).replace(/\.md$/, '').replace(/^\d{4}-\d{2}-\d{2}-/, '').slice(0, 30);
|
|
690
|
-
artPills += '<span onclick="' + artBackFn + 'openInboxNote(\'' + escapeHtml(noteFile.slice(8)) + '\')" style="' + pillStyle + ';opacity:0.7">📄 ' + escapeHtml(archLabel) + ' <span style="font-size:
|
|
690
|
+
artPills += '<span onclick="' + artBackFn + 'openInboxNote(\'' + escapeHtml(noteFile.slice(8)) + '\')" style="' + pillStyle + ';opacity:0.7">📄 ' + escapeHtml(archLabel) + ' <span style="font-size:var(--text-xs)">(archived)</span></span> ';
|
|
691
691
|
} else {
|
|
692
692
|
var noteLabel = noteFile.replace(/\.md$/, '').slice(0, 30);
|
|
693
693
|
artPills += '<span onclick="' + artBackFn + 'openInboxNote(\'' + escapeHtml(noteFile) + '\')" style="' + pillStyle + '">📝 ' + escapeHtml(noteLabel) + '</span> ';
|
package/dashboard/js/utils.js
CHANGED
|
@@ -247,7 +247,7 @@ function _renderMdCore(s) {
|
|
|
247
247
|
// 1. Extract code blocks and inline code into placeholders (protect from other transforms)
|
|
248
248
|
const codeSlots = [];
|
|
249
249
|
html = html.replace(/```(\w*)\n([\s\S]*?)```/g, function(_, lang, code) {
|
|
250
|
-
codeSlots.push('<pre style="background:var(--bg);padding:8px;border-radius:4px;overflow-x:auto;font-size:
|
|
250
|
+
codeSlots.push('<pre style="background:var(--bg);padding:8px;border-radius:4px;overflow-x:auto;font-size:var(--text-base);margin:4px 0"><code>' + code + '</code></pre>');
|
|
251
251
|
return '\x00CB' + (codeSlots.length - 1) + '\x00';
|
|
252
252
|
});
|
|
253
253
|
|
|
@@ -343,7 +343,7 @@ function _renderMdCore(s) {
|
|
|
343
343
|
i++;
|
|
344
344
|
}
|
|
345
345
|
i--; // back up one since the for loop will increment
|
|
346
|
-
var tableHtml = '<div class="md-table-wrap"><table style="font-size:
|
|
346
|
+
var tableHtml = '<div class="md-table-wrap"><table style="font-size:var(--text-base)"><thead><tr>';
|
|
347
347
|
if (tableRows.length > 0) {
|
|
348
348
|
tableRows[0].forEach(function(c) { tableHtml += '<th>' + c + '</th>'; });
|
|
349
349
|
tableHtml += '</tr></thead><tbody>';
|
|
@@ -446,7 +446,7 @@ function _renderMdChunked(fullText) {
|
|
|
446
446
|
var uid = '_mdChunk' + (++_mdChunkUid);
|
|
447
447
|
if (chunks.length <= 1) return firstHtml;
|
|
448
448
|
|
|
449
|
-
var sentinel = '<div id="' + uid + '" style="padding:12px 0;color:var(--muted);font-size:
|
|
449
|
+
var sentinel = '<div id="' + uid + '" style="padding:12px 0;color:var(--muted);font-size:var(--text-base)">Loading more content...</div>';
|
|
450
450
|
|
|
451
451
|
setTimeout(function() {
|
|
452
452
|
var el = document.getElementById(uid);
|
|
@@ -493,7 +493,7 @@ function openBugReport() {
|
|
|
493
493
|
var container = document.createElement('div');
|
|
494
494
|
container.style.cssText = 'display:flex;flex-direction:column;gap:12px';
|
|
495
495
|
var intro = document.createElement('p');
|
|
496
|
-
intro.style.cssText = 'color:var(--muted);font-size:
|
|
496
|
+
intro.style.cssText = 'color:var(--muted);font-size:var(--text-md);margin:0';
|
|
497
497
|
intro.textContent = 'File a bug on the Minions repo (yemi33/minions).';
|
|
498
498
|
|
|
499
499
|
var titleLabel = document.createElement('label');
|
|
@@ -559,7 +559,7 @@ async function submitBugReport() {
|
|
|
559
559
|
var container = document.createElement('div');
|
|
560
560
|
container.style.cssText = 'padding:24px;text-align:center';
|
|
561
561
|
var icon = document.createElement('div');
|
|
562
|
-
icon.style.cssText = 'font-size:
|
|
562
|
+
icon.style.cssText = 'font-size:var(--text-display);margin-bottom:12px';
|
|
563
563
|
icon.textContent = '\u{1F41B}';
|
|
564
564
|
var heading = document.createElement('div');
|
|
565
565
|
heading.style.cssText = 'color:var(--green);font-weight:600;margin-bottom:8px';
|
|
@@ -571,12 +571,12 @@ async function submitBugReport() {
|
|
|
571
571
|
link.href = safeUrl(d.url);
|
|
572
572
|
link.target = '_blank';
|
|
573
573
|
link.rel = 'noopener noreferrer';
|
|
574
|
-
link.style.cssText = 'color:var(--blue);font-size:
|
|
574
|
+
link.style.cssText = 'color:var(--blue);font-size:var(--text-lg)';
|
|
575
575
|
link.textContent = 'View issue on GitHub';
|
|
576
576
|
container.appendChild(link);
|
|
577
577
|
} else {
|
|
578
578
|
var msg = document.createElement('span');
|
|
579
|
-
msg.style.cssText = 'color:var(--muted);font-size:
|
|
579
|
+
msg.style.cssText = 'color:var(--muted);font-size:var(--text-md)';
|
|
580
580
|
msg.textContent = 'Issue created on yemi33/minions';
|
|
581
581
|
container.appendChild(msg);
|
|
582
582
|
}
|
|
@@ -596,7 +596,7 @@ async function submitBugReport() {
|
|
|
596
596
|
if (!errDiv) {
|
|
597
597
|
errDiv = document.createElement('div');
|
|
598
598
|
errDiv.id = 'bug-error';
|
|
599
|
-
errDiv.style.cssText = 'color:var(--red);font-size:
|
|
599
|
+
errDiv.style.cssText = 'color:var(--red);font-size:var(--text-md);padding:8px;background:rgba(248,81,73,0.1);border-radius:4px';
|
|
600
600
|
btn?.parentElement?.parentElement?.appendChild(errDiv);
|
|
601
601
|
}
|
|
602
602
|
errDiv.textContent = 'Error: ' + e.message;
|