@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.
Files changed (40) hide show
  1. package/dashboard/js/command-center.js +36 -36
  2. package/dashboard/js/detail-panel.js +12 -12
  3. package/dashboard/js/fre.js +9 -9
  4. package/dashboard/js/live-stream.js +2 -2
  5. package/dashboard/js/modal-qa.js +17 -17
  6. package/dashboard/js/qa.js +3 -3
  7. package/dashboard/js/refresh.js +8 -8
  8. package/dashboard/js/render-agents.js +12 -12
  9. package/dashboard/js/render-dispatch.js +8 -8
  10. package/dashboard/js/render-inbox.js +5 -5
  11. package/dashboard/js/render-managed.js +16 -16
  12. package/dashboard/js/render-meetings.js +36 -36
  13. package/dashboard/js/render-other.js +23 -23
  14. package/dashboard/js/render-pinned.js +1 -1
  15. package/dashboard/js/render-pipelines.js +36 -36
  16. package/dashboard/js/render-plans.js +23 -23
  17. package/dashboard/js/render-prd.js +100 -100
  18. package/dashboard/js/render-prs.js +10 -10
  19. package/dashboard/js/render-schedules.js +23 -23
  20. package/dashboard/js/render-skills.js +7 -7
  21. package/dashboard/js/render-utils.js +22 -22
  22. package/dashboard/js/render-watches.js +37 -37
  23. package/dashboard/js/render-work-items.js +34 -34
  24. package/dashboard/js/utils.js +8 -8
  25. package/dashboard/layout.html +20 -20
  26. package/dashboard/pages/engine.html +4 -4
  27. package/dashboard/pages/home.html +4 -4
  28. package/dashboard/pages/inbox.html +3 -3
  29. package/dashboard/pages/meetings.html +2 -2
  30. package/dashboard/pages/pipelines.html +2 -2
  31. package/dashboard/pages/plans.html +3 -3
  32. package/dashboard/pages/prs.html +2 -2
  33. package/dashboard/pages/schedule.html +2 -2
  34. package/dashboard/pages/tools.html +1 -1
  35. package/dashboard/pages/watches.html +2 -2
  36. package/dashboard/pages/work.html +3 -3
  37. package/dashboard/styles.css +38 -38
  38. package/docs/onboarding.md +2 -2
  39. package/engine.js +52 -6
  40. package/package.json +1 -1
@@ -110,11 +110,11 @@ function prRow(pr) {
110
110
  const prId = pr.id || '—';
111
111
  const pendingReason = pr._pendingReason ? String(pr._pendingReason) : '';
112
112
  const pendingReasonHtml = pendingReason
113
- ? '<div style="font-size:9px;color:var(--muted);margin-top:2px" title="Pending reason: ' + escapeHtml(pendingReason) + '">' + escapeHtml(pendingReason.replace(/_/g, ' ')) + '</div>'
113
+ ? '<div style="font-size:var(--text-xs);color:var(--muted);margin-top:2px" title="Pending reason: ' + escapeHtml(pendingReason) + '">' + escapeHtml(pendingReason.replace(/_/g, ' ')) + '</div>'
114
114
  : '';
115
115
  var followupCount = _countPrFollowups(pr);
116
116
  var followupChip = followupCount > 0
117
- ? ' <span class="pr-badge draft" style="font-size:8px" title="' + followupCount + ' follow-up work item(s) dispatched from comments on this PR">+' + followupCount + ' follow-up' + (followupCount === 1 ? '' : 's') + '</span>'
117
+ ? ' <span class="pr-badge draft" style="font-size:var(--text-xs)" title="' + followupCount + ' follow-up work item(s) dispatched from comments on this PR">+' + followupCount + ' follow-up' + (followupCount === 1 ? '' : 's') + '</span>'
118
118
  : '';
119
119
  // Issue #2969 — paused-cause chip(s). Prefer the API-enriched _pausedCauses
120
120
  // field; fall back to deriving from _noOpFixes for the /state/ disk-fetch
@@ -135,7 +135,7 @@ function prRow(pr) {
135
135
  + (rec.reason || 'unknown') + '. Click to resume (clears _noOpFixes['
136
136
  + cause + '] so the next discovery pass can re-dispatch).';
137
137
  return ' <button class="pr-badge rejected pr-paused-chip" '
138
- + 'style="font-size:8px;cursor:pointer;border:none" '
138
+ + 'style="font-size:var(--text-xs);cursor:pointer;border:none" '
139
139
  + 'title="' + escapeHtml(titleAttr) + '" '
140
140
  + 'data-pr-id="' + escapeHtml(String(pr.id || '')) + '" '
141
141
  + 'data-pr-cause="' + escapeHtml(cause) + '" '
@@ -151,7 +151,7 @@ function prRow(pr) {
151
151
  ? '<span class="pr-agent" style="color:var(--muted)" title="Vote pending confirmation">' + escapeHtml(sq.reviewer) + '…</span>'
152
152
  : pr.reviewedBy && pr.reviewedBy.length
153
153
  ? '<span class="pr-agent" title="' + escapeHtml(pr.reviewedBy.join(', ')) + '">' + escapeHtml(pr.reviewedBy.join(', ')) + '</span>'
154
- : '<span style="color:var(--muted);font-size:11px">—</span>';
154
+ : '<span style="color:var(--muted);font-size:var(--text-base)">—</span>';
155
155
  const createdLabel = (pr.created || '—').slice(0, 16).replace('T', ' ');
156
156
  // Per-row auto-observe toggle (W-mpmwxkzm0009ba0b). _contextOnly === true
157
157
  // means the engine polls status/comments but does NOT dispatch review/fix
@@ -201,9 +201,9 @@ function prRow(pr) {
201
201
  '<td>' + reviewerCell + '</td>' +
202
202
  '<td><span class="pr-badge ' + buildClass + '" title="' + escapeHtml(buildTitle || buildLabel) + '">' + escapeHtml(buildLabel) + '</span></td>' +
203
203
  '<td><span class="pr-badge ' + statusClass + '" title="' + escapeHtml(statusLabel) + '">' + escapeHtml(statusLabel) + '</span></td>' +
204
- '<td>' + (observeBtn || '<span style="color:var(--muted);font-size:11px">—</span>') + '</td>' +
204
+ '<td>' + (observeBtn || '<span style="color:var(--muted);font-size:var(--text-base)">—</span>') + '</td>' +
205
205
  '<td><span class="pr-date" title="' + escapeHtml(createdLabel) + '">' + escapeHtml(createdLabel) + '</span></td>' +
206
- '<td><button class="pr-pager-btn" style="font-size:9px;padding:1px 5px;color:var(--red);border-color:var(--red)" data-pr-id="' + escapeHtml(String(prId)) + '" onclick="event.stopPropagation();unlinkPr(this.dataset.prId)" title="Remove from tracking">x</button></td>' +
206
+ '<td><button class="pr-pager-btn" style="font-size:var(--text-xs);padding:1px 5px;color:var(--red);border-color:var(--red)" data-pr-id="' + escapeHtml(String(prId)) + '" onclick="event.stopPropagation();unlinkPr(this.dataset.prId)" title="Remove from tracking">x</button></td>' +
207
207
  '</tr>';
208
208
  }
209
209
 
@@ -305,8 +305,8 @@ function openModal(i) {
305
305
  document.getElementById('modal-title').textContent = item.name;
306
306
  // eslint-disable-next-line no-unsanitized/property -- reason: renderMd() escapes item.content before assembling HTML; item.name is wrapped in escapeHtml() (see dashboard/js/utils.js)
307
307
  document.getElementById('modal-body').innerHTML =
308
- '<div style="margin-bottom:12px"><button class="pr-pager-btn" style="font-size:10px;padding:3px 10px" onclick="promoteToKB(\'' + escapeHtml(item.name) + '\')">Add to Knowledge Base</button></div>' +
309
- '<div style="font-size:12px;line-height:1.7;color:var(--muted)">' + renderMd(item.content) + '</div>';
308
+ '<div style="margin-bottom:12px"><button class="pr-pager-btn" style="font-size:var(--text-sm);padding:3px 10px" onclick="promoteToKB(\'' + escapeHtml(item.name) + '\')">Add to Knowledge Base</button></div>' +
309
+ '<div style="font-size:var(--text-md);line-height:1.7;color:var(--muted)">' + renderMd(item.content) + '</div>';
310
310
  _modalDocContext = { title: item.name, content: item.content, selection: '' };
311
311
  _modalFilePath = 'notes/inbox/' + item.name; showModalQa();
312
312
  // Clear notification badge when opening this document
@@ -327,7 +327,7 @@ function openAddPrModal() {
327
327
  // added any project yet. We still allow the link (read-only tracking is valid),
328
328
  // but warn that auto-fix / auto-review can't dispatch without a project worktree.
329
329
  const noProjectsWarning = projects.length === 0
330
- ? '<div id="pr-link-no-projects-warning" style="padding:8px 12px;background:rgba(210,153,34,0.15);border:1px solid rgba(210,153,34,0.3);border-radius:var(--radius-sm);color:var(--yellow);font-size:11px;line-height:1.5;margin-bottom:4px">' +
330
+ ? '<div id="pr-link-no-projects-warning" style="padding:8px 12px;background:rgba(210,153,34,0.15);border:1px solid rgba(210,153,34,0.3);border-radius:var(--radius-sm);color:var(--yellow);font-size:var(--text-base);line-height:1.5;margin-bottom:4px">' +
331
331
  '<div style="font-weight:700;margin-bottom:2px">&#x26A0; No project configured.</div>' +
332
332
  '<div style="color:var(--text)">This PR will be tracked, but auto-fix and auto-review cannot dispatch against it &mdash; agents need a project worktree to operate in. Add a project first (Projects tab) to enable automation.</div>' +
333
333
  '</div>'
@@ -346,7 +346,7 @@ function openAddPrModal() {
346
346
  '<input type="checkbox" id="pr-link-observe" style="width:16px;height:16px;accent-color:var(--blue)">' +
347
347
  '<span>Auto-observe <span style="color:var(--muted);font-weight:400">(monitor builds, resolve comments, fix failures)</span></span>' +
348
348
  '</label>' +
349
- '<div style="font-size:11px;color:var(--muted);margin-top:-4px;padding-left:24px">Off = context only (e.g. teammate\'s PR). On = agents actively monitor and fix issues.</div>' +
349
+ '<div style="font-size:var(--text-base);color:var(--muted);margin-top:-4px;padding-left:24px">Off = context only (e.g. teammate\'s PR). On = agents actively monitor and fix issues.</div>' +
350
350
  '<div style="display:flex;justify-content:flex-end;gap:8px;margin-top:8px">' +
351
351
  '<button onclick="closeModal()" class="pr-pager-btn">Cancel</button>' +
352
352
  '<button onclick="_submitLinkPr(event)" style="padding:6px 16px;background:var(--blue);color:#fff;border:none;border-radius:var(--radius-sm);cursor:pointer">Link PR</button>' +
@@ -240,8 +240,8 @@ const _SLOT_COLORS = {
240
240
  function _renderViewToggle() {
241
241
  const isList = _schedViewMode === 'list';
242
242
  return '<div style="display:flex;gap:4px;margin-bottom:8px">' +
243
- '<button class="pr-pager-btn" style="font-size:9px;padding:2px 8px;' + (isList ? 'background:var(--blue);color:#fff;border-color:var(--blue)' : '') + '" onclick="_schedSetView(\'list\')">List</button>' +
244
- '<button class="pr-pager-btn" style="font-size:9px;padding:2px 8px;' + (!isList ? 'background:var(--blue);color:#fff;border-color:var(--blue)' : '') + '" onclick="_schedSetView(\'calendar\')">Calendar</button>' +
243
+ '<button class="pr-pager-btn" style="font-size:var(--text-xs);padding:2px 8px;' + (isList ? 'background:var(--blue);color:#fff;border-color:var(--blue)' : '') + '" onclick="_schedSetView(\'list\')">List</button>' +
244
+ '<button class="pr-pager-btn" style="font-size:var(--text-xs);padding:2px 8px;' + (!isList ? 'background:var(--blue);color:#fff;border-color:var(--blue)' : '') + '" onclick="_schedSetView(\'calendar\')">Calendar</button>' +
245
245
  '</div>';
246
246
  }
247
247
 
@@ -299,7 +299,7 @@ function _renderScheduleCalendar(schedules) {
299
299
  html += '<div class="sched-cal-slot" style="background:' + colors.bg + ';border-left-color:' + colors.border + ';color:' + colors.text + ';opacity:' + opacity + '" ' +
300
300
  'onclick="if(shouldIgnoreSelectionClick(event))return;openScheduleDetail(\'' + escHtml(s.id) + '\')" title="' + escHtml(s.title + ' — ' + timeLabel + ' — ' + (s.type || 'implement')) + '">' +
301
301
  '<span style="font-weight:600;' + strikeStyle + '">' + escHtml((s.title || s.id).slice(0, 25)) + '</span>' +
302
- '<span style="font-size:9px;opacity:0.7"> ' + timeLabel + '</span>' +
302
+ '<span style="font-size:var(--text-xs);opacity:0.7"> ' + timeLabel + '</span>' +
303
303
  '</div>';
304
304
  }
305
305
  if (cellSlots.length === 0) html += '&nbsp;';
@@ -345,17 +345,17 @@ function renderSchedules(schedules, opts) {
345
345
  html += '<tr data-sched-id="' + escHtml(s.id || '') + '" style="cursor:pointer" onclick="if(shouldIgnoreSelectionClick(event))return;openScheduleDetail(\'' + escHtml(s.id) + '\')">' +
346
346
  '<td><span class="pr-id">' + escHtml(s.id || '') + '</span></td>' +
347
347
  '<td style="max-width:200px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap" title="' + escHtml(s.title || '') + '">' + escHtml(s.title || '') + '</td>' +
348
- '<td><span title="' + escHtml(s.cron || '') + '" style="font-size:11px;color:var(--blue)">' + escHtml(humanCron) + '</span></td>' +
348
+ '<td><span title="' + escHtml(s.cron || '') + '" style="font-size:var(--text-base);color:var(--blue)">' + escHtml(humanCron) + '</span></td>' +
349
349
  '<td>' + typeBadge + '</td>' +
350
- '<td><span style="font-size:10px;color:var(--muted)">' + escHtml(s.project || '') + '</span></td>' +
350
+ '<td><span style="font-size:var(--text-sm);color:var(--muted)">' + escHtml(s.project || '') + '</span></td>' +
351
351
  '<td><span class="pr-agent">' + escHtml(s.agent || 'auto') + '</span></td>' +
352
352
  '<td>' + enabledBadge + '</td>' +
353
353
  '<td><span class="pr-date">' + escHtml(lastRun) + '</span></td>' +
354
354
  '<td style="white-space:nowrap">' +
355
- '<button class="pr-pager-btn" style="font-size:9px;padding:1px 6px;color:var(--green);border-color:var(--green);margin-right:4px" onclick="event.stopPropagation();runScheduleNow(\'' + escHtml(s.id) + '\',this)" title="Run now">Run now</button>' +
356
- '<button class="pr-pager-btn' + (_schedToggleInFlight.has(s.id) ? ' disabled' : '') + '" style="font-size:9px;padding:1px 6px;color:' + (s.enabled ? 'var(--yellow)' : 'var(--green)') + ';border-color:' + (s.enabled ? 'var(--yellow)' : 'var(--green)') + ';margin-right:4px" onclick="event.stopPropagation();toggleScheduleEnabled(\'' + escHtml(s.id) + '\',' + !s.enabled + ')" title="' + (s.enabled ? 'Disable' : 'Enable') + '">' + (s.enabled ? '&#x23F8;' : '&#x25B6;') + '</button>' +
357
- '<button class="pr-pager-btn" style="font-size:9px;padding:1px 6px;color:var(--blue);border-color:var(--blue);margin-right:4px" onclick="event.stopPropagation();openEditScheduleModal(\'' + escHtml(s.id) + '\')" title="Edit">&#x270E;</button>' +
358
- '<button class="pr-pager-btn" style="font-size:9px;padding:1px 6px;color:var(--red);border-color:var(--red)" onclick="event.stopPropagation();deleteSchedule(\'' + escHtml(s.id) + '\')" title="Delete">&#x2715;</button>' +
355
+ '<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();runScheduleNow(\'' + escHtml(s.id) + '\',this)" title="Run now">Run now</button>' +
356
+ '<button class="pr-pager-btn' + (_schedToggleInFlight.has(s.id) ? ' disabled' : '') + '" style="font-size:var(--text-xs);padding:1px 6px;color:' + (s.enabled ? 'var(--yellow)' : 'var(--green)') + ';border-color:' + (s.enabled ? 'var(--yellow)' : 'var(--green)') + ';margin-right:4px" onclick="event.stopPropagation();toggleScheduleEnabled(\'' + escHtml(s.id) + '\',' + !s.enabled + ')" title="' + (s.enabled ? 'Disable' : 'Enable') + '">' + (s.enabled ? '&#x23F8;' : '&#x25B6;') + '</button>' +
357
+ '<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();openEditScheduleModal(\'' + escHtml(s.id) + '\')" title="Edit">&#x270E;</button>' +
358
+ '<button class="pr-pager-btn" style="font-size:var(--text-xs);padding:1px 6px;color:var(--red);border-color:var(--red)" onclick="event.stopPropagation();deleteSchedule(\'' + escHtml(s.id) + '\')" title="Delete">&#x2715;</button>' +
359
359
  '</td>' +
360
360
  '</tr>';
361
361
  }
@@ -390,15 +390,15 @@ function openScheduleDetail(id) {
390
390
  // eslint-disable-next-line no-unsanitized/property -- reason: structural HTML is a string literal; all user data wrapped in escHtml() (fields: schedule title, schedule id)
391
391
  document.getElementById('modal-title').innerHTML = escHtml(s.title || s.id) +
392
392
  ' <div style="display:flex;gap:4px;margin-top:4px">' +
393
- '<button class="pr-pager-btn" style="font-size:10px;padding:2px 10px;color:var(--green)" onclick="runScheduleNow(\'' + escHtml(s.id) + '\',this)">Run now</button>' +
394
- '<button class="pr-pager-btn" style="font-size:10px;padding:2px 10px;color:var(--blue)" onclick="closeModal();openEditScheduleModal(\'' + escHtml(s.id) + '\')">Edit</button>' +
395
- '<button class="pr-pager-btn" style="font-size:10px;padding:2px 10px;color:' + (s.enabled ? 'var(--yellow)' : 'var(--green)') + '" onclick="toggleScheduleEnabled(\'' + escHtml(s.id) + '\',' + !s.enabled + ');closeModal()">' + (s.enabled ? 'Disable' : 'Enable') + '</button>' +
396
- '<button class="pr-pager-btn" style="font-size:10px;padding:2px 10px;color:var(--red)" onclick="deleteSchedule(\'' + escHtml(s.id) + '\');closeModal()">Delete</button>' +
393
+ '<button class="pr-pager-btn" style="font-size:var(--text-sm);padding:2px 10px;color:var(--green)" onclick="runScheduleNow(\'' + escHtml(s.id) + '\',this)">Run now</button>' +
394
+ '<button class="pr-pager-btn" style="font-size:var(--text-sm);padding:2px 10px;color:var(--blue)" onclick="closeModal();openEditScheduleModal(\'' + escHtml(s.id) + '\')">Edit</button>' +
395
+ '<button class="pr-pager-btn" style="font-size:var(--text-sm);padding:2px 10px;color:' + (s.enabled ? 'var(--yellow)' : 'var(--green)') + '" onclick="toggleScheduleEnabled(\'' + escHtml(s.id) + '\',' + !s.enabled + ');closeModal()">' + (s.enabled ? 'Disable' : 'Enable') + '</button>' +
396
+ '<button class="pr-pager-btn" style="font-size:var(--text-sm);padding:2px 10px;color:var(--red)" onclick="deleteSchedule(\'' + escHtml(s.id) + '\');closeModal()">Delete</button>' +
397
397
  '</div>';
398
398
 
399
- var body = '<div style="display:flex;flex-direction:column;gap:10px;font-size:12px;line-height:1.6">' +
399
+ var body = '<div style="display:flex;flex-direction:column;gap:10px;font-size:var(--text-md);line-height:1.6">' +
400
400
  '<div><strong style="color:var(--muted)">ID:</strong> ' + escHtml(s.id) + '</div>' +
401
- '<div><strong style="color:var(--muted)">Schedule:</strong> <span style="color:var(--blue)">' + escHtml(humanCron) + '</span> <code style="background:var(--bg);padding:1px 4px;border-radius:3px;font-size:10px">' + escHtml(s.cron || '') + '</code></div>' +
401
+ '<div><strong style="color:var(--muted)">Schedule:</strong> <span style="color:var(--blue)">' + escHtml(humanCron) + '</span> <code style="background:var(--bg);padding:1px 4px;border-radius:3px;font-size:var(--text-sm)">' + escHtml(s.cron || '') + '</code></div>' +
402
402
  '<div><strong style="color:var(--muted)">Type:</strong> <span class="dispatch-type ' + escHtml(s.type || 'implement') + '">' + escHtml(s.type || 'implement') + '</span></div>' +
403
403
  '<div><strong style="color:var(--muted)">Priority:</strong> ' + escHtml(s.priority || 'medium') + '</div>' +
404
404
  '<div><strong style="color:var(--muted)">Project:</strong> ' + escHtml(s.project || 'any') + '</div>' +
@@ -426,9 +426,9 @@ function _scheduleFormHtml(sched, isEdit) {
426
426
  const agentOpts = '<option value="">Auto</option>' + (cmdAgents || []).map(a => '<option value="' + escHtml(a.id) + '"' + (sched.agent === a.id ? ' selected' : '') + '>' + escHtml(a.name) + '</option>').join('');
427
427
 
428
428
  const inputStyle = 'display:block;width:100%;margin-top:4px;padding:6px 8px;background:var(--bg);border:1px solid var(--border);border-radius:var(--radius-sm);color:var(--text);font-size:var(--text-md);font-family:inherit';
429
- const pillStyle = 'display:inline-block;padding:4px 10px;margin:2px;border:1px solid var(--border);border-radius:12px;cursor:pointer;font-size:11px;color:var(--text);background:var(--bg);user-select:none;transition:all 0.15s';
429
+ const pillStyle = 'display:inline-block;padding:4px 10px;margin:2px;border:1px solid var(--border);border-radius:12px;cursor:pointer;font-size:var(--text-base);color:var(--text);background:var(--bg);user-select:none;transition:all 0.15s';
430
430
  const pillActiveExtra = 'background:var(--blue);color:#fff;border-color:var(--blue)';
431
- const linkStyle = 'font-size:10px;color:var(--blue);cursor:pointer;text-decoration:underline;margin-right:8px';
431
+ const linkStyle = 'font-size:var(--text-sm);color:var(--blue);cursor:pointer;text-decoration:underline;margin-right:8px';
432
432
 
433
433
  // Parse existing cron for picker defaults
434
434
  const picker = _parseCronToPicker(sched.cron || '');
@@ -458,14 +458,14 @@ function _scheduleFormHtml(sched, isEdit) {
458
458
  // ID section: auto-generated for create, read-only label for edit
459
459
  let idSection = '';
460
460
  if (isEdit) {
461
- idSection = '<div style="color:var(--muted);font-size:11px;margin-bottom:4px">ID: <strong style="color:var(--text)">' + escHtml(sched.id || '') + '</strong></div>';
461
+ idSection = '<div style="color:var(--muted);font-size:var(--text-base);margin-bottom:4px">ID: <strong style="color:var(--text)">' + escHtml(sched.id || '') + '</strong></div>';
462
462
  } else {
463
- idSection = '<div id="sched-auto-id" style="color:var(--muted);font-size:11px;margin-bottom:4px">ID: <strong style="color:var(--text)">auto-generated from title</strong></div>';
463
+ idSection = '<div id="sched-auto-id" style="color:var(--muted);font-size:var(--text-base);margin-bottom:4px">ID: <strong style="color:var(--text)">auto-generated from title</strong></div>';
464
464
  }
465
465
 
466
466
  return '<div style="display:flex;flex-direction:column;gap:12px;font-family:inherit">' +
467
467
  idSection +
468
- '<div id="sched-form-error" style="display:none;color:var(--red);font-size:12px;padding:6px 10px;background:rgba(255,50,50,0.1);border-radius:var(--radius-sm)"></div>' +
468
+ '<div id="sched-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>' +
469
469
  '<label style="color:var(--text);font-size:var(--text-md)">Title' +
470
470
  '<input id="sched-edit-title" value="' + escHtml(sched.title || '') + '" style="' + inputStyle + '"' +
471
471
  (!isEdit ? " oninput=\"(function(v){var el=document.querySelector('#sched-auto-id strong');if(el)el.textContent=v?window._generateScheduleId(v):'auto-generated from title'})(this.value)\"" : '') + '>' +
@@ -487,11 +487,11 @@ function _scheduleFormHtml(sched, isEdit) {
487
487
  '<div id="sched-cron-nl" style="display:none">' +
488
488
  '<label style="color:var(--text);font-size:var(--text-md)">Schedule (natural language)</label>' +
489
489
  '<textarea id="sched-nl-input" rows="2" placeholder="every weekday at 9am" style="' + inputStyle + ';resize:vertical;margin-top:4px"></textarea>' +
490
- '<button onclick="_parseNaturalCron()" style="margin-top:6px;padding:4px 12px;font-size:11px;background:var(--blue);color:#fff;border:none;border-radius:var(--radius-sm);cursor:pointer">Parse \u2192</button>' +
491
- '<div id="sched-nl-error" style="color:var(--red);font-size:11px;margin-top:4px"></div>' +
490
+ '<button onclick="_parseNaturalCron()" style="margin-top:6px;padding:4px 12px;font-size:var(--text-base);background:var(--blue);color:#fff;border:none;border-radius:var(--radius-sm);cursor:pointer">Parse \u2192</button>' +
491
+ '<div id="sched-nl-error" style="color:var(--red);font-size:var(--text-base);margin-top:4px"></div>' +
492
492
  '</div>' +
493
493
  '<div style="margin-top:2px">' +
494
- '<span id="sched-cron-preview" style="font-size:11px;color:var(--blue)">\u2192 cron: ' + escHtml(computedCron) + '</span>' +
494
+ '<span id="sched-cron-preview" style="font-size:var(--text-base);color:var(--blue)">\u2192 cron: ' + escHtml(computedCron) + '</span>' +
495
495
  '<br><span id="sched-cron-mode-toggle" style="' + linkStyle + ';margin-top:4px;display:inline-block" onclick="_toggleCronMode()">Use natural language</span>' +
496
496
  '</div>' +
497
497
  '<div style="display:flex;gap:12px">' +
@@ -63,7 +63,7 @@ function renderSkills(skills) {
63
63
  let html = '<div style="display:flex;gap:4px;margin-bottom:8px;flex-wrap:wrap">';
64
64
  for (const t of tabs) {
65
65
  const active = _skillsTab === t.key;
66
- html += '<button class="pr-pager-btn" style="font-size:9px;padding:2px 8px;' +
66
+ html += '<button class="pr-pager-btn" style="font-size:var(--text-xs);padding:2px 8px;' +
67
67
  (active ? 'background:var(--green);color:#fff;border-color:var(--green)' : '') +
68
68
  '" onclick="_skillsSelectTab(' + _jsArg(t.key) + ')">' + escHtml(t.label) + '</button>';
69
69
  }
@@ -73,7 +73,7 @@ function renderSkills(skills) {
73
73
  // native locations (~/.claude/skills, ~/.copilot/skills, plugin skills) are
74
74
  // only visible to that runtime. The "agent" tab (~/.agents/skills) is the
75
75
  // cross-runtime portable bucket and IS visible to every runtime.
76
- html += '<div style="font-size:9px;color:var(--muted);margin-bottom:8px;line-height:1.4">' +
76
+ html += '<div style="font-size:var(--text-xs);color:var(--muted);margin-bottom:8px;line-height:1.4">' +
77
77
  'Skills are reference docs agents read on demand — they are not injected wholesale into prompts. ' +
78
78
  'Each tab reflects what the matching runtime would see; runtime-native skills are NOT cross-visible. ' +
79
79
  'The agent tab (~/.agents/skills) is the cross-runtime portable bucket — visible to every runtime.' +
@@ -90,10 +90,10 @@ function renderSkills(skills) {
90
90
  html += '<div style="display:flex;flex-direction:column;gap:6px">';
91
91
  for (const r of page) {
92
92
  const meta = _skillMetaOf(r.source);
93
- const autoTag = r.autoGenerated ? '<span style="font-size:8px;background:rgba(63,185,80,0.15);color:var(--green);padding:1px 4px;border-radius:3px;margin-left:4px">auto</span>' : '';
93
+ const autoTag = r.autoGenerated ? '<span style="font-size:var(--text-xs);background:rgba(63,185,80,0.15);color:var(--green);padding:1px 4px;border-radius:3px;margin-left:4px">auto</span>' : '';
94
94
  html += '<div class="inbox-item" onclick="openSkill(' + _jsArg(r.file) + ',' + _jsArg(r.source || 'claude-code') + ',' + _jsArg(r.dir || '') + ')" style="border-left-color:var(--green)">' +
95
95
  '<div class="inbox-name"><span style="color:var(--green);font-weight:600">' + meta.icon + ' ' + escHtml(r.name) + '</span>' + autoTag +
96
- '<span style="font-size:9px;color:var(--muted);margin-left:auto">' + escHtml(meta.label) + '</span>' +
96
+ '<span style="font-size:var(--text-xs);color:var(--muted);margin-left:auto">' + escHtml(meta.label) + '</span>' +
97
97
  '</div>' +
98
98
  (r.description ? '<div class="inbox-preview" style="color:var(--text)">' + escHtml(r.description) + '</div>' : '') +
99
99
  '</div>';
@@ -103,11 +103,11 @@ function renderSkills(skills) {
103
103
  // Pagination controls
104
104
  if (totalPages > 1) {
105
105
  html += '<div style="display:flex;align-items:center;gap:8px;margin-top:6px;justify-content:center">';
106
- html += '<button class="pr-pager-btn" style="font-size:9px;padding:2px 8px" ' +
106
+ html += '<button class="pr-pager-btn" style="font-size:var(--text-xs);padding:2px 8px" ' +
107
107
  (_skillsPage === 0 ? 'disabled' : '') +
108
108
  ' onclick="_skillsPage--;renderSkills(window._lastSkills)">&laquo;</button>';
109
- html += '<span style="font-size:10px;color:var(--muted)">' + (_skillsPage + 1) + ' / ' + totalPages + '</span>';
110
- html += '<button class="pr-pager-btn" style="font-size:9px;padding:2px 8px" ' +
109
+ html += '<span style="font-size:var(--text-sm);color:var(--muted)">' + (_skillsPage + 1) + ' / ' + totalPages + '</span>';
110
+ html += '<button class="pr-pager-btn" style="font-size:var(--text-xs);padding:2px 8px" ' +
111
111
  (_skillsPage >= totalPages - 1 ? 'disabled' : '') +
112
112
  ' onclick="_skillsPage++;renderSkills(window._lastSkills)">&raquo;</button>';
113
113
  html += '</div>';
@@ -15,7 +15,7 @@ function renderToolChip(t) {
15
15
  var input = typeof t === 'string' ? {} : (t.input || {});
16
16
  var status = typeof t === 'string' ? null : (t.status || null);
17
17
  var style = _CC_TOOL_CHIP_STYLE[status] || _CC_TOOL_CHIP_STYLE.pending;
18
- return '<div style="color:' + style.color + ';font-size:10px;font-family:monospace">'
18
+ return '<div style="color:' + style.color + ';font-size:var(--text-sm);font-family:monospace">'
19
19
  + '<span style="flex-shrink:0">' + style.marker + '</span> '
20
20
  + formatToolSummary(name, input)
21
21
  + '</div>';
@@ -91,25 +91,25 @@ function _renderJsonObj(obj, state) {
91
91
 
92
92
  function assistantBubbleHtml(text) {
93
93
  return '<div style="display:flex;align-items:baseline;gap:6px;margin:4px 0">' +
94
- '<span style="color:var(--muted);font-size:10px;flex-shrink:0">&#9679;</span>' +
95
- '<div style="background:var(--surface2);padding:8px 12px;border-radius:12px 12px 12px 2px;max-width:90%;font-size:12px;word-break:break-word">' + renderMd(text) + '</div>' +
94
+ '<span style="color:var(--muted);font-size:var(--text-sm);flex-shrink:0">&#9679;</span>' +
95
+ '<div style="background:var(--surface2);padding:8px 12px;border-radius:12px 12px 12px 2px;max-width:90%;font-size:var(--text-md);word-break:break-word">' + renderMd(text) + '</div>' +
96
96
  '</div>';
97
97
  }
98
98
  function toolUseHtml(name, input) {
99
99
  var summary = formatToolSummary(name || 'tool', input || {});
100
100
  var rawJson = escHtml(JSON.stringify(input || {}, null, 2).slice(0, 500));
101
- return '<div style="display:flex;align-items:center;gap:4px;margin:2px 0;font-size:10px;color:var(--muted);font-family:monospace">' +
101
+ return '<div style="display:flex;align-items:center;gap:4px;margin:2px 0;font-size:var(--text-sm);color:var(--muted);font-family:monospace">' +
102
102
  '<span style="flex-shrink:0">&#9679;</span>' +
103
103
  '<span>' + summary + '</span>' +
104
104
  '<span style="cursor:pointer;opacity:0.6;margin-left:4px" onclick="var t=this.parentElement.nextElementSibling;t.style.display=t.style.display===\'none\'?\'block\':\'none\';this.textContent=t.style.display===\'none\'?\'[+]\':\'[-]\'">[+]</span>' +
105
105
  '</div>' +
106
- '<div style="display:none;background:var(--bg);padding:4px 8px;border-radius:4px;margin:0 0 4px 16px;font-size:10px;font-family:monospace;white-space:pre-wrap;max-height:200px;overflow-y:auto;color:var(--muted)">' + rawJson + '</div>';
106
+ '<div style="display:none;background:var(--bg);padding:4px 8px;border-radius:4px;margin:0 0 4px 16px;font-size:var(--text-sm);font-family:monospace;white-space:pre-wrap;max-height:200px;overflow-y:auto;color:var(--muted)">' + rawJson + '</div>';
107
107
  }
108
108
  function toolResultHtml(text) {
109
109
  if (!text || text.length <= 10) return '';
110
110
  var truncated = text.length > 3000;
111
111
  var displayText = truncated ? text.slice(0, 3000) + '...' : text;
112
- return '<div style="background:var(--surface);border-left:2px solid var(--border);padding:2px 8px;margin:0 0 2px 16px;font-size:9px;font-family:monospace;color:var(--muted);max-height:160px;overflow-y:auto;white-space:pre-wrap;cursor:pointer" onclick="this.style.maxHeight=this.style.maxHeight===\'160px\'?\'none\':\'160px\'">' + escHtml(displayText) + '</div>';
112
+ return '<div style="background:var(--surface);border-left:2px solid var(--border);padding:2px 8px;margin:0 0 2px 16px;font-size:var(--text-xs);font-family:monospace;color:var(--muted);max-height:160px;overflow-y:auto;white-space:pre-wrap;cursor:pointer" onclick="this.style.maxHeight=this.style.maxHeight===\'160px\'?\'none\':\'160px\'">' + escHtml(displayText) + '</div>';
113
113
  }
114
114
  function toolKey(name, input) {
115
115
  try { return String(name || 'tool') + '|' + JSON.stringify(input || {}); }
@@ -121,7 +121,7 @@ function _renderJsonObj(obj, state) {
121
121
  for (var i = 0; i < content.length; i++) {
122
122
  var block = content[i];
123
123
  if (block.type === 'thinking') {
124
- parts.push('<div style="font-size:10px;color:var(--muted);padding:2px 8px;font-style:italic">\u{1F4AD} Thinking...</div>');
124
+ parts.push('<div style="font-size:var(--text-sm);color:var(--muted);padding:2px 8px;font-style:italic">\u{1F4AD} Thinking...</div>');
125
125
  }
126
126
  if (block.type === 'text' && block.text) {
127
127
  parts.push(assistantBubbleHtml(block.text));
@@ -144,7 +144,7 @@ function _renderJsonObj(obj, state) {
144
144
 
145
145
  if (obj.type === 'assistant.message_delta' && typeof obj.data?.deltaContent === 'string') {
146
146
  if (state.copilotReasoningPending) {
147
- parts.push('<div style="font-size:10px;color:var(--muted);padding:2px 8px;font-style:italic">\u{1F4AD} Thinking...</div>');
147
+ parts.push('<div style="font-size:var(--text-sm);color:var(--muted);padding:2px 8px;font-style:italic">\u{1F4AD} Thinking...</div>');
148
148
  state.copilotReasoningPending = false;
149
149
  }
150
150
  state.copilotDeltaBuffer += obj.data.deltaContent;
@@ -152,7 +152,7 @@ function _renderJsonObj(obj, state) {
152
152
 
153
153
  if (obj.type === 'assistant.message') {
154
154
  if (state.copilotReasoningPending) {
155
- parts.push('<div style="font-size:10px;color:var(--muted);padding:2px 8px;font-style:italic">\u{1F4AD} Thinking...</div>');
155
+ parts.push('<div style="font-size:var(--text-sm);color:var(--muted);padding:2px 8px;font-style:italic">\u{1F4AD} Thinking...</div>');
156
156
  state.copilotReasoningPending = false;
157
157
  }
158
158
  state.copilotDeltaBuffer = '';
@@ -221,13 +221,13 @@ function renderAgentOutput(text) {
221
221
 
222
222
  function flushCopilotPending() {
223
223
  if (state.copilotReasoningPending) {
224
- fragments.push('<div style="font-size:10px;color:var(--muted);padding:2px 8px;font-style:italic">\u{1F4AD} Thinking...</div>');
224
+ fragments.push('<div style="font-size:var(--text-sm);color:var(--muted);padding:2px 8px;font-style:italic">\u{1F4AD} Thinking...</div>');
225
225
  state.copilotReasoningPending = false;
226
226
  }
227
227
  if (state.copilotDeltaBuffer) {
228
228
  fragments.push('<div style="display:flex;align-items:baseline;gap:6px;margin:4px 0">' +
229
- '<span style="color:var(--muted);font-size:10px;flex-shrink:0">&#9679;</span>' +
230
- '<div style="background:var(--surface2);padding:8px 12px;border-radius:12px 12px 12px 2px;max-width:90%;font-size:12px;word-break:break-word">' + renderMd(state.copilotDeltaBuffer) + '</div>' +
229
+ '<span style="color:var(--muted);font-size:var(--text-sm);flex-shrink:0">&#9679;</span>' +
230
+ '<div style="background:var(--surface2);padding:8px 12px;border-radius:12px 12px 12px 2px;max-width:90%;font-size:var(--text-md);word-break:break-word">' + renderMd(state.copilotDeltaBuffer) + '</div>' +
231
231
  '</div>');
232
232
  state.copilotDeltaBuffer = '';
233
233
  }
@@ -253,16 +253,16 @@ function renderAgentOutput(text) {
253
253
  // Human steering
254
254
  if (trimmed.startsWith('[human-steering]')) {
255
255
  var msg = trimmed.replace('[human-steering] ', '');
256
- fragments.push('<div style="align-self:flex-end;background:var(--blue);color:#fff;padding:6px 12px;border-radius:12px 12px 2px 12px;max-width:80%;margin:4px 0;font-size:12px">' +
256
+ fragments.push('<div style="align-self:flex-end;background:var(--blue);color:#fff;padding:6px 12px;border-radius:12px 12px 2px 12px;max-width:80%;margin:4px 0;font-size:var(--text-md)">' +
257
257
  '<span style="margin-right:4px">❯</span>' + escHtml(msg) +
258
- '<div style="font-size:9px;opacity:0.7;margin-top:2px">\u2713 Queued</div></div>');
258
+ '<div style="font-size:var(--text-xs);opacity:0.7;margin-top:2px">\u2713 Queued</div></div>');
259
259
  continue;
260
260
  }
261
261
 
262
262
  // Steering failed
263
263
  if (trimmed.startsWith('[steering-failed]')) {
264
264
  var failMsg = trimmed.replace('[steering-failed] ', '');
265
- fragments.push('<div style="background:rgba(248,81,73,0.1);border:1px solid var(--red);color:var(--red);padding:6px 12px;border-radius:8px;margin:4px 0;font-size:11px">\u26A0 ' + escHtml(failMsg) + '</div>');
265
+ fragments.push('<div style="background:rgba(248,81,73,0.1);border:1px solid var(--red);color:var(--red);padding:6px 12px;border-radius:8px;margin:4px 0;font-size:var(--text-base)">\u26A0 ' + escHtml(failMsg) + '</div>');
266
266
  continue;
267
267
  }
268
268
 
@@ -293,10 +293,10 @@ function renderAgentOutput(text) {
293
293
 
294
294
  // Stderr
295
295
  if (trimmed.startsWith('[stderr]')) {
296
- fragments.push('<div style="font-size:9px;color:var(--red);font-family:monospace;padding:1px 4px">' + escHtml(trimmed) + '</div>');
296
+ fragments.push('<div style="font-size:var(--text-xs);color:var(--red);font-family:monospace;padding:1px 4px">' + escHtml(trimmed) + '</div>');
297
297
  } else {
298
298
  // Plain text fallback
299
- fragments.push('<div style="font-size:10px;color:var(--muted);font-family:monospace;padding:1px 4px">' + escHtml(trimmed) + '</div>');
299
+ fragments.push('<div style="font-size:var(--text-sm);color:var(--muted);font-family:monospace;padding:1px 4px">' + escHtml(trimmed) + '</div>');
300
300
  }
301
301
  }
302
302
 
@@ -340,15 +340,15 @@ function renderTerminalBanner(event) {
340
340
  headline = glyph + ' Task ended with ' + escHtml(String(reasonWord));
341
341
  }
342
342
  var extra = '';
343
- if (event.summary) extra += '<div style="font-size:11px;margin-top:4px;opacity:0.9">' + escHtml(event.summary) + '</div>';
343
+ if (event.summary) extra += '<div style="font-size:var(--text-base);margin-top:4px;opacity:0.9">' + escHtml(event.summary) + '</div>';
344
344
  if (event.reason && event.reason !== event.summary) {
345
- extra += '<div style="font-size:10px;margin-top:2px;opacity:0.75">' + escHtml(event.reason) + '</div>';
345
+ extra += '<div style="font-size:var(--text-sm);margin-top:2px;opacity:0.75">' + escHtml(event.reason) + '</div>';
346
346
  }
347
347
  if (event.prUrl) {
348
348
  var safeUrl = encodeURI(String(event.prUrl));
349
- extra += '<div style="font-size:11px;margin-top:4px"><a href="' + escHtml(safeUrl) + '" target="_blank" rel="noopener" style="color:' + color + '">' + escHtml(event.prUrl) + '</a></div>';
349
+ extra += '<div style="font-size:var(--text-base);margin-top:4px"><a href="' + escHtml(safeUrl) + '" target="_blank" rel="noopener" style="color:' + color + '">' + escHtml(event.prUrl) + '</a></div>';
350
350
  }
351
- return '<div style="background:' + bg + ';border:1px solid ' + color + ';padding:8px 12px;border-radius:8px;margin:8px 0;font-size:12px;color:' + color + '">' +
351
+ return '<div style="background:' + bg + ';border:1px solid ' + color + ';padding:8px 12px;border-radius:8px;margin:8px 0;font-size:var(--text-md);color:' + color + '">' +
352
352
  headline + extra +
353
353
  '</div>';
354
354
  }
@@ -399,7 +399,7 @@ function renderPager(opts) {
399
399
  function pinButton(pinKey, pinned, source, opts) {
400
400
  var extraStyle = (opts && opts.extraStyle) || '';
401
401
  return '<button class="pr-pager-btn pin-btn' + (pinned ? ' pinned' : '') +
402
- '" style="font-size:9px;padding:2px 8px;' + extraStyle +
402
+ '" style="font-size:var(--text-xs);padding:2px 8px;' + extraStyle +
403
403
  '" data-pin-key="' + escHtml(pinKey) +
404
404
  '" onclick="event.stopPropagation();_togglePinAndRefresh(this.dataset.pinKey,\'' + source + '\')">' +
405
405
  (pinned ? 'Unpin' : 'Pin') + '</button>';