gm-skill 2.0.1392 → 2.0.1394

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-plugkit",
3
- "version": "2.0.1392",
3
+ "version": "2.0.1394",
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": {
@@ -1868,7 +1868,9 @@ async function runSpoolWatcher(instance, spoolDir) {
1868
1868
  const holderSha = parts[2] || '';
1869
1869
  const lockTs = parseInt(tsStr, 10);
1870
1870
  const age = Date.now() - lockTs;
1871
- if (age < 15000) {
1871
+ const holderPidNum = parseInt(pidStr, 10);
1872
+ const holderAlive = Number.isFinite(holderPidNum) && isProcessAliveSync(holderPidNum);
1873
+ if (age < 15000 && holderAlive) {
1872
1874
  if (_ownWrapperSha12 && holderSha && holderSha !== _ownWrapperSha12) {
1873
1875
  try { logEvent('plugkit', 'peer.stale-wrapper-takeover', { holder_pid: pidStr, holder_sha: holderSha, own_sha: _ownWrapperSha12, lock_age_ms: age }); } catch (_) {}
1874
1876
  console.error(`[plugkit-wasm] peer wrapper-sha mismatch (holder=${holderSha} own=${_ownWrapperSha12}); killing pid=${pidStr} and taking over`);
@@ -1896,6 +1898,9 @@ async function runSpoolWatcher(instance, spoolDir) {
1896
1898
  } catch (_) {}
1897
1899
  process.exit(75);
1898
1900
  }
1901
+ } else if (!holderAlive) {
1902
+ console.error(`[plugkit-wasm] stale lock (holder pid=${pidStr} dead, age=${age}ms); taking over`);
1903
+ try { logEvent('plugkit', 'watcher.lock-pid-dead-takeover', { stale_pid: pidStr, lock_age_ms: age }); } catch (_) {}
1899
1904
  } else {
1900
1905
  console.error(`[plugkit-wasm] stale lock (age=${age}ms); taking over`);
1901
1906
  }
@@ -2776,6 +2781,13 @@ async function runSpoolWatcher(instance, spoolDir) {
2776
2781
  } catch (_) {}
2777
2782
  const fileV = readFileVersionOnly() || null;
2778
2783
  const instV = _instanceVersionAtBoot || null;
2784
+ let updateAvailable = null;
2785
+ try {
2786
+ const upd = JSON.parse(fs.readFileSync(path.join(spoolDir, '.update-available.json'), 'utf-8'));
2787
+ if (upd && upd.installed && upd.latest && upd.installed !== upd.latest) {
2788
+ updateAvailable = { installed: upd.installed, latest: upd.latest };
2789
+ }
2790
+ } catch (_) {}
2779
2791
  fs.writeFileSync(TURN_SUMMARY_PATH, JSON.stringify({
2780
2792
  ts: Date.now(),
2781
2793
  watcher_pid: process.pid,
@@ -2787,6 +2799,7 @@ async function runSpoolWatcher(instance, spoolDir) {
2787
2799
  last_instruction_age_ms: lastInstructionAgeMs,
2788
2800
  long_gap_threshold_ms: 300000,
2789
2801
  browser_sessions_alive: browserSessions,
2802
+ update_available: updateAvailable,
2790
2803
  }));
2791
2804
  } catch (_) {}
2792
2805
  }
package/gm.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gm",
3
- "version": "2.0.1392",
3
+ "version": "2.0.1394",
4
4
  "description": "Spool-dispatch orchestration engine with unified state machine, 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-skill",
3
- "version": "2.0.1392",
3
+ "version": "2.0.1394",
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",
@@ -22,13 +22,15 @@ Every turn: dispatch `instruction` (you are the one dispatching it), read the re
22
22
 
23
23
  **Boot before dispatching. Always check first.** Writing to `.gm/exec-spool/in/instruction/N.txt` while the watcher is dead is the canonical cold-start failure — the request sits forever, you read no response, you fabricate the chain from memory of the prose. The spool directory's existence does NOT mean the watcher is alive; `.status.json` mtime within the last 15s does. The leftover `.status.json` from yesterday's dead watcher is the most common trap.
24
24
 
25
- Your first tool call of every session is the boot probe, in one Bash invocation:
25
+ Your first tool call of every session is the boot probe, in one Bash invocation. Read `.status.json` (liveness) and `.turn-summary.json` (orientation) together — the watcher precomputes both every 5s, so the two files give you everything you'd otherwise extract via gmsniff queries, git, yaml-parse, and ports-file scans:
26
26
 
27
27
  ```bash
28
- cat .gm/exec-spool/.status.json 2>/dev/null; date +%s%3N
28
+ cat .gm/exec-spool/.status.json 2>/dev/null; echo ---; cat .gm/exec-spool/.turn-summary.json 2>/dev/null; echo ---; date +%s%3N
29
29
  ```
30
30
 
31
- Compare the `ts` field to the printed epoch ms. If the gap is >15000, the watcher is dead boot it:
31
+ `.turn-summary.json` carries `phase`, `last_skill`, `prd_pending`, `last_instruction_ts`, `last_instruction_age_ms`, `long_gap_threshold_ms`, `browser_sessions_alive`, `update_available`. When age exceeds the threshold, your next non-orienting verb will be gated — dispatch `instruction` first. When `update_available` is non-null, the watcher has detected drift: kill the watcher and re-bootstrap before continuing so the next instruction lands on the fresh wasm.
32
+
33
+ Compare `.status.json` `ts` field to the printed epoch ms. If the gap is >15000, the watcher is dead — boot it:
32
34
 
33
35
  ```bash
34
36
  bun x gm-plugkit@latest spool > /dev/null 2>&1 &