gm-plugkit 2.0.1513 → 2.0.1514

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gm-plugkit",
3
- "version": "2.0.1513",
3
+ "version": "2.0.1514",
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": {
@@ -15,6 +15,10 @@ let _writeStatusBusy = () => {};
15
15
  // Latest busy_until epoch ms stamped by a long synchronous verb (codesearch rebuild, chromium
16
16
  // spawn). scanStalledTurns reads it so a busy watcher is not mis-flagged as an idle stall.
17
17
  let _lastBusyUntil = 0;
18
+ // First 12 hex of sha256 of this watcher's own gmTools wrapper. Module-scoped so writeStatus
19
+ // (a different function scope) can stamp status.wrapper_sha, which the supervisor compares
20
+ // against the on-disk wrapper to recycle a watcher running a stale wrapper-only fix.
21
+ let _ownWrapperSha12 = '';
18
22
 
19
23
  function spawnSync(cmd, args, opts) {
20
24
  return _rawSpawnSync(cmd, args, { windowsHide: true, ...(opts || {}) });
@@ -2078,7 +2082,6 @@ async function runSpoolWatcher(instance, spoolDir) {
2078
2082
 
2079
2083
 
2080
2084
  const LOCK_PATH = path.join(spoolDir, '.watcher.lock');
2081
- let _ownWrapperSha12 = '';
2082
2085
  try {
2083
2086
  const _crypto = require('crypto');
2084
2087
  const _wp = path.join(GM_TOOLS_ROOT, 'plugkit-wasm-wrapper.js');
package/supervisor.js CHANGED
@@ -4,8 +4,18 @@
4
4
  const fs = require('fs');
5
5
  const path = require('path');
6
6
  const os = require('os');
7
+ const crypto = require('crypto');
7
8
  const { spawn, spawnSync } = require('child_process');
8
9
 
10
+ function wrapperSha12OnDisk() {
11
+ try {
12
+ const primary = path.join(os.homedir(), '.gm-tools', 'plugkit-wasm-wrapper.js');
13
+ const fallback = path.join(os.homedir(), '.claude', 'gm-tools', 'plugkit-wasm-wrapper.js');
14
+ const wp = fs.existsSync(primary) ? primary : fallback;
15
+ return crypto.createHash('sha256').update(fs.readFileSync(wp)).digest('hex').slice(0, 12);
16
+ } catch (_) { return null; }
17
+ }
18
+
9
19
  const projectDir = process.env.CLAUDE_PROJECT_DIR || process.cwd();
10
20
  const spoolDir = path.join(projectDir, '.gm', 'exec-spool');
11
21
  fs.mkdirSync(spoolDir, { recursive: true });
@@ -227,6 +237,25 @@ function checkWatcherHealth() {
227
237
  if (process.platform === 'win32') {
228
238
  try { spawnSync('taskkill', ['/F', '/T', '/PID', String(currentChildPid)], { stdio: 'ignore', windowsHide: true, timeout: 3000 }); } catch (_) {}
229
239
  }
240
+ return;
241
+ }
242
+ // A published wrapper-only fix (no wasm version bump) lands in ~/.gm-tools via the next
243
+ // bootstrap's ensureWrapperFresh, but a healthy running watcher keeps the old wrapper until it
244
+ // restarts. On wrapper_sha drift (watcher's reported sha != on-disk), recycle so the fix goes
245
+ // live without a manual kill. busy_until already returned above, so the watcher is not mid-verb.
246
+ const reported = status.wrapper_sha || null;
247
+ const onDisk = wrapperSha12OnDisk();
248
+ if (reported && onDisk && reported !== onDisk) {
249
+ logEvent('supervisor.wrapper-sha-drift', {
250
+ watcher_pid: currentChildPid,
251
+ reported_sha: reported,
252
+ on_disk_sha: onDisk,
253
+ severity: 'info',
254
+ });
255
+ try { process.kill(currentChildPid, 'SIGTERM'); } catch (_) {}
256
+ if (process.platform === 'win32') {
257
+ try { spawnSync('taskkill', ['/F', '/T', '/PID', String(currentChildPid)], { stdio: 'ignore', windowsHide: true, timeout: 3000 }); } catch (_) {}
258
+ }
230
259
  }
231
260
  }
232
261