gm-skill 2.0.2220 → 2.0.2222

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
@@ -34,7 +34,7 @@ The `gm-plugkit` npm identity stays load-bearing as the thin launcher edge only:
34
34
 
35
35
  **`bin/install.js` hard-requires agentplug-runner.** It downloads the sha256-verified native runner from `AnEntrypoint/agentplug-bin` for the host platform, and if none is published (or the download/verify fails) it fails the install loudly with a clear message rather than leaving the user with no loader. There is no JS-host fallback to silently fall through to anymore.
36
36
 
37
- **agentplug-runner auto-updates the wasm it serves, not itself.** Polls `plugkit-bin` every 600s; executable self-update is `bin/install.js` re-run or the daemon's own takeover-handoff protocol. Full mechanics: the recall store (`recall: agentplug daemon.rs self-update handoff protocol`). The poll's own liveness is observable directly: `~/.agentplug/daemon-status.json` carries `last_plugin_update_poll_ts`/`last_runner_update_poll_ts`, refreshed every `plugin_update_poll_interval_secs`/`runner_update_poll_interval_secs` tick (600s default each) -- a null or stale value there, not a `.update-check-cache.json`/`.wasm-update-respawn-guard.json` file, is the live signal (those two filenames belong solely to the retired `plugkit-wasm-wrapper.js` JS host and are never written by agentplug-runner; their staleness once agentplug-runner is the active loader is expected, not a defect). A plugin whose installed `.version` marker is not real release semver (e.g. a hand-built `0.0.0-local-dev` sideload) is never silently auto-overwritten -- the daemon warns loudly to stderr at both boot and every stale-poll tick, and records `~/.agentplug/plugins/<name>.local-dev-sideload.json` so the state is queryable rather than indistinguishable from a released build.
37
+ **agentplug-runner auto-updates both the wasm it serves and its own executable, fully autonomously.** Two independent 600s polls; a staged `.new` runner is swapped in by a self-triggered takeover handoff on the next idle tick, so no `bin/install.js` re-run and no restart is ever required. Poll-liveness signal (`daemon-status.json` poll timestamps, never the retired JS host's cache files) and non-semver sideload protection: the recall store (`recall: agentplug daemon.rs self-update handoff protocol`, `recall: agentplug-runner update-poll observability sideload`).
38
38
 
39
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`).
40
40
 
@@ -99,7 +99,7 @@ Every skill's `allowed-tools:` reduced to `Skill, Read, Write` (plus SKILL.md bo
99
99
 
100
100
  A task that reduces to read/investigate/report, or a change confined to files the subagent owns for the turn, dispatches straight through -- stating the read-only boundary explicitly ("report only, no writes") is task-scope, not gm-protocol restatement, so it's not a violation of the rule above. A task whose plain description asks for an irreversible or shared-state-affecting action (delete data, force-push, merge/close a PR, deploy, rename a shared branch) is not silently handed off -- name the risk in the prompt and require the subagent to surface it back rather than execute it, the same blast-radius judgment the top-level agent applies to its own actions; the action still routes through the gm-driven skill invocation, never a prompt-authored imperative sequence that bypasses it. Contrast: "find every caller of X and summarize" dispatches as-is; "drop the staging table and reseed it" gets confirmed before any subagent is scoped to carry it out.
101
101
 
102
- **A subagent dispatched to build/commit/push in a submodule (`agentplug`, `rs-plugkit`, `rs-codeinsight`, `agentplug-bert`, `agentplug-libsql`, `agentplug-treesitter`, `rs-search`) closes the loop back to gm's own pin as its last step, every time, no exceptions.** These repos are checked out INSIDE this repo's own tree as git submodules -- a commit landed and pushed only to the submodule's standalone remote leaves gm's own tracked pointer silently pointing at the prior commit, invisible until the next explicit `git rev-parse HEAD` (submodule) vs `git rev-parse origin/main` comparison surfaces the drift. Live-hit twice in one session (two distinct commit pairs) before this rule existed -- each time required a manual `git checkout <sha> --detach` in the submodule dir + a `git_finalize` in gm to close. Every subagent prompt dispatching work into one of these submodules must include, as an explicit final step: after pushing the submodule's own commit, `cd` back to gm's root, `git add <submodule-path>`, and commit+push gm's own updated pointer in the SAME turn -- never leave that as an implicit "someone will notice." A top-level `gm` session that itself lands a submodule-touching commit (directly or via a subagent) checks `git status --porcelain` for the submodule path specifically before calling the turn done.
102
+ **A subagent dispatched to build/commit/push in a submodule (`agentplug`, `rs-plugkit`, `rs-codeinsight`, `agentplug-bert`, `agentplug-libsql`, `agentplug-treesitter`, `rs-search`) closes the loop back to gm's own pin as its last step, every time, no exceptions.** These repos are checked out INSIDE this repo's own tree as git submodules -- a commit landed and pushed only to the submodule's standalone remote leaves gm's own tracked pointer silently pointing at the prior commit, invisible until the next explicit `git rev-parse HEAD` (submodule) vs `git rev-parse origin/main` comparison surfaces the drift. Incident history: the recall store (`recall: gm submodule-pin-drift incident history`). Every subagent prompt dispatching work into one of these submodules must include, as an explicit final step: after pushing the submodule's own commit, `cd` back to gm's root, `git add <submodule-path>`, and commit+push gm's own updated pointer in the SAME turn -- never leave that as an implicit "someone will notice." A top-level `gm` session that itself lands a submodule-touching commit (directly or via a subagent) checks `git status --porcelain` for the submodule path specifically before calling the turn done.
103
103
 
104
104
  ## Core Rules
105
105
 
@@ -181,7 +181,7 @@ The `gm-runner` crate and its separate `gm-runner.yml` CI workflow are retired a
181
181
 
182
182
  **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`).
183
183
 
184
- **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.
184
+ **agentplug is a separate parallel pipeline that CONSUMES the cascade's output, not a stage in it**, decoupled at the `plugkit-bin` release artifact. Detail: the recall store (`recall: agentplug parallel pipeline decoupling`).
185
185
 
186
186
  **To update every possible thing**: push to the relevant repo. No manual version bumps, no local `cargo update`/`cargo build` -- push, let CI build.
187
187
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gm-plugkit",
3
- "version": "2.0.2220",
3
+ "version": "2.0.2222",
4
4
  "description": "Bootstrap and daemon-spawn tool for gm plugkit binary. Downloads the correct platform wasm, verifies SHA256, and launches agentplug-runner (the native wasm host) as the spool watcher daemon.",
5
5
  "main": "index.js",
6
6
  "bin": {
package/gm.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gm",
3
- "version": "2.0.2220",
3
+ "version": "2.0.2222",
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.2220",
3
+ "version": "2.0.2222",
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",
@@ -84,19 +84,13 @@ Two more real, code-checked env toggles beyond `GM_PLUGKIT_SKIP_SELF_STALE_CHECK
84
84
 
85
85
  **Correct `browser` verb body shape (real spec, not CLI-flag syntax): plain-text prefixed bodies only.** The body is NEVER `-s <id> -e "<script>"` or any other CLI-flag-style string -- that is raw playwriter CLI syntax and does not apply here; the native agentplug-host `browser` handler parses the body itself using these prefixes: `session new` (bare, no script), `session list` (bare, no script), `session close <id>` / `session reset <id>` (id required, own line, no script -- `reset` is the idempotent form, no error if the id wasn't live), `timeout=<ms>\n<expr>`, `url=<target>\n<expr>` (or a bare `https://...` URL alone), `screenshot[=name]\n<expr>`, `dom=<selector>\n<expr>`, or a bare JS expression/statement body with no prefix. Prefixes stack top-to-bottom, e.g. `timeout=90000\nurl=http://host/path?a=1&b=2\nawait page.waitForTimeout(5000);\nreturn {ok:true};`. A `?`-query-string `&` in a URL is safe to include directly (fixed, see below) -- do not URL-encode it defensively. A normal eval dispatch (no `session *` prefix) always targets the dispatch's own sessionId automatically; only `session close <id>`/`session reset <id>` take an explicit id argument, which lets one dispatch close a DIFFERENT session than the one it's nominally running under.
86
86
 
87
- **Sessions persist a real live Chrome process, not just the profile directory.** As of agentplug commit `912f396`, the Chrome process launched by `session new` (or by any dispatch's first-touch of a session_id) stays alive and visible across every subsequent dispatch sharing that session_id -- it is no longer killed at the end of each dispatch. A live session is reused directly (no relaunch, no ~5-10s Chrome-boot overhead) until it is explicitly closed (`session close <id>`/`session reset <id>`), auto-reaped after an idle timeout (`.gm/browser-config.json`'s `session_idle_timeout_ms`, default 30 minutes), or the agentplug-runner daemon itself exits. The on-disk `--user-data-dir` profile under `.gm/browser-chrome-profile-<session_id>/` survives even a `session close` (only the process dies), so a later `session new` under the same id still gets a warm profile. `session list` reports every live session for the current project as `{session_id, port, alive, idle_ms}`.
87
+ Sessions persist a real live Chrome process (reused directly until `session close`/`session reset`, idle-reaped via `.gm/browser-config.json`'s `session_idle_timeout_ms`, or daemon exit). `session list` reports every live session as `{session_id, port, alive, idle_ms}`. Rationale: the recall store (`recall: gm SKILL.md browser session persistence rationale`).
88
88
 
89
89
  **`.gm/browser-config.json` has 6 tunable fields total, per-project, all optional (`BrowserConfig::load`, re-read on every dispatch -- missing file or missing field falls back to the default, zero behavior change for an unconfigured project):** `session_idle_timeout_ms` (above, default 1800000); `cdp_poll_timeout_ms` (default 1000, per-attempt timeout polling Chrome's `/json/version` HTTP endpoint while waiting for the CDP port to come up); `cdp_poll_interval_ms` (default 250, delay between those poll attempts); `chrome_ready_deadline_ms` (default 30000, total wall-clock budget for Chrome to become CDP-ready before the launch is given up on); `eval_timeout_grace_ms` (default 6000, extra grace window added on top of a dispatch's own `timeout=` before the eval is force-killed); `headless` (default `false` -- Chrome launches headful/visible by default; a project that genuinely wants headless, e.g. CI with no display attached, sets `{"headless": true}`).
90
90
 
91
- **Debug capture, GL error tracking, and profiling are ALWAYS ON as of gm-plugkit >= 2.0.1916 -- no `capture`/`profile`/`trace` prefix needed for basic visibility.** Every `browser` dispatch response now includes `result.debug: {console, pageErrors, network, performance, gl: {errors, drawCalls, errorTotalCount}}` regardless of body shape (plain eval, `url=`, `screenshot=`, `dom=`) -- console.log output, uncaught page errors, failed/slow network requests, Core Web Vitals-style perf metrics, and live WebGL error tracking are captured by default on every dispatch. The GL error tracking specifically: `debugSetup` patches `HTMLCanvasElement.prototype.getContext` pre-navigation (via `page.addInitScript`, NOT `page.evaluateOnNewDocument` -- that is a Puppeteer method name that does not exist on playwriter's real Playwright `Page` object and silently no-ops if ever reintroduced) to wrap every `drawArrays`/`drawElements`/`drawArraysInstanced`/`drawElementsInstanced` call with a post-call `gl.getError()` drain. `window.__gmGlErrors` (as of 2026-07-17, DEDUPED by signature -- draw-fn + error code + mode + count + instanceCount -- capped at 40 DISTINCT signatures, not 40 raw occurrences: a recurring error updates its own entry's `occurrenceCount`/`lastDrawCallIndex` instead of being dropped once the old fixed-count cap filled, so a still-firing-every-frame error no longer looks frozen/stale across a long multi-dispatch debugging session; each entry also carries a real captured `stack` -- last 8 frames -- from its FIRST occurrence, so finding the triggering call site no longer requires hand-rolling a fresh `new Error().stack` monkeypatch every session) and `window.__gmGlDrawCalls` (per-fn call counts) are both live-readable via `page.evaluate` mid-script and are also returned in every response's `debug.gl`. `window.__gmGlErrorTotalCount` is a true cumulative counter (also in `debug.gl.errorTotalCount`) independent of the 40-signature cap -- read it to see real total volume even once the dedup table is full. `window.__gmGlLastDrainedError` (`{fn,error,errorName,drawCallIndex}`) exposes the wrapper's OWN most recently drained GL error code: a user script's own post-draw `gl.getError()` call always reads `NO_ERROR`, because this wrapper's `getError()` drain already ran first inside the wrapped draw function (WebGL's error state is a single-slot FIFO, only the first reader after a draw ever sees a real code) -- read this global instead of re-calling `gl.getError()` in user code, which can only ever see zero. This capture is the standing capability for GPU rendering-bug root-causing (stale buffer/VAO bindings, sampler-unit collisions, type mismatches between an index buffer's real typed-array and the GL type constant a draw call requests, etc) -- it replaces hand-rolling the same `gl.*=function(){...gl.getError()...}` monkeypatch ad hoc every session. The `capture\n<expr>` / `profile interval=<us> topN=<n>\n<expr>` / `trace\n<expr>` prefixes remain for their ORIGINAL purpose (CPU sampling profile, CDP GPU/compositor tracing) -- they are not required just to get console/network/GL visibility anymore, that part is unconditional. The `profile` prefix's response (and `exec_js opts.profile:true`'s) `culprits` array is now paired with a `gpu_hint` field: when the top culprit is the unattributed `(program)`/`(native)` bucket at >=40% self-time, `gpu_hint` proactively names the next diagnostic step -- on the browser surface, the `trace\n<script>` prefix (real `gpu_us`/`viz_us`/`cc_us` wall-clock GPU-process activity via CDP Tracing, which the CPU sampler cannot see) instead of leaving that discovery to a second manually-reasoned-into-existence dispatch; on the `exec_js` node surface, an accurate node-specific note instead (no GPU-tracing follow-up applies to a pure Node script).
91
+ Debug capture, GL error tracking, and profiling are always on (no `capture`/`profile`/`trace` prefix needed for basic visibility): every `browser` response includes `result.debug: {console, pageErrors, network, performance, gl: {errors, drawCalls, errorTotalCount}}` regardless of body shape. `window.__gmGlErrors`/`__gmGlDrawCalls`/`__gmGlErrorTotalCount`/`__gmGlLastDrainedError` are live-readable via `page.evaluate` for GPU rendering-bug root-causing. `capture\n<expr>` / `profile interval=<us> topN=<n>\n<expr>` / `trace\n<expr>` prefixes remain for CPU sampling / CDP GPU-compositor tracing specifically. Mechanism detail: the recall store (`recall: gm SKILL.md browser verb GL-capture mechanism detail`).
92
92
 
93
- **Historical note, resolved (was previously documented here as an open bug, now fixed and confirmed live, 2026-07-15, gm commits `27b3009`/`d6f696a`/`0ce18ef` on `AnEntrypoint/gm` main):** four real bugs in the plugkit wrapper's `browser` verb handler caused the prior "fixed-size stub response" / "session_id pins to a stale session" / "result silently truncated" / "debug capture never actually installs" symptoms this section used to describe:
94
- 1. `spawnSync(..., {shell:true})` on Windows routes through cmd.exe, which treats `&|<>^` as command separators even inside double-quoted arguments -- any script/URL containing `&` (e.g. a real `?a=1&b=2` query string) was silently truncated mid-argument. Fixed by spawning `bun.exe` directly with `shell:false` (a real binary needs no shell at all); the remaining `.cmd`-wrapper fallback paths get proper caret-escaping.
95
- 2. `bun x <pkg> -e <script>` panics on Windows with a real, known `oven-sh/bun` fixed-buffer-size "index out of bounds" bug once combined argv gets long enough (which the debug-capture prelude alone exceeds). Fixed by writing the script to a temp file and invoking playwriter's `-f` flag instead of inlining via `-e`.
96
- 3. playwriter's own `executor.js` truncates its DISPLAYED stdout text at a fixed 10000 chars, which silently ate the `__GM_RESULT__` sentinel line (always appended last, after any console-log volume) on any dispatch whose combined output exceeded that cap. Fixed by having the executed script write its result to a dedicated temp file (via the sandboxed `require('fs')`, scoped to `os.tmpdir()` which is an allowed sandbox directory) and having the wrapper read that file directly, bypassing playwriter's stdout formatting entirely.
97
- 4. `page.evaluateOnNewDocument` is a **Puppeteer** method name; playwriter's `page` is a real Playwright `Page`, whose equivalent is `page.addInitScript`. The wrong name meant `window.__gmErrors` (and later the GL instrumentation) never actually installed on ANY dispatch, ever, silently swallowed by an enclosing try/catch -- an independently real, pre-existing bug (not something the 2026-07-15 session introduced, though the new GL-instrumentation block did copy the same wrong pattern from the existing code). Also had to `await` the `addInitScript(...)` call itself, since it's async and was racing the immediately-following `page.goto(...)`.
98
-
99
- **Historical note, resolved (2026-07-17, gm-plugkit source fix committed on `AnEntrypoint/gm` main):** the GL-error dedup/stack-trace/`gpu_hint` improvements described in the paragraph above were themselves discovered as real, live-hit debugging-productivity gaps -- not designed speculatively -- while root-causing a game-engine FPS regression: the pre-2026-07-17 `window.__gmGlErrors` cap counted raw OCCURRENCES (first 40, ever, per page load), so a GL error firing every single frame filled the array within the first second and every subsequent `browser` dispatch for the rest of a many-minutes debugging session read back the exact same frozen entries, making a still-firing error look capped/stale/resolved. Fixed to the per-signature dedup table described above. If a future session again observes `debug.gl.errors` looking suspiciously static across several dispatches spanning real wall-clock time, that is the SAME class of bug recurring somewhere else in the capture pipeline (not user error) -- check `debug.gl.errorTotalCount` first (it is never capped): a growing total against a static `errors` array length means a NEW dedup-adjacent bug, not a fixed one regressing.
93
+ Prior playwriter-wrapper bug sweep (Windows shell-truncation, bun argv panic, stdout-truncation, wrong Puppeteer method name) and the GL-error dedup fix: both resolved and detailed in the recall store (`recall: gm SKILL.md historical playwriter-wrapper-bugs sweep`, `recall: gm SKILL.md GL-error dedup history`).
100
94
 
101
95
  If similar symptoms recur (stub-like responses, silent truncation, debug fields always empty), do NOT re-add a stale-bug workaround section here -- instead root-cause in the real browser-host source, which is now native in agentplug (clone `AnEntrypoint/agentplug`, edit `crates/agentplug-host/src/browser.rs` and its embedded `cdp_eval.js`, rebuild agentplug-runner, verify live against the locally-built `~/.gm-tools/agentplug-runner`, then commit+push to `AnEntrypoint/agentplug` main so the fix ships through the agentplug-bin release path) and update this section with the real fix, the same discipline used for the bugs above.
102
96