@yemi33/minions 0.1.400 → 0.1.402

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,11 +1,13 @@
1
1
  # Changelog
2
2
 
3
- ## 0.1.400 (2026-04-06)
3
+ ## 0.1.402 (2026-04-06)
4
4
 
5
5
  ### Features
6
6
  - pipeline stages detect and link inbox notes as artifacts
7
7
 
8
8
  ### Fixes
9
+ - prevent auto-review of human PRs + add unlink button
10
+ - reconcilePrs only auto-tracks PRs linked to minions work items
9
11
  - auto-detect main branch when configured mainBranch doesn't exist
10
12
  - engine restart button shows toast + green checkmark, suppresses stale banner 30s
11
13
 
@@ -28,12 +28,13 @@ function prRow(pr) {
28
28
  '<td><span class="pr-badge ' + buildClass + '">' + escHtml(buildLabel) + '</span></td>' +
29
29
  '<td><span class="pr-badge ' + statusClass + '">' + escHtml(statusLabel) + '</span></td>' +
30
30
  '<td><span class="pr-date">' + escHtml((pr.created || '—').slice(0, 16).replace('T', ' ')) + '</span></td>' +
31
+ '<td><button class="pr-pager-btn" style="font-size:9px;padding:1px 5px;color:var(--red);border-color:var(--red)" data-pr-id="' + escHtml(String(prId)) + '" onclick="event.stopPropagation();unlinkPr(this.dataset.prId)" title="Remove from tracking">x</button></td>' +
31
32
  '</tr>';
32
33
  }
33
34
 
34
35
  function prTableHtml(rows) {
35
36
  return '<div class="pr-table-wrap"><table class="pr-table"><thead><tr>' +
36
- '<th>PR</th><th>Title</th><th>Agent</th><th>Branch</th><th>Review</th><th>Signed Off By</th><th>Build</th><th>Status</th><th>Created</th>' +
37
+ '<th>PR</th><th>Title</th><th>Agent</th><th>Branch</th><th>Review</th><th>Signed Off By</th><th>Build</th><th>Status</th><th>Created</th><th></th>' +
37
38
  '</tr></thead><tbody>' + rows + '</tbody></table></div>';
38
39
  }
39
40
 
@@ -150,4 +151,17 @@ async function _submitLinkPr() {
150
151
  } catch (e) { alert('Error: ' + e.message); openAddPrModal(); }
151
152
  }
152
153
 
153
- window.MinionsPrs = { prRow, prTableHtml, renderPrs, prPrev, prNext, openAllPrs, openModal, openAddPrModal };
154
+ async function unlinkPr(id) {
155
+ if (!confirm('Remove ' + id + ' from tracking?')) return;
156
+ try {
157
+ const res = await fetch('/api/pull-requests/delete', {
158
+ method: 'POST', headers: { 'Content-Type': 'application/json' },
159
+ body: JSON.stringify({ id })
160
+ });
161
+ if (!res.ok) { const d = await res.json().catch(() => ({})); alert('Failed: ' + (d.error || 'unknown')); return; }
162
+ showToast('cmd-toast', id + ' removed', true);
163
+ refresh();
164
+ } catch (e) { alert('Error: ' + e.message); }
165
+ }
166
+
167
+ window.MinionsPrs = { prRow, prTableHtml, renderPrs, prPrev, prNext, openAllPrs, openModal, openAddPrModal, unlinkPr };
package/dashboard.js CHANGED
@@ -3631,6 +3631,26 @@ What would you like to discuss or change? When you're happy, say "approve" and I
3631
3631
  return jsonReply(res, 200, { ok: true, id: prId });
3632
3632
  }},
3633
3633
 
3634
+ { method: 'POST', path: '/api/pull-requests/delete', desc: 'Remove a PR from tracking', params: 'id, project?', handler: async (req, res) => {
3635
+ const body = await readBody(req);
3636
+ const { id, project: projectName } = body;
3637
+ if (!id) return jsonReply(res, 400, { error: 'id required' });
3638
+ reloadConfig();
3639
+ const projects = shared.getProjects(CONFIG);
3640
+ const targetProject = projectName ? projects.find(p => p.name?.toLowerCase() === projectName.toLowerCase()) : projects[0];
3641
+ const prPath = targetProject ? shared.projectPrPath(targetProject) : path.join(MINIONS_DIR, 'pull-requests.json');
3642
+ let found = false;
3643
+ mutateJsonFileLocked(prPath, (prs) => {
3644
+ if (!Array.isArray(prs)) return prs;
3645
+ const idx = prs.findIndex(p => p.id === id);
3646
+ if (idx >= 0) { prs.splice(idx, 1); found = true; }
3647
+ return prs;
3648
+ }, { defaultValue: [] });
3649
+ if (!found) return jsonReply(res, 404, { error: 'PR not found' });
3650
+ invalidateStatusCache();
3651
+ return jsonReply(res, 200, { ok: true });
3652
+ }},
3653
+
3634
3654
  { method: 'POST', path: '/api/plans/create', desc: 'Create a plan from user-provided content', params: 'title, content, project?', handler: async (req, res) => {
3635
3655
  const body = await readBody(req);
3636
3656
  const { title, content, project: projectName } = body;
package/engine/ado.js CHANGED
@@ -399,6 +399,11 @@ async function reconcilePrs(config) {
399
399
  continue;
400
400
  }
401
401
 
402
+ // Only auto-track PRs that are linked to a minions work item.
403
+ // PRs on feat/ or work/ branches without a work item ID (P-xxx, W-xxx, PL-xxx)
404
+ // are human-authored and should not be auto-tracked or auto-reviewed.
405
+ if (!confirmedItemId) continue;
406
+
402
407
  const prUrl = project.prUrlBase ? project.prUrlBase + adoPr.pullRequestId : '';
403
408
  existingPrs.push({
404
409
  id: prId,
@@ -409,12 +414,12 @@ async function reconcilePrs(config) {
409
414
  status: 'active',
410
415
  created: adoPr.creationDate || ts(),
411
416
  url: prUrl,
412
- prdItems: confirmedItemId ? [confirmedItemId] : [],
417
+ prdItems: [confirmedItemId],
413
418
  });
414
- if (confirmedItemId) addPrLink(prId, confirmedItemId);
419
+ addPrLink(prId, confirmedItemId);
415
420
  existingIds.add(prId);
416
421
  projectAdded++;
417
- log('info', `PR reconciliation: added ${prId} (branch: ${branch}${confirmedItemId ? ', linked to ' + confirmedItemId : ''}) to ${project.name}`);
422
+ log('info', `PR reconciliation: added ${prId} (branch: ${branch}, linked to ${confirmedItemId}) to ${project.name}`);
418
423
  }
419
424
 
420
425
  // Backfill prdItems from pr-links for any PR with empty array
package/engine/github.js CHANGED
@@ -396,6 +396,9 @@ async function reconcilePrs(config) {
396
396
  continue;
397
397
  }
398
398
 
399
+ // Only auto-track PRs linked to a minions work item — skip human-authored PRs
400
+ if (!confirmedItemId) continue;
401
+
399
402
  const prUrl = project.prUrlBase ? project.prUrlBase + ghPr.number : ghPr.html_url || '';
400
403
 
401
404
  existingPrs.push({
@@ -407,13 +410,13 @@ async function reconcilePrs(config) {
407
410
  status: 'active',
408
411
  created: ghPr.created_at || ts(),
409
412
  url: prUrl,
410
- prdItems: confirmedItemId ? [confirmedItemId] : [],
413
+ prdItems: [confirmedItemId],
411
414
  });
412
- if (confirmedItemId) addPrLink(prId, confirmedItemId);
415
+ addPrLink(prId, confirmedItemId);
413
416
  existingIds.add(prId);
414
417
  projectAdded++;
415
418
 
416
- log('info', `GitHub PR reconciliation: added ${prId} (branch: ${branch}${confirmedItemId ? ', linked to ' + confirmedItemId : ''}) to ${project.name}`);
419
+ log('info', `GitHub PR reconciliation: added ${prId} (branch: ${branch}, linked to ${confirmedItemId}) to ${project.name}`);
417
420
  }
418
421
 
419
422
  // Backfill prdItems from pr-links for any PR with empty array
package/engine.js CHANGED
@@ -1261,9 +1261,14 @@ function discoverFromPrs(config, project) {
1261
1261
  (dispatch.active || []).filter(d => d.meta?.pr?.id).map(d => d.meta.pr.id)
1262
1262
  );
1263
1263
 
1264
+ const knownAgents = new Set(Object.keys(config.agents || {}));
1264
1265
  for (const pr of prs) {
1265
1266
  if (pr.status !== 'active') continue;
1266
1267
  if (activePrIds.has(pr.id)) continue; // Skip PRs with active dispatch (prevent race)
1268
+ // Skip human-authored PRs not linked to any work item — only auto-manage agent PRs
1269
+ // Manually-linked PRs with autoObserve are allowed through (they have _autoObserve flag)
1270
+ const isAgentPr = knownAgents.has((pr.agent || '').toLowerCase()) || (pr.prdItems && pr.prdItems.length > 0) || pr._autoObserve;
1271
+ if (!isAgentPr) continue;
1267
1272
 
1268
1273
  const prNumber = (pr.id || '').replace(/^PR-/, '');
1269
1274
  // Use reviewStatus as single source of truth (synced from ADO/GitHub votes)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yemi33/minions",
3
- "version": "0.1.400",
3
+ "version": "0.1.402",
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"