@yemi33/minions 0.1.613 → 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,13 @@
1
1
  # Changelog
2
2
 
3
- ## 0.1.613 (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
10
+ - kill process holding worktree lock before removal attempt
9
11
  - dedup worktree removal attempts, add Windows rd fallback
10
12
  - accurate LLM call timing and agent metrics on engine page
11
13
  - worktree count now checks for .git file instead of any directory
package/engine/cleanup.js CHANGED
@@ -39,6 +39,53 @@ function worktreeDirMatchesBranch(dirLower, branch) {
39
39
  return dirLower === branchSlug || dirLower.includes(branchSlug + '-') || dirLower.endsWith('-' + branchSlug);
40
40
  }
41
41
 
42
+ /**
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
+ */
46
+ function _killProcessInWorktree(dir, activeProcesses) {
47
+ const dirLower = dir.toLowerCase();
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
52
+ for (const [id, info] of activeProcesses.entries()) {
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`);
58
+ }
59
+
60
+ // Check PID files in engine/tmp/ — only kill if no active dispatch matches
61
+ try {
62
+ const tmpDir = path.join(ENGINE_DIR, 'tmp');
63
+ for (const f of fs.readdirSync(tmpDir)) {
64
+ if (!f.startsWith('pid-') || !f.endsWith('.pid')) continue;
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
83
+ }
84
+ try { fs.unlinkSync(path.join(tmpDir, f)); } catch {}
85
+ }
86
+ } catch {} // tmp dir may not exist
87
+ }
88
+
42
89
  // ─── Cleanup Orchestrator ────────────────────────────────────────────────────
43
90
 
44
91
  function runCleanup(config, verbose = false) {
@@ -264,6 +311,8 @@ function runCleanup(config, verbose = false) {
264
311
 
265
312
  if (_attemptedWorktreePaths.has(entry.wtPath)) continue;
266
313
  _attemptedWorktreePaths.add(entry.wtPath);
314
+ // Kill any process still running in this worktree before removal
315
+ _killProcessInWorktree(entry.dir, activeProcesses);
267
316
  if (shared.removeWorktree(entry.wtPath, root, worktreeRoot)) {
268
317
  cleaned.worktrees++;
269
318
  if (verbose) console.log(` Removed worktree: ${entry.wtPath}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yemi33/minions",
3
- "version": "0.1.613",
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"