@yemi33/minions 0.1.614 → 0.1.615

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,12 @@
1
1
  # Changelog
2
2
 
3
- ## 0.1.614 (2026-04-08)
3
+ ## 0.1.615 (2026-04-08)
4
4
 
5
5
  ### Features
6
6
  - clickable pinned notes and skills with full content + doc-chat
7
7
 
8
8
  ### Fixes
9
+ - only kill orphaned processes before worktree removal, not active ones
9
10
  - kill process holding worktree lock before removal attempt
10
11
  - dedup worktree removal attempts, add Windows rd fallback
11
12
  - accurate LLM call timing and agent metrics on engine page
package/engine/cleanup.js CHANGED
@@ -40,39 +40,48 @@ function worktreeDirMatchesBranch(dirLower, branch) {
40
40
  }
41
41
 
42
42
  /**
43
- * Kill any tracked or PID-filed process whose dispatch ID appears in the worktree dir name.
44
- * Must run BEFORE removeWorktree so file handles are released on Windows.
43
+ * Kill orphaned processes whose dispatch ID appears in the worktree dir name.
44
+ * Only kills processes NOT in the active dispatch queue never kills live agents.
45
45
  */
46
46
  function _killProcessInWorktree(dir, activeProcesses) {
47
47
  const dirLower = dir.toLowerCase();
48
- // Check tracked active processes
48
+ const dispatch = getDispatch();
49
+ const activeIds = new Set((dispatch.active || []).map(d => d.id));
50
+
51
+ // Check tracked in-memory processes — only kill if dispatch is no longer active
49
52
  for (const [id, info] of activeProcesses.entries()) {
50
- if (dirLower.includes(id.toLowerCase().slice(-8))) {
51
- try { shared.killImmediate(info.proc); } catch {}
52
- activeProcesses.delete(id);
53
- }
53
+ if (!dirLower.includes(id.toLowerCase().slice(-8))) continue;
54
+ if (activeIds.has(id)) continue; // still active — do not kill
55
+ try { shared.killImmediate(info.proc); } catch {}
56
+ activeProcesses.delete(id);
57
+ log('info', `Killed orphaned process for dispatch ${id} before worktree removal`);
54
58
  }
55
- // Check PID files in engine/tmp/ — format: pid-{label}-{id}.pid
59
+
60
+ // Check PID files in engine/tmp/ — only kill if no active dispatch matches
56
61
  try {
57
62
  const tmpDir = path.join(ENGINE_DIR, 'tmp');
58
63
  for (const f of fs.readdirSync(tmpDir)) {
59
64
  if (!f.startsWith('pid-') || !f.endsWith('.pid')) continue;
60
- // Extract dispatch ID suffix from filename
61
- const parts = f.replace(/^pid-/, '').replace(/\.pid$/, '').split('-');
62
- const suffix = parts.slice(-1)[0];
63
- if (suffix && dirLower.includes(suffix)) {
64
- const pid = parseInt(fs.readFileSync(path.join(tmpDir, f), 'utf8').trim(), 10);
65
- if (pid > 0) {
66
- try {
67
- if (process.platform === 'win32') {
68
- exec(`taskkill /F /PID ${pid}`, { stdio: 'pipe', timeout: 5000, windowsHide: true });
69
- } else {
70
- process.kill(pid, 'SIGKILL');
71
- }
72
- } catch {} // process may already be dead
73
- }
74
- try { fs.unlinkSync(path.join(tmpDir, f)); } catch {}
65
+ const pidFileName = f.replace(/^pid-/, '').replace(/\.pid$/, '');
66
+ if (!dirLower.includes(pidFileName.slice(-8))) continue;
67
+ // Verify this PID file's dispatch is not active
68
+ const isActive = [...activeIds].some(id => pidFileName.includes(id.slice(-8)));
69
+ if (isActive) continue; // still active — do not kill
70
+ const pid = parseInt(fs.readFileSync(path.join(tmpDir, f), 'utf8').trim(), 10);
71
+ if (pid > 0) {
72
+ // Verify the process is actually a node/claude process before killing
73
+ try {
74
+ if (process.platform === 'win32') {
75
+ const taskInfo = exec(`tasklist /FI "PID eq ${pid}" /NH`, { encoding: 'utf8', timeout: 3000, windowsHide: true });
76
+ if (!taskInfo.toLowerCase().includes('node')) continue; // not a node process — skip
77
+ exec(`taskkill /F /PID ${pid}`, { stdio: 'pipe', timeout: 5000, windowsHide: true });
78
+ } else {
79
+ process.kill(pid, 'SIGKILL');
80
+ }
81
+ log('info', `Killed orphaned PID ${pid} (${f}) before worktree removal`);
82
+ } catch {} // process may already be dead
75
83
  }
84
+ try { fs.unlinkSync(path.join(tmpDir, f)); } catch {}
76
85
  }
77
86
  } catch {} // tmp dir may not exist
78
87
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yemi33/minions",
3
- "version": "0.1.614",
3
+ "version": "0.1.615",
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"