gm-skill 2.0.2020 → 2.0.2022

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
@@ -24,11 +24,17 @@ Skills encode environment-specific constraints that override general knowledge.
24
24
 
25
25
  Repo root = package root = published `gm-skill` npm package; no factory, no separate build-output dir. Entry: `skills/gm/SKILL.md`. Orchestration lives in rs-plugkit, served on-demand via `instruction`. The 8 phase-prose files (entry/plan/execute/emit/verify/consolidate/update_docs/browser) live single-sourced inside rs-plugkit itself (`crates/plugkit-core/src/orchestrator/instructions/prose/*.md`, `include_str!`'d at build) -- a prose edit there requires a Rust rebuild via the normal cascade, no cross-repo sync step. Gate/residual text stays genuinely zero-rebuild: editable `gm-plugkit/instructions/gates/` and `gm-plugkit/instructions/residual/` in this repo, read at runtime with `prose.rs`'s per-key fallback to a compiled default (`.gm/instructions/<key>.md` per-project-overridable). Detail in the recall store (`recall: string-externalization project`).
26
26
 
27
- ## WASM-only, now with an optional native runner
27
+ ## WASM guest, three interchangeable hosts (agentplug-runner is the live one)
28
28
 
29
- Plugkit = wasm cdylib. Two host loaders exist and coexist: `plugkit-wasm-wrapper.js` under Node/bun (original, still the default) and `gm-runner` (rs-plugkit `crates/gm-runner/`, a real native cross-platform binary built by CI and published to `AnEntrypoint/gm-runner-bin` releases) -- gm-runner links `wasmtime` and hosts the same wasm module directly, no Node/bun dependency for the boot step. Both loaders serve the byte-identical spool ABI (`in/`/`out/` layout, verb names), so a gm-driven session works the same regardless of which loader booted it. `bin/install.js` best-effort-downloads gm-runner (sha256-verified against its release's `.sha256` sidecar) but never hard-requires it -- a platform with no published gm-runner binary, or a failed download, silently falls back to bun/npx exactly as before. `plugkit.wasm` itself is fetched at bootstrap from `plugkit-wasm` npm / `plugkit-bin` gh-releases, sha256-pinned, by whichever loader is running (gm-runner's own `download.rs::bootstrap_plugkit_wasm` mirrors the JS wrapper's fetch+verify). Size + embedded-model (offline in-wasm embeddings) mechanics: the recall store (`recall: WASM-only plugkit size mechanics`).
29
+ Plugkit-core = the wasm cdylib guest (the gm brain), published as `plugkit.wasm`/`plugkit-slim.wasm` from `AnEntrypoint/plugkit-bin` by the cascade. It is host-agnostic: THREE distinct native/JS hosts load that same byte-identical wasm and serve the byte-identical spool ABI (`in/`/`out/` layout, verb names), so a gm-driven session works identically regardless of which booted it. In precedence order (`gm-plugkit/cli.js::tryDelegateToRunner`):
30
30
 
31
- **gm-runner auto-updates the wasm it serves, not itself.** `spool.rs::run_spool_watcher` polls `plugkit-bin`'s GitHub Releases API every 600s for a newer tag (`download.rs::fetch_latest_plugkit_version`); on a mismatch it downloads+verifies the new wasm and the existing 30s local-version-skew check picks up the on-disk change and triggers a clean in-process reload (`StopReason::Reload`). The gm-runner *executable* itself has no such remote self-update loop yet -- a stale installed gm-runner binary keeps running until the next `bin/install.js` re-run re-checks `gm-runner-bin`'s latest release tag.
31
+ 1. **`agentplug-runner`** (repo `AnEntrypoint/agentplug`, published to `AnEntrypoint/agentplug-bin`) -- the LIVE, preferred host. A real native wasmtime binary that loads gm.wasm as one plugin among siblings (`bert`/`libsql`/`treesitter`), routing gm.wasm's `host_plugin_call`/`host_vec_embed` to those shared plugins. This is why gm fetches `plugkit-slim.wasm` (no baked-in embedding weights -- bert supplies them out-of-wasm). `.status.json` `runtime` reads `agentplug` when this host is serving. Browser is driven via direct CDP and task via a native process registry, both native in agentplug-host.
32
+ 2. **`gm-runner`** (rs-plugkit `crates/gm-runner/`, published to `AnEntrypoint/gm-runner-bin`) -- a native FALLBACK, tried second. Loads the same wasm as a single module with a stub `host_plugin_call` and no shared-plugin routing; strictly a subset of agentplug-runner. Its own CDP browser + task registry were ported to match agentplug. Retirement is tracked (`gm-runner-redundant-host-consolidation`).
33
+ 3. **`plugkit-wasm-wrapper.js`** (JS/bun, in `gm-plugkit/`) -- the original JS host, tried last, only when no native runner is published for the platform. The `gm-plugkit` npm identity + `bootstrap.js` (seed/refresh) + `cli.js` (delegation) stay load-bearing as the thin launcher edge (`bun x gm-plugkit@latest spool` re-execs into the first available native runner and exits); the wrapper's own wasm-host code + `supervisor.js` only run as the pure-JS fallback.
34
+
35
+ `bin/install.js` best-effort-downloads BOTH native runners (agentplug-runner and gm-runner, each sha256-verified) but hard-requires neither -- a platform with no published binary silently falls through to the JS host. Each host fetches the same `plugkit.wasm`/`plugkit-slim.wasm` from `plugkit-bin`, sha256-pinned. Size + embedded-model mechanics: the recall store (`recall: WASM-only plugkit size mechanics`).
36
+
37
+ **Native runners auto-update the wasm they serve, not themselves.** agentplug-runner and gm-runner each poll `plugkit-bin`'s Releases API every 600s for a newer tag; on a mismatch they download+verify the new wasm and a local-version-skew check triggers a clean in-process reload. The runner *executables* self-update only via `bin/install.js` re-run (agentplug-runner additionally adopts a staged `.new` on the next start).
32
38
 
33
39
  Wasm host-import link-module rule (`#[link(wasm_import_module="env")]` on every host-import extern block, every dep crate): the recall store (`recall: wasm host-import link-module trap`).
34
40
 
@@ -160,6 +166,8 @@ A push touching `rs-plugkit/crates/gm-runner/**` additionally triggers its own `
160
166
 
161
167
  **Repos involved (push to any triggers cascade):** `AnEntrypoint/{rs-codeinsight, rs-search, rs-plugkit, gm}`. rs-learn and rs-exec are retired (crates removed from / never depended on by rs-plugkit; their spool-dispatch and memory surfaces reimplemented natively in rs-plugkit wasm_dispatch; repos archived as tombstones, README points at rs-plugkit). Roles, npm package names, legacy-retirement detail: the recall store (`recall: cascade repos involved roles`, `recall: legacy gm-skill variants retired`).
162
168
 
169
+ **agentplug is a separate parallel pipeline that CONSUMES the cascade's output, not a stage in it.** The cascade above produces the wasm guest (`plugkit-bin` release). `AnEntrypoint/{agentplug, agentplug-bert, agentplug-libsql, agentplug-treesitter}` are their own repos: agentplug's CI builds only the native host binary (`agentplug-runner`, 6 platforms, published to `AnEntrypoint/agentplug-bin`) and the sibling plugins their own `*-bin` releases; none of them build or publish the gm wasm. agentplug fetches the SAME `plugkit-slim.wasm` from `plugkit-bin` at runtime. The two pipelines are cleanly decoupled at the `plugkit-bin` release artifact -- a plugkit-core change flows through the cascade to `plugkit-bin`, and every host (agentplug-runner included) picks it up via its 600s poll, with no agentplug rebuild needed. An agentplug-host change (a new native subsystem like browser/task) rebuilds only `agentplug-runner`, independent of the cascade.
170
+
163
171
  **To update every possible thing**: push to the relevant repo. No manual version bumps, no local `cargo update`/`cargo build` -- push, let CI build.
164
172
 
165
173
  ## Spool-dispatch architecture replaces hooks
package/bin/install.js CHANGED
@@ -172,37 +172,11 @@ function runPlugkitBootstrap() {
172
172
  return Promise.resolve(false);
173
173
  }
174
174
 
175
- // Maps process.platform/process.arch to the exact release-asset basename
176
- // gm-runner's CI (rs-plugkit/.github/workflows/gm-runner.yml) publishes to
177
- // AnEntrypoint/gm-runner-bin -- must stay byte-identical to that workflow's
178
- // `artifact:` matrix values, this is the only other place that name is
179
- // spelled. Returns null for a host combination CI does not build (no crash,
180
- // caller falls back to the existing bun/npx path).
181
- function gmRunnerAssetName() {
182
- const plat = process.platform;
183
- const arch = process.arch;
184
- if (plat === 'win32') {
185
- if (arch === 'x64') return 'gm-runner-windows-x64.exe';
186
- if (arch === 'arm64') return 'gm-runner-windows-arm64.exe';
187
- return null;
188
- }
189
- if (plat === 'darwin') {
190
- if (arch === 'x64') return 'gm-runner-macos-x64';
191
- if (arch === 'arm64') return 'gm-runner-macos-arm64';
192
- return null;
193
- }
194
- if (plat === 'linux') {
195
- if (arch === 'x64') return 'gm-runner-linux-x64';
196
- if (arch === 'arm64') return 'gm-runner-linux-arm64';
197
- return null;
198
- }
199
- return null;
200
- }
201
-
202
- // Same mapping as gmRunnerAssetName, for agentplug-runner's own CI
203
- // (AnEntrypoint/agentplug's .github/workflows/release.yml) publishing to
204
- // AnEntrypoint/agentplug-bin -- must stay byte-identical to that workflow's
205
- // `artifact:` matrix values.
175
+ // Maps process.platform/process.arch to the exact release-asset basename for
176
+ // agentplug-runner's CI (AnEntrypoint/agentplug's .github/workflows/release.yml)
177
+ // publishing to AnEntrypoint/agentplug-bin -- must stay byte-identical to that
178
+ // workflow's `artifact:` matrix values. Returns null for a host combination CI
179
+ // does not build, so the caller falls back to the JS host without crashing.
206
180
  function agentplugRunnerAssetName() {
207
181
  const plat = process.platform;
208
182
  const arch = process.arch;
@@ -256,96 +230,40 @@ function gmToolsDir() {
256
230
  return path.join(home, '.gm-tools');
257
231
  }
258
232
 
259
- // Downloads the platform-matched gm-runner binary from gm-runner-bin's
260
- // GitHub Releases (native runner replacing the bun/node spool-boot path),
261
- // verified against the release's own .sha256 sidecar before the atomic
262
- // rename lands -- same trust model as gm-runner's own
263
- // download::download_and_verify for plugkit.wasm, so a corrupt/partial
264
- // download is never silently accepted. Best-effort: any failure (offline,
265
- // asset missing for this host, network error) resolves false rather than
266
- // throwing, so install never hard-fails over a runner-binary fetch -- the
267
- // bun/npx spool path remains the fallback until remove-node-bun-from-native-path
268
- // lands.
269
- async function downloadGmRunner({ silent } = {}) {
270
- const assetName = gmRunnerAssetName();
233
+
234
+ // Downloads agentplug-runner (the sole native wasm plugin-host now -- hosts
235
+ // gm.wasm plus the separate libsql/bert/treesitter plugin wasm modules via a
236
+ // host-mediated plugin_call ABI) from agentplug-bin's GitHub Releases,
237
+ // sha256-sidecar-verified with an atomic rename, so a corrupt/partial download
238
+ // is never accepted. Best-effort: any failure (offline, unpublished platform,
239
+ // network) resolves false rather than throwing, so install never hard-fails
240
+ // over a runner fetch -- cli.js's tryDelegateToRunner then falls back to the
241
+ // pure-JS wasm host. gm-runner was retired once agentplug-runner reached full
242
+ // 6-platform parity (it was a strictly-inferior single-module duplicate).
243
+ async function downloadAgentplugRunner({ silent } = {}) {
244
+ const assetName = agentplugRunnerAssetName();
271
245
  if (!assetName) {
272
- if (!silent) err(`gm-runner: no published binary for platform=${process.platform} arch=${process.arch}, skipping native runner install`);
246
+ if (!silent) err(`agentplug-runner: no published binary for platform=${process.platform} arch=${process.arch}, skipping`);
273
247
  return false;
274
248
  }
275
249
  const destDir = gmToolsDir();
276
- const destPath = path.join(destDir, assetName.endsWith('.exe') ? 'gm-runner.exe' : 'gm-runner');
277
-
278
- // gm-runner stages a verified self-update as <asset>.new and then renames it
279
- // over its own exe -- which Windows refuses while that exe is running, so the
280
- // staged file was abandoned and gm-runner never updated itself (witnessed: a
281
- // 29h-old .new beside a byte-different in-use binary; the identical rename
282
- // succeeded immediately once no gm-runner process was running). The installer
283
- // is the right place to complete it: it runs as node, outside the target
284
- // binary, so it does not hold the lock that blocks gm-runner's own attempt.
250
+ const destPath = path.join(destDir, assetName.endsWith('.exe') ? 'agentplug-runner.exe' : 'agentplug-runner');
251
+
252
+ // agentplug-runner stages a verified self-update as <asset>.new and renames
253
+ // it over its own exe, which Windows refuses while that exe is running -- so
254
+ // the staged file is abandoned unless something outside the binary completes
255
+ // it. The installer runs as node, outside the target binary, so it adopts any
256
+ // staged .new here before downloading.
285
257
  try {
286
258
  const staged = path.join(destDir, assetName + '.new');
287
259
  if (fs.existsSync(staged)) {
288
260
  fs.renameSync(staged, destPath);
289
- if (!silent) out(`Adopted staged gm-runner self-update from ${staged}`);
290
- }
291
- } catch (e) {
292
- if (!silent) err(`gm-runner: staged self-update could not be adopted (${e && e.message || e}); leaving it in place`);
293
- }
294
-
295
- try {
296
- const releaseInfo = JSON.parse((await httpsGetBuffer('https://api.github.com/repos/AnEntrypoint/gm-runner-bin/releases/latest')).toString('utf8'));
297
- const tag = releaseInfo && releaseInfo.tag_name;
298
- if (!tag) { if (!silent) err('gm-runner: no releases published yet at AnEntrypoint/gm-runner-bin, skipping'); return false; }
299
- const base = `https://github.com/AnEntrypoint/gm-runner-bin/releases/download/${tag}`;
300
- const binUrl = `${base}/${assetName}`;
301
- const shaUrl = `${binUrl}.sha256`;
302
-
303
- const versionFile = path.join(destDir, 'gm-runner.version');
304
- if (fs.existsSync(destPath) && fs.existsSync(versionFile)) {
305
- const installed = fs.readFileSync(versionFile, 'utf8').trim();
306
- if (installed === tag) { if (!silent) out(`gm-runner ${tag} already installed at ${destPath}`); return true; }
307
- }
308
-
309
- const [binBuf, shaBuf] = await Promise.all([httpsGetBuffer(binUrl), httpsGetBuffer(shaUrl)]);
310
- const expectedSha = shaBuf.toString('utf8').trim().split(/\s+/)[0];
311
- const actualSha = sha256Hex(binBuf);
312
- if (!expectedSha || actualSha.toLowerCase() !== expectedSha.toLowerCase()) {
313
- if (!silent) err(`gm-runner: sha256 mismatch downloading ${binUrl} (expected ${expectedSha}, got ${actualSha}), not installing`);
314
- return false;
261
+ if (!silent) out(`Adopted staged agentplug-runner self-update from ${staged}`);
315
262
  }
316
-
317
- fs.mkdirSync(destDir, { recursive: true });
318
- const tmp = destPath + '.tmp' + process.pid;
319
- fs.writeFileSync(tmp, binBuf);
320
- if (process.platform !== 'win32') { try { fs.chmodSync(tmp, 0o755); } catch (_) {} }
321
- fs.renameSync(tmp, destPath);
322
- fs.writeFileSync(versionFile, tag);
323
- if (!silent) out(`Installed gm-runner ${tag} to ${destPath}`);
324
- return true;
325
263
  } catch (e) {
326
- if (!silent) err(`gm-runner download skipped: ${e && e.message || e}`);
327
- return false;
264
+ if (!silent) err(`agentplug-runner: staged self-update could not be adopted (${e && e.message || e}); leaving it in place`);
328
265
  }
329
- }
330
266
 
331
- // Downloads agentplug-runner (the generic wasm plugin-host runner gm-runner
332
- // is migrating to -- hosts gm.wasm plus optional libsql/bert/treesitter
333
- // plugin wasm modules via a host-mediated plugin_call ABI) from
334
- // agentplug-bin's GitHub Releases, same sha256-sidecar/atomic-rename trust
335
- // model as downloadGmRunner. Installed ALONGSIDE gm-runner, not instead of
336
- // it yet -- cli.js's tryDelegateToRunner prefers agentplug-runner when
337
- // present (it's the same spool ABI, agentplug-runner is a strict superset),
338
- // falling back to gm-runner, falling back to bun/npx, so an agentplug-bin
339
- // download failure (new/unpublished platform, network issue) never
340
- // regresses an install that already had a working gm-runner.
341
- async function downloadAgentplugRunner({ silent } = {}) {
342
- const assetName = agentplugRunnerAssetName();
343
- if (!assetName) {
344
- if (!silent) err(`agentplug-runner: no published binary for platform=${process.platform} arch=${process.arch}, skipping`);
345
- return false;
346
- }
347
- const destDir = gmToolsDir();
348
- const destPath = path.join(destDir, assetName.endsWith('.exe') ? 'agentplug-runner.exe' : 'agentplug-runner');
349
267
  try {
350
268
  const releaseInfo = JSON.parse((await httpsGetBuffer('https://api.github.com/repos/AnEntrypoint/agentplug-bin/releases/latest')).toString('utf8'));
351
269
  const tag = releaseInfo && releaseInfo.tag_name;
@@ -432,7 +350,6 @@ async function main() {
432
350
  }
433
351
 
434
352
  await runPlugkitBootstrap();
435
- await downloadGmRunner({ silent: false });
436
353
  await downloadAgentplugRunner({ silent: false });
437
354
 
438
355
  out('');
@@ -1 +1 @@
1
- 9ef5d76e08618f51cbeb35134907719634ca8f2a52a040a6b585590443a1b698 plugkit-slim.wasm
1
+ 3bc79b1c7d1c83b7efd2990cab87bb631fdde61d18828feadfc42a65dba8cf9a plugkit-slim.wasm
@@ -1 +1 @@
1
- 0.1.933
1
+ 0.1.934
@@ -1 +1 @@
1
- a129ec1242c0b2ad5bd203880b81295c80df1b586404e5abd868a70fffdf3c9c plugkit.wasm
1
+ 5dc08988a361a648386ee930234fb42811130bc00b469e62bd4f7523eb5ed96b plugkit.wasm
package/gm-plugkit/cli.js CHANGED
@@ -230,27 +230,25 @@ function writeCliError(phase, err) {
230
230
  } catch (_) {}
231
231
  }
232
232
 
233
- // gm-runner is a genuine, sha256-verified drop-in replacement for this
234
- // entire bun/node boot path -- when it's installed, delegate to it
235
- // immediately and exit, before any bun/node-specific bootstrap logic runs.
236
- // This is the actual code-level enforcement of what was previously only a
237
- // documented convention (SKILL.md telling an LLM agent to manually prefer
238
- // gm-runner) -- with this in place bun/node are only ever exercised on a
239
- // platform neither runner has a published binary for, or during the
240
- // one-time install before either runner lands on disk.
241
- //
242
- // agentplug-runner is tried FIRST, gm-runner second -- agentplug-runner
243
- // serves the identical spool ABI (same in/out layout, same verb names;
244
- // gm.wasm is just one of its loadable plugins now) so it's a strict
245
- // superset, not an alternative; gm-runner stays as the fallback for any
246
- // install that has it but hasn't picked up agentplug-runner yet (installer
247
- // re-run pending, or a platform agentplug-bin hasn't published for yet
248
- // while gm-runner-bin already has).
233
+ // agentplug-runner is the sole native host and a sha256-verified drop-in
234
+ // replacement for this entire bun/node boot path -- when it's installed,
235
+ // delegate to it immediately and exit, before any bun/node bootstrap runs.
236
+ // It serves the identical spool ABI (same in/out layout, same verb names;
237
+ // gm.wasm is one of its loadable plugins alongside libsql/bert/treesitter),
238
+ // so bun/node are only ever exercised as the pure-JS fallback on a platform
239
+ // agentplug-bin has no published binary for, or during the one-time install
240
+ // before the runner lands on disk. (gm-runner, a strictly-inferior
241
+ // single-module duplicate, was retired once agentplug-runner reached full
242
+ // 6-platform parity.)
249
243
  function tryDelegateToRunner(args) {
250
244
  if (process.env.GM_PLUGKIT_NO_RUNNER_DELEGATE === '1') return false;
245
+ // agentplug-runner is the sole native host now -- gm-runner (a strictly
246
+ // inferior single-module duplicate) was retired once agentplug-runner had
247
+ // full 6-platform parity published to agentplug-bin. The JS wasm-host below
248
+ // is the only fallback, for a platform with no published native binary.
251
249
  const candidates = process.platform === 'win32'
252
- ? ['agentplug-runner.exe', 'gm-runner.exe']
253
- : ['agentplug-runner', 'gm-runner'];
250
+ ? ['agentplug-runner.exe']
251
+ : ['agentplug-runner'];
254
252
  for (const exeName of candidates) {
255
253
  const runnerPath = path.join(gmToolsDir(), exeName);
256
254
  if (!fs.existsSync(runnerPath)) continue;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gm-plugkit",
3
- "version": "2.0.2020",
3
+ "version": "2.0.2022",
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": {
@@ -1 +1 @@
1
- 9ef5d76e08618f51cbeb35134907719634ca8f2a52a040a6b585590443a1b698 plugkit-slim.wasm
1
+ 3bc79b1c7d1c83b7efd2990cab87bb631fdde61d18828feadfc42a65dba8cf9a plugkit-slim.wasm
@@ -1 +1 @@
1
- 0.1.933
1
+ 0.1.934
package/gm.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gm",
3
- "version": "2.0.2020",
3
+ "version": "2.0.2022",
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.933"
20
+ "plugkitVersion": "0.1.934"
21
21
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gm-skill",
3
- "version": "2.0.2020",
3
+ "version": "2.0.2022",
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",
@@ -62,7 +62,7 @@ bun x gm-plugkit@latest spool
62
62
 
63
63
  (`npx -y gm-plugkit@latest spool` if no `bun`.) Fire-and-forget: spawns the detached daemon and returns immediately (already-alive watcher also returns at once, unchanged) -- it does NOT wait for the watcher to confirm serving. No `&`, no `sleep`, no re-`cat`; write your first verb to `in/` right after it returns. A first-read "file does not exist" on that verb is normal (the just-spawned watcher hasn't noticed the file yet) -- re-Read next message, same as any dead-watcher-adjacent recheck. If you need to actively confirm serving before dispatching (rare), read `.gm/exec-spool/.status.json` yourself and check `ts` freshness.
64
64
 
65
- **A native `gm-runner` binary at `~/.gm-tools/gm-runner` (`gm-runner.exe` on Windows) is a drop-in replacement for the bun/npx boot line above, when present** -- `gm-runner spool` serves the identical spool ABI (same `in/`/`out/` layout, same verb names) directly from a compiled binary, no bun/npx/node_modules dependency for the boot step. It is optional and additive right now, not a required cutover: `bin/install.js`'s installer best-effort-downloads it (sha256-verified, from `AnEntrypoint/gm-runner-bin` releases) but silently no-ops if the platform has no published binary yet or the download fails, and gm-runner itself only auto-updates its own served `plugkit.wasm` (a background 600s remote-version poll), not its own executable. If `~/.gm-tools/gm-runner` (or `.exe`) exists, prefer it for the boot line; otherwise fall back to `bun x gm-plugkit@latest spool` exactly as before -- both are equally valid, check-for-binary-then-fallback, never a hard requirement on one or the other.
65
+ **The boot line resolves to a native runner when one is installed; `bun x gm-plugkit@latest spool` is the thin launcher that re-execs into it.** `gm-plugkit/cli.js::tryDelegateToRunner` picks the host in this precedence: (1) **`agentplug-runner`** (`~/.gm-tools/agentplug-runner`) -- the LIVE, preferred host, a native wasmtime binary that loads gm.wasm alongside shared `bert`/`libsql`/`treesitter` plugins (so gm runs `plugkit-slim.wasm`, browser via direct CDP, task via a native registry); `.status.json` `runtime` reads `agentplug` when it serves. (2) **`gm-runner`** (`~/.gm-tools/gm-runner`) -- native fallback, a single-module subset of agentplug-runner. (3) the JS wasm-host in `plugkit-wasm-wrapper.js` -- last resort when no native runner is published for the platform. All three serve the identical spool ABI, so a session works the same regardless. `bin/install.js` best-effort-downloads both native runners (sha256-verified from `AnEntrypoint/agentplug-bin` / `gm-runner-bin`) and hard-requires neither; each native runner auto-updates only its served `plugkit.wasm` (600s poll), not its own executable (that self-updates on the next `bin/install.js` re-run; agentplug-runner also adopts a staged `.new` on next start). You never pick the host by hand -- `bun x gm-plugkit@latest spool` always resolves to the best available one.
66
66
 
67
67
  The `Resolving dependencies` / `Saved lockfile` chatter before the JSON payload is `bunx` re-resolving the `@latest` tag against the registry, not gm-plugkit hanging -- the daemon already spawns detached+unref'd and the CLI itself exits the instant that happens; the visible delay is entirely bunx's own network round-trip, unavoidable on `@latest` (a pinned exact version, once bunx-cached, skips it). `GM_PLUGKIT_SKIP_SELF_STALE_CHECK=1` skips the CLI's own redundant npm-registry version probe (already covered by `@latest`'s resolution) for a faster boot on repeat same-session invocations. In PowerShell 5.1, never `2>&1`-redirect this command into another cmdlet (e.g. `| Select-Object`) -- PowerShell wraps every stderr line from a native exe in a `NativeCommandError` record and reports failure even on exit 0, turning bun's routine stderr progress output into a misleading red error block; run it bare or capture stdout only.
68
68