@yemi33/minions 0.1.1106 → 0.1.1108

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Changelog
2
2
 
3
- ## 0.1.1106 (2026-04-18)
3
+ ## 0.1.1108 (2026-04-18)
4
4
 
5
5
  ### Features
6
6
  - seed realActivityMap at spawn time, stamp pid in live-output (#1200)
@@ -24,6 +24,50 @@
24
24
  - harden settings save and migrate pr poll config
25
25
 
26
26
  ### Other
27
+ - Clarify PR poll labels
28
+ - Prevent modal opens on text selection
29
+ - refactor: clarify settings page section structure and PR polling dependencies
30
+ - refactor: extract _probeClaudePackage helper, use shared.log for spawn errors
31
+ - Make work item descriptions scrollable
32
+ - Use PAT for publish merges
33
+ - test(queries): add unit tests for invalidateDispatchCache/getInbox/getAgentCharter (#1214)
34
+ - test(shared): add unit tests for truncateTextBytes/tailTextBytes/execSilent/trackReviewMetric/parseCanonicalPrId (#1215)
35
+ - Fix publish workflow merge
36
+ - chore: raise default meeting round timeout
37
+ - Harden prompt context handling
38
+ - Harden loop watch conversion
39
+ - Add watches sidebar activity badge
40
+ - test(cli): add unit tests for handleCommand, start, stop, kill, spawn (#1191)
41
+ - chore: untrack pipeline files — local config only
42
+ - restore: recover daily-arch-improvement and weekly-dead-code-cleanup pipelines
43
+ - Harden CC stream resilience
44
+
45
+ ## 0.1.1107 (2026-04-18)
46
+
47
+ ### Features
48
+ - seed realActivityMap at spawn time, stamp pid in live-output (#1200)
49
+
50
+ ### Fixes
51
+ - preserve buildErrorLog through transient build states (#1232) (#1274)
52
+ - annotate fast-exit empty-output failures with diagnostic hint (#1276)
53
+ - invalidate PRD cache on pr-links.json change + guard aggregate PRs (#1220) (#1272)
54
+ - pass --add-dir for minions + ~/.claude to agents (#1271)
55
+ - preserve VERDICT marker by tail-slicing agent output (#1234) (#1270)
56
+ - PRD info cache staleness and aggregate PR bleed-through (#1222)
57
+ - avoid no-op work item writes
58
+ - resilient claude binary resolution + surface spawn errors
59
+ - resolve native claude.exe from npm wrapper on Windows
60
+ - cap temp-agent creation at maxConcurrent per tick (#1219)
61
+ - reassign pending items from unspawned temp agents to idle named agents (#1204) (#1212)
62
+ - guard undefined agent in pending dispatch loop (closes #1206) (#1210)
63
+ - improve fallback meeting conclusion
64
+ - remove command center chevron
65
+ - stamp live-output.log stub before spawn (#1198)
66
+ - harden settings save and migrate pr poll config
67
+
68
+ ### Other
69
+ - Clarify PR poll labels
70
+ - Prevent modal opens on text selection
27
71
  - refactor: clarify settings page section structure and PR polling dependencies
28
72
  - refactor: extract _probeClaudePackage helper, use shared.log for spawn errors
29
73
  - Make work item descriptions scrollable
@@ -4,7 +4,7 @@ function renderAgents(agents) {
4
4
  agentData = agents;
5
5
  const grid = document.getElementById('agents-grid');
6
6
  grid.innerHTML = agents.map(a => `
7
- <div class="agent-card ${statusColor(a.status)}" onclick="openAgentDetail('${escHtml(a.id)}')">
7
+ <div class="agent-card ${statusColor(a.status)}" onclick="if(shouldIgnoreSelectionClick(event))return;openAgentDetail('${escHtml(a.id)}')">
8
8
  <div class="agent-card-header">
9
9
  <span class="agent-name"><span class="agent-emoji">${escHtml(a.emoji)}</span>${escHtml(a.name)}</span>
10
10
  <span class="status-badge ${escHtml(a.status)}">${escHtml(a.status)}</span>
@@ -48,7 +48,7 @@ function renderMeetings(meetings) {
48
48
  const dt = m.completedAt || m.createdAt;
49
49
  const timeStr = dt ? new Date(dt).toLocaleString(undefined, { month: 'short', day: 'numeric', hour: 'numeric', minute: '2-digit' }) : '';
50
50
 
51
- return '<div data-file="meetings/' + escHtml(m.id) + '.json" style="background:var(--surface);border:1px solid var(--border);border-radius:8px;padding:12px 16px;margin-bottom:8px;cursor:pointer;position:relative" onclick="openMeetingDetail(\'' + escHtml(m.id) + '\')">' +
51
+ return '<div data-file="meetings/' + escHtml(m.id) + '.json" style="background:var(--surface);border:1px solid var(--border);border-radius:8px;padding:12px 16px;margin-bottom:8px;cursor:pointer;position:relative" onclick="if(shouldIgnoreSelectionClick(event))return;openMeetingDetail(\'' + escHtml(m.id) + '\')">' +
52
52
  '<div style="display:flex;justify-content:space-between;align-items:center">' +
53
53
  '<strong style="font-size:13px">' + escHtml(m.title) + '</strong>' +
54
54
  '<div style="display:flex;align-items:center;gap:8px">' +
@@ -13,7 +13,7 @@ function renderPinned(entries) {
13
13
  el.innerHTML = entries.map((e, i) =>
14
14
  '<div class="pinned-card" data-file="pinned:' + escHtml(e.title) + '" style="padding:8px 12px;margin-bottom:6px;background:var(--surface2);border-left:3px solid ' +
15
15
  (e.level === 'critical' ? 'var(--red)' : e.level === 'warning' ? 'var(--yellow)' : 'var(--blue)') +
16
- ';border-radius:4px;cursor:pointer" onclick="openPinnedView(' + i + ')">' +
16
+ ';border-radius:4px;cursor:pointer" onclick="if(shouldIgnoreSelectionClick(event))return;openPinnedView(' + i + ')">' +
17
17
  '<div style="display:flex;justify-content:space-between;align-items:center">' +
18
18
  '<strong style="font-size:var(--text-md)">' + escHtml(e.title) + '</strong>' +
19
19
  '<button class="pr-pager-btn" style="font-size:9px;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>' +
@@ -277,7 +277,7 @@ function renderPipelines(pipelines) {
277
277
  var allResources = _collectMonitoredResources(p);
278
278
  var resourcesHtml = _renderMonitoredResources(allResources, { compact: true });
279
279
 
280
- return '<div style="background:var(--surface);border:1px solid var(--border);border-radius:8px;padding:12px 16px;margin-bottom:8px;cursor:pointer" onclick="openPipelineDetail(\'' + escHtml(p.id) + '\')">' +
280
+ return '<div style="background:var(--surface);border:1px solid var(--border);border-radius:8px;padding:12px 16px;margin-bottom:8px;cursor:pointer" onclick="if(shouldIgnoreSelectionClick(event))return;openPipelineDetail(\'' + escHtml(p.id) + '\')">' +
281
281
  '<div style="display:flex;justify-content:space-between;align-items:center">' +
282
282
  '<strong style="font-size:13px">' + escHtml(p.title) + '</strong>' +
283
283
  '<div style="display:flex;align-items:center;gap:8px">' +
@@ -263,7 +263,7 @@ function renderPlans(plans) {
263
263
  const versionBadge = p.version ? ' <span style="font-size:9px;font-weight:700;padding:1px 5px;border-radius:3px;background:rgba(56,139,253,0.15);color:var(--blue);vertical-align:middle">v' + p.version + '</span>' : '';
264
264
  const statusColors = { 'completed': 'var(--green)', 'dispatched': 'var(--blue)', 'converting': 'var(--yellow)', 'paused': 'var(--muted)', 'awaiting-approval': 'var(--yellow)', 'approved': 'var(--green)', 'rejected': 'var(--red)', 'has-failures': 'var(--red)', 'revision-requested': 'var(--purple,#a855f7)', 'active': 'var(--muted)' };
265
265
  const cardClass = effectiveStatus === 'dispatched' || effectiveStatus === 'converting' ? 'working' : effectiveStatus === 'awaiting-approval' || effectiveStatus === 'paused' ? 'awaiting' : effectiveStatus;
266
- return '<div class="plan-card ' + cardClass + '" data-file="plans/' + escHtml(p.file) + '" style="cursor:pointer' + (isArchived ? ';opacity:0.7' : '') + '" onclick="planView(\'' + escHtml(p.file) + '\')">' +
266
+ return '<div class="plan-card ' + cardClass + '" data-file="plans/' + escHtml(p.file) + '" style="cursor:pointer' + (isArchived ? ';opacity:0.7' : '') + '" onclick="if(shouldIgnoreSelectionClick(event))return;planView(\'' + escHtml(p.file) + '\')">' +
267
267
  '<div class="plan-card-header">' +
268
268
  '<div><div class="plan-card-title">' + escHtml(p.summary || p.file) + versionBadge + '</div>' +
269
269
  '<div class="plan-card-meta">' +
@@ -323,7 +323,7 @@ function openArchivedPlansModal() {
323
323
  const html = plans.map(p => {
324
324
  const itemCount = p.itemCount || 0;
325
325
  const completed = p.completedAt ? p.completedAt.slice(0, 10) : '';
326
- return '<div class="plan-card" data-file="plans/' + escHtml(p.file) + '" style="cursor:pointer;opacity:0.8" onclick="planView(\'' + escHtml(p.file) + '\')">' +
326
+ return '<div class="plan-card" data-file="plans/' + escHtml(p.file) + '" style="cursor:pointer;opacity:0.8" onclick="if(shouldIgnoreSelectionClick(event))return;planView(\'' + escHtml(p.file) + '\')">' +
327
327
  '<div class="plan-card-header">' +
328
328
  '<div><div class="plan-card-title" style="font-size:13px">' + escHtml(p.summary || p.file) + '</div>' +
329
329
  '<div class="plan-card-meta">' +
@@ -203,7 +203,7 @@ function renderPrdProgress(prog) {
203
203
  ? '<span onclick="event.stopPropagation();prdItemReopen(\'' + escHtml(i.source || '') + '\',\'' + escHtml(i.id) + '\')" style="color:var(--blue);cursor:pointer;font-size:9px;padding:1px 5px;background:rgba(56,139,253,0.1);border:1px solid rgba(56,139,253,0.3);border-radius:3px" title="Re-open: set to updated so engine re-dispatches on existing branch">re-open</span>'
204
204
  : '';
205
205
 
206
- return '<div class="prd-item-row st-' + (i.status || 'missing') + '" style="flex-wrap:wrap;cursor:pointer" onclick="prdItemEdit(\'' + src + '\',\'' + iid + '\')">' +
206
+ return '<div class="prd-item-row st-' + (i.status || 'missing') + '" style="flex-wrap:wrap;cursor:pointer" onclick="if(shouldIgnoreSelectionClick(event))return;prdItemEdit(\'' + src + '\',\'' + iid + '\')">' +
207
207
  statusBadge(i.status, i.id) +
208
208
  '<span class="prd-item-id">' + escHtml(i.id) + '</span>' +
209
209
  '<span class="prd-item-name" title="' + escHtml(i.name) + '">' + escHtml(i.name) + '</span>' +
@@ -579,7 +579,7 @@ function openArchivedPrdModal() {
579
579
  const done = g.items.filter(it => it.status === 'done').length;
580
580
  const failed = g.items.filter(it => it.status === 'failed').length;
581
581
  const completed = g.completedAt ? new Date(g.completedAt).toLocaleDateString() : '';
582
- return '<div class="plan-card" style="cursor:pointer;margin-bottom:8px" onclick="showArchivedPrdDetail(\'' + escHtml(g.file) + '\')">' +
582
+ return '<div class="plan-card" style="cursor:pointer;margin-bottom:8px" onclick="if(shouldIgnoreSelectionClick(event))return;showArchivedPrdDetail(\'' + escHtml(g.file) + '\')">' +
583
583
  '<div class="plan-card-title" style="font-size:13px">' + escHtml(g.summary || g.file) + '</div>' +
584
584
  '<div class="plan-card-meta">' +
585
585
  (g._projects.length > 0 ? g._projects.map(function(p) { return '<span>' + escHtml(p) + '</span>'; }).join(' ') : '') +
@@ -250,7 +250,7 @@ function _renderScheduleCalendar(schedules) {
250
250
  var strikeStyle = s.enabled === false ? 'text-decoration:line-through;' : '';
251
251
  var timeLabel = String(sl.hour).padStart(2, '0') + ':' + String(sl.minute).padStart(2, '0');
252
252
  html += '<div class="sched-cal-slot" style="background:' + colors.bg + ';border-left-color:' + colors.border + ';color:' + colors.text + ';opacity:' + opacity + '" ' +
253
- 'onclick="openScheduleDetail(\'' + escHtml(s.id) + '\')" title="' + escHtml(s.title + ' — ' + timeLabel + ' — ' + (s.type || 'implement')) + '">' +
253
+ 'onclick="if(shouldIgnoreSelectionClick(event))return;openScheduleDetail(\'' + escHtml(s.id) + '\')" title="' + escHtml(s.title + ' — ' + timeLabel + ' — ' + (s.type || 'implement')) + '">' +
254
254
  '<span style="font-weight:600;' + strikeStyle + '">' + escHtml((s.title || s.id).slice(0, 25)) + '</span>' +
255
255
  '<span style="font-size:9px;opacity:0.7"> ' + timeLabel + '</span>' +
256
256
  '</div>';
@@ -292,7 +292,7 @@ function renderSchedules(schedules) {
292
292
  const lastRun = s._lastRun ? timeAgo(s._lastRun) : 'never';
293
293
  const typeBadge = '<span class="dispatch-type ' + escHtml(s.type || 'implement') + '">' + escHtml(s.type || 'implement') + '</span>';
294
294
  const humanCron = _cronToHuman(s.cron || '');
295
- html += '<tr style="cursor:pointer" onclick="openScheduleDetail(\'' + escHtml(s.id) + '\')">' +
295
+ html += '<tr style="cursor:pointer" onclick="if(shouldIgnoreSelectionClick(event))return;openScheduleDetail(\'' + escHtml(s.id) + '\')">' +
296
296
  '<td><span class="pr-id">' + escHtml(s.id || '') + '</span></td>' +
297
297
  '<td style="max-width:200px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap" title="' + escHtml(s.title || '') + '">' + escHtml(s.title || '') + '</td>' +
298
298
  '<td><span title="' + escHtml(s.cron || '') + '" style="font-size:11px;color:var(--blue)">' + escHtml(humanCron) + '</span></td>' +
@@ -89,7 +89,7 @@ function renderWatches(watchesData) {
89
89
  var lastTriggered = w.last_triggered ? timeAgo(w.last_triggered) : 'never';
90
90
  var triggerInfo = (w.triggerCount || 0) + (w.stopAfter > 0 ? '/' + w.stopAfter : '');
91
91
 
92
- html += '<tr style="cursor:pointer" onclick="openWatchDetail(\'' + escHtml(w.id) + '\')">' +
92
+ html += '<tr style="cursor:pointer" onclick="if(shouldIgnoreSelectionClick(event))return;openWatchDetail(\'' + escHtml(w.id) + '\')">' +
93
93
  '<td><span class="pr-id">' + escHtml(w.id) + '</span></td>' +
94
94
  '<td style="max-width:180px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap" title="' + escHtml(w.description || w.target) + '">' + escHtml(w.target) + '</td>' +
95
95
  '<td><span class="dispatch-type explore">' + escHtml(targetLabel) + '</span></td>' +
@@ -40,7 +40,7 @@ function wiRow(item) {
40
40
  : (item.branchStrategy === 'shared-branch' && item.status === 'done')
41
41
  ? '<span style="font-size:9px;color:var(--muted)" title="Part of shared branch — aggregate PR created at verify stage">shared branch</span>'
42
42
  : '<span style="color:var(--muted)">—</span>';
43
- return '<tr style="cursor:pointer" onclick="if(window.getSelection().toString().length>0)return;openWorkItemDetail(\'' + escHtml(item.id) + '\')">' +
43
+ return '<tr style="cursor:pointer" onclick="if(shouldIgnoreSelectionClick(event))return;openWorkItemDetail(\'' + escHtml(item.id) + '\')">' +
44
44
  '<td><span class="pr-id">' + escHtml(item.id || '') + '</span></td>' +
45
45
  '<td style="max-width:220px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap" title="' + escHtml((item.title || '').slice(0, 200)) + '">' + escHtml(item.title || '') + '</td>' +
46
46
  '<td><span style="font-size:10px;color:var(--muted)">' + escHtml(item._source || '') + '</span>' +
@@ -68,8 +68,8 @@ async function openSettings() {
68
68
  '</div>' +
69
69
  settingsToggle('GitHub Polling', 'set-ghPollEnabled', e.ghPollEnabled !== false, 'Keeps GitHub PR build results, votes, and comments fresh each tick (reconciliation always runs regardless)') +
70
70
  '<div style="display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-top:10px">' +
71
- settingsField('Status Poll Frequency', 'set-prPollStatusEvery', e.prPollStatusEvery ?? e.adoPollStatusEvery ?? 12, 'ticks', 'Poll PR build/review/merge status every N ticks for both ADO and GitHub (~12 min at default tick rate)') +
72
- settingsField('Comments Poll Frequency', 'set-prPollCommentsEvery', e.prPollCommentsEvery ?? e.adoPollCommentsEvery ?? 12, 'ticks', 'Poll PR human comments every N ticks for both ADO and GitHub (~12 min at default tick rate)') +
71
+ settingsField('PR Status Poll Frequency', 'set-prPollStatusEvery', e.prPollStatusEvery ?? e.adoPollStatusEvery ?? 12, 'ticks', 'Poll PR build/review/merge status every N ticks for both ADO and GitHub (~12 min at default tick rate)') +
72
+ settingsField('PR Comments Poll Frequency', 'set-prPollCommentsEvery', e.prPollCommentsEvery ?? e.adoPollCommentsEvery ?? 12, 'ticks', 'Poll PR human comments every N ticks for both ADO and GitHub (~12 min at default tick rate)') +
73
73
  '</div>' +
74
74
  '</div>' +
75
75
 
@@ -129,6 +129,26 @@ function statusColor(s) {
129
129
  return s === 'working' ? 'working' : s === 'done' ? 'done' : s === 'error' ? 'error' : '';
130
130
  }
131
131
 
132
+ var SELECTION_CLICK_GUARD_MS = 300;
133
+ var _lastTextSelectionAt = 0;
134
+
135
+ function _selectionHasText() {
136
+ var sel = window.getSelection ? window.getSelection() : null;
137
+ return !!(sel && !sel.isCollapsed && sel.toString().trim());
138
+ }
139
+
140
+ function _markRecentTextSelection() {
141
+ if (_selectionHasText()) _lastTextSelectionAt = Date.now();
142
+ }
143
+
144
+ document.addEventListener('selectionchange', _markRecentTextSelection);
145
+ document.addEventListener('mouseup', _markRecentTextSelection);
146
+
147
+ function shouldIgnoreSelectionClick() {
148
+ if (_selectionHasText()) return true;
149
+ return (Date.now() - _lastTextSelectionAt) < SELECTION_CLICK_GUARD_MS;
150
+ }
151
+
132
152
  function llmCopyBtn() {
133
153
  return '<button class="llm-copy-btn" onclick="event.stopPropagation();copyLlmText(this)" title="Copy">&#x2398;</button>';
134
154
  }
@@ -462,4 +482,4 @@ async function submitBugReport() {
462
482
  }
463
483
  }
464
484
 
465
- window.MinionsUtils = { wakeEngine, escHtml, renderMd, normalizePlanFile, timeAgo, statusColor, llmCopyBtn, copyLlmText, openBugReport, submitBugReport };
485
+ window.MinionsUtils = { wakeEngine, escHtml, renderMd, normalizePlanFile, timeAgo, statusColor, shouldIgnoreSelectionClick, llmCopyBtn, copyLlmText, openBugReport, submitBugReport };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yemi33/minions",
3
- "version": "0.1.1106",
3
+ "version": "0.1.1108",
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"