@yemi33/minions 0.1.2158 → 0.1.2159

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.
@@ -118,7 +118,7 @@ function renderDetailContent(detail, tab) {
118
118
  el.innerHTML =
119
119
  '<div style="display:flex;gap:6px;margin-bottom:8px">' +
120
120
  '<button class="pr-pager-btn" id="charter-edit-btn" style="font-size:var(--text-sm);padding:2px 10px" onclick="_toggleCharterEdit()">Edit</button>' +
121
- '<button class="pr-pager-btn" id="charter-save-btn" style="font-size:var(--text-sm);padding:2px 10px;color:var(--green);border-color:var(--green);display:none" onclick="_saveCharter()">Save</button>' +
121
+ '<button class="modal-copy is-success" id="charter-save-btn" style="display:none" onclick="_saveCharter()">Save</button>' +
122
122
  '<button class="pr-pager-btn" id="charter-cancel-btn" style="font-size:var(--text-sm);padding:2px 10px;display:none" onclick="_cancelCharterEdit()">Cancel</button>' +
123
123
  '</div>' +
124
124
  '<div id="charter-view" class="section">' + renderMd(charterContent || 'No charter found. Click Edit to create one.') + '</div>' +
@@ -120,17 +120,10 @@ function renderFre(statusOrProjects) {
120
120
  'flex-shrink:0',
121
121
  ].join(';');
122
122
 
123
- const btnPrimary = [
124
- 'padding:6px 14px',
125
- 'background:var(--blue)',
126
- 'color:#fff',
127
- 'border:none',
128
- 'border-radius:var(--radius-sm)',
129
- 'cursor:pointer',
130
- 'font-size:var(--text-md)',
131
- 'font-weight:600',
132
- 'margin-top:8px',
133
- ].join(';');
123
+ // W-mq57qetc0009ed48: blue-primary CTA inline blob removed; "+ Add Project"
124
+ // now uses the shared .btn-primary-solid primitive. Only the layout-only
125
+ // margin-top:8px stays inline.
126
+ const btnPrimaryMarginTop = 'margin-top:8px';
134
127
 
135
128
  const btnGhost = [
136
129
  'padding:6px 14px',
@@ -187,7 +180,7 @@ function renderFre(statusOrProjects) {
187
180
  '<div style="color:var(--muted);font-size:var(--text-md);line-height:1.5">' +
188
181
  'Projects map a local git worktree to a remote repo. Without a project, agents have nowhere to run.' +
189
182
  '</div>' +
190
- '<button onclick="addProject()" style="' + btnPrimary + '">+ Add Project</button>' +
183
+ '<button onclick="addProject()" class="btn-primary-solid" style="' + btnPrimaryMarginTop + '">+ Add Project</button>' +
191
184
  '</div>' +
192
185
  '</div>' +
193
186
 
@@ -229,8 +229,8 @@ async function loadQaRunbooks() {
229
229
  '</div>' +
230
230
  '</div>' +
231
231
  '<div class="qa-runbook-actions" style="display:flex;gap:var(--space-2)">' +
232
- '<button class="qa-btn-primary qa-runbook-run-btn" data-runbook-id="' + escHtml(id) + '" onclick="qaRunRunbook(this.dataset.runbookId)">Run</button>' +
233
- '<button class="qa-btn-ghost qa-btn-danger qa-runbook-delete-btn" data-runbook-id="' + escHtml(id) + '" onclick="qaDeleteRunbook(this.dataset.runbookId)">Delete</button>' +
232
+ '<button class="btn-primary-solid qa-runbook-run-btn" data-runbook-id="' + escHtml(id) + '" onclick="qaRunRunbook(this.dataset.runbookId)">Run</button>' +
233
+ '<button class="btn-ghost qa-btn-danger qa-runbook-delete-btn" data-runbook-id="' + escHtml(id) + '" onclick="qaDeleteRunbook(this.dataset.runbookId)">Delete</button>' +
234
234
  '</div>' +
235
235
  '</div>';
236
236
  }).join('');
@@ -350,7 +350,7 @@ function _qaRenderRunRow(run) {
350
350
  // to click.
351
351
  let deleteBtn = '';
352
352
  if (_qaIsTerminalStatus(status)) {
353
- deleteBtn = '<button class="qa-btn-ghost qa-run-delete-btn" ' +
353
+ deleteBtn = '<button class="btn-ghost qa-run-delete-btn" ' +
354
354
  'data-run-id="' + escHtml(id) + '" ' +
355
355
  'onclick="qaDeleteRun(this.dataset.runId)">Delete</button>';
356
356
  }
@@ -731,14 +731,14 @@ function _qaRenderSessionCard(s) {
731
731
  // - terminal → no actions
732
732
  let actions = '';
733
733
  if (state === 'awaiting-approval') {
734
- actions += '<button class="qa-btn-ghost" onclick="qaSessionReviewDraft(\'' + escHtml(id) + '\')">Review draft</button>';
735
- actions += '<button class="qa-btn-primary" onclick="qaSessionApprove(\'' + escHtml(id) + '\')">Approve &amp; run</button>';
736
- actions += '<button class="qa-btn-ghost" onclick="qaSessionEditPrompt(\'' + escHtml(id) + '\')">Edit</button>';
737
- actions += '<button class="qa-btn-ghost" onclick="qaSessionCancel(\'' + escHtml(id) + '\')">Cancel</button>';
734
+ actions += '<button class="btn-ghost" onclick="qaSessionReviewDraft(\'' + escHtml(id) + '\')">Review draft</button>';
735
+ actions += '<button class="btn-primary-solid" onclick="qaSessionApprove(\'' + escHtml(id) + '\')">Approve &amp; run</button>';
736
+ actions += '<button class="btn-ghost" onclick="qaSessionEditPrompt(\'' + escHtml(id) + '\')">Edit</button>';
737
+ actions += '<button class="btn-ghost" onclick="qaSessionCancel(\'' + escHtml(id) + '\')">Cancel</button>';
738
738
  }
739
739
  if (!isTerminal) {
740
- actions += '<button class="qa-btn-ghost" onclick="qaSessionDismiss(\'' + escHtml(id) + '\')">Dismiss</button>';
741
- actions += '<button class="qa-btn-ghost qa-btn-danger" onclick="qaSessionKill(\'' + escHtml(id) + '\')">Kill spawn</button>';
740
+ actions += '<button class="btn-ghost" onclick="qaSessionDismiss(\'' + escHtml(id) + '\')">Dismiss</button>';
741
+ actions += '<button class="btn-ghost qa-btn-danger" onclick="qaSessionKill(\'' + escHtml(id) + '\')">Kill spawn</button>';
742
742
  }
743
743
 
744
744
  let meta = '';
@@ -976,7 +976,7 @@ function _qaBuildModalShell(sessionId) {
976
976
  header.appendChild(title);
977
977
  const closeBtn = document.createElement('button');
978
978
  closeBtn.type = 'button';
979
- closeBtn.className = 'qa-btn-ghost qa-modal-close';
979
+ closeBtn.className = 'btn-ghost qa-modal-close';
980
980
  closeBtn.setAttribute('aria-label', 'Close');
981
981
  closeBtn.textContent = '×';
982
982
  closeBtn.addEventListener('click', _qaModalClose);
@@ -1080,7 +1080,7 @@ function _qaModalRenderBody(payload) {
1080
1080
  if (!payload.truncated) {
1081
1081
  const approve = document.createElement('button');
1082
1082
  approve.type = 'button';
1083
- approve.className = 'qa-btn-primary';
1083
+ approve.className = 'btn-primary-solid';
1084
1084
  approve.textContent = 'Approve & run';
1085
1085
  approve.addEventListener('click', () => {
1086
1086
  _qaModalClose();
@@ -1090,7 +1090,7 @@ function _qaModalRenderBody(payload) {
1090
1090
  }
1091
1091
  const editBtn = document.createElement('button');
1092
1092
  editBtn.type = 'button';
1093
- editBtn.className = 'qa-btn-ghost';
1093
+ editBtn.className = 'btn-ghost';
1094
1094
  editBtn.textContent = 'Request edit';
1095
1095
  editBtn.addEventListener('click', () => {
1096
1096
  _qaModalClose();
@@ -1099,7 +1099,7 @@ function _qaModalRenderBody(payload) {
1099
1099
  footer.appendChild(editBtn);
1100
1100
  const closeBtn = document.createElement('button');
1101
1101
  closeBtn.type = 'button';
1102
- closeBtn.className = 'qa-btn-ghost';
1102
+ closeBtn.className = 'btn-ghost';
1103
1103
  closeBtn.textContent = 'Close';
1104
1104
  closeBtn.addEventListener('click', _qaModalClose);
1105
1105
  footer.appendChild(closeBtn);
@@ -143,7 +143,7 @@ async function openAgentDetail(id) {
143
143
  document.getElementById('detail-content').innerHTML =
144
144
  '<div style="padding:24px;text-align:center">' +
145
145
  '<div style="color:var(--red);margin-bottom:12px">Error loading agent detail: ' + escapeHtml(e.message) + '</div>' +
146
- '<button data-agent-id="' + escapeHtml(id) + '" onclick="openAgentDetail(this.dataset.agentId)" style="padding:6px 16px;background:var(--blue);color:#fff;border:none;border-radius:var(--radius-sm);cursor:pointer;font-size:var(--text-md)">Retry</button>' +
146
+ '<button data-agent-id="' + escapeHtml(id) + '" onclick="openAgentDetail(this.dataset.agentId)" class="btn-primary-lg">Retry</button>' +
147
147
  ' <button onclick="closeDetail()" style="padding:6px 16px;background:var(--surface2);border:1px solid var(--border);border-radius:var(--radius-sm);cursor:pointer;font-size:var(--text-md);color:var(--text)">Close</button>' +
148
148
  '</div>';
149
149
  }
@@ -270,7 +270,7 @@ function openQuickNoteModal() {
270
270
  '<textarea id="note-content" rows="6" style="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);resize:vertical;font-family:inherit" placeholder="Write your note... Agents will see this after consolidation."></textarea></label>' +
271
271
  '<div style="display:flex;justify-content:flex-end;gap:8px">' +
272
272
  '<button onclick="closeModal()" class="pr-pager-btn">Cancel</button>' +
273
- '<button onclick="submitQuickNote()" style="padding:6px 16px;background:var(--blue);color:#fff;border:none;border-radius:var(--radius-sm);cursor:pointer">Save Note</button>' +
273
+ '<button onclick="submitQuickNote()" class="btn-primary-lg">Save Note</button>' +
274
274
  '</div>' +
275
275
  '</div>';
276
276
  document.getElementById('modal').classList.add('open');
@@ -222,7 +222,7 @@ function openCreateKbModal() {
222
222
  '<textarea id="kb-new-content" rows="8" style="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);resize:vertical;font-family:inherit" placeholder="Write your knowledge entry..."></textarea></label>' +
223
223
  '<div style="display:flex;justify-content:flex-end;gap:8px">' +
224
224
  '<button onclick="closeModal()" class="pr-pager-btn">Cancel</button>' +
225
- '<button onclick="submitKbEntry(event)" style="padding:6px 16px;background:var(--blue);color:#fff;border:none;border-radius:var(--radius-sm);cursor:pointer">Save</button>' +
225
+ '<button onclick="submitKbEntry(event)" class="btn-primary-lg">Save</button>' +
226
226
  '</div>' +
227
227
  '</div>';
228
228
  document.getElementById('modal').classList.add('open');
@@ -123,7 +123,7 @@ function renderMeetings(meetings, opts) {
123
123
  (m.status === 'archived'
124
124
  ? '<button class="pr-pager-btn" style="font-size:var(--text-xs);padding:1px 6px" onclick="event.stopPropagation();_unarchiveMeeting(\'' + escHtml(m.id) + '\')">Unarchive</button>'
125
125
  : (m.status === 'completed' ? '<button class="pr-pager-btn" style="font-size:var(--text-xs);padding:1px 6px" onclick="event.stopPropagation();_archiveMeeting(\'' + escHtml(m.id) + '\')">Archive</button>' : '')) +
126
- '<button class="pr-pager-btn" style="font-size:var(--text-xs);padding:1px 6px;color:var(--red);border-color:var(--red)" onclick="event.stopPropagation();_deleteMeeting(\'' + escHtml(m.id) + '\')">Delete</button>' +
126
+ '<button class="btn-destructive" onclick="event.stopPropagation();_deleteMeeting(\'' + escHtml(m.id) + '\')">Delete</button>' +
127
127
  '</div>' +
128
128
  '</div>' +
129
129
  (timeStr ? '<div style="margin-top:4px;font-size:var(--text-sm);color:var(--muted)">' + escHtml(timeStr) + '</div>' : '') +
@@ -246,17 +246,17 @@ function _renderMeetingDetail(m) {
246
246
  if (m.status === 'archived') {
247
247
  html += '<div style="display:flex;gap:8px;border-top:1px solid var(--border);padding-top:8px">' +
248
248
  '<button class="pr-pager-btn" style="font-size:var(--text-xs);padding:2px 8px" onclick="_unarchiveMeeting(\'' + escHtml(m.id) + '\')">Unarchive</button>' +
249
- '<button class="pr-pager-btn" style="font-size:var(--text-xs);padding:2px 8px;color:var(--red);border-color:var(--red)" onclick="_deleteMeeting(\'' + escHtml(m.id) + '\')">Delete</button>' +
249
+ '<button class="btn-destructive btn-destructive-md" onclick="_deleteMeeting(\'' + escHtml(m.id) + '\')">Delete</button>' +
250
250
  '</div>';
251
251
  } else if (m.status === 'completed') {
252
252
  const linkedPlan = _findLinkedPlan(m);
253
253
  html += '<div style="display:flex;gap:8px;flex-wrap:wrap;border-top:1px solid var(--border);padding-top:8px">' +
254
254
  (linkedPlan
255
255
  ? '<button class="pr-pager-btn" style="font-size:var(--text-xs);padding:2px 8px;color:var(--blue);border-color:var(--blue)" onclick="_viewPlanWithBack(\'' + escHtml(linkedPlan.file) + '\',\'' + escHtml(m.id) + '\')">View Plan</button>' +
256
- '<button class="pr-pager-btn" style="font-size:var(--text-xs);padding:2px 8px;color:var(--green);border-color:var(--green)" onclick="_createPlanFromMeeting(\'' + escHtml(m.id) + '\',this)">New Plan</button>'
257
- : '<button class="pr-pager-btn" style="font-size:var(--text-xs);padding:2px 8px;color:var(--green);border-color:var(--green)" onclick="_createPlanFromMeeting(\'' + escHtml(m.id) + '\',this)">Create Plan from Meeting</button>') +
256
+ '<button class="btn-action btn-action-md" onclick="_createPlanFromMeeting(\'' + escHtml(m.id) + '\',this)">New Plan</button>'
257
+ : '<button class="btn-action btn-action-md" onclick="_createPlanFromMeeting(\'' + escHtml(m.id) + '\',this)">Create Plan from Meeting</button>') +
258
258
  '<button class="pr-pager-btn" style="font-size:var(--text-xs);padding:2px 8px" onclick="_archiveMeeting(\'' + escHtml(m.id) + '\')">Archive</button>' +
259
- '<button class="pr-pager-btn" style="font-size:var(--text-xs);padding:2px 8px;color:var(--red);border-color:var(--red)" onclick="_deleteMeeting(\'' + escHtml(m.id) + '\')">Delete</button>' +
259
+ '<button class="btn-destructive btn-destructive-md" onclick="_deleteMeeting(\'' + escHtml(m.id) + '\')">Delete</button>' +
260
260
  '</div>' +
261
261
  '<div id="meeting-plan-toast" class="cmd-toast cmd-toast-inline" style="margin-top:6px"></div>' +
262
262
  '<div style="font-size:var(--text-xs);color:var(--muted);margin-top:4px">Use the Q&amp;A below to discuss action items' + (linkedPlan ? '' : ', then create a plan to execute them') + '.</div>';
@@ -267,8 +267,8 @@ function _renderMeetingDetail(m) {
267
267
  '</div>' +
268
268
  '<div style="display:flex;gap:8px;margin-top:4px">' +
269
269
  '<button class="pr-pager-btn" style="font-size:var(--text-xs);padding:2px 8px;color:var(--yellow);border-color:var(--yellow)" onclick="_advanceMeeting(\'' + escHtml(m.id) + '\',this)">Skip to Next Round</button>' +
270
- '<button class="pr-pager-btn" style="font-size:var(--text-xs);padding:2px 8px;color:var(--red);border-color:var(--red)" onclick="_endMeeting(\'' + escHtml(m.id) + '\',this)">End Meeting</button>' +
271
- '<button class="pr-pager-btn" style="font-size:var(--text-xs);padding:2px 8px;color:var(--red);border-color:var(--red)" onclick="_deleteMeeting(\'' + escHtml(m.id) + '\')">Delete</button>' +
270
+ '<button class="btn-destructive btn-destructive-md" onclick="_endMeeting(\'' + escHtml(m.id) + '\',this)">End Meeting</button>' +
271
+ '<button class="btn-destructive btn-destructive-md" onclick="_deleteMeeting(\'' + escHtml(m.id) + '\')">Delete</button>' +
272
272
  '</div>';
273
273
  }
274
274
 
@@ -347,7 +347,7 @@ function openCreateMeetingModal() {
347
347
  '<div style="color:var(--text);font-size:var(--text-md)">Participants<div style="display:flex;flex-direction:column;gap:4px;margin-top:4px" id="mtg-participants">' + agentOpts + '</div></div>' +
348
348
  '<div style="display:flex;justify-content:flex-end;gap:8px;margin-top:4px">' +
349
349
  '<button onclick="closeModal()" class="pr-pager-btn">Cancel</button>' +
350
- '<button onclick="_submitCreateMeeting(event)" style="padding:6px 16px;background:var(--blue);color:#fff;border:none;border-radius:var(--radius-sm);cursor:pointer">Start Meeting</button>' +
350
+ '<button onclick="_submitCreateMeeting(event)" class="btn-primary-lg">Start Meeting</button>' +
351
351
  '</div>' +
352
352
  '</div>';
353
353
  document.getElementById('modal').classList.add('open');
@@ -5,8 +5,8 @@ function renderProjects(projects) {
5
5
  const visible = (projects || []).filter(p => typeof isDeleted === 'function' ? !isDeleted('project:' + p.name) : true);
6
6
  if (!visible.length) {
7
7
  list.innerHTML = '<span style="color:var(--muted);font-style:italic">No projects linked.</span>' +
8
- '<span onclick="addProject()" style="background:var(--surface2);border:1px solid var(--border);border-radius:4px;padding:3px 10px;color:var(--green);font-weight:500;cursor:pointer;border-style:dashed;margin-left:8px">+ Add Project</span>' +
9
- '<span onclick="openScanProjectsModal()" style="background:var(--surface2);border:1px solid var(--border);border-radius:4px;padding:3px 10px;color:var(--blue);font-weight:500;cursor:pointer;border-style:dashed;font-size:var(--text-sm)">Scan</span>';
8
+ '<span onclick="addProject()" class="empty-state-add" style="margin-left:8px">+ Add Project</span>' +
9
+ '<span onclick="openScanProjectsModal()" class="empty-state-add empty-state-add-blue">Scan</span>';
10
10
  return;
11
11
  }
12
12
  // eslint-disable-next-line no-unsanitized/property -- reason: structural HTML is a string literal; all user data wrapped in escHtml() (fields: project name, path, branch metadata)
@@ -17,8 +17,8 @@ function renderProjects(projects) {
17
17
  '<span onclick="event.stopPropagation();projectChipRemove(\'' + escHtml(p.name) + '\')" title="Remove project (cancels pending work, archives data dir)" style="color:var(--muted);font-weight:600;cursor:pointer;padding:0 2px;line-height:1" onmouseover="this.style.color=\'var(--red)\'" onmouseout="this.style.color=\'var(--muted)\'">&times;</span>' +
18
18
  '</span>'
19
19
  ).join('') +
20
- '<span onclick="addProject()" style="background:var(--surface2);border:1px solid var(--border);border-radius:4px;padding:3px 10px;color:var(--muted);font-weight:500;cursor:pointer;border-style:dashed">+ Add</span>' +
21
- '<span onclick="openScanProjectsModal()" style="background:var(--surface2);border:1px solid var(--border);border-radius:4px;padding:3px 10px;color:var(--blue);font-weight:500;cursor:pointer;border-style:dashed;font-size:var(--text-sm)">Scan</span>';
20
+ '<span onclick="addProject()" class="empty-state-add empty-state-add-muted">+ Add</span>' +
21
+ '<span onclick="openScanProjectsModal()" class="empty-state-add empty-state-add-blue">Scan</span>';
22
22
 
23
23
  }
24
24
 
@@ -422,7 +422,7 @@ async function openScanProjectsModal() {
422
422
  '<label style="width:60px;color:var(--text);font-size:var(--text-md)">Depth' +
423
423
  '<input id="scan-depth" type="number" value="3" min="1" max="6" style="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)">' +
424
424
  '</label>' +
425
- '<button onclick="_runProjectScan()" style="padding:6px 16px;background:var(--blue);color:#fff;border:none;border-radius:var(--radius-sm);cursor:pointer;white-space:nowrap">Scan</button>' +
425
+ '<button onclick="_runProjectScan()" class="btn-primary-lg" style="white-space:nowrap">Scan</button>' +
426
426
  '</div>' +
427
427
  '<div id="scan-results" style="color:var(--muted);font-size:var(--text-md)">Click Scan to find git repos in the directory.</div>' +
428
428
  '<div class="cmd-toast" id="scan-toast" style="margin-top:0"></div>' +
@@ -17,7 +17,7 @@ function renderPinned(entries) {
17
17
  ';border-radius:4px;cursor:pointer" onclick="if(shouldIgnoreSelectionClick(event))return;openPinnedView(' + i + ')">' +
18
18
  '<div style="display:flex;justify-content:space-between;align-items:center">' +
19
19
  '<strong style="font-size:var(--text-md)">' + escHtml(e.title) + '</strong>' +
20
- '<button class="pr-pager-btn" style="font-size:var(--text-xs);padding:1px 6px;color:var(--red);border-color:var(--red)" data-pin-title="' + escHtml(e.title) + '" onclick="event.stopPropagation();removePinnedNote(this.dataset.pinTitle)">Unpin</button>' +
20
+ '<button class="btn-destructive" data-pin-title="' + escHtml(e.title) + '" onclick="event.stopPropagation();removePinnedNote(this.dataset.pinTitle)">Unpin</button>' +
21
21
  '</div>' +
22
22
  '<div style="font-size:var(--text-sm);color:var(--muted);margin-top:4px">' + renderMd(e.content.slice(0, 200)) + (e.content.length > 200 ? '...' : '') + '</div>' +
23
23
  '</div>'
@@ -44,7 +44,7 @@ function openPinNoteModal() {
44
44
  '<label style="color:var(--text);font-size:var(--text-md)">Title<input id="pin-title" style="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)" placeholder="e.g. API freeze until Friday"></label>' +
45
45
  '<label style="color:var(--text);font-size:var(--text-md)">Content<textarea id="pin-content" rows="4" style="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);resize:vertical;font-family:inherit" placeholder="Context all agents should see..."></textarea></label>' +
46
46
  '<label style="color:var(--text);font-size:var(--text-md)">Level<select id="pin-level" style="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)"><option value="info">Info</option><option value="warning">Warning</option><option value="critical">Critical</option></select></label>' +
47
- '<div style="display:flex;justify-content:flex-end;gap:8px"><button onclick="closeModal()" class="pr-pager-btn">Cancel</button><button onclick="submitPinnedNote(event)" style="padding:6px 16px;background:var(--blue);color:#fff;border:none;border-radius:var(--radius-sm);cursor:pointer">Pin</button></div>' +
47
+ '<div style="display:flex;justify-content:flex-end;gap:8px"><button onclick="closeModal()" class="pr-pager-btn">Cancel</button><button onclick="submitPinnedNote(event)" class="btn-primary-lg">Pin</button></div>' +
48
48
  '</div>';
49
49
  document.getElementById('modal').classList.add('open');
50
50
  }
@@ -194,7 +194,7 @@ function openPinnedEdit(idx) {
194
194
  cancelBtn.textContent = 'Cancel';
195
195
  cancelBtn.onclick = function() { openPinnedView(idx); };
196
196
  const saveBtn = document.createElement('button');
197
- saveBtn.style.cssText = 'padding:6px 16px;background:var(--blue);color:#fff;border:none;border-radius:var(--radius-sm);cursor:pointer';
197
+ saveBtn.className = 'btn-primary-lg';
198
198
  saveBtn.textContent = 'Save';
199
199
  saveBtn.onclick = function(ev) { submitPinnedEdit(originalTitle, ev); };
200
200
  actions.appendChild(cancelBtn);
@@ -399,12 +399,12 @@ function openPipelineDetail(id) {
399
399
  '<span style="font-size:var(--text-sm);color:var(--muted)">' + _renderPipelineTriggerLabel(p.trigger?.cron) + ' · ' + escHtml(_getPipelineStageLabel(p)) + '</span>' +
400
400
  '<div style="display:flex;gap:6px">' +
401
401
  (activeRun
402
- ? '<button class="pr-pager-btn" style="font-size:var(--text-xs);padding:2px 8px;color:var(--red);border-color:var(--red)" onclick="_abortPipeline(\'' + escHtml(id) + '\',this)">Abort</button>' +
402
+ ? '<button class="btn-destructive btn-destructive-md" onclick="_abortPipeline(\'' + escHtml(id) + '\',this)">Abort</button>' +
403
403
  '<button class="pr-pager-btn" style="font-size:var(--text-xs);padding:2px 8px;color:var(--yellow);border-color:var(--yellow)" onclick="_retriggerPipeline(\'' + escHtml(id) + '\',this)">Retrigger</button>'
404
- : '<button class="pr-pager-btn" style="font-size:var(--text-xs);padding:2px 8px;color:var(--green);border-color:var(--green)" onclick="_triggerPipeline(\'' + escHtml(id) + '\',this)">Run Now</button>') +
404
+ : '<button class="btn-action btn-action-md" onclick="_triggerPipeline(\'' + escHtml(id) + '\',this)">Run Now</button>') +
405
405
  '<button class="pr-pager-btn" style="font-size:var(--text-xs);padding:2px 8px;color:var(--blue);border-color:var(--blue)" onclick="openEditPipelineModal(\'' + escHtml(id) + '\')">Edit</button>' +
406
406
  '<button class="pr-pager-btn' + (_pipelineToggleInFlight.has(id) ? ' disabled' : '') + '" style="font-size:var(--text-xs);padding:2px 8px" onclick="_togglePipelineEnabled(\'' + escHtml(id) + '\',' + !p.enabled + ',this)">' + (p.enabled !== false ? 'Disable' : 'Enable') + '</button>' +
407
- '<button class="pr-pager-btn" style="font-size:var(--text-xs);padding:2px 8px;color:var(--red);border-color:var(--red)" onclick="_deletePipelineConfirm(\'' + escHtml(id) + '\')">Delete</button>' +
407
+ '<button class="btn-destructive btn-destructive-md" onclick="_deletePipelineConfirm(\'' + escHtml(id) + '\')">Delete</button>' +
408
408
  '</div>' +
409
409
  '</div>';
410
410
 
@@ -454,7 +454,7 @@ function openPipelineDetail(id) {
454
454
  _renderMonitoredResources(s.monitoredResources || []) +
455
455
  _renderArtifactLinks(stageRun.artifacts, id) +
456
456
  (stageRun.output ? '<div class="pipeline-stage-output" style="margin-top:6px;font-size:var(--text-base);max-height:150px;overflow-y:auto">' + renderMd(stageRun.output.slice(0, 500)) + '</div>' : '') +
457
- (stageStatus === 'waiting-human' ? '<button class="pr-pager-btn" style="font-size:var(--text-xs);padding:2px 8px;color:var(--green);border-color:var(--green);margin-top:6px" onclick="_continuePipeline(\'' + escHtml(id) + '\',\'' + escHtml(s.id) + '\',this)">Continue</button>' : '') +
457
+ (stageStatus === 'waiting-human' ? '<button class="btn-action btn-action-md" style="margin-top:6px" onclick="_continuePipeline(\'' + escHtml(id) + '\',\'' + escHtml(s.id) + '\',this)">Continue</button>' : '') +
458
458
  '</div>';
459
459
  });
460
460
 
@@ -726,7 +726,7 @@ function openCreatePipelineModal() {
726
726
  '<label style="color:var(--text);font-size:var(--text-md)">Stages (JSON array)<textarea id="pl-stages" rows="10" style="' + inputStyle + ';resize:vertical;font-family:Consolas,monospace" placeholder=\'[{"id":"audit","type":"task","title":"Audit codebase","taskType":"explore"},{"id":"discuss","type":"meeting","title":"Discuss findings","dependsOn":["audit"],"participants":["all"]}]\'></textarea></label>' +
727
727
  '<div style="display:flex;justify-content:flex-end;gap:8px;margin-top:4px">' +
728
728
  '<button onclick="closeModal()" class="pr-pager-btn">Cancel</button>' +
729
- '<button onclick="_submitCreatePipeline()" style="padding:6px 16px;background:var(--blue);color:#fff;border:none;border-radius:var(--radius-sm);cursor:pointer">Create Pipeline</button>' +
729
+ '<button onclick="_submitCreatePipeline()" class="btn-primary-lg">Create Pipeline</button>' +
730
730
  '</div>' +
731
731
  '</div>';
732
732
  document.getElementById('modal').classList.add('open');
@@ -828,7 +828,7 @@ function openEditPipelineModal(id) {
828
828
  '<label style="color:var(--text);font-size:var(--text-md)">Stages (JSON array)<textarea id="pl-stages" rows="10" style="' + inputStyle + ';resize:vertical;font-family:Consolas,monospace">' + escHtml(JSON.stringify(p.stages || [], null, 2)) + '</textarea></label>' +
829
829
  '<div style="display:flex;justify-content:flex-end;gap:8px;margin-top:4px">' +
830
830
  '<button onclick="closeModal()" class="pr-pager-btn">Cancel</button>' +
831
- '<button onclick="_submitEditPipeline()" style="padding:6px 16px;background:var(--blue);color:#fff;border:none;border-radius:var(--radius-sm);cursor:pointer">Save</button>' +
831
+ '<button onclick="_submitEditPipeline()" class="btn-primary-lg">Save</button>' +
832
832
  '</div>' +
833
833
  '</div>';
834
834
  document.getElementById('modal-body').style.whiteSpace = 'normal';
@@ -22,7 +22,7 @@ function openCreatePlanModal() {
22
22
  '<div style="font-size:var(--text-base);color:var(--muted)">After creating, click Execute on the plan card to have an agent convert it into a PRD with work items.</div>' +
23
23
  '<div style="display:flex;justify-content:flex-end;gap:8px;margin-top:4px">' +
24
24
  '<button onclick="closeModal()" class="pr-pager-btn">Cancel</button>' +
25
- '<button onclick="_submitCreatePlan(event)" style="padding:6px 16px;background:var(--blue);color:#fff;border:none;border-radius:var(--radius-sm);cursor:pointer">Create Plan</button>' +
25
+ '<button onclick="_submitCreatePlan(event)" class="btn-primary-lg">Create Plan</button>' +
26
26
  '</div>' +
27
27
  '</div>';
28
28
  document.getElementById('modal').classList.add('open');
@@ -468,7 +468,7 @@ function planReexecuteModal(file, project) {
468
468
  '<div style="font-size:var(--text-base);color:var(--muted)">Leave blank to re-run without steering. The agent will read the existing PRD and rewrite it.</div>' +
469
469
  '<div style="display:flex;justify-content:flex-end;gap:8px;margin-top:4px">' +
470
470
  '<button onclick="closeModal()" class="pr-pager-btn">Cancel</button>' +
471
- '<button onclick="planReexecuteSubmit(\'' + escapeHtml(file) + '\',\'' + escapeHtml(project || '') + '\')" style="padding:6px 16px;background:var(--blue);color:#fff;border:none;border-radius:var(--radius-sm);cursor:pointer">Re-execute</button>' +
471
+ '<button onclick="planReexecuteSubmit(\'' + escapeHtml(file) + '\',\'' + escapeHtml(project || '') + '\')" class="btn-primary-lg">Re-execute</button>' +
472
472
  '</div>' +
473
473
  '</div>';
474
474
  document.getElementById('modal').classList.add('open');
@@ -105,15 +105,15 @@ 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:var(--text-xs);padding:1px 6px;color:var(--green);border-color:var(--green);margin-left:4px" onclick="planApprove(\'' + escHtml(prdFile) + '\',this)">Approve</button>';
108
+ actions = ' <button class="btn-action" style="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:var(--text-xs);padding:1px 6px;color:var(--green);border-color:var(--green);margin-left:4px" onclick="triggerVerify(\'' + escHtml(prdFile) + '\',this)">Verify</button>') +
111
+ actions = (hasVerifyWi ? '' : ' <button class="btn-action" style="margin-left:4px" onclick="triggerVerify(\'' + escHtml(prdFile) + '\',this)">Verify</button>') +
112
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
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:var(--text-xs);padding:1px 6px;color:var(--green);border-color:var(--green);margin-left:4px" onclick="planApprove(\'' + escHtml(prdFile) + '\',this)">Resume</button>' +
116
+ actions = ' <button class="btn-action" style="margin-left:4px" onclick="planApprove(\'' + escHtml(prdFile) + '\',this)">Resume</button>' +
117
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
  }
@@ -823,7 +823,7 @@ async function prdItemEdit(source, itemId) {
823
823
  '<label style="font-size:var(--text-base);color:var(--muted)">Description</label>' +
824
824
  '<div style="display:flex;gap:6px">' +
825
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>' +
826
+ '<button id="prd-desc-save-btn" type="button" class="btn-action btn-action-lg" aria-label="Save description" style="display:none" onclick="_savePrdDesc(\'' + escHtml(source) + '\',\'' + escHtml(itemId) + '\')">Save</button>' +
827
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>' +
@@ -204,7 +204,7 @@ function prRow(pr) {
204
204
  '<td><span class="pr-badge ' + statusClass + '" title="' + escapeHtml(statusLabel) + '">' + escapeHtml(statusLabel) + '</span></td>' +
205
205
  '<td>' + (observeBtn || '<span style="color:var(--muted);font-size:var(--text-base)">—</span>') + '</td>' +
206
206
  '<td><span class="pr-date" title="' + escapeHtml(createdLabel) + '">' + escapeHtml(createdLabel) + '</span></td>' +
207
- '<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
+ '<td><button class="btn-destructive" style="padding:1px 5px" data-pr-id="' + escapeHtml(String(prId)) + '" onclick="event.stopPropagation();unlinkPr(this.dataset.prId)" title="Remove from tracking">x</button></td>' +
208
208
  '</tr>';
209
209
  }
210
210
 
@@ -350,7 +350,7 @@ function openAddPrModal() {
350
350
  '<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>' +
351
351
  '<div style="display:flex;justify-content:flex-end;gap:8px;margin-top:8px">' +
352
352
  '<button onclick="closeModal()" class="pr-pager-btn">Cancel</button>' +
353
- '<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>' +
353
+ '<button onclick="_submitLinkPr(event)" class="btn-primary-lg">Link PR</button>' +
354
354
  '</div>' +
355
355
  '</div>';
356
356
  document.getElementById('modal').classList.add('open');
@@ -352,10 +352,10 @@ function renderSchedules(schedules, opts) {
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: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>' +
355
+ '<button class="btn-action" style="margin-right:4px" onclick="event.stopPropagation();runScheduleNow(\'' + escHtml(s.id) + '\',this)" title="Run now">Run now</button>' +
356
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
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>' +
358
+ '<button class="btn-destructive" onclick="event.stopPropagation();deleteSchedule(\'' + escHtml(s.id) + '\')" title="Delete">&#x2715;</button>' +
359
359
  '</td>' +
360
360
  '</tr>';
361
361
  }
@@ -515,7 +515,7 @@ function _scheduleFormHtml(sched, isEdit) {
515
515
  '</label>' +
516
516
  '<div style="display:flex;justify-content:flex-end;gap:8px;margin-top:8px">' +
517
517
  '<button onclick="closeModal()" class="pr-pager-btn" style="padding:6px 16px;font-size:var(--text-md)">Cancel</button>' +
518
- '<button onclick="submitSchedule(' + isEdit + ',event)" style="padding:6px 16px;font-size:var(--text-md);background:var(--blue);color:#fff;border:none;border-radius:var(--radius-sm);cursor:pointer">' + (isEdit ? 'Save' : 'Create') + '</button>' +
518
+ '<button onclick="submitSchedule(' + isEdit + ',event)" class="btn-primary-lg">' + (isEdit ? 'Save' : 'Create') + '</button>' +
519
519
  '</div>' +
520
520
  '</div>';
521
521
  }
@@ -216,11 +216,11 @@ function renderWatches(watchesData, opts) {
216
216
  if (w.status === 'active') {
217
217
  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">&#x23F8;</button>';
218
218
  } else if (w.status === 'paused') {
219
- 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">&#x25B6;</button>';
219
+ html += '<button class="btn-action' + pauseBusyCls + '" style="margin-right:4px" onclick="event.stopPropagation();toggleWatchPause(\'' + escHtml(w.id) + '\',false)" title="Resume">&#x25B6;</button>';
220
220
  }
221
221
 
222
222
  // Delete button
223
- 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">&#x2715;</button>';
223
+ html += '<button class="btn-destructive" onclick="event.stopPropagation();deleteWatch(\'' + escHtml(w.id) + '\')" title="Delete">&#x2715;</button>';
224
224
  html += '</td></tr>';
225
225
  }
226
226
 
@@ -548,7 +548,7 @@ function _addWatchStepRow(initial) {
548
548
  row.innerHTML =
549
549
  '<div style="display:flex;align-items:center;justify-content:space-between;gap:8px">' +
550
550
  '<select id="watch-step-' + idx + '-type" style="' + inputStyle + ';margin-top:0;flex:1" onchange="_updateWatchStepParamsHint(' + idx + ')">' + actionOpts + '</select>' +
551
- '<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>' +
551
+ '<button type="button" class="btn-destructive btn-destructive-lg" onclick="_removeWatchStepRow(' + idx + ')">Remove</button>' +
552
552
  '</div>' +
553
553
  '<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>' +
554
554
  '<textarea id="watch-step-' + idx + '-params" rows="3" placeholder=\'{"title": "Re-check {{target}} after merge"}\' style="' + inputStyle + ';font-family:monospace"></textarea>' +
@@ -612,7 +612,7 @@ function _addRequireRow(initial) {
612
612
  '<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>' +
613
613
  '<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>' +
614
614
  '<label style="color:var(--text);font-size:var(--text-base);margin:0">Condition<select id="watch-require-' + idx + '-condition" style="' + inputStyle + '"></select></label>' +
615
- '<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>';
615
+ '<button type="button" class="btn-destructive btn-destructive-lg" style="padding:6px 8px" onclick="_removeRequireRow(' + idx + ')">Remove</button>';
616
616
  container.appendChild(row);
617
617
  if (initTarget) document.getElementById('watch-require-' + idx + '-target').value = initTarget;
618
618
  if (initTT) document.getElementById('watch-require-' + idx + '-target-type').value = initTT;
@@ -655,7 +655,7 @@ function _updateWatchConditionOptions() {
655
655
 
656
656
  function _renderCreateWatchModal() {
657
657
  document.getElementById('modal-title').innerHTML = 'Create Watch' +
658
- ' <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>';
658
+ ' <button class="btn-action btn-action-lg" style="padding:2px 12px;margin-left:8px" onclick="submitWatch()">Create</button>';
659
659
  // 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)
660
660
  document.getElementById('modal-body').innerHTML = _watchFormHtml();
661
661
  document.getElementById('modal-body').style.whiteSpace = 'normal';
@@ -246,9 +246,9 @@ function wiRow(item) {
246
246
  '<td style="white-space:nowrap">' +
247
247
  ((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">&#x270E;</button>' : '') +
248
248
  ((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">&#x1F4E6;</button>' : '') +
249
- ((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">&#x1F44D;&#x1F44E;</button>' : (item._humanFeedback ? '<span style="font-size:var(--text-xs)" title="Feedback given">' + (item._humanFeedback.rating === 'up' ? '&#x1F44D;' : '&#x1F44E;') + '</span> ' : '')) +
249
+ ((item.status === 'done' || item.status === 'failed') && !item._humanFeedback ? '<button class="btn-action" style="margin-right:4px" onclick="event.stopPropagation();feedbackWorkItem(\'' + escapeHtml(item.id) + '\',\'' + escapeHtml(item._source || '') + '\')" title="Give feedback">&#x1F44D;&#x1F44E;</button>' : (item._humanFeedback ? '<span style="font-size:var(--text-xs)" title="Feedback given">' + (item._humanFeedback.rating === 'up' ? '&#x1F44D;' : '&#x1F44E;') + '</span> ' : '')) +
250
250
  ((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">&#x1F6AB;</button>' : '') +
251
- '<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">&#x2715;</button>' +
251
+ '<button class="btn-destructive" onclick="event.stopPropagation();deleteWorkItem(\'' + escapeHtml(item.id) + '\',\'' + escapeHtml(item._source || '') + '\')" title="Delete work item and kill agent">&#x2715;</button>' +
252
252
  '</td>' +
253
253
  '</tr>';
254
254
  }
@@ -380,7 +380,7 @@ async function editWorkItem(id, source) {
380
380
  '</label>' +
381
381
  '<div style="display:flex;justify-content:flex-end;gap:8px;margin-top:8px">' +
382
382
  '<button onclick="closeModal()" class="pr-pager-btn" style="padding:6px 16px;font-size:var(--text-md)">Cancel</button>' +
383
- '<button onclick="submitWorkItemEdit(\'' + escapeHtml(id) + '\',\'' + escapeHtml(source || '') + '\',event)" style="padding:6px 16px;font-size:var(--text-md);background:var(--blue);color:#fff;border:none;border-radius:var(--radius-sm);cursor:pointer">Save</button>' +
383
+ '<button onclick="submitWorkItemEdit(\'' + escapeHtml(id) + '\',\'' + escapeHtml(source || '') + '\',event)" class="btn-primary-lg">Save</button>' +
384
384
  '</div>' +
385
385
  '</div>';
386
386
  document.getElementById('modal').classList.add('open');
@@ -601,7 +601,7 @@ function openCreateWorkItemModal() {
601
601
  '<label id="wi-new-skippr-row" style="color:var(--text);font-size:var(--text-md);display:flex;gap:8px;align-items:center;cursor:pointer"><input type="checkbox" id="wi-new-skippr"> Skip PR creation (push branch only)</label>' +
602
602
  '<div style="display:flex;justify-content:flex-end;gap:8px;margin-top:4px">' +
603
603
  '<button onclick="closeModal()" class="pr-pager-btn">Cancel</button>' +
604
- '<button onclick="_submitCreateWorkItem(event)" style="padding:6px 16px;background:var(--blue);color:#fff;border:none;border-radius:var(--radius-sm);cursor:pointer">Create</button>' +
604
+ '<button onclick="_submitCreateWorkItem(event)" class="btn-primary-lg">Create</button>' +
605
605
  '</div>' +
606
606
  '</div>';
607
607
  document.getElementById('modal').classList.add('open');
@@ -488,8 +488,7 @@ async function openSettings() {
488
488
  if (!document.getElementById('modal-settings-reset')) {
489
489
  const resetBtn = document.createElement('button');
490
490
  resetBtn.id = 'modal-settings-reset';
491
- resetBtn.className = 'modal-copy';
492
- resetBtn.style.cssText = 'color:var(--red);border-color:var(--red)';
491
+ resetBtn.className = 'modal-copy is-danger';
493
492
  resetBtn.textContent = 'Reset';
494
493
  resetBtn.onclick = resetSettingsToDefaults;
495
494
  actions.insertBefore(resetBtn, actions.lastElementChild);
@@ -497,8 +496,7 @@ async function openSettings() {
497
496
  if (!document.getElementById('modal-settings-save')) {
498
497
  const saveBtn = document.createElement('button');
499
498
  saveBtn.id = 'modal-settings-save';
500
- saveBtn.className = 'modal-copy';
501
- saveBtn.style.cssText = 'color:var(--green);border-color:var(--green)';
499
+ saveBtn.className = 'modal-copy is-success';
502
500
  saveBtn.innerHTML = '<svg width="12" height="12" viewBox="0 0 16 16" fill="currentColor"><path d="M13.78 4.22a.75.75 0 010 1.06l-7.25 7.25a.75.75 0 01-1.06 0L2.22 9.28a.75.75 0 011.06-1.06L6 10.94l6.72-6.72a.75.75 0 011.06 0z"/></svg> Save';
503
501
  saveBtn.onclick = saveSettings;
504
502
  actions.insertBefore(saveBtn, actions.lastElementChild);
@@ -122,7 +122,7 @@
122
122
  <h3 id="modal-title">—</h3>
123
123
  <div class="modal-header-actions">
124
124
  <button class="modal-copy" id="modal-edit-btn" onclick="modalToggleEdit()" title="Edit" style="display:none"><svg width="12" height="12" viewBox="0 0 16 16" fill="currentColor"><path d="M11.013 1.427a1.75 1.75 0 012.474 0l1.086 1.086a1.75 1.75 0 010 2.474l-8.61 8.61c-.21.21-.47.364-.756.445l-3.251.93a.75.75 0 01-.927-.928l.929-3.25c.081-.286.235-.547.445-.758l8.61-8.61zM12.9 2.97L4.288 11.58l-.537 1.878 1.878-.537L14.242 4.31 12.9 2.97z"/></svg> Edit</button>
125
- <button class="modal-copy" id="modal-save-btn" onclick="modalSaveEdit()" title="Save" style="display:none;color:var(--green);border-color:var(--green)"><svg width="12" height="12" viewBox="0 0 16 16" fill="currentColor"><path d="M13.78 4.22a.75.75 0 010 1.06l-7.25 7.25a.75.75 0 01-1.06 0L2.22 9.28a.75.75 0 011.06-1.06L6 10.94l6.72-6.72a.75.75 0 011.06 0z"/></svg> Save</button>
125
+ <button class="modal-copy is-success" id="modal-save-btn" onclick="modalSaveEdit()" title="Save" style="display:none"><svg width="12" height="12" viewBox="0 0 16 16" fill="currentColor"><path d="M13.78 4.22a.75.75 0 010 1.06l-7.25 7.25a.75.75 0 01-1.06 0L2.22 9.28a.75.75 0 011.06-1.06L6 10.94l6.72-6.72a.75.75 0 011.06 0z"/></svg> Save</button>
126
126
  <button class="modal-copy" id="modal-cancel-edit-btn" onclick="modalCancelEdit()" title="Cancel edit" style="display:none">Cancel</button>
127
127
  <button class="modal-copy pin-btn" id="modal-pin-btn" onclick="toggleModalPin()" title="Pin to top" style="display:none">Pin</button>
128
128
  <button class="modal-copy" id="modal-copy-btn" onclick="copyModalContent()" title="Copy to clipboard"><svg width="12" height="12" viewBox="0 0 16 16" fill="currentColor"><path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 010 1.5h-1.5a.25.25 0 00-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 00.25-.25v-1.5a.75.75 0 011.5 0v1.5A1.75 1.75 0 019.25 16h-7.5A1.75 1.75 0 010 14.25z"/><path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0114.25 11h-7.5A1.75 1.75 0 015 9.25zm1.75-.25a.25.25 0 00-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 00.25-.25v-7.5a.25.25 0 00-.25-.25z"/></svg> Copy</button>
@@ -15,7 +15,7 @@
15
15
  </ul>
16
16
  </div>
17
17
  <div style="display:flex;gap:var(--space-3);align-items:center;margin-top:var(--space-2)">
18
- <button type="button" id="qa-cc-pitch-open" class="qa-btn-primary" onclick="qaFocusCommandCenter()">Open Command Center →</button>
18
+ <button type="button" id="qa-cc-pitch-open" class="btn-primary-solid" onclick="qaFocusCommandCenter()">Open Command Center →</button>
19
19
  <a href="/state/docs/qa-runbook-lifecycle.md" target="_blank" rel="noopener" class="qa-cc-pitch-docs" style="color:var(--blue);font-size:var(--text-base)">Docs →</a>
20
20
  </div>
21
21
  </div>
@@ -488,6 +488,170 @@
488
488
  .btn-add.disabled { opacity: 0.4; cursor: not-allowed; pointer-events: none; }
489
489
  .btn-add.btn-add-lg { font-size: var(--text-sm); padding: 2px 8px; }
490
490
 
491
+ /* W-mq57qetc0009ed48 — green-bordered action button family WITHOUT a
492
+ leading "+" glyph (Approve / Verify / Resume / Save / Run Now /
493
+ Continue / Create / New Plan / Trigger Verify / etc). Sibling to
494
+ .btn-add — same green/surface2 visual identity, but semantically a
495
+ verb-action rather than a creator. Three padding+size variants cover
496
+ every callsite that was previously inline `style="font-size:…;
497
+ padding:…;color:var(--green);border-color:var(--green)"` on top of
498
+ .pr-pager-btn:
499
+ .btn-action — compact text-xs / 1px 6px (inline PRD
500
+ chips, work-item feedback)
501
+ .btn-action.btn-action-md — text-xs / 2px 8px (meetings, pipelines,
502
+ watches resume, schedule run-now chip)
503
+ .btn-action.btn-action-lg — text-sm / 2px 10px (modal Save, watch
504
+ Create, charter Save, schedule modal Run
505
+ now)
506
+ Positional/layout-only inline styles (e.g. margin-left:8px, margin-
507
+ right:4px, margin-top:6px) stay at the callsite. Do NOT re-create the
508
+ green inline blob — extend this primitive instead. */
509
+ .btn-action {
510
+ background: var(--surface2);
511
+ border: 1px solid var(--green);
512
+ color: var(--green);
513
+ font-size: var(--text-xs);
514
+ padding: 1px 6px;
515
+ border-radius: var(--radius-sm);
516
+ cursor: pointer;
517
+ transition: background var(--transition-base);
518
+ }
519
+ .btn-action:hover { background: rgba(63,185,80,0.1); }
520
+ .btn-action:focus-visible { outline: 2px solid var(--green); outline-offset: 1px; }
521
+ .btn-action:disabled,
522
+ .btn-action.disabled { opacity: 0.4; cursor: not-allowed; pointer-events: none; }
523
+ .btn-action.btn-action-md { padding: 2px 8px; }
524
+ .btn-action.btn-action-lg { font-size: var(--text-sm); padding: 2px 10px; }
525
+
526
+ /* W-mq57qetc0009ed48 — red-bordered destructive button family (Delete /
527
+ Abort / Remove / Unpin / unlink-x). Visual sibling to .btn-action —
528
+ same surface2 background, same padding scale, same hover-tint pattern,
529
+ just swapped to var(--red). Three size variants:
530
+ .btn-destructive — compact text-xs / 1px 6px (work-item
531
+ delete, watch delete, schedule delete,
532
+ unpin, unlink-x in PR row)
533
+ .btn-destructive.btn-destructive-md — text-xs / 2px 8px (pipelines
534
+ Abort + Delete)
535
+ .btn-destructive.btn-destructive-lg — text-sm / 2px 10px (watch
536
+ builder Remove step / Remove
537
+ requirement)
538
+ Positional / outlier inline overrides (padding:1px 5px on the PR
539
+ unlink-x chip, padding:6px 8px on the requirement-row Remove) stay
540
+ at the callsite. Do NOT re-create the red inline blob — extend this
541
+ primitive instead. */
542
+ .btn-destructive {
543
+ background: var(--surface2);
544
+ border: 1px solid var(--red);
545
+ color: var(--red);
546
+ font-size: var(--text-xs);
547
+ padding: 1px 6px;
548
+ border-radius: var(--radius-sm);
549
+ cursor: pointer;
550
+ transition: background var(--transition-base);
551
+ }
552
+ .btn-destructive:hover { background: rgba(248,81,73,0.1); }
553
+ .btn-destructive:focus-visible { outline: 2px solid var(--red); outline-offset: 1px; }
554
+ .btn-destructive:disabled,
555
+ .btn-destructive.disabled { opacity: 0.4; cursor: not-allowed; pointer-events: none; }
556
+ .btn-destructive.btn-destructive-md { padding: 2px 8px; }
557
+ .btn-destructive.btn-destructive-lg { font-size: var(--text-sm); padding: 2px 10px; }
558
+
559
+ /* W-mq57qetc0009ed48 — solid-blue primary CTA. Single source of truth
560
+ for the filled-blue rectangle that gates submission flows (QA "Start
561
+ QA Session", "+ New runbook", "Save" in the QA runbook editor, FRE
562
+ "+ Add Project"). Replaces the standalone .qa-btn-primary (now
563
+ removed — all callsites migrated) and the ad-hoc
564
+ `background:var(--blue);color:#fff;border:none;…` style blob in
565
+ fre.js. */
566
+ .btn-primary-solid {
567
+ background: var(--blue);
568
+ color: #fff;
569
+ border: none;
570
+ border-radius: var(--radius-sm);
571
+ padding: var(--space-3) var(--space-7);
572
+ font-size: var(--text-md);
573
+ font-weight: 600;
574
+ cursor: pointer;
575
+ transition: opacity var(--transition-base);
576
+ }
577
+ .btn-primary-solid:hover { opacity: 0.9; }
578
+ .btn-primary-solid:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
579
+ .btn-primary-solid:disabled,
580
+ .btn-primary-solid.disabled { opacity: 0.4; cursor: not-allowed; pointer-events: none; }
581
+
582
+ /* W-mq57qetc0009ed48 — solid-blue modal CTA. Lighter-weight sibling to
583
+ .btn-primary-solid: same filled-blue rectangle, padding:6px 16px, but
584
+ without the font-weight:600 used by qa/fre primary CTAs. Used for the
585
+ "Save" / "Create Plan" / "Re-execute" / "Save Note" buttons inside
586
+ dashboard modals (render-inbox, render-kb, render-plans) and the
587
+ "Retry" button in the agent-detail error state. Replaces the ad-hoc
588
+ `background:var(--blue);color:#fff;border:none;border-radius:sm;
589
+ padding:6px 16px` blob that was duplicated across five callsites. */
590
+ .btn-primary-lg {
591
+ background: var(--blue);
592
+ color: #fff;
593
+ border: none;
594
+ border-radius: var(--radius-sm);
595
+ padding: 6px 16px;
596
+ font-size: var(--text-md);
597
+ cursor: pointer;
598
+ transition: opacity var(--transition-base);
599
+ }
600
+ .btn-primary-lg:hover { opacity: 0.9; }
601
+ .btn-primary-lg:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
602
+ .btn-primary-lg:disabled,
603
+ .btn-primary-lg.disabled { opacity: 0.4; cursor: not-allowed; pointer-events: none; }
604
+
605
+ /* W-mq57qetc0009ed48 — muted ghost button. Transparent background,
606
+ bordered, muted text. Used for secondary actions next to a primary
607
+ CTA (QA Cancel / Edit / Dismiss / "− remove artifact row" / "+ Add
608
+ artifact"). Replaces the standalone .qa-btn-ghost (now removed —
609
+ all callsites migrated). */
610
+ .btn-ghost {
611
+ background: transparent;
612
+ color: var(--muted);
613
+ border: 1px solid var(--border);
614
+ border-radius: var(--radius-sm);
615
+ padding: var(--space-2) var(--space-5);
616
+ font-size: var(--text-base);
617
+ cursor: pointer;
618
+ transition: color var(--transition-base), background var(--transition-base);
619
+ }
620
+ .btn-ghost:hover { color: var(--text); background: var(--surface); }
621
+ .btn-ghost:focus-visible { outline: 2px solid var(--blue); outline-offset: 1px; }
622
+ .btn-ghost:disabled,
623
+ .btn-ghost.disabled { opacity: 0.4; cursor: not-allowed; pointer-events: none; }
624
+
625
+ /* W-mq57qetc0009ed48 — dashed empty-state chip ("+ Add Project" in
626
+ the projects empty-state). Same chip footprint as the project chips
627
+ in render-other.js, but with a dashed border + green text to read as
628
+ a placeholder/call-to-action. */
629
+ .empty-state-add {
630
+ display: inline-block;
631
+ background: var(--surface2);
632
+ border: 1px dashed var(--border);
633
+ color: var(--green);
634
+ font-weight: 500;
635
+ padding: 3px 10px;
636
+ border-radius: var(--radius-sm);
637
+ cursor: pointer;
638
+ transition: background var(--transition-base);
639
+ }
640
+ .empty-state-add:hover { background: rgba(63,185,80,0.1); }
641
+ .empty-state-add:focus-visible { outline: 2px solid var(--green); outline-offset: 1px; }
642
+ .empty-state-add:disabled,
643
+ .empty-state-add.disabled { opacity: 0.4; cursor: not-allowed; pointer-events: none; }
644
+ /* Muted variant used when the chip sits next to existing project chips
645
+ (so it reads as a secondary "add another" affordance rather than the
646
+ primary empty-state CTA). */
647
+ .empty-state-add.empty-state-add-muted { color: var(--muted); }
648
+ .empty-state-add.empty-state-add-muted:hover { background: var(--surface); }
649
+ /* Blue variant used for the "Scan" affordance that sits next to "+ Add
650
+ Project" in the projects empty-state — same dashed chip, but text-sm and
651
+ blue text instead of green. */
652
+ .empty-state-add.empty-state-add-blue { color: var(--blue); font-size: var(--text-sm); }
653
+ .empty-state-add.empty-state-add-blue:hover { background: rgba(88,166,255,0.1); }
654
+
491
655
  /* Badge — unified badge/pill base */
492
656
  .badge {
493
657
  font-size: var(--text-sm); font-weight: 600;
@@ -796,6 +960,8 @@
796
960
  .modal-copy { background: var(--surface2); border: 1px solid var(--border); color: var(--muted); font-size: var(--text-base); cursor: pointer; padding: var(--space-2) var(--space-5); border-radius: var(--radius-sm); display: flex; align-items: center; gap: var(--space-2); transition: all var(--transition-base); }
797
961
  .modal-copy:hover { color: var(--text); border-color: var(--text); }
798
962
  .modal-copy.copied { color: var(--green); border-color: var(--green); }
963
+ .modal-copy.is-success { color: var(--green); border-color: var(--green); }
964
+ .modal-copy.is-danger { color: var(--red); border-color: var(--red); }
799
965
  .modal-close { background: none; border: none; color: var(--muted); font-size: var(--text-2xl); cursor: pointer; padding: var(--space-2) var(--space-4); }
800
966
  .modal-close:hover { color: var(--text); }
801
967
 
@@ -1019,20 +1185,10 @@
1019
1185
  .qa-add-artifact-btn { align-self: flex-start; margin-top: var(--space-2); }
1020
1186
  .qa-form-actions { flex-direction: row; align-items: center; gap: var(--space-4); }
1021
1187
  .qa-form-msg { font-size: var(--text-base); margin-left: var(--space-3); }
1022
- .qa-btn-primary {
1023
- background: var(--blue); color: #fff; border: none;
1024
- border-radius: var(--radius-sm); padding: var(--space-3) var(--space-7);
1025
- font-size: var(--text-md); font-weight: 600; cursor: pointer;
1026
- }
1027
- .qa-btn-primary:hover { opacity: 0.9; }
1028
- .qa-btn-primary:disabled { opacity: 0.4; cursor: not-allowed; }
1029
- .qa-btn-ghost {
1030
- background: transparent; color: var(--muted);
1031
- border: 1px solid var(--border); border-radius: var(--radius-sm);
1032
- padding: var(--space-2) var(--space-5); font-size: var(--text-base);
1033
- cursor: pointer;
1034
- }
1035
- .qa-btn-ghost:hover { color: var(--text); background: var(--surface); }
1188
+ /* .qa-btn-primary and .qa-btn-ghost were removed in W-mq57qetc0009ed48
1189
+ (PR #80 follow-up). All callsites migrated to the shared .btn-primary-solid
1190
+ and .btn-ghost primitives defined near .btn-add. .qa-btn-danger is kept
1191
+ as a color-only modifier composable with .btn-ghost. */
1036
1192
 
1037
1193
  .qa-runbooks-list { display: flex; flex-direction: column; gap: var(--space-3); }
1038
1194
  .qa-runbook-row {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yemi33/minions",
3
- "version": "0.1.2158",
3
+ "version": "0.1.2159",
4
4
  "description": "Multi-agent AI dev team that runs from ~/.minions/ — five autonomous agents share a single engine, dashboard, and knowledge base",
5
5
  "bin": {
6
6
  "minions": "bin/minions.js"