gm-codex 2.0.936 → 2.0.937

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gm-codex",
3
- "version": "2.0.936",
3
+ "version": "2.0.937",
4
4
  "description": "State machine agent with hooks, skills, and automated git enforcement",
5
5
  "author": {
6
6
  "name": "AnEntrypoint",
package/bin/bootstrap.js CHANGED
@@ -338,6 +338,7 @@ async function bootstrap(opts) {
338
338
  log(`installed ${finalPath}`);
339
339
  obsEvent('bootstrap', 'install.done', { path: finalPath, version, kind: 'plugkit' });
340
340
  pruneOldVersions(root, version);
341
+ proactiveKillForNewInstall(version);
341
342
  // Best-effort rtk fetch: failures here never block plugkit usage
342
343
  try { await bootstrapRtk(verDir, version, wrapperDir, opts.silent); }
343
344
  catch (err) { log(`rtk fetch skipped: ${err.message}`); }
@@ -439,23 +440,67 @@ function writeDaemonVersion(v) {
439
440
  try { fs.writeFileSync(daemonVersionSentinel(), String(v)); } catch (_) {}
440
441
  }
441
442
 
443
+ function killPid(pid) {
444
+ if (!Number.isFinite(pid) || pid === process.pid || !pidAlive(pid)) return false;
445
+ try { process.kill(pid, 'SIGTERM'); }
446
+ catch (_) { try { process.kill(pid); } catch (_) {} }
447
+ if (os.platform() === 'win32' && pidAlive(pid)) {
448
+ try {
449
+ const { spawnSync } = require('child_process');
450
+ spawnSync('taskkill', ['/F', '/PID', String(pid)], { stdio: 'ignore', windowsHide: true });
451
+ } catch (_) {}
452
+ }
453
+ return true;
454
+ }
455
+
442
456
  function killRunningDaemons(reason) {
443
457
  const tmp = os.tmpdir();
444
- let killed = 0;
458
+ const killedPids = [];
445
459
  for (const pidFile of ['glootie-runner.pid', 'plugkit-runner.pid']) {
446
460
  const pidPath = path.join(tmp, pidFile);
447
461
  if (!fs.existsSync(pidPath)) continue;
448
462
  try {
449
463
  const pid = parseInt(fs.readFileSync(pidPath, 'utf8').trim(), 10);
450
- if (Number.isFinite(pid) && pid !== process.pid && pidAlive(pid)) {
451
- try { process.kill(pid, 'SIGTERM'); killed++; }
452
- catch (_) { try { process.kill(pid); killed++; } catch (_) {} }
464
+ if (killPid(pid)) {
465
+ killedPids.push(pid);
453
466
  obsEvent('bootstrap', 'daemon.killed', { pid, pidFile, reason });
454
467
  }
455
468
  try { fs.unlinkSync(pidPath); } catch (_) {}
456
469
  } catch (_) {}
457
470
  }
458
- return killed;
471
+ return killedPids;
472
+ }
473
+
474
+ function killSpoolWatcherInCwd(reason) {
475
+ try {
476
+ const pidPath = path.join(process.cwd(), '.gm', 'exec-spool', '.watcher.pid');
477
+ if (!fs.existsSync(pidPath)) return null;
478
+ const pid = parseInt(fs.readFileSync(pidPath, 'utf8').trim(), 10);
479
+ if (killPid(pid)) {
480
+ obsEvent('bootstrap', 'watcher.killed', { pid, reason });
481
+ try { fs.unlinkSync(pidPath); } catch (_) {}
482
+ return pid;
483
+ }
484
+ try { fs.unlinkSync(pidPath); } catch (_) {}
485
+ } catch (_) {}
486
+ return null;
487
+ }
488
+
489
+ function proactiveKillForNewInstall(installedVersion) {
490
+ try {
491
+ const recorded = readDaemonVersion();
492
+ if (recorded === installedVersion) return;
493
+ const reason = `install:${recorded || 'none'}->${installedVersion}`;
494
+ const killed = killRunningDaemons(reason);
495
+ const watcherPid = killSpoolWatcherInCwd(reason);
496
+ if (killed.length || watcherPid) {
497
+ const parts = [];
498
+ if (killed.length) parts.push(`daemon pid=${killed.join(',')} v${recorded || '?'}`);
499
+ if (watcherPid) parts.push(`watcher pid=${watcherPid}`);
500
+ try { process.stderr.write(`[bootstrap] killed stale ${parts.join(' + ')}, new binary ${installedVersion} ready\n`); } catch (_) {}
501
+ }
502
+ writeDaemonVersion(installedVersion);
503
+ } catch (_) {}
459
504
  }
460
505
 
461
506
  // Compare wrapper-pinned version against last-recorded daemon version. If
@@ -469,7 +514,7 @@ function killStaleDaemonIfVersionChanged(wrapperDir) {
469
514
  writeDaemonVersion(currentVersion);
470
515
  }
471
516
 
472
- module.exports = { bootstrap, resolveCachedBinary, resolveCachedRtk, platformKey, binaryName, rtkBinaryName, cacheRoot, obsEvent, killRunningDaemons, killStaleDaemonIfVersionChanged };
517
+ module.exports = { bootstrap, resolveCachedBinary, resolveCachedRtk, platformKey, binaryName, rtkBinaryName, cacheRoot, obsEvent, killRunningDaemons, killStaleDaemonIfVersionChanged, killSpoolWatcherInCwd, proactiveKillForNewInstall };
473
518
 
474
519
  if (require.main === module) {
475
520
  bootstrap({ silent: false })
package/gm.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gm",
3
- "version": "2.0.936",
3
+ "version": "2.0.937",
4
4
  "description": "State machine agent with hooks, skills, and automated git enforcement",
5
5
  "author": "AnEntrypoint",
6
6
  "license": "MIT",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gm-codex",
3
- "version": "2.0.936",
3
+ "version": "2.0.937",
4
4
  "description": "State machine agent with hooks, skills, and automated git enforcement",
5
5
  "author": "AnEntrypoint",
6
6
  "license": "MIT",
package/plugin.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gm",
3
- "version": "2.0.936",
3
+ "version": "2.0.937",
4
4
  "description": "State machine agent with hooks, skills, and automated git enforcement",
5
5
  "author": {
6
6
  "name": "AnEntrypoint",