gm-skill 2.0.2050 → 2.0.2052
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 +4 -2
- package/gm-plugkit/package.json +1 -1
- package/gm.json +1 -1
- package/package.json +1 -1
- package/skills/gm/SKILL.md +5 -1
package/AGENTS.md
CHANGED
|
@@ -22,7 +22,7 @@ Skills encode environment-specific constraints that override general knowledge.
|
|
|
22
22
|
|
|
23
23
|
# Architecture & Philosophy
|
|
24
24
|
|
|
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.
|
|
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. `prose.rs::resolve()` is the only override mechanism, and it is a per-key three-tier chain with no separate gate/residual path: `.gm/instructions/<key>.md` (per-project vendored file, always wins) -> a configured source-repo's synced cache (`.gm/instructions/source.json` + `.gm/instructions-source-cache/<key>.md`) -> the compiled default. Gate-denial and residual copy (deviation text, gate reasons) is compiled directly into `gates.rs`/`residual.rs`/`transitions.rs` with no file-override surface at all -- there is no `gm-plugkit/instructions/gates/` or `gm-plugkit/instructions/residual/` directory in this repo, and none is read by any Rust source; overriding a gate/residual message requires editing those Rust files and going through the normal cascade rebuild, same as the compiled-default phase prose. Detail in the recall store (`recall: string-externalization project`).
|
|
26
26
|
|
|
27
27
|
## WASM guest, one native host (agentplug-runner is the sole loader)
|
|
28
28
|
|
|
@@ -103,7 +103,9 @@ A task that reduces to read/investigate/report, or a change confined to files th
|
|
|
103
103
|
|
|
104
104
|
**Memory is human-readable md, tracked; derived stores are transient, never tracked.** Detail: the recall store (`recall: gm memory storage mechanics`, `recall: gm managed-gitignore mechanics`).
|
|
105
105
|
|
|
106
|
-
**Disciplines are isolated knowledge stores**, tracked, `@<name>` sigil-scoped. Detail: the recall store (`recall: gm disciplines mechanics`).
|
|
106
|
+
**Disciplines are isolated knowledge stores**, tracked, `@<name>` sigil-scoped, enabled list at `.gm/disciplines/enabled.txt` (one name per line; `discipline_note.rs::active_policies()` auto-surfaces each enabled discipline's `.gm/disciplines/<name>/policy.md` on every `instruction`). Detail: the recall store (`recall: gm disciplines mechanics`).
|
|
107
|
+
|
|
108
|
+
**Every runtime config surface, indexed**: `.gm/instructions/<key>.md` + `.gm/instructions/source.json` (prose vendoring, see above); `.gm/instructions/fsm/graph.json` (phase-graph override, write path is the `fsm-vendor` verb, see SKILL.md); `.gm/browser-config.json` (`BrowserConfig::load`, per-project -- `cdp_poll_timeout_ms` default 1000, `cdp_poll_interval_ms` default 250, `chrome_ready_deadline_ms` default 30000, `eval_timeout_grace_ms` default 6000, `headless` default false, `session_idle_timeout_ms` default 1800000); `.gm/daemon-project-config.json` (`gm_concurrency_limit`, per-project fairness cap on the shared pool); `~/.agentplug/daemon-config.json` (`DaemonConfig::load`, machine-wide daemon lifecycle timing); `.gm/disciplines/enabled.txt` + `.gm/disciplines/<name>/policy.md` (above); `AGENTPLUG_NO_DAEMON`/`CLAUDE_PROJECT_DIR`/`GM_PLUGKIT_SKIP_SELF_STALE_CHECK` (env toggles, SKILL.md documents the third). Daemon-scoped fields (`daemon-project-config.json`, `~/.agentplug/daemon-config.json`) fully detailed in `.gm/daemon-config-reference.md`; this line is the top-level index into that doc and the others.
|
|
107
109
|
|
|
108
110
|
**Nothing fake in source the user runs**: stub/mock/placeholder-return/fixture-only-path/demo-mode-short-circuit/"TODO: implement" forbidden in shipped code. Scaffolds/shims permitted only delegating to real behavior (upstream API, subprocess, disk); check for an existing library before adding a shim. Detection = behavioral: always-succeeds, input-invariant, or type-signature-satisfying short-circuit = stub. Acceptance = real input through real code into real output, witnessed. `Mock*`/`Fake*`/`Stub*` names checked at VERIFY explicitly, not left prose-only (`recall: nevil false-completion mock-network incident`). A row marked `completed` by documenting it (a README "Future Optimizations" section, a design note) instead of implementing it is the same violation -- `prd-resolve` structurally refuses two PRD rows sharing byte-identical `witness_evidence` text (`deviation.prd-resolve-duplicate-witness`), the copy-paste tell of rubber-stamped completion.
|
|
109
111
|
|
package/gm-plugkit/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gm-plugkit",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.2052",
|
|
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
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gm-skill",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.2052",
|
|
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",
|
package/skills/gm/SKILL.md
CHANGED
|
@@ -64,10 +64,12 @@ bun x gm-plugkit@latest spool
|
|
|
64
64
|
|
|
65
65
|
(`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.
|
|
66
66
|
|
|
67
|
-
**The boot line resolves to agentplug-runner, the sole spool loader; `bun x gm-plugkit@latest spool` is the thin launcher that re-execs into it.** `gm-plugkit/cli.js::tryDelegateToRunner` execs `~/.gm-tools/agentplug-runner` -- 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. The JS wasm-host (`plugkit-wasm-wrapper.js`) and the redundant `gm-runner` native host are retired -- there is no fallback loader. `bin/install.js` hard-requires agentplug-runner: it downloads the sha256-verified binary from `AnEntrypoint/agentplug-bin` for the host platform and fails loudly if none is published (or the download fails) rather than leaving no loader. agentplug-runner auto-updates
|
|
67
|
+
**The boot line resolves to agentplug-runner, the sole spool loader; `bun x gm-plugkit@latest spool` is the thin launcher that re-execs into it.** `gm-plugkit/cli.js::tryDelegateToRunner` execs `~/.gm-tools/agentplug-runner` -- 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. The JS wasm-host (`plugkit-wasm-wrapper.js`) and the redundant `gm-runner` native host are retired -- there is no fallback loader. `bin/install.js` hard-requires agentplug-runner: it downloads the sha256-verified binary from `AnEntrypoint/agentplug-bin` for the host platform and fails loudly if none is published (or the download fails) rather than leaving no loader. agentplug-runner auto-updates both its served `plugkit.wasm` and its own executable fully autonomously (600s poll each): a newer runner build is staged to `.new` in the background, then swapped in via a self-triggered `takeover` handoff on the next idle tick -- no agent action, no `bin/install.js` re-run, no restart ever required.
|
|
68
68
|
|
|
69
69
|
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.
|
|
70
70
|
|
|
71
|
+
Two more real, code-checked env toggles beyond `GM_PLUGKIT_SKIP_SELF_STALE_CHECK`: `AGENTPLUG_NO_DAEMON` (set on the agentplug-runner process to force the non-daemon single-shot code path instead of registering with the shared machine-wide daemon) and `CLAUDE_PROJECT_DIR` (read by `gm-plugkit/bootstrap.js`/`cli.js`, `agentplug-runner`'s `main.rs`, and allowlisted through rs-plugkit's `env_get` verb -- the explicit project-root override used when the working directory isn't the project root, e.g. under a Workflow's worktree isolation).
|
|
72
|
+
|
|
71
73
|
**Dispatch shape: Write request + Read response, SAME tool-call block.** Never proceed/narrate/begin work before reading the response and following its `instruction` field. First-read "file does not exist" mid-verb = normal, re-Read next message. Never poll with `sleep && ls` -- plugkit is synchronous; missing response = dead watcher (recheck `ts`) or slow verb, never "still processing."
|
|
72
74
|
|
|
73
75
|
**Dead-watcher recovery is mandatory, not optional.** Two consecutive missing re-Reads AND stale `ts` (>5min) AND no future `busy_until` = dead: `bun x gm-plugkit@latest spool` boots fresh, re-dispatch the original verb. If `busy_until` is set, the watcher is processing a long verb; wait instead of rebooting. Recovery = notice-dead -> boot -> re-dispatch, always -- never substitute a raw tool for the dead verb.
|
|
@@ -84,6 +86,8 @@ The `Resolving dependencies` / `Saved lockfile` chatter before the JSON payload
|
|
|
84
86
|
|
|
85
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}`.
|
|
86
88
|
|
|
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
|
+
|
|
87
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).
|
|
88
92
|
|
|
89
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:
|