@yemi33/minions 0.1.125 → 0.1.127

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,5 +1,27 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.127 (2026-04-01)
4
+
5
+ ### Engine
6
+ - engine.js
7
+ - engine/meeting.js
8
+
9
+ ### Dashboard
10
+ - dashboard/js/render-kb.js
11
+ - dashboard/js/render-schedules.js
12
+
13
+ ## 0.1.126 (2026-04-01)
14
+
15
+ ### Engine
16
+ - engine.js
17
+ - engine/shared.js
18
+
19
+ ### Dashboard
20
+ - dashboard/js/detail-panel.js
21
+ - dashboard/js/render-meetings.js
22
+ - dashboard/js/render-work-items.js
23
+ - dashboard/js/settings.js
24
+
3
25
  ## 0.1.125 (2026-04-01)
4
26
 
5
27
  ### Dashboard
@@ -135,6 +135,7 @@ function _cancelCharterEdit() {
135
135
  }
136
136
 
137
137
  async function _saveCharter() {
138
+ if (!currentAgentId) { alert('No agent selected'); return; }
138
139
  const content = document.getElementById('charter-editor').value;
139
140
  const btn = document.getElementById('charter-save-btn');
140
141
  btn.textContent = 'Saving...'; btn.style.pointerEvents = 'none';
@@ -147,15 +147,14 @@ async function submitKbEntry() {
147
147
  const title = document.getElementById('kb-new-title').value;
148
148
  const content = document.getElementById('kb-new-content').value;
149
149
  if (!title || !content) { alert('Title and content are required'); return; }
150
- try { closeModal(); } catch { /* may not be open */ }
151
- showToast('cmd-toast', 'KB entry created', true);
152
150
  try {
153
151
  const res = await fetch('/api/knowledge', {
154
152
  method: 'POST', headers: { 'Content-Type': 'application/json' },
155
153
  body: JSON.stringify({ category, title, content })
156
154
  });
157
- if (res.ok) { refreshKnowledgeBase(); } else { const d = await res.json().catch(() => ({})); alert('KB create failed: ' + (d.error || 'unknown')); openNewKbModal(); }
158
- } catch (e) { alert('Error: ' + e.message); openNewKbModal(); }
155
+ if (res.ok) { closeModal(); refreshKnowledgeBase(); showToast('cmd-toast', 'KB entry created', true); }
156
+ else { const d = await res.json().catch(() => ({})); alert('KB create failed: ' + (d.error || 'unknown')); }
157
+ } catch (e) { alert('Error: ' + e.message); }
159
158
  }
160
159
 
161
160
  async function kbOpenItem(category, file) {
@@ -305,7 +305,7 @@ async function _unarchiveMeeting(id) {
305
305
  method: 'POST', headers: { 'Content-Type': 'application/json' },
306
306
  body: JSON.stringify({ id })
307
307
  });
308
- if (!res.ok) { const d = await res.json().catch(() => ({})); alert('Delete failed: ' + (d.error || 'unknown')); refresh(); }
308
+ if (!res.ok) { const d = await res.json().catch(() => ({})); alert('Unarchive failed: ' + (d.error || 'unknown')); refresh(); }
309
309
  } catch (e) { alert('Error: ' + e.message); refresh(); }
310
310
  }
311
311
 
@@ -366,8 +366,8 @@ function _scheduleFormHtml(sched, isEdit) {
366
366
  const priorities = ['high', 'medium', 'low'];
367
367
  const typeOpts = types.map(t => '<option value="' + t + '"' + ((sched.type || 'implement') === t ? ' selected' : '') + '>' + t + '</option>').join('');
368
368
  const priOpts = priorities.map(p => '<option value="' + p + '"' + ((sched.priority || 'medium') === p ? ' selected' : '') + '>' + p + '</option>').join('');
369
- const projOpts = '<option value="">Any</option>' + cmdProjects.map(p => '<option value="' + escHtml(p.name) + '"' + (sched.project === p.name ? ' selected' : '') + '>' + escHtml(p.name) + '</option>').join('');
370
- const agentOpts = '<option value="">Auto</option>' + cmdAgents.map(a => '<option value="' + escHtml(a.id) + '"' + (sched.agent === a.id ? ' selected' : '') + '>' + escHtml(a.name) + '</option>').join('');
369
+ const projOpts = '<option value="">Any</option>' + (cmdProjects || []).map(p => '<option value="' + escHtml(p.name) + '"' + (sched.project === p.name ? ' selected' : '') + '>' + escHtml(p.name) + '</option>').join('');
370
+ const agentOpts = '<option value="">Auto</option>' + (cmdAgents || []).map(a => '<option value="' + escHtml(a.id) + '"' + (sched.agent === a.id ? ' selected' : '') + '>' + escHtml(a.name) + '</option>').join('');
371
371
 
372
372
  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';
373
373
  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';
@@ -161,7 +161,8 @@ async function submitWorkItemEdit(id, source) {
161
161
  async function deleteWorkItem(id, source) {
162
162
  if (!confirm('Delete work item ' + id + '? This will kill any running agent and remove all dispatch history.')) return;
163
163
  markDeleted('wi:' + id);
164
- document.querySelectorAll('tr').forEach(function(r) { if (r.textContent.includes(id)) r.remove(); });
164
+ var wiTable = document.getElementById('work-items-content');
165
+ (wiTable || document).querySelectorAll('tr').forEach(function(r) { if (r.textContent.includes(id)) r.remove(); });
165
166
  try {
166
167
  const res = await fetch('/api/work-items/delete', {
167
168
  method: 'POST', headers: { 'Content-Type': 'application/json' },
@@ -173,7 +174,8 @@ async function deleteWorkItem(id, source) {
173
174
 
174
175
  async function archiveWorkItem(id, source) {
175
176
  markDeleted('wi:' + id);
176
- document.querySelectorAll('tr').forEach(function(r) { if (r.textContent.includes(id)) r.remove(); });
177
+ var wiTable = document.getElementById('work-items-content');
178
+ (wiTable || document).querySelectorAll('tr').forEach(function(r) { if (r.textContent.includes(id)) r.remove(); });
177
179
  showToast('cmd-toast', 'Archived ' + id, true);
178
180
  try {
179
181
  const res = await fetch('/api/work-items/archive', {
@@ -39,6 +39,7 @@ async function openSettings() {
39
39
  '</div>' +
40
40
  '<div style="display:flex;flex-direction:column;gap:6px;margin-bottom:16px">' +
41
41
  settingsToggle('Auto-approve Plans', 'set-autoApprovePlans', !!e.autoApprovePlans, 'PRDs are approved automatically without human review') +
42
+ settingsToggle('Auto-review PRs', 'set-autoReview', e.autoReview !== false, 'Automatically dispatch review agents for new PRs') +
42
43
  settingsToggle('Auto-decompose', 'set-autoDecompose', e.autoDecompose !== false, 'Large implement items are auto-split into sub-tasks') +
43
44
  settingsToggle('Allow Temp Agents', 'set-allowTempAgents', !!e.allowTempAgents, 'Spawn ephemeral agents when all permanent agents are busy') +
44
45
  '</div>' +
@@ -121,6 +122,7 @@ async function saveSettings() {
121
122
  restartGracePeriod: document.getElementById('set-restartGracePeriod').value,
122
123
  meetingRoundTimeout: document.getElementById('set-meetingRoundTimeout').value,
123
124
  autoApprovePlans: document.getElementById('set-autoApprovePlans').checked,
125
+ autoReview: document.getElementById('set-autoReview').checked,
124
126
  autoDecompose: document.getElementById('set-autoDecompose').checked,
125
127
  allowTempAgents: document.getElementById('set-allowTempAgents').checked,
126
128
  };
package/engine/meeting.js CHANGED
@@ -179,6 +179,7 @@ function discoverMeetingWork(config) {
179
179
  * Called from runPostCompletionHooks when type === 'meeting'.
180
180
  */
181
181
  function collectMeetingFindings(meetingId, agentId, roundName, output) {
182
+ const e = engine();
182
183
  const meeting = getMeeting(meetingId);
183
184
  if (!meeting) return;
184
185
 
package/engine/shared.js CHANGED
@@ -337,6 +337,7 @@ const ENGINE_DEFAULTS = {
337
337
  allowTempAgents: false, // opt-in: spawn ephemeral agents when all permanent agents are busy
338
338
  autoDecompose: true, // auto-decompose implement:large items into sub-tasks
339
339
  autoApprovePlans: false, // auto-approve PRDs without waiting for human approval
340
+ autoReview: true, // auto-dispatch review agents for new PRs (disable for manual review workflow)
340
341
  meetingRoundTimeout: 600000, // 10min per meeting round before auto-advance
341
342
  };
342
343
 
package/engine.js CHANGED
@@ -1185,8 +1185,10 @@ function materializePlansAsWorkItems(config) {
1185
1185
  // Pre-create shared feature branch if branch_strategy is shared-branch
1186
1186
  if (plan.branch_strategy === 'shared-branch' && plan.feature_branch) {
1187
1187
  try {
1188
- const root = path.resolve(project.localPath);
1189
- const mainBranch = project.mainBranch || 'main';
1188
+ const firstProject = itemsByProject.values().next().value?.project;
1189
+ if (!firstProject?.localPath) throw new Error('no project with localPath');
1190
+ const root = path.resolve(firstProject.localPath);
1191
+ const mainBranch = firstProject.mainBranch || 'main';
1190
1192
  const branch = sanitizeBranch(plan.feature_branch);
1191
1193
  // Create branch from main (idempotent — ignores if exists)
1192
1194
  exec(`git branch "${branch}" "${mainBranch}" 2>/dev/null || true`, { cwd: root, stdio: 'pipe' });
@@ -1245,7 +1247,8 @@ function discoverFromPrs(config, project) {
1245
1247
  const reviewStatus = pr.reviewStatus || 'pending';
1246
1248
 
1247
1249
  // PRs needing review: pending or waiting (review dispatched but no verdict yet)
1248
- const needsReview = reviewStatus === 'pending' || reviewStatus === 'waiting';
1250
+ const autoReview = config.engine?.autoReview !== false;
1251
+ const needsReview = autoReview && (reviewStatus === 'pending' || reviewStatus === 'waiting');
1249
1252
  if (needsReview) {
1250
1253
  const key = `review-${project?.name || 'default'}-${pr.id}`;
1251
1254
  if (isAlreadyDispatched(key) || isOnCooldown(key, cooldownMs)) continue;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yemi33/minions",
3
- "version": "0.1.125",
3
+ "version": "0.1.127",
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"