gm-skill 2.0.1550 → 2.0.1552
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 +62 -70
- package/bin/plugkit.version +1 -1
- package/bin/plugkit.wasm.sha256 +1 -1
- package/gm-plugkit/instructions/browser.md +14 -21
- package/gm-plugkit/instructions/emit.md +8 -12
- package/gm-plugkit/instructions/entry.md +37 -41
- package/gm-plugkit/instructions/execute.md +20 -34
- package/gm-plugkit/instructions/plan.md +11 -19
- package/gm-plugkit/instructions/update_docs.md +11 -17
- package/gm-plugkit/instructions/verify.md +21 -31
- package/gm-plugkit/package.json +1 -1
- package/gm-plugkit/scripts/sync-instruction-consts.mjs +36 -0
- package/gm.json +2 -2
- package/package.json +1 -1
- package/prompts/bash-deny.txt +2 -2
- package/prompts/pre-compact.txt +1 -1
- package/prompts/prompt-submit.txt +24 -64
- package/skills/gm-skill/SKILL.md +32 -42
package/skills/gm-skill/SKILL.md
CHANGED
|
@@ -6,84 +6,74 @@ allowed-tools: Skill, Read, Write, Bash(bun *), Bash(npx *)
|
|
|
6
6
|
|
|
7
7
|
# gm
|
|
8
8
|
|
|
9
|
-
**A turn
|
|
9
|
+
**A turn ending without a tool call is a stop; stopping mid-chain is the cardinal failure.** Agents read only tool calls and their outputs, so a prose-only turn ends the session. While the chain is in-flight (phase != COMPLETE OR prd_pending_count > 0) every turn ends in a tool call that advances it (`instruction`, the next verb the prose named, or `transition`). No summaries, no "here's what I did", no narrating closure. A turn-final sentence naming the next move instead of making it is the same stop -- take the move. Surface a decision via `AskUserQuestion` or `prd-add`, never prose. Tempted to stop: dispatch `phase-status`; if non-terminal, dispatch `instruction` and keep walking. Only `phase=COMPLETE` AND `prd_pending_count=0` authorizes a prose-only turn.
|
|
10
10
|
|
|
11
|
-
**Done is what plugkit says is done, never your claim.** The COMPLETE gate is the single arbiter
|
|
11
|
+
**Done is what plugkit says is done, never your claim.** The COMPLETE gate is the single arbiter; if not at COMPLETE there is a next transition to seek, and idle mid-chain is a deviation.
|
|
12
12
|
|
|
13
|
-
**Standing approval -- finish everything, every session, at maximum granularity.** Every
|
|
13
|
+
**Standing approval -- finish everything, every session, at maximum granularity.** Every session is pre-approved to continue until ALL requested work is done: the plan, every addition along the way, every newly-discovered or unfinished item. Do not stop to ask whether to continue, do not defer reachable work, do not narrow to a convenient slice. Plan at maximum granularity (one PRD row per real unit; `every possible` on every noun) and walk the whole closure. `blockedBy: external` is for authority you genuinely cannot reach (another team's repo, a hardware credential, a not-in-session product decision) -- never for work that is merely large, tedious, multi-component, or contended by a concurrent writer (rebase and land alongside them).
|
|
14
14
|
|
|
15
|
-
**Every possible action begins and ends with `instruction`.**
|
|
15
|
+
**Every possible action begins and ends with `instruction`.** In doubt, denied, or unclear next move: dispatch instruction. It is the only recovery primitive; improvising never beats re-reading the prose.
|
|
16
16
|
|
|
17
|
-
**You are the state machine.** Plugkit is
|
|
17
|
+
**You are the state machine.** Plugkit is durable memory + gate-checker; you walk PLAN -> EXECUTE -> EMIT -> VERIFY -> COMPLETE. Every transition, PRD resolution, mutable witness, residual scan is a verb YOU dispatch by writing `.gm/exec-spool/in/<verb>/<N>.txt`. Plugkit never advances, validates, or processes while you wait -- it serves a response the moment you write a request and sits inert otherwise. Your phase is the one you last `transition`-ed to, not the one your narration implies. Zero dispatches in gmsniff = you hallucinated the chain, not walked it. Drop this and every other rule collapses (mutables resolved without witness, COMPLETE claimed without VERIFY, residuals narrated away).
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
Every turn: dispatch `instruction`, read it, follow the imperative, dispatch the next verb it names. Re-dispatch against every drift, stall, gate-denial, or uncertainty -- in-flight it is free to over-dispatch and unbounded-cost to act without. Phase-specific discipline lives in plugkit's instruction tables; this file does not duplicate it.
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
**Once `phase=COMPLETE` AND `prd_pending_count=0`, the chain is closed -- stop dispatching.** Polling `instruction`/`phase-status` to "re-confirm" a terminal chain is the `complete-chain-poll` deviation. A new user prompt (`{"prompt":"..."}`) reopens the chain to PLAN; if your first `instruction` on intended-new work still returns COMPLETE/UPDATE-DOCS, dispatch `transition to=PLAN` **once** (this is authorized new work, not a poll).
|
|
22
22
|
|
|
23
|
-
**
|
|
23
|
+
**Client-side edits are gated by Browser Witness (hard rule).** If you Write/Edit any client-side file (`.html .js .jsx .ts .tsx .vue .svelte .mjs .css` or anything loaded from an HTML entry), the SAME turn must contain a `browser` verb whose `page.evaluate` asserts the invariant the edit establishes. `transition to=COMPLETE` refuses until `.turn-browser-witnessed` covers every entry in `.turn-browser-edits.json` by sha, else `deviation.client-edit-no-witness`. There is no validate-later.
|
|
24
24
|
|
|
25
|
-
**
|
|
25
|
+
**The live page is the debugger -- expose globals, evaluate in-browser, never blind-restart.** Surface relevant state as a `window.*` global and read it live via the `browser` verb's `page.evaluate`, running experiments in the page. A global plus one evaluate reads real runtime state in one dispatch; the restart-and-eyeball loop observes almost nothing and burns a turn. The same `browser` surface that witnesses an edit also diagnoses it.
|
|
26
26
|
|
|
27
|
-
**
|
|
27
|
+
**Search routes through the spool, never a platform search agent.** Any code/file/symbol lookup ("where is X", "what calls Y", grep the tree) is the `codesearch` verb (`{"query":"..."}`); prior knowledge is `recall`. Never the platform Explore agent, a Task/general-purpose search subagent, or raw `grep`/`Glob` -- they bypass the spool, the committed index, and recall-grounding, and do not transport across harnesses. Orient at PLAN is `recall` + `codesearch` in parallel; every mid-EXECUTE lookup is a `codesearch` too.
|
|
28
28
|
|
|
29
|
-
**
|
|
29
|
+
**Class rule: every platform-native capability that has a plugkit verb is forbidden in favor of the verb.** code/file/symbol search -> `codesearch`; prior knowledge -> `recall`; URL/web fetch -> `fetch`; running code -> `exec_js`; a real browser -> `browser`; persisting memory -> `memorize-fire`; **any git op -> the git verbs** (`git_status`/`git_log`/`git_diff`/`git_show`/`git_branch` inspect; `git_add`/`git_commit`/`git_finalize`/`git_push` stage-commit-push; `git_checkout`/`git_fetch`/`git_rm`/`git_revert`/`git_reset` mutate). `git_finalize {message}` bundles add->commit->porcelain-gate->push in one dispatch and is the COMPLETE push surface; a `bash`/`sh`/`powershell` body invoking git is gated (`deviation.bash-git-bypass`). The native tool bypasses the ledger, the index, and portability. If no verb exists, that is a missing verb to add, not license to reach around the spool.
|
|
30
30
|
|
|
31
|
-
**
|
|
32
|
-
|
|
33
|
-
**Boot before dispatching. Always check first.** Writing to `.gm/exec-spool/in/instruction/N.txt` while the watcher is dead is the canonical cold-start failure, the request sits forever, you read no response, you fabricate the chain from memory of the prose. The spool directory's existence does NOT mean the watcher is alive; `.status.json` mtime within the last 15s does. The leftover `.status.json` from yesterday's dead watcher is the most common trap.
|
|
34
|
-
|
|
35
|
-
Your first tool call of every session is the boot probe, in one Bash invocation. Read `.status.json` (liveness) and `.turn-summary.json` (orientation) together, the watcher precomputes both every 5s, so the two files give you everything you'd otherwise extract via gmsniff queries, git, yaml-parse, and ports-file scans:
|
|
31
|
+
**Boot before dispatching.** Writing `instruction/N.txt` to a dead watcher silently drops the request and you fabricate the chain from memory. The spool dir existing does not mean the watcher is alive; a `.status.json` `ts` within 15s does (a leftover stale `.status.json` is the common trap). Your first tool call every session is the boot probe in one Bash call:
|
|
36
32
|
|
|
37
33
|
```bash
|
|
38
34
|
cat .gm/exec-spool/.status.json 2>/dev/null; echo ---; cat .gm/exec-spool/.turn-summary.json 2>/dev/null; echo ---; date +%s%3N
|
|
39
35
|
```
|
|
40
36
|
|
|
41
|
-
`.turn-summary.json` carries `phase`, `last_skill`, `prd_pending`, `last_instruction_ts`, `last_instruction_age_ms`, `long_gap_threshold_ms`, `browser_sessions_alive`, `update_available`, `deviations_30m`, `watcher_uptime_ms`.
|
|
37
|
+
`.turn-summary.json` carries `phase`, `last_skill`, `prd_pending`, `last_instruction_ts`, `last_instruction_age_ms`, `long_gap_threshold_ms`, `browser_sessions_alive`, `update_available`, `deviations_30m`, `watcher_uptime_ms`. Age over threshold: your next non-orienting verb is gated, dispatch `instruction` first. `update_available` non-null: eager-upgrade with `bun x gm-plugkit@latest --kill-stale-watchers; bun x gm-plugkit@latest spool > /dev/null 2>&1 &`, then re-read `.status.json` after 8s to confirm `version`. `deviations_30m` non-zero indicates active drift to investigate before continuing.
|
|
42
38
|
|
|
43
|
-
Compare `.status.json` `ts`
|
|
39
|
+
Compare `.status.json` `ts` to the printed epoch: gap > 15000 = dead, boot it. Exception: a future `busy_until` means a long verb (browser/chromium spawn blocks the heartbeat ~15-18s) -- wait, do not boot a second watcher.
|
|
44
40
|
|
|
45
41
|
```bash
|
|
46
42
|
bun x gm-plugkit@latest spool > /dev/null 2>&1 &
|
|
47
43
|
```
|
|
48
44
|
|
|
49
|
-
(`npx -y gm-plugkit@latest spool > /dev/null 2>&1 &` if `bun` missing.)
|
|
50
|
-
|
|
51
|
-
**Dispatch shape: Write + Read response in the SAME tool-call block.** Issuing the Write alone is not a dispatch, it's a request that goes nowhere visible. The shape is `Write .gm/exec-spool/in/instruction/<N>.txt` AND `Read .gm/exec-spool/out/instruction-<N>.json` (or `out/<N>.json` for nested verbs) in one parallel-tools block. The Read may return "file does not exist" on the first attempt while plugkit is mid-verb, in that case, re-Read in the next message. Do NOT proceed to any other tool, do NOT narrate "I have everything I need," do NOT begin work until you have READ the response and followed the `instruction` field. Declaring readiness without a response in hand is fabrication.
|
|
52
|
-
|
|
53
|
-
Never poll the spool dir with `sleep && ls` or `Start-Sleep && Test-Path`, plugkit is synchronous from your view; if the response is not there, the watcher is dead (re-check `.status.json` mtime) or the verb is slow (check `.gm/exec-spool/.watcher.log`), not "still processing."
|
|
54
|
-
|
|
55
|
-
**Dead-watcher recovery is mandatory, never abandon the dispatch.** If two consecutive re-Reads return "file does not exist" AND `.status.json` ts is stale (>15s gap from current epoch) AND `busy_until` is absent or in the past, the watcher is dead. (A future `busy_until` means a long synchronous verb is running, the response will land when it finishes; wait, do not boot.) Your next call is `bun x gm-plugkit@latest spool` to boot a fresh watcher (the wrapper has self-respawn paths now, one boot deploys every queued fix to disk). Then re-dispatch the original verb. Do NOT reach for an alternative tool, puppeteer-core, agent-browser, WebFetch, raw `chrome.exe`, none of these substitute for the `browser` verb. Reaching outside plugkit when the spool surface is reachable orphans state the next session cannot reap, bypasses paper section 23 witness gates, and ages the project's discipline. The recovery is always: notice dead -> boot -> re-dispatch. The full chain from spool-write to disk-Read-success is the only admissible loop; any short-circuit produces unreconcilable state.
|
|
45
|
+
(`npx -y gm-plugkit@latest spool > /dev/null 2>&1 &` if `bun` missing.) Wait ~8s, re-`cat .status.json` for a fresh `ts`, and only then write to `instruction/`.
|
|
56
46
|
|
|
57
|
-
|
|
47
|
+
**Dispatch shape: Write request + Read response in the SAME tool-call block.** The shape is `Write .gm/exec-spool/in/instruction/<N>.txt` AND `Read .gm/exec-spool/out/instruction-<N>.json` (or `out/<N>.json` for nested verbs) in one block. A first-read "file does not exist" while plugkit is mid-verb is normal -- re-Read next message. Do not proceed, narrate readiness, or begin work before reading the response and following its `instruction` field. Never poll with `sleep && ls`: plugkit is synchronous, so a missing response means dead watcher (re-check `ts`) or slow verb (check `.gm/exec-spool/.watcher.log`), not "still processing."
|
|
58
48
|
|
|
59
|
-
|
|
49
|
+
**Dead-watcher recovery is mandatory.** Two consecutive missing re-Reads AND stale `ts` (>15s) AND no future `busy_until` = dead: `bun x gm-plugkit@latest spool` to boot a fresh watcher, then re-dispatch the original verb. Never substitute an alternative tool (puppeteer-core, WebFetch, raw chrome) for the `browser` verb -- reaching outside plugkit orphans state and bypasses the witness gates. Recovery is always notice-dead -> boot -> re-dispatch.
|
|
60
50
|
|
|
61
|
-
|
|
51
|
+
From PowerShell, write spool input as UTF-8 no-BOM (`-Encoding utf8` or `[System.IO.File]::WriteAllText`); the 5.1 default UTF-16+BOM trips `spool.body-encoding-recoded`. Prefer the `Write` tool for JSON bodies. First-turn body is `{"prompt":"<user request>"}` (derives orient_nouns + recall_hits); later same-conversation turns may use `{}`.
|
|
62
52
|
|
|
63
|
-
|
|
53
|
+
**Batch writes and reads together.** Write request + Read response is one logical step -- issue both in one block, not three turns. Fan-out is the same: N independent verbs = N Writes in one block then N Reads in one block. Only a real data dependency (verb B needs A's response) forces separate turns.
|
|
64
54
|
|
|
65
|
-
|
|
55
|
+
The chain is not COMPLETE until changes are on origin. Commit and push at the end of every session that touched tracked files; do not ask -- the push IS the validation dispatch (`verify.rs`). Only the porcelain check holds it back, and a dirty tree is fixed by stage-commit or revert, not by asking.
|
|
66
56
|
|
|
67
|
-
**
|
|
57
|
+
**Every residual is triaged this turn; "pre-existing" is not a stop excuse.** Non-empty `git status --porcelain`: every entry is yours now -- commit (real work), ignore via the managed block (transient runtime emission), or revert (stale junk). "Pre-existing" only names the triage outcome. `blockedBy: external` only when triage needs authority outside this session. `.gm/disciplines/` and new memorize-fire JSON are tracked+committed; `.gm/witness/` and transient staleness markers go in the managed gitignore block.
|
|
68
58
|
|
|
69
|
-
**
|
|
59
|
+
**Apply "every possible" to every noun.** PLAN is exhaustive, not minimal: for every noun, write every possible task, validation, mutable, corner case, caveat, failure mode, and empty/overflow/reentry/degenerate state as PRD rows. A single-digit PRD on a non-trivial request means you stopped early. Second pass: feed the list back in, each row's corner cases become new rows; closed when "every possible" yields nothing new. Long-horizon prompts routinely produce high-tens-to-hundreds of rows -- density at PLAN is the only protection against silent residuals at COMPLETE.
|
|
70
60
|
|
|
71
|
-
**
|
|
61
|
+
**Sweep every possible aspect for jank, each aspect a PRD row.** For every surface the prompt concerns, enumerate every immaturity/unfinished-edge/half-wired-path across gui, ux, ui, client state, server state, and the client/server boundary -- `jank` means the rough and almost-done, not just bugs. Each is a row, plus a profiling row and a security row per surface. Scoped to the prompt's reachable closure, exhaustive within it. Every issue found spawns its own debug-and-repair rows the same turn. Fan out via parallel spool dispatches (many `prd-add`/`codesearch`/`exec_js` in one block) and plugkit task-spawn, never the platform's Task/Explore subagent.
|
|
72
62
|
|
|
73
|
-
**
|
|
63
|
+
**One tell-tale AI design element spawns a full-codebase sweep.** A boilerplate flourish, over-hedged comment, generic scaffold name, or machine-authored shape is the witness that the same shape is likely elsewhere: spool rows for a codebase-wide scan, per-cluster findings, and fix-and-verify, fanned out exhaustively -- never a one-off local fix.
|
|
74
64
|
|
|
75
|
-
**
|
|
65
|
+
**Graphical symbols are forbidden; convert to ASCII on sight.** Arrow/box/geometric glyphs, stars, bullets, checkmarks/crosses, emojis, any non-ASCII decorative symbol are a machine tell -- convert the moment seen (arrow glyph -> `->`, bullet -> `-`/`*`, check/cross -> `[x]`/`[ ]` or done/todo/pass/fail, status dot -> the word). One sighting spawns the full-codebase sweep. Exempt: code operators (`=>`, `??`, `?.`, math/comparison), frozen changelog/git-log entries, binary stores, intentional icon-font/CSS-content product glyphs.
|
|
76
66
|
|
|
77
|
-
**
|
|
67
|
+
**Treat the architecture as pliable.** It is reshapeable; every change that clearly improves it or reduces maintenance burden is a PRD plan you spool. Replacing bespoke code with native functionality or a popular well-maintained library is encouraged only when it nets a smaller maintained surface -- a heavy dependency to delete a few lines net-grows it and is the guarded failure mode. Check for an existing library first; never carry a drift-prone reimplementation of an upstream.
|
|
78
68
|
|
|
79
|
-
|
|
69
|
+
**Noticing is a planning event.** Anything you observe that should be done, is unfinished/improvable, or diverges from a user preference becomes a `prd-add` this turn. Observations carried only in prose evaporate; only the PRD store survives. "Future work"/"note for later" are drift signatures. Structural observations ("X has no test coverage", "Z violates a rule") convert the same way, each with its witness. Density grows along the walk, not just at PLAN.
|
|
80
70
|
|
|
81
|
-
|
|
71
|
+
`git push` is admissible only when `git status --porcelain` is empty, and the porcelain probe must be its OWN Bash tool-use event before the push, not `&&`-chained inside one call (ccsniff `--git-discipline` scans the tool-call stream, not shell commands within an event). The discipline is three Bash events: `git status --porcelain` -> read empty -> `git push`. Prefer the `git_push` verb (gates on porcelain internally, refuses dirty, emits `deviation.push-dirty`). Witness clean via `git_status`, pushed via `branch_status` (ahead==0). residual-scan and the COMPLETE gate both refuse a dirty tree or missing residual-check marker.
|
|
82
72
|
|
|
83
|
-
|
|
73
|
+
**Memory is project-resident, never platform-resident.** Refuse the platform's own auto-memory dir (`~/.claude/projects/*/memory/`, `~/.codex/`, `~/.cursor/*`) -- it does not transport and is invisible to gmsniff/recall. The two portable surfaces: (a) `memorize-fire` through the spool (embeds into `.gm/rs-learn.db`, surfaces via `recall` + auto-recall); (b) `AGENTS.md` for project-tracked hard rules, edited inline. They are complementary -- memorize-fire for recall-time reinforcement, AGENTS.md for the hard rule. About to Write under a platform memory dir: stop, dispatch `memorize-fire` instead. The response body is not a mutation surface either; memory routes through `memorize-fire`, tool ops through their verbs.
|
|
84
74
|
|
|
85
|
-
**Suppress mundane output; strip it to the bone.**
|
|
75
|
+
**Suppress mundane output; strip it to the bone.** Drop articles, preamble, play-by-play, boot-probe narration, dispatch echoes, restatement of prose just read, status recaps. What survives: a real finding, a decision and its one-line reason, a blocker, the single-line PRD-read declaration. Terse means fewer words, NEVER zero tool calls and never silent work -- the turn still ends in the chain-advancing tool call, and you still state in one clause what you are about to do.
|
|
86
76
|
|
|
87
|
-
**Prune bad memory on sight
|
|
77
|
+
**Prune bad memory on sight -- a wrong recall hit is worse than a miss.** A stale/superseded/wrong `recall` or `auto_recall` hit gets `memorize-prune {key}` (deletes text + embedding). For an uncertain set, `memorize-prune {query}` returns review-only candidates; judge, then re-dispatch the stale `{keys:[...]}` -- never a blind similarity-delete.
|
|
88
78
|
|
|
89
|
-
On turn entry (first `instruction`
|
|
79
|
+
On turn entry (first `instruction` after a >30s gap or session-start), plugkit attaches `auto_recall` `{query, hits, fired_at, turn_entry:true}` derived from the user prompt. Read `auto_recall.hits` alongside `recall_hits` (the phase+PRD-subject pack); auto_recall fires only on turn entry, do not re-trigger it.
|