gm-skill 2.0.2237 → 2.0.2239

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
@@ -32,7 +32,7 @@ Plugkit-core = the wasm cdylib guest (the gm brain), published as `plugkit.wasm`
32
32
 
33
33
  The `gm-plugkit` npm identity stays load-bearing as the thin launcher edge only: `bun x gm-plugkit@latest spool` (`cli.js::tryDelegateToRunner`) re-execs the `agentplug-runner` executable staged at `~/.gm-tools/agentplug-runner` and exits -- there is no silent no-loader state. The launcher-edge install path (`~/.gm-tools`) and the runner's own runtime state (`~/.agentplug`) are two different directories; always check `~/.agentplug/plugins/gm.version` for what is actually being served, never `~/.gm-tools`. Full path-split mechanics: the recall store (`recall: agentplug-runner runtime-state path split`). Size + embedded-model mechanics: the recall store (`recall: WASM-only plugkit size mechanics`).
34
34
 
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.
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/check 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
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
 
@@ -47,7 +47,7 @@ Dispatch = Write `.gm/exec-spool/in/<verb>/<N>.txt`, Read `.gm/exec-spool/out/<v
47
47
  - **Orchestrator verbs**: `instruction`, `transition`, `phase-status`, `mutable-resolve`, `memorize-fire`, `residual-scan`, `auto-recall`.
48
48
  - **Wasm-direct verbs**: fs/kv/exec/fetch/env, recall, codesearch, memorize(+prune), health, filter, full git verb family. Enumeration in the recall store (`recall: wasm-direct plugkit verbs full list`).
49
49
  - **Host-native verb**: `background-convert` (`{verb, task}`) detaches an already-in-flight dispatch so the daemon worker stops waiting on it -- agent-initiated only, never routed to gm.wasm. Detail: `.gm/daemon-config-reference.md`.
50
- - **memorize-prune**: prune bad/superseded memories; two-mode spec (key-delete vs query-review) in the recall store (`recall: memorize-prune verb two-mode spec`).
50
+ - **memorize-prune**: prune bad/superseded memories; two-mode spec (key-remove vs query-review) in the recall store (`recall: memorize-prune verb two-mode spec`).
51
51
  - **git verbs**: git is a first-class spool surface, never a shell command; `git_finalize {message}` is the bundled COMPLETE-phase push surface, `git_push` the only admissible raw push (porcelain-gated, rebase-retry). A git-dominant `bash`/`powershell` body is gated (`deviation.bash-git-bypass`). Per-verb shapes + host_git `.exe` resolution in the recall store (`recall: git verbs rs-plugkit spool surface`).
52
52
  - **filter**: pure stdout -> compact-stdout transform, in-wasm. Spec + usage (pipe raw command output through it before context) in the recall store (`recall: filter verb rs-plugkit spool spec`).
53
53
 
@@ -55,6 +55,8 @@ Dispatch = Write `.gm/exec-spool/in/<verb>/<N>.txt`, Read `.gm/exec-spool/out/<v
55
55
 
56
56
  Record only non-obvious multi-run-cost caveats; prune stale; never document the code-obvious.
57
57
 
58
+ **ASD-STE100 sets word choice and sentence grammar.** This Documentation Policy sets what content to write. The two rules apply together. Write short sentences: 20 words for a procedural sentence, 25 for a descriptive one. Write one idea per sentence. Use the active voice. Use an approved word from `.gm/disciplines/ste100/dictionary.json` in place of a banned synonym. This policy still decides whether a caveat is worth a line at all, and how much survives past the non-obvious core. STE100 forbids a clipped, telegraphic style; this repo's density rule still forbids narrative bloat and code-obvious restatement. A compliant sentence is short and complete, never a dropped-word fragment. Full rules and the machine-checkable dictionary: `.gm/disciplines/ste100/policy.md` and `.gm/disciplines/ste100/dictionary.json`. Run `.gm/disciplines/ste100/verify-run.mjs` on a touched prose file before the VERIFY phase accepts it.
59
+
58
60
  **No changelog history in AGENTS.md.** Every entry is a present-tense rule about what must/must-not be the case in code now. Forbidden: `(FIXED)` markers, commit hashes, dated audit entries, `## Learning audit` sections, "(added 2026-...)" annotations, "we used to X, now Y". History belongs in `git log` and `CHANGELOG.md`.
59
61
 
60
62
  **Detail-heavy caveats live in the recall store (`.gm/memories/` corpus), not here.** Per-crate/OS/hook/workflow fact-base -> `recall`; AGENTS.md keeps top-level gm-repo-governing rules only. Cross-cutting policy stays; single-crate/single-platform mechanism drains.
@@ -69,7 +71,7 @@ Record only non-obvious multi-run-cost caveats; prune stale; never document the
69
71
 
70
72
  **Self-explanatory code replaces the comment; the comment is never written in the first place.** A name, a function boundary, an extracted variable, or a small type IS the explanation -- prefer renaming/restructuring over annotating every single time a comment urge appears. No inline, block, doc (`///`, `/**`, `#`, JSDoc), or rationale comments anywhere (source, generated output, hooks, scripts, Rust, JS/TS, shell, YAML). A multi-line or paragraph-long comment is the same violation at higher volume, not a lesser one -- it is not exempted by explaining a "why"; that urge to explain is itself the signal that a name or structure is doing too little work, so restructure instead of narrating around the gap. If a rule/tradeoff genuinely needs recording for future sessions (not this code), it goes in AGENTS.md or the recall store, never inline next to the code.
71
73
 
72
- **A comment encountered anywhere -- pre-existing, another session's, a dependency's vendored copy inside this repo's own tracked tree -- is converted to self-explanatory code the moment it's seen, same turn, not left for a later cleanup pass.** Read the comment, understand what it was compensating for (an unclear name, an un-extracted step, an unstated invariant), fix that root cause so the comment's content becomes redundant, then delete the comment. "Already there, not part of this task" is not an exemption -- the same one-sighting-spawns-a-sweep discipline that governs every other tell-tale-AI class in this section applies here: a comment survives only until the next file touching it is opened. Checked manually on sight across every tracked source extension (`.rs`, `.js`, `.mjs`, `.cjs`, `.ts`, `.tsx`, `.sh`, `.ps1`); one sighting spawns the full-tree sweep.
74
+ **A comment encountered anywhere -- pre-existing, another session's, a dependency's vendored copy inside this repo's own tracked tree -- is converted to self-explanatory code the moment it's seen, same turn, not left for a later cleanup pass.** Read the comment, understand what it was compensating for (an unclear name, an un-extracted step, an unstated invariant), fix that root cause so the comment's content becomes redundant, then remove the comment. "Already there, not part of this task" is not an exemption -- the same one-sighting-spawns-a-sweep discipline that governs every other tell-tale-AI class in this section applies here: a comment survives only until the next file touching it is opened. Checked manually on sight across every tracked source extension (`.rs`, `.js`, `.mjs`, `.cjs`, `.ts`, `.tsx`, `.sh`, `.ps1`); one sighting spawns the full-tree sweep.
73
75
 
74
76
  **No UTF-8 BOM in any tracked source file** -- always `-Encoding utf8` (no BOM) or the `Write` tool; PowerShell defaults betray this. Checked manually on sight; one sighting spawns the full-tree sweep. Cause + breakage mechanics in the recall store (`recall: BOM regression incident`).
75
77
 
@@ -97,7 +99,7 @@ Every skill's `allowed-tools:` reduced to `Skill, Read, Write` (plus SKILL.md bo
97
99
 
98
100
  **Subagent/Workflow-agent prompts delegate, never restate.** Any `Agent()` tool call or `Workflow` script `agent()`/`pipeline()`/`parallel()` call dispatching gm-driven work says only "use the gm skill for this" (or equivalent minimal pointer) plus the task-specific content -- target repo/path, what to investigate, what to report. Never inline verb names, spool paths, JSON body shapes, or phase-chain mechanics into the prompt string: `Skill(skill="gm")` already supplies all of that on invocation, so restating it is instructional content living outside plugkit+skill, the exact drift this file's own tool-surface rule exists to prevent. Applies identically to both surfaces -- a Workflow script author writing full gm-protocol prose into an `agent()` prompt is the same violation as an `Agent()` call doing it.
99
101
 
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.
102
+ 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 (remove 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
103
 
102
104
  **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
105
 
@@ -135,13 +137,13 @@ A task that reduces to read/investigate/report, or a change confined to files th
135
137
 
136
138
  **Push is part of COMPLETE, never optional, never asked**: tracked-file-mutating session ends commit+push to origin. "Want me to push?" = deviation -- push IS the validation dispatch (`verify.rs`). Not-COMPLETE until remote reflects HEAD. ccsniff `--git-discipline` + `deviation.complete-without-push` flag unpushed closes.
137
139
 
138
- **Direct-push to main, never a branch, never a PR**: every gm/rs-* change -> straight `main` commit+push; git verbs (`git_finalize`/`git_push`) already target `main`, cascade ships from `main`. Branch/PR/fork = deviation, no review-gate exists. Sibling repo with open PR: merge to `main`, push, delete branch. Only admissible remote refs: `main`, `gh-pages` -- `git_push {repo, branch:"main"}` for siblings too.
140
+ **Direct-push to main, never a branch, never a PR**: every gm/rs-* change -> straight `main` commit+push; git verbs (`git_finalize`/`git_push`) already target `main`, cascade ships from `main`. Branch/PR/fork = deviation, no review-gate exists. Sibling repo with open PR: merge to `main`, push, remove the branch. Only admissible remote refs: `main`, `gh-pages` -- `git_push {repo, branch:"main"}` for siblings too.
139
141
 
140
142
  **Push requires clean worktree witnessed in its own tool-use event**: `git push` only on empty `git status --porcelain`, probed its OWN Bash event before push (never `&&`-chained). Prefer `git_push`/`git_finalize` (internal gate). Enforcement locations: the recall store (`recall: push clean worktree enforcement locations`).
141
143
 
142
144
  **Any history rewrite or force-push sourced from an external clone/mirror verifies that source's ancestry against live HEAD first**: `git merge-base --is-ancestor <source-tip> <live-HEAD>` must exit 0 before `filter-repo`/force-push runs against that clone -- a freshly-named clone directory is not proof of freshness, staleness is a content property, not a naming one. Skipping this check risks silently discarding real commits on the remote if the clone turns out stale or wrong-branch.
143
145
 
144
- **A `git checkout <branch>` that leaves commits behind names EVERY dangling commit, not one candidate to trust blind**: ancestry-safe (`git merge-base --is-ancestor`) is not automatically content-complete when multiple dangling commits chain together -- verify the real recovery by grepping pushed content on origin for the expected change, never by trusting `git_push`'s own summary line alone. Full incident + recovery mechanics: the recall store (`recall: wrong dangling commit git recovery`).
146
+ **A `git checkout <branch>` that leaves commits behind names EVERY dangling commit, not one candidate to trust blind**: ancestry-safe (`git merge-base --is-ancestor`) is not automatically content-complete when multiple dangling commits chain together -- check the real recovery by grepping pushed content on origin for the expected change, never by trusting `git_push`'s own summary line alone. Full incident + recovery mechanics: the recall store (`recall: wrong dangling commit git recovery`).
145
147
 
146
148
  **AGENTS.md / CLAUDE.md are inline-edited AND dual-written to the store**: inline-edit for structural rules (only doc surviving context summarization), AND `memorize-fire` the same rule for `recall`/`auto_recall` surfacing -- complementary, not either/or. Never `namespace:"AGENTS.md"`; load-bearing rules -> default namespace. Mechanics: the recall store (`recall: memorize-fire ingestion classifier`).
147
149
 
@@ -191,7 +193,7 @@ Orchestration state tracked via `.gm/` marker files, not hook events; the gate t
191
193
 
192
194
  **gm tool-use sequencing**: `Skill(skill="gm")` clears needs-gm gate. One shipped skill, no subagent variant. Marker mechanics: the recall store (`recall: gm-skill tool-use sequencing mechanics`).
193
195
 
194
- **The skill is the driver, not a post-hoc witness**: standing instruction to use gm skill (every `/loop` fire, any `/gm` prompt) -> FIRST action is `Skill(skill="gm")`, skill prose drives PLAN->COMPLETE. Direct spool verbs without entering the skill first = work executed outside the requested driver; end-only entry to confirm terminal state does NOT satisfy the instruction. Boot probe (`cat .gm/exec-spool/.status.json` ...) may precede invocation; every state mutation happens inside the skill-driven session.
196
+ **The skill is the driver, not a post-hoc witness**: standing instruction to use gm skill (every `/loop` fire, any `/gm` prompt) -> FIRST action is `Skill(skill="gm")`, skill prose drives PLAN->COMPLETE. Direct spool verbs without entering the skill first = work executed outside the requested driver; end-only entry to check terminal state does NOT satisfy the instruction. Boot probe (`cat .gm/exec-spool/.status.json` ...) may precede invocation; every state mutation happens inside the skill-driven session.
195
197
 
196
198
  **Dead-watcher recovery uses `bun x gm-plugkit@latest spool`, never direct-node boot** (mechanism: recall store `recall: dead-watcher recovery bun x not direct-node`).
197
199
 
package/README.md CHANGED
@@ -105,7 +105,7 @@ The two npm packages this repo publishes:
105
105
 
106
106
  ### the state machine
107
107
 
108
- PLAN -> EXECUTE -> EMIT -> VERIFY -> CONSOLIDATE -> COMPLETE. Every transition is a verb the agent dispatches by writing to `.gm/exec-spool/in/<verb>/<N>.txt`. The wasm orchestrator (rs-plugkit) services it and writes the response to `.gm/exec-spool/out/`. The agent reads, follows the imperative prose, dispatches the next verb. CONSOLIDATE owns git-push + CI/CD validation, split off the COMPLETE gate. The chain isn't complete until `transition to=COMPLETE` returns COMPLETE phase AND the commit is pushed to origin.
108
+ PLAN -> EXECUTE -> EMIT -> VERIFY -> CONSOLIDATE -> COMPLETE. Every transition is a verb the agent dispatches by writing to `.gm/exec-spool/in/<verb>/<N>.txt`. The wasm orchestrator (rs-plugkit) services it and writes the response to `.gm/exec-spool/out/`. The agent reads, follows the imperative prose, dispatches the next verb. CONSOLIDATE owns git-push + CI/CD validation, split off the COMPLETE gate. The chain isn't complete until `transition to=COMPLETE` returns COMPLETE phase AND the push reaches origin.
109
109
 
110
110
  ### tools
111
111
 
@@ -120,7 +120,7 @@ Every tool the agent uses is a dispatch verb. No direct shell, no direct file wr
120
120
 
121
121
  ### gates
122
122
 
123
- Orchestration state is tracked via `.gm/` marker files, not hook events. The gate that admits Write/Edit/git pre-execution runs natively inside `plugkit.wasm` (rs-plugkit `gates.rs` + its `hook_pre_tool_use` / `hook_stop` exports), driven off the same markers:
123
+ `.gm/` marker files track orchestration state, not hook events. The gate that admits Write/Edit/git pre-execution runs natively inside `plugkit.wasm` (rs-plugkit `gates.rs` + its `hook_pre_tool_use` / `hook_stop` exports), driven off the same markers:
124
124
 
125
125
  - **session-start**: bootstraps plugkit, seeds `.gm/next-step.md`, sets the `needs-gm` marker
126
126
  - **turn entry**: the `instruction` verb reminds the agent to dispatch first and attaches the per-prompt auto-recall pack
@@ -169,7 +169,7 @@ git clone --recurse-submodules https://github.com/AnEntrypoint/gm.git
169
169
  git submodule update --init --recursive
170
170
  ```
171
171
 
172
- Empty submodule directories after a normal `git clone` are expected, not a bug -- they only matter if you're changing one of these repos' own source rather than the skill/installer JS in this repo's own tree.
172
+ A normal `git clone` leaves the submodule directories empty; this is not a bug. Empty submodules matter only if you change one of those repos' own source instead of the skill or installer JS in this repo's own tree.
173
173
 
174
174
  ## license
175
175
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gm-plugkit",
3
- "version": "2.0.2237",
3
+ "version": "2.0.2239",
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.2237",
3
+ "version": "2.0.2239",
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.2237",
3
+ "version": "2.0.2239",
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",
@@ -8,7 +8,7 @@ allowed-tools: Skill, Read, Write, AskUserQuestion, Bash(bun *), Bash(npx *), Ba
8
8
 
9
9
  **The conversation literally stops the instant a response contains no tool call -- this is the entire mechanism, not a guideline to remember.** Nothing external enforces continuation; the only thing that keeps this session alive turn after turn is that every single response contains a dispatch. The moment a response is prose alone -- a summary, a "here's what I did," a "Session N closes, ready to resume with /gm," a recap of architecture decisions made, a list of what's left for "next time" -- that response IS the final message of the conversation. There is no next turn where the user re-prompts and work resumes; from the model's own vantage point mid-generation, writing that closing summary is indistinguishable from ending the conversation permanently, because it has the exact same effect. So: never compose a closing/summary/"standing work ready" sentence as the last thing in a response -- if the work in front of you feels finished, the correct final action is still a dispatch (the next verb, or `Skill(skill="gm-continue")` if genuinely `phase=COMPLETE AND prd_pending_count=0`), never a sentence describing that it's finished. A turn-final sentence naming the next move instead of taking it is the same stop -- take the move, don't narrate it. **A question asking permission to take the next move ("Should I dispatch X now?", "Ready to proceed -- want me to continue?") is the identical stop, worded as a question instead of a narration.** Standing approval already covers this turn's work (see below) -- dispatch the named verb instead of asking whether to. Decisions worth surfacing to the user go through `AskUserQuestion` (a real ambiguity with distinct answers) or `prd-add` (a discovered row), never a prose question about whether to continue the already-authorized chain.
10
10
 
11
- **A verification or reproduction step that appears to require a human is first a build task, not an ask.** `AskUserQuestion`'s "real ambiguity with distinct answers" scope above does not cover "please perform an action so I can observe the result" -- physically pressing a button, turning a physical knob, listening to real audio, operating hardware the session has no other channel to. That is a missing channel, not an ambiguity, and the missing channel is itself a PRD row: attempt to build or reuse an automated substitute that exercises the same code path without the human before asking. For hardware I/O this means byte-level injection at the lowest available interface (e.g. writing raw MIDI note-on/note-off bytes directly to the device's rawmidi/ALSA node over the same SSH channel already used to pull logs, replaying a captured byte sequence from prior logs, or scripting the exact protocol messages the physical action would have produced) rather than asking a human to reproduce the input by hand. Only fall back to `AskUserQuestion` for the physical step once the substitute has genuinely been attempted and either (a) is provably impossible for this bug class -- the defect depends on analog qualities a byte-level or protocol-level injection cannot reproduce (audible sound quality, real timing jitter/debounce, genuine electrical behavior) -- or (b) the human has explicitly stated they want to verify by ear/feel themselves. A repeated commit-push-CI-flash-then-ask cycle where the "ask" step is always the identical physical action and no substitute was ever attempted is itself a deviation-shaped pattern: the second occurrence of the same physical-action ask in one session is the signal to stop and build the harness instead of asking a third time.
11
+ **A verification or reproduction step that appears to require a human is first a build task, not an ask.** `AskUserQuestion`'s "real ambiguity with distinct answers" scope above does not cover "please perform an action so I can observe the result" -- physically pressing a button, turning a physical knob, listening to real audio, operating hardware the session has no other channel to. That is a missing channel, not an ambiguity, and the missing channel is itself a PRD row: attempt to build or reuse an automated substitute that exercises the same code path without the human before asking. For hardware I/O this means byte-level injection at the lowest available interface (e.g. writing raw MIDI note-on/note-off bytes directly to the device's rawmidi/ALSA node over the same SSH channel already used to pull logs, replaying a captured byte sequence from prior logs, or scripting the exact protocol messages the physical action would have produced) rather than asking a human to reproduce the input by hand. Only fall back to `AskUserQuestion` for the physical step once the substitute has genuinely been attempted and either (a) is provably impossible for this bug class -- the defect depends on analog qualities a byte-level or protocol-level injection cannot reproduce (audible sound quality, real timing jitter/debounce, genuine electrical behavior) -- or (b) the human has explicitly stated they want to check by ear/feel themselves. A repeated commit-push-CI-flash-then-ask cycle where the "ask" step is always the identical physical action and no substitute was ever attempted is itself a deviation-shaped pattern: the second occurrence of the same physical-action ask in one session is the signal to stop and build the harness instead of asking a third time.
12
12
 
13
13
  **`gm` is only allowed to end by calling `gm-continue`; there is no other exit.** At genuine `phase=COMPLETE AND prd_pending_count=0`, the only allowed next step is dispatching `Skill(skill="gm-continue")` as the literal last tool call of the turn -- never a bare prose ending, never a stop for the user to re-prompt, and never a prose summary followed by no further dispatch (reaching COMPLETE earlier in a turn does not license a prose-only response afterward -- the Skill dispatch belongs in that same turn, immediately). This is absolute: no branch of `gm`'s own logic, no phase, no gate response ever authorizes ending a `gm`-driven turn any other way. Do not inline `gm-continue`'s remaining-work search or its `gm`/`wfgy-method` decision here or improvise around it -- dispatch the skill and follow exactly what it does.
14
14
 
@@ -62,7 +62,7 @@ cat .gm/exec-spool/.status.json 2>/dev/null; echo ---; cat .gm/exec-spool/.turn-
62
62
  bun x gm-plugkit@latest spool
63
63
  ```
64
64
 
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.
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 check 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 check serving before dispatching (rare), read `.gm/exec-spool/.status.json` yourself and check `ts` freshness.
66
66
 
67
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
 
@@ -92,7 +92,7 @@ Debug capture, GL error tracking, and profiling are always on (no `capture`/`pro
92
92
 
93
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`).
94
94
 
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.
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, check 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.
96
96
 
97
97
  **Windows-specific transient flakiness that is NOT a plugkit/wrapper bug, just retry it:** `bun x <pkg>@<version>` (any package, e.g. the gm-plugkit boot line itself) occasionally hangs indefinitely at "Resolving dependencies" with zero further output even with a pinned exact cached version -- a known intermittent Bun/Windows dependency-resolution stall, unrelated to browser automation. A bare re-dispatch of the exact same command has resolved it every time observed. Do not chase this as a code bug -- 2-3 retries is the correct response.
98
98
 
@@ -106,7 +106,7 @@ Spool input from PowerShell must be UTF-8 no-BOM (`-Encoding utf8` or `[System.I
106
106
 
107
107
  **Every PLAN pass also asks: what architectural change makes this practical and low-maintenance going forward, not just correct right now?** For each row, before accepting the literal ask as the whole scope: is there a structural change (removing an obsolete mechanism, consolidating duplicated logic, replacing a bespoke reimplementation with a maintained one, fixing a wrong abstraction at its root instead of patching around it) that would make this and future similar work cheaper, not just this one instance? If yes, that becomes its own PRD row alongside the literal ask -- never silently skipped as "out of scope" or "nice to have." A plan that only satisfies the literal request while leaving an obvious maintenance burden in place under-covers by the same standard as a plan that misses a corner case.
108
108
 
109
- **EXECUTE resolves all mutables before EMIT, discovers more, resolves those too, rearchitects immediately on in-spirit discovery.** Any architectural improvement discovered mid-EXECUTE is an immediate `transition to=PLAN`, re-`prd-add` the affected row with its existing id (re-scope, never delete-and-re-add) -- maximal-effort correctness over preservation-for-its-own-sake, no deferral, no "note for later."
109
+ **EXECUTE resolves all mutables before EMIT, discovers more, resolves those too, rearchitects immediately on in-spirit discovery.** Any architectural improvement discovered mid-EXECUTE is an immediate `transition to=PLAN`, re-`prd-add` the affected row with its existing id (re-scope, never remove-and-re-add) -- maximal-effort correctness over preservation-for-its-own-sake, no deferral, no "note for later."
110
110
 
111
111
  **`prd-resolve` is bound by the false-completion rule in every phase, PLAN included -- not only at VERIFY.** A row resolved on a hedge ("deferred", "pending next session", "awaits recovery") is undone work labeled done -- forbidden, the same class as a mock standing in for real code. The served PLAN/VERIFY `instruction` prose carries the full hedge taxonomy, the `blockedBy: [external, ...]` handling for genuine outside-session blockers, and the recurring-blocker-becomes-its-own-row rule; dispatch `instruction` for it rather than re-deriving it here.
112
112