@yemi33/minions 0.1.233 → 0.1.235

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,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.235 (2026-04-03)
4
+
5
+ ### Fixes
6
+ - CLI audit — kill dashboard on restart, expose kill/complete, update help
7
+ - clean _pendingReason on all status→done transitions, not just updateWorkItemStatus
8
+
3
9
  ## 0.1.233 (2026-04-03)
4
10
 
5
11
  ### Fixes
package/bin/minions.js CHANGED
@@ -431,6 +431,7 @@ const engineCmds = new Set([
431
431
  'start', 'stop', 'status', 'pause', 'resume',
432
432
  'queue', 'sources', 'discover', 'dispatch',
433
433
  'spawn', 'work', 'cleanup', 'mcp-sync', 'plan',
434
+ 'kill', 'complete',
434
435
  ]);
435
436
 
436
437
  if (!cmd || cmd === 'help' || cmd === '--help' || cmd === '-h') {
@@ -454,9 +455,13 @@ if (!cmd || cmd === 'help' || cmd === '--help' || cmd === '-h') {
454
455
  minions pause / resume Pause/resume dispatching
455
456
  minions dispatch Force a dispatch cycle
456
457
  minions discover Dry-run work discovery
458
+ minions queue Show dispatch queue (pending/active/completed)
459
+ minions sources Show work source status per project
457
460
  minions work <title> [opts] Add a work item
458
461
  minions spawn <agent> <prompt> Manually spawn an agent
459
462
  minions plan <file|text> [proj] Run a plan
463
+ minions kill Kill all active agents and reset to pending
464
+ minions complete <dispatch-id> Manually mark a dispatch as completed
460
465
  minions cleanup Clean temp files, worktrees, zombies
461
466
  minions nuke --confirm Factory reset (delete state, reset config to defaults)
462
467
 
@@ -484,8 +489,22 @@ if (!cmd || cmd === 'help' || cmd === '--help' || cmd === '-h') {
484
489
  } else if (cmd === 'up' || cmd === 'restart') {
485
490
  // Start both engine and dashboard — the go-to command after a reboot
486
491
  ensureInstalled();
487
- // Stop engine if running (ignore errors)
492
+ // Stop engine if running
488
493
  try { execSync(`node "${path.join(MINIONS_HOME, 'engine.js')}" stop`, { stdio: 'ignore', cwd: MINIONS_HOME }); } catch {}
494
+ // Kill existing dashboard
495
+ try {
496
+ if (process.platform === 'win32') {
497
+ const out = execSync('wmic process where "name=\'node.exe\'" get processid,commandline /format:csv', { encoding: 'utf8', timeout: 10000, windowsHide: true });
498
+ for (const line of out.split('\n')) {
499
+ if (line.includes('dashboard.js') && line.includes('minions')) {
500
+ const pid = line.split(',').pop()?.trim();
501
+ if (pid && pid !== String(process.pid)) try { process.kill(parseInt(pid)); } catch {}
502
+ }
503
+ }
504
+ } else {
505
+ try { execSync('lsof -ti:7331 | xargs kill -9 2>/dev/null', { timeout: 5000 }); } catch {}
506
+ }
507
+ } catch {}
489
508
  const engineProc = spawn(process.execPath, [path.join(MINIONS_HOME, 'engine.js'), 'start'], {
490
509
  cwd: MINIONS_HOME, stdio: 'ignore', detached: true, windowsHide: true
491
510
  });
package/engine/cleanup.js CHANGED
@@ -364,6 +364,7 @@ function runCleanup(config, verbose = false) {
364
364
  for (const item of items) {
365
365
  if (LEGACY_DONE_STATUSES.has(item.status)) {
366
366
  item.status = 'done';
367
+ delete item._pendingReason;
367
368
  migrated++;
368
369
  }
369
370
  }
@@ -381,6 +382,7 @@ function runCleanup(config, verbose = false) {
381
382
  for (const item of centralItems) {
382
383
  if (LEGACY_DONE_STATUSES.has(item.status)) {
383
384
  item.status = 'done';
385
+ delete item._pendingReason;
384
386
  migrated++;
385
387
  }
386
388
  }
package/engine/cli.js CHANGED
@@ -37,8 +37,9 @@ function handleCommand(cmd, args) {
37
37
  console.log(' spawn <a> <p> Manually spawn agent with prompt');
38
38
  console.log(' work <title> [o] Add to work-items.json queue');
39
39
  console.log(' plan <src> [p] Generate PRD from a plan (file or text)');
40
- console.log(' complete <id> Mark dispatch as done');
41
- console.log(' cleanup Clean temp files, worktrees, zombies');
40
+ console.log(' kill Kill all active agents, reset to pending');
41
+ console.log(' complete <id> Mark a dispatch as done');
42
+ console.log(' cleanup Clean temp files, worktrees, zombies');
42
43
  console.log(' mcp-sync Sync MCP servers from ~/.claude.json');
43
44
  console.log(' doctor Check prerequisites and runtime health');
44
45
  process.exit(1);
@@ -567,11 +568,19 @@ const commands = {
567
568
 
568
569
  complete(id) {
569
570
  if (!id) {
570
- console.log('Usage: node .minions/engine.js complete <dispatch-id>');
571
+ console.log('Usage: minions complete <dispatch-id>');
572
+ return;
573
+ }
574
+ const dispatch = getDispatch();
575
+ const found = (dispatch.active || []).some(d => d.id === id);
576
+ if (!found) {
577
+ console.log(` Dispatch "${id}" not found in active queue.`);
578
+ const pending = (dispatch.pending || []).some(d => d.id === id);
579
+ if (pending) console.log(' (It is in pending — it hasn\'t started yet.)');
571
580
  return;
572
581
  }
573
582
  engine().completeDispatch(id, 'success');
574
- console.log(`Marked ${id} as completed.`);
583
+ console.log(` Marked ${id} as completed.`);
575
584
  },
576
585
 
577
586
  dispatch() {
@@ -284,23 +284,33 @@ function checkPlanCompletion(meta, config) {
284
284
  shared.safeWrite(planPath, plan);
285
285
  }
286
286
 
287
- // Also archive the source .md plan if it exists
287
+ // Also archive the source .md plan if it exists (use source_plan field, not content matching)
288
288
  const planArchiveDir = path.join(PLANS_DIR, 'archive');
289
289
  if (!fs.existsSync(planArchiveDir)) fs.mkdirSync(planArchiveDir, { recursive: true });
290
- try {
291
- const mdFiles = fs.readdirSync(PLANS_DIR).filter(f => f.endsWith('.md'));
292
- for (const md of mdFiles) {
293
- const mdContent = shared.safeRead(path.join(PLANS_DIR, md)) || '';
294
- // Match by project name or plan summary appearing in the .md content
295
- if (mdContent.includes(projectName) || mdContent.includes(plan.plan_summary?.slice(0, 40) || '___nomatch___')) {
296
- try {
297
- fs.renameSync(path.join(PLANS_DIR, md), path.join(planArchiveDir, md));
298
- log('info', `Archived source plan: plans/archive/${md}`);
299
- } catch (err) { log('warn', `Failed to archive plan ${md}: ${err.message}`); }
300
- break;
301
- }
290
+ if (plan.source_plan) {
291
+ const mdPath = path.join(PLANS_DIR, plan.source_plan);
292
+ if (fs.existsSync(mdPath)) {
293
+ try {
294
+ fs.renameSync(mdPath, path.join(planArchiveDir, plan.source_plan));
295
+ log('info', `Archived source plan: plans/archive/${plan.source_plan}`);
296
+ } catch (err) { log('warn', `Failed to archive source plan ${plan.source_plan}: ${err.message}`); }
302
297
  }
303
- } catch (err) { log('warn', `Plan archive scan: ${err.message}`); }
298
+ } else {
299
+ // Fallback: scan for matching .md files (legacy PRDs without source_plan)
300
+ try {
301
+ const mdFiles = fs.readdirSync(PLANS_DIR).filter(f => f.endsWith('.md'));
302
+ for (const md of mdFiles) {
303
+ const mdContent = shared.safeRead(path.join(PLANS_DIR, md)) || '';
304
+ if (mdContent.includes(projectName) || mdContent.includes(plan.plan_summary?.slice(0, 40) || '___nomatch___')) {
305
+ try {
306
+ fs.renameSync(path.join(PLANS_DIR, md), path.join(planArchiveDir, md));
307
+ log('info', `Archived source plan: plans/archive/${md}`);
308
+ } catch (err) { log('warn', `Failed to archive plan ${md}: ${err.message}`); }
309
+ break;
310
+ }
311
+ }
312
+ } catch (err) { log('warn', `Plan archive scan: ${err.message}`); }
313
+ }
304
314
 
305
315
  // 6. Clean up ALL worktrees created for this plan's work items (shared-branch + per-item)
306
316
  try {
@@ -791,6 +801,7 @@ async function handlePostMerge(pr, project, config, newStatus) {
791
801
  log('info', `Post-merge: marking work item ${mergedItemId} as done (was ${item.status}) for ${pr.id}`);
792
802
  item.status = 'done';
793
803
  item.completedAt = ts();
804
+ delete item._pendingReason;
794
805
  item._mergedVia = pr.id;
795
806
  found = true;
796
807
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yemi33/minions",
3
- "version": "0.1.233",
3
+ "version": "0.1.235",
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"