gm-skill 2.0.1843 → 2.0.1845

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 +1 @@
1
- 0.1.841
1
+ 0.1.842
@@ -1 +1 @@
1
- d98719a4fca87818408763e4c52d56f704544f073b2a0477cadd37fd0d9a7e46 plugkit.wasm
1
+ 9fa5c0c01535c51918470d2e6f38ac22559a2b001cb2908a08239b8e3c4f63e9 plugkit.wasm
@@ -751,12 +751,31 @@ function ensureWrapperFresh() {
751
751
  if (a === b) same = true;
752
752
  } catch (_) {}
753
753
  }
754
- if (!same) {
755
- fs.mkdirSync(gmToolsDir(), { recursive: true });
756
- fs.copyFileSync(wrapperSrc, wrapperDst);
754
+ if (same) return false;
755
+ // Many independent per-project watchers share this one gmToolsDir() install --
756
+ // concurrent CLI invocations from different projects can race this copy, so
757
+ // it's lock-guarded (atomic O_EXCL) + tmp-write-then-rename, never a direct
758
+ // in-place copyFileSync another reader could observe half-written.
759
+ fs.mkdirSync(gmToolsDir(), { recursive: true });
760
+ const lockPath = wrapperDst + '.lock';
761
+ acquireLock(lockPath);
762
+ try {
763
+ let stillSame = false;
764
+ if (fs.existsSync(wrapperDst)) {
765
+ try {
766
+ const a = sha256OfFileSync(wrapperSrc);
767
+ const b = sha256OfFileSync(wrapperDst);
768
+ if (a === b) stillSame = true;
769
+ } catch (_) {}
770
+ }
771
+ if (stillSame) return false;
772
+ const tmpDst = wrapperDst + '.tmp.' + process.pid;
773
+ fs.copyFileSync(wrapperSrc, tmpDst);
774
+ fs.renameSync(tmpDst, wrapperDst);
757
775
  return true;
776
+ } finally {
777
+ releaseLock(lockPath);
758
778
  }
759
- return false;
760
779
  } catch (_) { return false; }
761
780
  }
762
781
 
package/gm-plugkit/cli.js CHANGED
@@ -219,19 +219,26 @@ function writeCliError(phase, err) {
219
219
  try { skillRefresh = ensureSkillMdFresh(); } catch (_) {}
220
220
  let wrapperRefreshed = false;
221
221
  try { wrapperRefreshed = ensureWrapperFresh(); } catch (_) {}
222
- writeCliStatus({ phase: 'ready', already_serving: true, watcher_pid: already.pid });
223
- console.log(JSON.stringify({
224
- ok: true,
225
- already_serving: true,
226
- watcher_pid: already.pid,
227
- version: already.version,
228
- skills_refreshed: skillRefresh && skillRefresh.refreshed || [],
229
- wrapper_refreshed: wrapperRefreshed,
230
- message: wrapperRefreshed
231
- ? 'plugkit already serving; wrapper file on disk was stale and has been refreshed -- restart the watcher to load it'
232
- : 'plugkit already serving, no bootstrap/spawn needed',
233
- }));
234
- process.exit(0);
222
+ if (wrapperRefreshed) {
223
+ writeCliStatus({ phase: 'wrapper-drift-detected', reason: 'on-disk-wrapper-refreshed', running_pid: already.pid });
224
+ console.error(`[gm-plugkit] running watcher (pid=${already.pid}) serves a stale wrapper; on-disk copy just refreshed -- forcing reboot`);
225
+ try {
226
+ if (process.platform === 'win32') cp.execFileSync('taskkill', ['/F', '/T', '/PID', String(already.pid)], { stdio: 'ignore', windowsHide: true });
227
+ else process.kill(already.pid, 'SIGTERM');
228
+ } catch (_) {}
229
+ } else {
230
+ writeCliStatus({ phase: 'ready', already_serving: true, watcher_pid: already.pid });
231
+ console.log(JSON.stringify({
232
+ ok: true,
233
+ already_serving: true,
234
+ watcher_pid: already.pid,
235
+ version: already.version,
236
+ skills_refreshed: skillRefresh && skillRefresh.refreshed || [],
237
+ wrapper_refreshed: false,
238
+ message: 'plugkit already serving, no bootstrap/spawn needed',
239
+ }));
240
+ process.exit(0);
241
+ }
235
242
  }
236
243
  if (versionDrifted) {
237
244
  const targetVersion = remoteVersionDrifted ? remoteUpdate.latest : onDiskVersion;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gm-plugkit",
3
- "version": "2.0.1843",
3
+ "version": "2.0.1845",
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": {
@@ -2833,7 +2833,7 @@ function makeHostFunctions(instanceRef) {
2833
2833
  domSelector = domMatch[1];
2834
2834
  evalBody = domMatch[2] && domMatch[2].trim() ? domMatch[2] : 'return null;';
2835
2835
  }
2836
- const navTimeout = Math.min(timeoutMs, 60000);
2836
+ const navTimeout = Math.min(timeoutMs, 120000);
2837
2837
  const gotoPrefix = startUrl
2838
2838
  ? `await page.goto(${JSON.stringify(startUrl)},{waitUntil:'load',timeout:${navTimeout}});\n`
2839
2839
  : '';
@@ -1 +1 @@
1
- 0.1.841
1
+ 0.1.842
package/gm.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gm",
3
- "version": "2.0.1843",
3
+ "version": "2.0.1845",
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.841"
20
+ "plugkitVersion": "0.1.842"
21
21
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gm-skill",
3
- "version": "2.0.1843",
3
+ "version": "2.0.1845",
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",