gm-skill 2.0.1779 → 2.0.1793

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/AGENTS.md CHANGED
@@ -66,9 +66,7 @@ Record only non-obvious multi-run-cost caveats; prune stale; never document the
66
66
 
67
67
  **No graphical symbols; convert to industry-standard text on sight.** Any non-ASCII decorative glyph (arrows, box/geometric glyphs, stars, dots, bullets, checks/crosses, emojis) is forbidden in all output and source -- convert it to its plain-ASCII equivalent the same turn (the word, `->`, `-`/`*`, `[x]`/`[ ]`, done/todo/pass/fail). Tell-tale-AI class: one sighting spawns the full-codebase sweep, never a one-off edit. Exempt: functional code operators (`=>`, `??`, `?.`, comparison/math), frozen changelog/git-log entries, binary stores, intentional icon-font/CSS-content product glyphs, and canonical CS/formal-logic notation in `.gm/constraints.md` / `gm-plugkit/constraints-default.md` (`.`, `->` as function-space, `|-`, set/quantifier symbols) -- these are semantic operators in a formal constraints spec, not decorative flourish. `ccsniff --glyph-discipline` flags decorative glyphs post-hoc (run each audit, like `--git-discipline`/`--search-discipline`).
68
68
 
69
- **Skill SKILL.md files:** strip explanatory prose; keep ONLY invocation syntax, transition markers (`->`), gate conditions, constraint lists, exact-usage code examples.
70
-
71
- **Implicit, not explicit, in skill prose.** Skill files (and prompt-submit.txt) elicit, never describe: terse imperatives triggering already-learned dispositions, not numbered procedures. Describes = agent could re-derive from the goal (recipe, do-X-then-Y, trigger-instance list, over-explained rationale, restated mechanism) -- convert. Elicits = constructs a predicament where the wrong move is structurally incoherent -- keep. Exception: boot-edge ABI (exact spool paths, JSON fields, verb names, globs, deviation ids, gate names) is non-derivable, stays explicit regardless. Forbidden: step-by-step recipes, "see paper section X", site/paper citations, multi-step manuals -- manual-shaped skill gets imitated as script, breaks at first edge case. Papers/site are discipline OUTPUTS, never link from a skill into docs. Cross-cutting rules needing citation belong here, not in skills.
69
+ **Implicit, not explicit, in skill prose**: skill files elicit, never describe -- terse imperatives, no recipes/citations/manuals; boot-edge ABI (spool paths, JSON fields, verb names, deviation ids, gate names) stays explicit; SKILL.md keeps only invocation syntax, transition markers, gate conditions, constraints, exact-usage examples. Full criteria: rs-learn (`recall: implicit-not-explicit skill prose criteria`).
72
70
 
73
71
  ## Build
74
72
 
@@ -92,9 +90,9 @@ Every skill's `allowed-tools:` reduced to `Skill, Read, Write` (plus SKILL.md bo
92
90
 
93
91
  ## Core Rules
94
92
 
95
- **Shared memory & search index are tracked, never ignored**: `.gm/rs-learn.db`, `.gm/code-search/` committed -- state shares cross-machine/session/CI. Never gitignore `.gm/`, `.gm/rs-learn.db`, `.gm/code-search/`, legacy `.code-search/`; transient `.gm/*` entries listed one-by-one between managed markers (parent-re-include caveat). Entry list + `ensureGitignored` mechanics: rs-learn (`recall: gm managed-gitignore mechanics`). Project-local persistent state -> `.gm/<name>/`, never top-level dotfile/dotdir.
93
+ **Memory is human-readable md, tracked; derived stores are transient, never tracked**: canonical memory = `.gm/memories/<key>.md` (project facts) + `.gm/disciplines/<name>/memories/<key>.md` (transferable discipline knowledge), frontmatter `key/ns/created/updated`, UTF-8 no BOM, LF -- text shares cross-machine/session/CI as reviewable diffs. Legacy flat-JSON KV (`.gm/disciplines/<ns>/*.json`) remains the live recall read path until rs-plugkit's md read-path cutover lands; it stays tracked until then, then retires. Derived state (embeddings/`*-vec`, codeinsight manifests/digests, local sqlite/index dbs) is rebuildable-from-corpus, listed one-by-one between managed gitignore markers (parent-re-include caveat). Entry list + `ensureGitignored` mechanics: rs-learn (`recall: gm managed-gitignore mechanics`). Project-local persistent state -> `.gm/<name>/`, never top-level dotfile/dotdir.
96
94
 
97
- **Disciplines are isolated knowledge stores**: per-project `<project>/.gm/disciplines/<name>/{rs-learn.db, code-search/}`, own DB+index each. `@<name>` sigil = strict isolation (cross-discipline reads forbidden). Sigil-less reads (recall/codesearch) fan across `default` + every `enabled.txt` line, merge-ranked `[discipline:<name>]`-prefixed; sigil-less writes -> `default` only. Tracked, never ignored (`ensureGitignored` excludes `.gm/disciplines`). Harness + every spool verb propagate `@<name>` verbatim.
95
+ **Disciplines are isolated knowledge stores**: per-project `<project>/.gm/disciplines/<name>/{memories/, code-search/}`, own corpus+index each; memorize-time routing auto-creates a not-previously-known discipline's store rather than mixing it into project memories. `@<name>` sigil = strict isolation (cross-discipline reads forbidden). Sigil-less reads (recall/codesearch) fan across `default` + every `enabled.txt` line, merge-ranked `[discipline:<name>]`-prefixed; sigil-less writes -> project store only. Tracked, never ignored (`ensureGitignored` excludes `.gm/disciplines`); derived per-discipline caches follow the transient rule above. Harness + every spool verb propagate `@<name>` verbatim.
98
96
 
99
97
  **Nothing fake in source the user runs**: stub/mock/placeholder-return/fixture-only-path/demo-mode-short-circuit/"TODO: implement" forbidden in shipped code. Scaffolds/shims permitted only delegating to real behavior (upstream API, subprocess, disk); check for an existing library before adding a shim. Detection = behavioral: always-succeeds, input-invariant, or type-signature-satisfying short-circuit = stub. Acceptance = real input through real code into real output, witnessed.
100
98
 
package/bin/bootstrap.js CHANGED
@@ -606,6 +606,29 @@ function writeDaemonVersion(v) {
606
606
  try { fs.writeFileSync(daemonVersionSentinel(), String(v)); } catch (_) {}
607
607
  }
608
608
 
609
+ function pidCommandLineForKillGuard(pid) {
610
+ try {
611
+ const { spawnSync } = require('child_process');
612
+ if (process.platform === 'win32') {
613
+ const r = spawnSync('powershell.exe', ['-NoProfile', '-NonInteractive', '-Command', `(Get-CimInstance Win32_Process -Filter "ProcessId=${Number(pid)}").CommandLine`], { encoding: 'utf8', windowsHide: true, timeout: 5000 });
614
+ return String((r && r.stdout) || '');
615
+ }
616
+ const r = spawnSync('ps', ['-p', String(pid), '-o', 'args='], { encoding: 'utf8', timeout: 5000 });
617
+ return String((r && r.stdout) || '');
618
+ } catch (_) { return ''; }
619
+ }
620
+
621
+ function pidIsPlugkitProcess(pid) {
622
+ return /plugkit-wasm-wrapper\.js|plugkit-supervisor\.js|gm-plugkit[\\\/]supervisor\.js/i.test(pidCommandLineForKillGuard(pid));
623
+ }
624
+
625
+ function writeKillAttribution(targetSpoolDir, info) {
626
+ try {
627
+ fs.mkdirSync(targetSpoolDir, { recursive: true });
628
+ fs.writeFileSync(path.join(targetSpoolDir, '.kill-attribution.json'), JSON.stringify({ killer_pid: process.pid, killer_cwd: process.cwd(), killer_script: __filename, ts: Date.now(), ...info }, null, 2));
629
+ } catch (_) {}
630
+ }
631
+
609
632
  function killPid(pid) {
610
633
  if (!Number.isFinite(pid) || pid === process.pid || !pidAlive(pid)) return false;
611
634
  try { process.kill(pid, 'SIGTERM'); }
@@ -624,6 +647,12 @@ function killSpoolWatcherInCwd(reason) {
624
647
  const pidPath = path.join(process.cwd(), '.gm', 'exec-spool', '.watcher.pid');
625
648
  if (!fs.existsSync(pidPath)) return null;
626
649
  const pid = parseInt(fs.readFileSync(pidPath, 'utf8').trim(), 10);
650
+ if (pidAlive(pid) && !pidIsPlugkitProcess(pid)) {
651
+ obsEvent('bootstrap', 'watcher.kill-skipped-pid-reused', { pid, reason });
652
+ try { fs.unlinkSync(pidPath); } catch (_) {}
653
+ return null;
654
+ }
655
+ writeKillAttribution(path.join(process.cwd(), '.gm', 'exec-spool'), { reason, target_pid: pid, via: 'killSpoolWatcherInCwd' });
627
656
  if (killPid(pid)) {
628
657
  obsEvent('bootstrap', 'watcher.killed', { pid, reason });
629
658
  try { fs.unlinkSync(pidPath); } catch (_) {}
@@ -1 +1 @@
1
- 0.1.807
1
+ 0.1.818
@@ -1 +1 @@
1
- fef755b5d1f6d510182fa9ee0130a643dd054f95d62c70c62ef01813dd110b7e plugkit.wasm
1
+ 5cfcad879b84f2443f28e5ce9182d725bc6ebfeae1bf2c84a5b21d5a84a55a1e plugkit.wasm
@@ -450,6 +450,28 @@ function writeDaemonVersion(v) {
450
450
  try { fs.writeFileSync(daemonVersionSentinel(), String(v)); } catch (_) {}
451
451
  }
452
452
 
453
+ function pidCommandLineForKillGuard(pid) {
454
+ try {
455
+ if (process.platform === 'win32') {
456
+ const r = spawnSync('powershell.exe', ['-NoProfile', '-NonInteractive', '-Command', `(Get-CimInstance Win32_Process -Filter "ProcessId=${Number(pid)}").CommandLine`], { encoding: 'utf8', windowsHide: true, timeout: 5000 });
457
+ return String((r && r.stdout) || '');
458
+ }
459
+ const r = spawnSync('ps', ['-p', String(pid), '-o', 'args='], { encoding: 'utf8', timeout: 5000 });
460
+ return String((r && r.stdout) || '');
461
+ } catch (_) { return ''; }
462
+ }
463
+
464
+ function pidIsPlugkitProcess(pid) {
465
+ return /plugkit-wasm-wrapper\.js|plugkit-supervisor\.js|gm-plugkit[\\\/]supervisor\.js/i.test(pidCommandLineForKillGuard(pid));
466
+ }
467
+
468
+ function writeKillAttribution(targetSpoolDir, info) {
469
+ try {
470
+ fs.mkdirSync(targetSpoolDir, { recursive: true });
471
+ fs.writeFileSync(path.join(targetSpoolDir, '.kill-attribution.json'), JSON.stringify({ killer_pid: process.pid, killer_cwd: process.cwd(), killer_script: __filename, ts: Date.now(), ...info }, null, 2));
472
+ } catch (_) {}
473
+ }
474
+
453
475
  function killPid(pid) {
454
476
  if (!Number.isFinite(pid) || pid === process.pid || !pidAlive(pid)) return false;
455
477
  try { process.kill(pid, 'SIGTERM'); }
@@ -465,6 +487,12 @@ function killSpoolWatcherInCwd(reason) {
465
487
  const pidPath = path.join(process.cwd(), '.gm', 'exec-spool', '.watcher.pid');
466
488
  if (!fs.existsSync(pidPath)) return null;
467
489
  const pid = parseInt(fs.readFileSync(pidPath, 'utf8').trim(), 10);
490
+ if (pidAlive(pid) && !pidIsPlugkitProcess(pid)) {
491
+ obsEvent('bootstrap', 'watcher.kill-skipped-pid-reused', { pid, reason });
492
+ try { fs.unlinkSync(pidPath); } catch (_) {}
493
+ return null;
494
+ }
495
+ writeKillAttribution(path.join(process.cwd(), '.gm', 'exec-spool'), { reason, target_pid: pid, via: 'killSpoolWatcherInCwd' });
468
496
  if (killPid(pid)) {
469
497
  obsEvent('bootstrap', 'watcher.killed', { pid, reason });
470
498
  try { fs.unlinkSync(pidPath); } catch (_) {}
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gm-plugkit",
3
- "version": "2.0.1779",
3
+ "version": "2.0.1793",
4
4
  "description": "Bootstrap and daemon-spawn tool for gm plugkit binary. Downloads the correct platform binary, verifies SHA256, and starts the spool watcher daemon. Includes plugkit-wasm-wrapper for WASM-based spool watching.",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -74,6 +74,28 @@ function emitShutdownReason(reason, err) {
74
74
  } catch (_) {}
75
75
  }
76
76
 
77
+ function pidCommandLineForKillGuard(pid) {
78
+ try {
79
+ if (process.platform === 'win32') {
80
+ const r = spawnSync('powershell.exe', ['-NoProfile', '-NonInteractive', '-Command', `(Get-CimInstance Win32_Process -Filter "ProcessId=${Number(pid)}").CommandLine`], { encoding: 'utf8', windowsHide: true, timeout: 5000 });
81
+ return String((r && r.stdout) || '');
82
+ }
83
+ const r = spawnSync('ps', ['-p', String(pid), '-o', 'args='], { encoding: 'utf8', timeout: 5000 });
84
+ return String((r && r.stdout) || '');
85
+ } catch (_) { return ''; }
86
+ }
87
+
88
+ function pidIsPlugkitProcess(pid) {
89
+ return /plugkit-wasm-wrapper\.js|plugkit-supervisor\.js|gm-plugkit[\\\/]supervisor\.js/i.test(pidCommandLineForKillGuard(pid));
90
+ }
91
+
92
+ function writeKillAttribution(targetSpoolDir, info) {
93
+ try {
94
+ fs.mkdirSync(targetSpoolDir, { recursive: true });
95
+ fs.writeFileSync(path.join(targetSpoolDir, '.kill-attribution.json'), JSON.stringify({ killer_pid: process.pid, killer_cwd: process.cwd(), killer_script: 'plugkit-wasm-wrapper', ts: Date.now(), ...info }, null, 2));
96
+ } catch (_) {}
97
+ }
98
+
77
99
  function writeVerbActive(verb, task) {
78
100
  __currentVerbContext = { verb, task, started_at_ms: Date.now(), pid: process.pid };
79
101
  try {
@@ -1558,7 +1580,8 @@ function cosineSim(a, b) {
1558
1580
  }
1559
1581
 
1560
1582
  let __wasmAbortFlag = { aborted: false, code: 0 };
1561
- const WASI_FILESYSTEM_ROOT = path.join(GM_TOOLS_ROOT, 'wasi-fs');
1583
+ const WASI_PROJECT_SLUG = crypto.createHash('sha256').update(String(process.env.CLAUDE_PROJECT_DIR || process.cwd()).toLowerCase().replace(/\\/g, '/')).digest('hex').slice(0, 16);
1584
+ const WASI_FILESYSTEM_ROOT = path.join(GM_TOOLS_ROOT, 'wasi-fs', WASI_PROJECT_SLUG);
1562
1585
  const wasiOpenFiles = new Map();
1563
1586
  let wasiNextFd = 100;
1564
1587
 
@@ -2256,6 +2279,19 @@ function makeHostFunctions(instanceRef) {
2256
2279
  }
2257
2280
  },
2258
2281
 
2282
+ host_fs_remove: (pathPtr, pathLen) => {
2283
+ try {
2284
+ const filePath = readWasmStr(instanceRef.value, pathPtr, pathLen);
2285
+ if (!filePath) return 0;
2286
+ const st = fs.statSync(filePath);
2287
+ if (st.isDirectory()) return 0;
2288
+ fs.unlinkSync(filePath);
2289
+ return 1;
2290
+ } catch (e) {
2291
+ return 0;
2292
+ }
2293
+ },
2294
+
2259
2295
  host_fs_readdir: (pathPtr, pathLen) => {
2260
2296
  try {
2261
2297
  const dirPath = readWasmStr(instanceRef.value, pathPtr, pathLen);
@@ -3038,7 +3074,12 @@ async function runSpoolWatcher(instance, spoolDir) {
3038
3074
  holder_sha: holderSha,
3039
3075
  }));
3040
3076
  } catch (_) {}
3041
- try { process.kill(parseInt(pidStr, 10), 'SIGTERM'); } catch (_) {}
3077
+ if (pidIsPlugkitProcess(holderPidNum)) {
3078
+ writeKillAttribution(spoolDir, { reason: 'peer-stale-takeover', target_pid: holderPidNum, via: 'lock-takeover', holder_sha: holderSha });
3079
+ try { process.kill(holderPidNum, 'SIGTERM'); } catch (_) {}
3080
+ } else {
3081
+ try { logEvent('plugkit', 'takeover-kill-skipped-pid-reused', { holder_pid: pidStr }); } catch (_) {}
3082
+ }
3042
3083
  return 'takeover';
3043
3084
  } else {
3044
3085
  const msg = JSON.stringify({ ok: false, reason: 'another-watcher-active', pid: pidStr, age_ms: age });
@@ -3249,6 +3290,11 @@ async function runSpoolWatcher(instance, spoolDir) {
3249
3290
  try {
3250
3291
  process.kill(peerPid, 0);
3251
3292
  } catch (_) { continue; }
3293
+ if (!pidIsPlugkitProcess(peerPid)) {
3294
+ logEvent('plugkit', 'peer.kill-skipped-pid-reused', { peer_cwd: peerCwd, peer_pid: peerPid });
3295
+ continue;
3296
+ }
3297
+ writeKillAttribution(path.join(peerCwd, '.gm', 'exec-spool'), { reason: 'peer-stale-takeover', target_pid: peerPid, via: 'peer-sweep', peer_sha: peerSha, own_sha: _ownWrapperSha12 });
3252
3298
  logEvent('plugkit', 'peer.stale-wrapper-killed', { peer_cwd: peerCwd, peer_pid: peerPid, peer_sha: peerSha, own_sha: _ownWrapperSha12, lock_age_ms: age });
3253
3299
  console.error(`[plugkit-wasm] peer-sweep killing stale-wrapper watcher pid=${peerPid} cwd=${peerCwd} sha=${peerSha} (own=${_ownWrapperSha12})`);
3254
3300
  try {
@@ -1 +1 @@
1
- 0.1.807
1
+ 0.1.818
@@ -64,6 +64,28 @@ function writeSupervisorStatus(state, extra) {
64
64
  } catch (_) {}
65
65
  }
66
66
 
67
+ function pidCommandLineForKillGuard(pid) {
68
+ try {
69
+ if (process.platform === 'win32') {
70
+ const r = spawnSync('powershell.exe', ['-NoProfile', '-NonInteractive', '-Command', `(Get-CimInstance Win32_Process -Filter "ProcessId=${Number(pid)}").CommandLine`], { encoding: 'utf8', windowsHide: true, timeout: 5000 });
71
+ return String((r && r.stdout) || '');
72
+ }
73
+ const r = spawnSync('ps', ['-p', String(pid), '-o', 'args='], { encoding: 'utf8', timeout: 5000 });
74
+ return String((r && r.stdout) || '');
75
+ } catch (_) { return ''; }
76
+ }
77
+
78
+ function pidIsPlugkitProcess(pid) {
79
+ return /plugkit-wasm-wrapper\.js|plugkit-supervisor\.js|gm-plugkit[\\\/]supervisor\.js/i.test(pidCommandLineForKillGuard(pid));
80
+ }
81
+
82
+ function writeKillAttribution(targetSpoolDir, info) {
83
+ try {
84
+ fs.mkdirSync(targetSpoolDir, { recursive: true });
85
+ fs.writeFileSync(path.join(targetSpoolDir, '.kill-attribution.json'), JSON.stringify({ killer_pid: process.pid, killer_cwd: process.cwd(), killer_script: __filename, ts: Date.now(), ...info }, null, 2));
86
+ } catch (_) {}
87
+ }
88
+
67
89
  function pidAlive(pid) {
68
90
  if (!Number.isFinite(pid) || pid <= 0) return false;
69
91
  try { process.kill(pid, 0); return true; } catch (_) { return false; }
@@ -100,9 +122,14 @@ function acquireSingleInstance() {
100
122
  spool_status_age_ms: now - spoolTs,
101
123
  severity: 'critical',
102
124
  });
103
- try { process.kill(other, 'SIGTERM'); } catch (_) {}
104
- if (process.platform === 'win32') {
105
- try { spawnSync('taskkill', ['/F', '/T', '/PID', String(other)], { stdio: 'ignore', windowsHide: true, timeout: 3000 }); } catch (_) {}
125
+ if (pidIsPlugkitProcess(other)) {
126
+ writeKillAttribution(spoolDir, { reason: 'supervisor-takeover-wedged', target_pid: other, via: 'supervisor-duel' });
127
+ try { process.kill(other, 'SIGTERM'); } catch (_) {}
128
+ if (process.platform === 'win32') {
129
+ try { spawnSync('taskkill', ['/F', '/T', '/PID', String(other)], { stdio: 'ignore', windowsHide: true, timeout: 3000 }); } catch (_) {}
130
+ }
131
+ } else {
132
+ logEvent('supervisor.takeover-kill-skipped-pid-reused', { existing_pid: other, severity: 'warn' });
106
133
  }
107
134
  }
108
135
  try { fs.unlinkSync(SUPERVISOR_PID_PATH); } catch (_) {}
package/gm.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gm",
3
- "version": "2.0.1779",
3
+ "version": "2.0.1793",
4
4
  "description": "Spool-dispatch orchestration engine with unified state machine, skills, and automated git enforcement",
5
5
  "author": "AnEntrypoint",
6
6
  "license": "MIT",
@@ -17,5 +17,5 @@
17
17
  "publishConfig": {
18
18
  "access": "public"
19
19
  },
20
- "plugkitVersion": "0.1.807"
20
+ "plugkitVersion": "0.1.818"
21
21
  }
@@ -406,6 +406,26 @@ function isProcessRunning() {
406
406
  return findPlugkitWasmPids().length > 0;
407
407
  }
408
408
 
409
+ function pidCommandLineForKillGuard(pid) {
410
+ try {
411
+ if (process.platform === 'win32') {
412
+ return execFileSync('powershell.exe', ['-NoProfile', '-NonInteractive', '-Command', `(Get-CimInstance Win32_Process -Filter "ProcessId=${Number(pid)}").CommandLine`], { encoding: 'utf8', windowsHide: true, timeout: 5000 }) || '';
413
+ }
414
+ return execFileSync('ps', ['-p', String(pid), '-o', 'args='], { encoding: 'utf8', timeout: 5000 }) || '';
415
+ } catch (_) { return ''; }
416
+ }
417
+
418
+ function pidIsPlugkitProcess(pid) {
419
+ return /plugkit-wasm-wrapper\.js|plugkit-supervisor\.js|gm-plugkit[\\\/]supervisor\.js/i.test(pidCommandLineForKillGuard(pid));
420
+ }
421
+
422
+ function writeKillAttribution(targetSpoolDir, info) {
423
+ try {
424
+ fs.mkdirSync(targetSpoolDir, { recursive: true });
425
+ fs.writeFileSync(path.join(targetSpoolDir, '.kill-attribution.json'), JSON.stringify({ killer_pid: process.pid, killer_cwd: process.cwd(), killer_script: __filename, ts: Date.now(), ...info }, null, 2));
426
+ } catch (_) {}
427
+ }
428
+
409
429
  function killExistingPlugkit() {
410
430
  try {
411
431
  const pids = findPlugkitWasmPids();
@@ -413,17 +433,24 @@ function killExistingPlugkit() {
413
433
  emitBootstrapEvent('info', 'No existing plugkit WASM watcher to kill');
414
434
  return;
415
435
  }
436
+ const killed = [];
416
437
  for (const pid of pids) {
438
+ if (!pidIsPlugkitProcess(pid)) {
439
+ emitBootstrapEvent('warn', 'Kill skipped: pid is not a plugkit process (stale or reused pid)', { pid });
440
+ continue;
441
+ }
442
+ writeKillAttribution(path.join(process.cwd(), '.gm', 'exec-spool'), { reason: 'bootstrap-refresh', target_pid: Number(pid), via: 'killExistingPlugkit' });
417
443
  try {
418
444
  if (process.platform === 'win32') {
419
445
  execFileSync('taskkill', ['/F', '/T', '/PID', String(pid)], { stdio: 'ignore', windowsHide: true });
420
446
  } else {
421
447
  execFileSync('kill', ['-9', String(pid)], { stdio: 'ignore' });
422
448
  }
449
+ killed.push(pid);
423
450
  } catch (e) {
424
451
  }
425
452
  }
426
- emitBootstrapEvent('info', 'Killed existing plugkit WASM watcher', { pids });
453
+ emitBootstrapEvent('info', 'Killed existing plugkit WASM watcher', { pids: killed });
427
454
  } catch (e) {
428
455
  emitBootstrapEvent('warn', 'Failed to kill existing plugkit', { error: e.message });
429
456
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gm-skill",
3
- "version": "2.0.1779",
3
+ "version": "2.0.1793",
4
4
  "description": "Canonical universal harness — AI-native software engineering via skill-driven orchestration; bootstraps plugkit for task execution and session isolation. Install in any AI coding agent host.",
5
5
  "author": "AnEntrypoint",
6
6
  "license": "MIT",