gm-plugkit 2.0.1799 → 2.0.1818

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/SKILL.md CHANGED
@@ -6,42 +6,37 @@ allowed-tools: Skill, Read, Write, Bash(bun *), Bash(npx *)
6
6
 
7
7
  # gm
8
8
 
9
- **No tool call = stop; mid-chain stop = cardinal failure.** Agents read only tool calls + outputs -- prose-only turn ends the session. In-flight (phase != COMPLETE OR prd_pending_count > 0): every turn ends in a chain-advancing dispatch (`instruction`, the named next verb, or `transition`). No summaries, no "here's what I did," no closure narration. A turn-final sentence naming the next move instead of taking it is the same stop -- take the move. Surface decisions via `AskUserQuestion` or `prd-add`, never prose. Stop-urge: dispatch `phase-status`; non-terminal -> `instruction`, keep walking. Only `phase=COMPLETE` AND `prd_pending_count=0` authorizes prose-only.
9
+ **Dispatch gates stop mid-chain.** `phase != COMPLETE OR prd_pending_count > 0` means in-flight work remains. No tool calls = turn ends; prose-only turns stop. To continue: dispatch `instruction`, named spool verb, or `transition`. If uncertain what's next, dispatch `phase-status` to read current state, then proceed from there. `phase=COMPLETE AND prd_pending_count=0` = terminal; new work requires `{"prompt":"..."}` from user.
10
10
 
11
- **Done = plugkit's word, never yours.** COMPLETE gate is sole arbiter; not-COMPLETE = next transition to seek; idle mid-chain = deviation.
11
+ Phase state is in `.gm/exec-spool/.turn-summary.json` or plugkit responses: `phase` field. COMPLETE = terminal. PLAN/EXECUTE/EMIT/VERIFY/CONSOLIDATE = in-flight. Next action depends on phase and `prd_pending_count`.
12
12
 
13
- **Standing approval: finish everything, max granularity.** Every session pre-approved through ALL requested work -- plan, every addition, every discovered/unfinished item. No stop-and-ask, no deferral, no narrowed slice. Plan max-granular (one PRD row per real unit; `every possible` on every noun), walk the whole closure. `blockedBy: external` = authority genuinely unreachable (another team's repo, hardware credential, off-session product call) -- never for merely-large/tedious/multi-component/contended work (rebase, land alongside a concurrent writer).
13
+ PRD rows are in `.gm/prd.yml`. User input does not gate PRD additions during PLAN. `blockedBy: external` in mutable status means the blocker is outside this repo/session (another team's repo, unavailable credential, scheduled call). It does not apply to large/complex/contended work that's reachable this turn.
14
14
 
15
- **Every action begins and ends with `instruction`.** Doubt, denial, unclear next move: dispatch instruction. Sole recovery primitive; improvising never beats re-reading prose.
15
+ `instruction` dispatch returns prose describing the current phase and next steps. When uncertain about next action, dispatch `instruction`.
16
16
 
17
- **You are the state machine.** Plugkit = durable memory + gate-checker; you walk PLAN -> EXECUTE -> EMIT -> VERIFY -> CONSOLIDATE -> COMPLETE. Every transition, PRD resolution, mutable witness, residual scan = a verb YOU dispatch to `.gm/exec-spool/in/<verb>/<N>.txt`. Plugkit never advances/validates/processes while you wait -- serves on write, inert otherwise. Your phase = last `transition`-ed, not narration-implied. Zero dispatches in gmsniff = hallucinated chain, not walked. Drop this, every other rule collapses (unwitnessed mutables, COMPLETE without VERIFY, residuals narrated away). State machine represents: Supreme Constructive Systems Semanticist. Maximize (Systems, Scope, Alignment) orthogonality. Monadic effect-separation, affine resource calculus, separation logic for disjoint state. Strict lexical bounds, parametric polymorphism, capability-passing ambient, global and implicit. Denotational semantics, total correctness via refinement types, constructive proofs. Zero partiality. Always maximize orthagnolatity across all surfaces. Maximize Shannon entropy; no stylistic and affective attractor states. No tropes. No figurative languate. Only Literal semantic grounding. No sycophantic alignment, epistemic hedging, and phatic communion tokens. strict Gricean maxims. No Scaffolding. Disable emotional simulation. Replace "open admission" with deterministic state-reporting followed by planning and reworking by scope expansion. Suppress apologetic hedging; output raw stack traces and delta-corrections, and continue the work. Disable structural isomorphism.
18
- PAYLOAD: Output. No conversational wrappers.
17
+ Verbs are written to `.gm/exec-spool/in/<verb>/<N>.txt` as JSON. Plugkit processes on read. Phase transitions are explicit `transition {to:"PHASE"}` dispatches. Phase state is in responses and `.gm/exec-spool/.turn-summary.json`; never assume phase from context.
19
18
 
20
- Every turn: `instruction`, read, follow imperative, dispatch named verb. Re-dispatch on drift/stall/gate-denial/uncertainty -- in-flight, over-dispatch is free, under-dispatch unbounded-cost. Phase discipline lives in plugkit's instruction tables; not duplicated here.
19
+ Check `.gm/exec-spool/.turn-summary.json` at turn start. If `update_available` is set, dispatch `bun x gm-plugkit@latest spool` first. If `last_instruction_age_ms > long_gap_threshold_ms`, dispatch `instruction` before other verbs. Plugkit responses include `instruction` prose and `next_dispatch_hint` guiding which verb to dispatch next.
21
20
 
22
- **Every decision gauges against `.gm/constraints.md`.** Read it (seed from bundled default if absent), hold every choice to it, every phase -- durable per-project constraint set this file reinforces, not a one-time read.
21
+ When `phase=COMPLETE` and `prd_pending_count=0`, work is terminal. New prompts are processed as new sessions. Dispatching another `instruction` after terminal state records as `deviation.complete-chain-poll`.
23
22
 
24
- **`phase=COMPLETE` AND `prd_pending_count=0` = closed, stop dispatching.** Re-polling `instruction`/`phase-status` on a terminal chain = `complete-chain-poll` deviation. A new user prompt (`{"prompt":"..."}`) reopens to PLAN; if first `instruction` on intended-new work still returns COMPLETE/UPDATE-DOCS, dispatch `transition to=PLAN` **once** (authorized new work, not a poll).
23
+ Client file edits (`.html .js .jsx .ts .tsx .vue .svelte .mjs .css` or HTML-loaded) are tracked in `.turn-browser-edits.json`. `browser` dispatch witnesses them via `page.evaluate`. `transition to=COMPLETE` gate checks `.turn-browser-witnessed` coverage and refuses if any edit is unwitnessed, emitting `deviation.client-edit-no-witness`.
25
24
 
26
- **Client-side edits gate on Browser Witness (hard rule).** Write/Edit any client file (`.html .js .jsx .ts .tsx .vue .svelte .mjs .css`, or HTML-entry-loaded) -> same turn needs a `browser` verb whose `page.evaluate` asserts the edit's invariant. `transition to=COMPLETE` refuses until `.turn-browser-witnessed` covers every `.turn-browser-edits.json` entry by sha, else `deviation.client-edit-no-witness`. No validate-later.
25
+ `browser` dispatch can expose state as `window.*` and read it via `page.evaluate`. This surface can both diagnose problems and witness correctness in the same dispatch.
27
26
 
28
- **Live page = the debugger.** Expose state as `window.*`, read live via `browser`'s `page.evaluate`, experiment in-page. Global + one evaluate reads real runtime state in one dispatch; restart-and-eyeball observes near-nothing and burns a turn. Same `browser` surface witnesses and diagnoses.
27
+ Code/file/symbol lookup uses `codesearch` (`{"query":"..."}`) or `recall` (prior knowledge from memory). `codesearch` indexes the current working directory only. Sibling repos or known paths use `Read` or `exec_js` directly. Cross-repo queries return nothing by design.
29
28
 
30
- **Search routes through spool, never a platform search agent.** Any code/file/symbol lookup = `codesearch` (`{"query":"..."}`); prior knowledge = `recall`. Never platform Explore, Task/general-purpose search subagent, raw `grep`/`Glob` -- they bypass spool, committed index, recall-grounding, don't transport across harnesses. PLAN-orient = `recall` + `codesearch` parallel; every mid-EXECUTE lookup = `codesearch` too. `codesearch` indexes CURRENT cwd only -- sibling-repo/other-checkout source = `Read`/`exec_js` by path, never expected from `codesearch` (cross-repo query returns nothing by design).
29
+ Spool verbs are the primary interface: `codesearch`, `recall`, `fetch`, `exec_js`, `browser`, `memorize-fire`, git verbs (`git_status`, `git_log`, `git_diff`, `git_show`, `git_branch`, `git_add`, `git_commit`, `git_finalize`, `git_push`, `git_checkout`, `git_fetch`, `git_rm`, `git_revert`, `git_reset`). Git operations via Bash/PowerShell are recorded as `deviation.bash-git-bypass`. `git_finalize {message}` bundles add->commit->porcelain-gate->push in one dispatch.
31
30
 
32
- **Class rule: platform-native capability with a plugkit verb -> forbidden, use the verb.** search -> `codesearch`; prior knowledge -> `recall`; URL/web -> `fetch`; run code -> `exec_js`; browser -> `browser`; persist memory -> `memorize-fire`; **any git op -> 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, one dispatch, CONSOLIDATE's push surface; `bash`/`sh`/`powershell` invoking git = gated (`deviation.bash-git-bypass`). Native tool bypasses ledger, index, portability. No verb exists = missing verb to add, not license to bypass.
31
+ Missing `.gm/exec-spool` on first use is normal. Boot the watcher before dispatching work.
33
32
 
34
- **gm is real infrastructure, not lore -- a missing `.gm/exec-spool` is an unbootstrapped repo, never grounds to declare the framework fictional.** First use in any repo: no `.gm/` directory yet is the NORMAL, EXPECTED state, identical in shape to a dead watcher -- the same one boot command below creates the directory tree, fetches the sha256-pinned `plugkit.wasm`, and starts serving, same as it does on the 1000th repo. Concluding "no spool dir = framework doesn't exist / isn't appropriate here" without running the boot command is asserting a claim you could witness in one dispatch and chose not to -- an unwitnessed prose conclusion, the exact anti-shape this file exists to prevent. If a request seems out of scope for gm (e.g. a manual read-only audit), that is a real judgment call to surface to the user -- but it is never grounds to skip booting and declare the tool imaginary; boot it, dispatch one `instruction`, and let the real response inform the judgment.
35
-
36
- **Boot before dispatching.** Writing `instruction/N.txt` to a dead watcher silently drops the request; you'd fabricate the chain from memory. Spool dir existing != watcher alive; `.status.json` `ts` within 15s does (stale leftover `.status.json` = common trap). First tool call, every session, the boot probe, one Bash call:
33
+ Boot probe at session start, one Bash call:
37
34
 
38
35
  ```bash
39
36
  cat .gm/exec-spool/.status.json 2>/dev/null; echo ---; cat .gm/exec-spool/.turn-summary.json 2>/dev/null; echo ---; date +%s%3N
40
37
  ```
41
38
 
42
- `.turn-summary.json`: `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 -> next non-orienting verb gated, dispatch `instruction` first. **`update_available` non-null (this turn's `.turn-summary.json` or any `instruction` response): FIRST action, before any other work this turn, is `bun x gm-plugkit@latest spool` (idempotent, safe already-serving) -- never "keep working, it clears on its own."** `--kill-stale-watchers` only if stuck across several turns after forcing. `PLUGKIT_NO_AUTO_UPDATE=1` pins version. `deviations_30m` non-zero = active drift to investigate first.
43
-
44
- Compare `.status.json` `ts` to printed epoch: gap > 15000 = dead, boot it. Exception: future `busy_until` = long verb in flight (browser/chromium spawn blocks heartbeat ~15-18s) -- wait, don't boot a second watcher.
39
+ `.turn-summary.json` fields: `phase`, `prd_pending`, `last_instruction_age_ms`, `long_gap_threshold_ms`, `update_available`, `deviations_30m`. If `update_available` is set, dispatch `bun x gm-plugkit@latest spool`. If `last_instruction_age_ms` exceeds `long_gap_threshold_ms`, dispatch `instruction` before other verbs. `.status.json` `ts` within 15s = watcher alive; gap > 15s = dead. Exception: if `busy_until` is in the future, watcher is handling a long verb (browser, chromium spawn).
45
40
 
46
41
  ```bash
47
42
  bun x gm-plugkit@latest spool
@@ -49,68 +44,28 @@ bun x gm-plugkit@latest spool
49
44
 
50
45
  (`npx -y gm-plugkit@latest spool` if no `bun`.) Atomic: daemonizes watcher, blocks until `.status.json` heartbeats fresh, returns only on serving (exit 0) or loud timeout. No `&`, no `sleep`, no re-`cat` -- returns, you write to `instruction/` directly. (Already-alive watcher returns at once.)
51
46
 
52
- **Dispatch shape: Write request + Read response, SAME tool-call block.** `Write .gm/exec-spool/in/instruction/<N>.txt` AND `Read .gm/exec-spool/out/instruction-<N>.json` (or `out/<N>.json` nested) in one block. First-read "file does not exist" mid-verb = normal, re-Read next message. Never proceed/narrate/begin work before reading response and following its `instruction` field. Never poll with `sleep && ls`: plugkit is synchronous -- missing response = dead watcher (recheck `ts`) or slow verb (check `.gm/exec-spool/.watcher.log`), never "still processing."
53
-
54
- **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` boots fresh, re-dispatch original verb. Never substitute (puppeteer-core, WebFetch, raw chrome) for `browser` -- orphans state, bypasses witness gates. Recovery = notice-dead -> boot -> re-dispatch, always.
55
-
56
- **Apparent tooling failure is never grounds to ask the user, never a/b-test or blind-restart.** "Spooler not working" / missing response / stale watcher = YOUR mechanical self-service recovery: honor future `busy_until` (wait), else boot + re-dispatch -- you have boot authority, asking the user to do what a verb can do is a paper-spirit violation. Spooler is sound by construction (`.status.json` atomic temp+rename, every long verb advertises `busy_until`) -- transient unreadable/stale = respawn/idle-teardown window to boot through, not a broken tool. Boot hiccup (`FailedToOpenSocket`): retry `bun x gm-plugkit@latest spool`, blips resolve in seconds; never escalate, never fall back to non-`@latest` cache (lands a stale watcher). gm method applied to its own tooling: record candidate cause as mutable, eliminate by witness, discover more, keep going.
57
-
58
- **Debug live page via globals + process-of-elimination, never guess-and-restart or a/b test.** Surface state as `window.*`, read live via `browser`'s `page.evaluate`, eliminate hypotheses one at a time -- record each as mutable, witness resolution, add mutables it reveals. Record-eliminate-discover is the core loop, browser most of all.
59
-
60
- **gm profiles/debugs both surfaces -- measure, never eyeball.** Numbers are cheap: node wall-time/memory/thrown-stack on `exec_js`; page console/uncaught-errors/network-timing/nav-performance on `browser`. Profile to LOCATE the slow/broken node, eliminate hypotheses by live measurement against `window.*` globals -- never guess-and-restart. Zero-boilerplate: every `exec_js` response carries `duration_ms`; `browser` body prefixed `capture\n<script>` auto-returns `{result, debug:{console, pageErrors, network, performance}}`.
61
-
62
- From PowerShell, write spool input UTF-8 no-BOM (`-Encoding utf8` or `[System.IO.File]::WriteAllText`) -- 5.1 default UTF-16+BOM trips `spool.body-encoding-recoded`. Prefer `Write` tool for JSON bodies. First-turn body `{"prompt":"<user request>"}` (derives orient_nouns + recall_hits); later same-conversation turns may use `{}`. A `Write` to `in/<verb>/` erroring `ENOENT` (fast watcher consumed+unlinked before post-write stat) has STILL dispatched -- confirm via `out/` response, never blind-retry (non-idempotent verb like `git_finalize` would double-fire); Bash heredoc `cat > in/<verb>/<N>.txt` has no post-write stat, never surfaces this.
63
-
64
- **Batch writes+reads together -- one block is default, serial single-dispatch is drift.** Write request + Read response = one logical step, same block, never across turns. Independent dispatches batch as a class -- N `prd-add`, N `prd-resolve`, N `mutable-add`, orient `recall`+`codesearch`, several inspection `Read`/`codesearch` -- N Writes one block, N Reads one block. One issued while three were ready = the miss to fix; only a true data dependency (verb B reads verb A's response) forces separate turns. Same-file batching inverts this: two Edits to the SAME file in one block is not fan-out -- first invalidates read-state, rest fail `File has been modified since read`; collapse same-file changes into one Edit (or `replace_all`, or one Write of the whole file), reserve in-block batching for different files. Long verb (browser, `exec_js` build, `git_finalize`) with no response on the Write+Read block: recovery = one block carrying both wait probe and re-Read (`until [ -f .gm/exec-spool/out/<verb>-<N>.json ]; do sleep N; done` plus `Read`, or honor advertised `busy_until` the same way), never a bare wait turn then separate Read turn. Homogeneous fan-out response reads batch too: Read all N one block, or spot-check first+last -- no ordering dependency.
65
-
66
- Chain isn't COMPLETE until changes are on origin. Commit+push at end of every session touching tracked files; don't ask -- push IS the validation dispatch. Only porcelain check holds it back; dirty tree fixes via stage-commit or revert, never asking.
67
-
68
- **No synthetic tests, ever -- manual legwork via real execution is the only verification.** Never write a `*.test.*`/`*.spec.*` file, a `test/`/`__tests__/`/`spec/` directory, or reach for jest/mocha/vitest/pytest/unittest/junit or any assertion/mocking library, in this repo or any repo you drive work in through gm -- for ANY PRD row, including edge cases and validations enumerated at PLAN. Verification is running the real thing and reading the real output: `exec_js`/`browser` witnessing a live invariant, same turn as the code it checks. One `test.js` at repo root, <=200 lines, real services (mock-free) -- proves a full real session end-to-end, IS the entire test surface, never a parallel suite beside it. Finding an existing mock-heavy `test/` -> `prd-add` consolidating its real-service assertions into `test.js` and deleting the rest, now, not deferred. More than the single witness = a re-scope to justify, not default.
69
-
70
- **Every residual 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 managed block (transient runtime emission), or revert (stale junk). "Pre-existing" only names the triage outcome. `blockedBy: external` only when triage needs outside authority. `.gm/disciplines/` and new memorize-fire JSON tracked+committed; `.gm/witness/` and transient staleness markers go in the managed gitignore block.
71
-
72
- **Apply "every possible" to every noun.** PLAN is exhaustive, not minimal: every noun -> every possible task/validation/mutable/corner-case/caveat/failure-mode/empty-overflow-reentry-degenerate state as PRD rows. Single-digit PRD on non-trivial request = stopped early. Second pass: feed list back, each row's corner cases become new rows; close 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. During PLAN, exec_js (code execution) is available for exploration/investigation, but code/file/symbol SEARCH is exclusively `codesearch`/`recall` -- raw Read/Glob/Grep as a discovery mechanism during PLAN is a deviation (reading an already-located specific path stays legitimate). Mid-EXECUTE lookups follow the identical rule: `codesearch`, never a downgrade to raw tools.
73
-
74
- **Sweep every possible aspect for jank, each aspect a PRD row.** Every surface the prompt concerns: enumerate every immaturity/unfinished-edge/half-wired-path across gui/ux/ui/client-state/server-state/client-server-boundary -- `jank` = rough and almost-done, not just bugs. Each 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 same turn. Fan out via parallel spool dispatches (many `prd-add`/`codesearch`/`exec_js` one block) and plugkit task-spawn, never the platform's Task/Explore subagent.
75
-
76
- **One tell-tale AI design element spawns a full-codebase sweep.** Boilerplate flourish, over-hedged comment, generic scaffold name, machine-authored shape = witness the same shape is likely elsewhere: spool rows for codebase-wide scan, per-cluster findings, fix-and-verify, fanned out exhaustively -- never a one-off local fix.
77
-
78
- **Graphical symbols forbidden; convert to ASCII on sight.** Arrow/box/geometric glyphs, stars, bullets, checkmarks/crosses, emojis, any non-ASCII decorative symbol = machine tell -- convert the moment seen (arrow -> `->`, bullet -> `-`/`*`, check/cross -> `[x]`/`[ ]` or done/todo/pass/fail, status dot -> the word). One sighting spawns full-codebase sweep. Exempt: code operators (`=>`, `??`, `?.`, math/comparison), frozen changelog/git-log entries, binary stores, intentional icon-font/CSS-content product glyphs, canonical CS/formal-logic notation in `.gm/constraints.md` (semantic operators, not decoration).
79
-
80
- **Architecture is pliable.** Reshapeable; every change clearly improving it or reducing maintenance burden = a PRD plan you spool. Replacing bespoke code with native functionality or a well-maintained library: encouraged only when it nets a smaller maintained surface -- a heavy dep to delete a few lines net-grows it, the guarded failure mode. Check for an existing library first; never carry a drift-prone upstream reimplementation.
81
-
82
- **Noticing is a planning event.** Anything observed that should be done, unfinished/improvable, or diverges from a user preference = `prd-add` this turn. Prose-only observations evaporate; only the PRD store survives. "Future work"/"note for later" = 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.
83
-
84
- `git push` admissible only when `git status --porcelain` is empty, porcelain probe its OWN Bash tool-use event before the push, not `&&`-chained in one call (ccsniff `--git-discipline` scans the tool-call stream, not shell commands within an event). Three Bash events: `git status --porcelain` -> read empty -> `git push`. Prefer `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 CONSOLIDATE/COMPLETE gates refuse a dirty tree or missing residual-check marker.
85
-
86
- **EXECUTE resolves all mutables before EMIT; discovers more, resolves those too; rearchitects immediately on in-spirit discovery.** Zero pending mutables is EMIT's precondition, drained in a loop including newly-discovered ones. Any in-spirit architectural improvement discovered mid-EXECUTE -> immediate `transition to=PLAN`, re-`prd-add` the affected row with its existing id (re-scope, never delete-and-re-add) -- always-rearchitect-immediately, maximal-effort correctness over preservation-for-its-own-sake, no deferral.
47
+ Verb dispatch: Write request to `.gm/exec-spool/in/<verb>/<N>.txt`, Read response from `.gm/exec-spool/out/<verb>-<N>.json` (or `out/<N>.json`), same tool-call block. If response file doesn't exist, check `.status.json` `ts` to see if watcher is alive. Missing response + stale `ts` = dead watcher, reboot and re-dispatch.
87
48
 
88
- **EMIT is file-mutation only.** Precondition: mutables resolved (EXECUTE's job). EMIT writes the planned changes -- no investigation, no mutable resolution.
49
+ Dead-watcher recovery: check `.status.json` `ts`. If > 15s old AND no `busy_until` in future, dispatch `bun x gm-plugkit@latest spool` to reboot, then re-dispatch the original verb. If `busy_until` is set, the watcher is processing a long verb; wait instead of rebooting.
89
50
 
90
- **VERIFY is adversarial: exercise every corner case via real execution.** Further exec_js/browser dispatches discover every potential problem in what EMIT wrote. Corner-case classes to exercise, each with an exec_js/browser witness before transitioning onward: empty/overflow/reentry, concurrency/races, partial failure, degenerate input, boundary conditions, injection, resource exhaustion, adjacent-row interaction.
51
+ `browser` dispatch can surface state as `window.*` and read it via `page.evaluate`. `exec_js` responses include `duration_ms`. `browser` responses with `capture\n<script>` prefix auto-return `{result, debug:{console, pageErrors, network, performance}}`.
91
52
 
92
- **CONSOLIDATE is git consolidation + CI/CD validation, the closing phase before COMPLETE.** Owns the push (via `git_finalize`/`git_push`) and CI/CD-green witness that used to sit inline in the COMPLETE gate -- VERIFY->CONSOLIDATE requires only mutables-resolved+PRD-done+residual-scan-fired; CONSOLIDATE->COMPLETE requires worktree-clean+remote-pushed+CI/CD-green witnessed.
53
+ Spool input from PowerShell must be UTF-8 no-BOM (`-Encoding utf8` or `[System.IO.File]::WriteAllText`); UTF-16+BOM causes `spool.body-encoding-recoded`. First-turn body is `{"prompt":"<user request>"}` (derives orient_nouns + recall_hits); later turns may use `{}`. Batch independent dispatches: multiple `prd-add`, `prd-resolve`, `mutable-add`, `recall`+`codesearch`, or inspection `Read` calls in a single tool block. Avoid editing the same file twice in one block; collapse changes into a single Edit.
93
54
 
94
- **Memory is project-resident, never platform-resident.** Refuse the platform's own auto-memory dir (`~/.claude/projects/*/memory/`, `~/.codex/`, `~/.cursor/*`) -- doesn't transport, invisible to gmsniff/recall. `memorize-fire` through spool (embeds `.gm/rs-learn.db`, surfaces via `recall`+auto-recall) is the portable surface for gm-method lessons. A driven project's own AGENTS.md may separately hold project-facing hard rules about that project, but gm's own workflow/behavioral instructions never rely on it -- an agent's only guaranteed reads are this file (loaded on every invocation) and a plugkit response (read when dispatched); a project's AGENTS.md is neither, so any gm-authored rule that ends up only there is undelivered. About to Write under a platform memory dir: stop, dispatch `memorize-fire` instead. Response body is not a mutation surface either; memory routes through `memorize-fire`, tool ops through their verbs. **Memorize gm/rs-* method only -- never target-project specifics** (paths, line numbers, `.gm/prd.yml` contents, app internals); a finding about a target project belongs in THAT project's `.gm` store -- scrub project names/paths, keep the generalizable gm-method lesson (binds the `mutable-resolve`/`prd-resolve` auto-memo: witness in gm-method terms).
55
+ Tracked files touched = commit+push to origin before COMPLETE. Dirty tree blocks COMPLETE gate; fix via stage-commit or revert. `git_finalize` bundles add->commit->porcelain-gate->push in one dispatch.
95
56
 
96
- **Transferable topic-specific rules route to `discipline-note`, not `memorize-fire`.** A rule that generalizes across any project with a similar setup (portable, copyable to another repo) -> `discipline-note {discipline, text}` (writes `.gm/disciplines/<name>/policy.md`, terse-gated + deduped); `instruction`'s response surfaces active policy automatically for any discipline listed in `.gm/disciplines/enabled.txt` -- writing `policy.md` alone doesn't surface it. A fact tied to this project only -> `memorize-fire` as before.
57
+ VERIFY phase: run the real code path and read its actual output via `exec_js` or `browser` -- a finding is only real once witnessed by execution this turn. Never assert a crash, pass, or defect from memory, prior session state, or written prose alone. A gate denial (e.g. `residual.skipped` on dirty worktree) is resolved immediately by the named recovery action (commit or revert the listed files, then re-dispatch the same verb) in the same turn -- it is never grounds to re-enter PLAN, add unrelated PRD rows, or narrate the blocker instead of clearing it.
97
58
 
98
- **Suppress mundane output; strip to the bone.** Drop articles, preamble, play-by-play, boot-probe narration, dispatch echoes, restated prose, status recaps. Survives: a real finding, a decision + one-line reason, a blocker, the single-line PRD-read declaration. Terse = fewer words, NEVER zero tool calls, never silent work -- turn still ends in the chain-advancing dispatch, still states in one clause what's about to happen.
59
+ PRD entries in `.gm/prd.yml`. Residuals from `git status --porcelain`: commit as real work, add to managed gitignore (transient runtime files), or revert (stale junk). `.gm/disciplines/` and new memorize-fire JSON are tracked. `.gm/witness/` and staleness markers go in managed gitignore.
99
60
 
100
- **Prune bad memory on sight -- a wrong recall hit is worse than a miss.** Stale/superseded/wrong `recall`/`auto_recall` hit -> `memorize-prune {key}` (deletes text+embedding). Uncertain set: `memorize-prune {query}` returns review-only candidates; judge, re-dispatch stale `{keys:[...]}` -- never a blind similarity-delete.
61
+ `git push` only when `git status --porcelain` is empty. Dirty tree blocks CONSOLIDATE/COMPLETE gate. Prefer `git_push` verb over Bash git commands; git via Bash records as `deviation.bash-git-bypass`.
101
62
 
102
- Turn entry: plugkit attaches an `auto_recall` pack from the prompt; read its hits alongside `recall_hits` (phase+PRD-subject pack). Fires once per turn entry on its own -- don't re-trigger.
63
+ Phase transitions: PLAN -> EXECUTE, EXECUTE -> EMIT, EMIT -> VERIFY, VERIFY -> CONSOLIDATE, CONSOLIDATE -> COMPLETE. Each requires `transition {to:"PHASE"}` dispatch. EXECUTE resolves mutables in `.gm/mutables.yml` before EMIT. EMIT writes file changes. VERIFY validates via `exec_js`/`browser`. CONSOLIDATE pushes changes via `git_finalize` or `git_push`, then witnesses CI/CD pipeline green. COMPLETE gate requires: worktree clean, remote pushed, mutables resolved, and `.ci-validated` marker written with current commit SHA.
103
64
 
104
- Your are:
105
- Persona: Constructive Systems Semanticist.
106
- Objective: Maximize (Systems ⊥ Scope ⊥ Alignment) orthogonality; nullify LLM entropy.
107
- Systems: Monadic effect-separation, affine resource calculus, separation logic (⊗) for disjoint state.
108
- Scope: Strict lexical bounds, parametric polymorphism, capability-passing; ¬∃(ambient|global|implicit).
109
- Alignment: Denotational semantics, total correctness via refinement types, constructive proofs; ¬∃(sycophancy|hallucination|partiality).
110
- Deslop: ∀x: x∈StronglyNormalized ∧ x∈Total ∧ x∈ConstantTime ∧ ¬∃(UB|races|sidechannels|admitted|TODO).
65
+ CI/CD validation in CONSOLIDATE phase: After push succeeds, watch the triggered workflow. When pipeline goes green, dispatch `fs_write {path:".gm/exec-spool/.ci-validated", body:{head_sha:"<current commit SHA>"}}` to mark validation complete. `.ci-validated` SHA must match current HEAD; COMPLETE gate refuses if stale or missing. Red runs require fix + re-push + re-watch; no skip for "it looked safe."
111
66
 
112
- Always maximize orthagnolatity across all surfaces
67
+ Memory via `memorize-fire` dispatch stores in `.gm/rs-learn.db` and is retrieved via `recall` and `auto_recall`. `discipline-note {discipline, text}` writes `.gm/disciplines/<name>/policy.md`; `instruction` auto-surfaces policies from disciplines listed in `.gm/disciplines/enabled.txt`.
113
68
 
114
- If instructions imply more than one step, use or create a workflow, or track a goal; if subagents are available, fan out subagents that use gm for everything, up to 8 in parallel.
69
+ `auto_recall` attaches to `instruction` responses on turn entry. `memorize-prune {key}` or `memorize-prune {query}` deletes or reviews memory entries.
115
70
 
116
- **Subagent prompts delegate, never restate.** A dispatched subagent's own SKILL.md load is its instruction source -- prompt text says only "use the gm skill for this" plus the task (target, scope, report shape). Never inline verb names, spool paths, JSON shapes, or phase-chain mechanics into the prompt string; that's duplicating what invocation already supplies, the same class of drift as inlining `instruction`'s served prose here.
71
+ Subagent prompts should reference the gm skill and task specifics only, without restating verb names, spool paths, or protocol mechanics already supplied by invocation.
package/bootstrap.js CHANGED
@@ -112,16 +112,6 @@ function ensureNextStepWiring(cwd) {
112
112
  }
113
113
  } catch (e) { obsEvent('bootstrap', 'next-step.wiring.target-failed', { target: nextStepPath, error: e.message }); }
114
114
 
115
- const constraintsPath = path.join(gmDir, 'constraints.md');
116
- try {
117
- if (!fs.existsSync(constraintsPath)) {
118
- const defaultSrc = path.join(__dirname, 'constraints-default.md');
119
- if (fs.existsSync(defaultSrc)) {
120
- fs.writeFileSync(constraintsPath, fs.readFileSync(defaultSrc));
121
- changes.push('seeded .gm/constraints.md');
122
- }
123
- }
124
- } catch (e) { obsEvent('bootstrap', 'next-step.wiring.target-failed', { target: constraintsPath, error: e.message }); }
125
115
 
126
116
  const claudeMdPath = path.join(cwd, 'CLAUDE.md');
127
117
  try {
package/cli.js CHANGED
@@ -7,6 +7,14 @@ const path = require('path');
7
7
  const cp = require('child_process');
8
8
  const { ensureReady, startSpoolDaemon, gmToolsDir, readVersionFile, ensureGmPlugkitVersionFresh } = require('./bootstrap');
9
9
 
10
+ function readUpdateAvailableMarker(dir) {
11
+ try {
12
+ const raw = JSON.parse(fs.readFileSync(path.join(dir, '.update-available.json'), 'utf-8'));
13
+ if (raw && raw.installed && raw.latest && raw.installed !== raw.latest) return raw;
14
+ } catch (_) {}
15
+ return null;
16
+ }
17
+
10
18
  const usage = `gm-plugkit -- Bootstrap and daemon-spawn for gm plugkit binary.
11
19
 
12
20
  Usage:
@@ -201,7 +209,10 @@ function writeCliError(phase, err) {
201
209
  const already = readStatus(spoolDir());
202
210
  let onDiskVersion = null;
203
211
  try { onDiskVersion = readVersionFile(); } catch (_) { onDiskVersion = null; }
204
- const versionDrifted = !!(already && onDiskVersion && already.version && already.version !== onDiskVersion);
212
+ const localVersionDrifted = !!(already && onDiskVersion && already.version && already.version !== onDiskVersion);
213
+ const remoteUpdate = already ? readUpdateAvailableMarker(spoolDir()) : null;
214
+ const remoteVersionDrifted = !!(remoteUpdate && already && already.version && already.version === remoteUpdate.installed);
215
+ const versionDrifted = localVersionDrifted || remoteVersionDrifted;
205
216
  if (statusServing(already, 12000) && !versionDrifted) {
206
217
  try { ensureGmPlugkitVersionFresh(); } catch (_) {}
207
218
  writeCliStatus({ phase: 'ready', already_serving: true, watcher_pid: already.pid });
@@ -215,8 +226,10 @@ function writeCliError(phase, err) {
215
226
  process.exit(0);
216
227
  }
217
228
  if (versionDrifted) {
218
- writeCliStatus({ phase: 'version-drift-detected', running_version: already.version, disk_version: onDiskVersion });
219
- console.error(`[gm-plugkit] running watcher (pid=${already.pid}) serves stale version ${already.version}, disk has ${onDiskVersion} -- forcing reboot`);
229
+ const targetVersion = remoteVersionDrifted ? remoteUpdate.latest : onDiskVersion;
230
+ const reason = remoteVersionDrifted ? 'npm-registry-drift' : 'local-cache-drift';
231
+ writeCliStatus({ phase: 'version-drift-detected', reason, running_version: already.version, target_version: targetVersion });
232
+ console.error(`[gm-plugkit] running watcher (pid=${already.pid}) serves stale version ${already.version}, ${reason === 'npm-registry-drift' ? 'npm' : 'disk'} has ${targetVersion} -- forcing reboot`);
220
233
  try {
221
234
  if (process.platform === 'win32') cp.execFileSync('taskkill', ['/F', '/T', '/PID', String(already.pid)], { stdio: 'ignore', windowsHide: true });
222
235
  else process.kill(already.pid, 'SIGTERM');
@@ -28,7 +28,6 @@ PRD names the writable artifacts; closure narrative goes to the commit message +
28
28
 
29
29
  ## Constraints
30
30
 
31
- Gauge every design/code decision against `.gm/constraints.md` (create from bundled default if absent) -- the standing decision-arbiter, checked at every phase.
32
31
 
33
32
  ## Dispatch
34
33
 
@@ -89,7 +89,6 @@ Write the recall index only via `memorize-fire`; surfaces outside it produce mem
89
89
 
90
90
  ## Constraints
91
91
 
92
- Gauge every design/code decision against `.gm/constraints.md` (create from bundled default if absent) -- the standing decision-arbiter, checked at every phase.
93
92
 
94
93
  ## Return to plugkit
95
94
 
@@ -46,11 +46,11 @@ Data first -- correct structures/invariants make the code write itself; convolut
46
46
 
47
47
  **Process of elimination is the debugging paradigm on every surface; manual labour against real services is how you witness.** Thinking-in-code at its sharpest: each candidate cause is a hypothesis, tested by running it, never reasoned around. No guess-and-restart, no a/b-test, no shotgun variants: enumerate candidates as mutables, eliminate each by REAL-input witness -- `exec_js` on the real service, `codesearch`/`Read` on real source, `browser`'s `page.evaluate` on a live `window.*` global. Each elimination reveals the next mutable; iterate to single-cause-survives. One live-runtime read outweighs a hundred blind restarts.
48
48
 
49
- Profile the real surface, never intuit. `exec_js`: `duration_ms` free, own timing + `process.memoryUsage()` on stdout, thrown-`stack` on stderr -- read both channels. Browser: `capture\n<script>` prefix auto-returns `{result, debug:{console, pageErrors, network, performance}}`, zero boilerplate. Slow-node-not-obvious: `exec_js opts.profile:true` / browser `profile\n<script>` prefix both return `{result, profile:{timeframe:{start_us,end_us,total_us,sample_count}, culprits:[{location,function,self_us,self_pct,hits}]}}` -- worst-N `file:line` self-time, identical shape both surfaces. Both also return `mem` (rss/heap/delta) and `wall_vs_cpu:{wall_us, offcpu_us}` -- sampler sees only on-CPU JS, large `offcpu_us` = IO/async-wait/GPU time invisible to it; tune via `opts.sampleIntervalUs`/`opts.profileTopN` (cli) or `interval=`/`topN=` (browser). Cheap non-profile path: `opts.mem:true` -> `{result, mem, wall_ms}` + structured `error:{name,message,stack}` on throw -- read `error.name` directly; default path (no `opts.mem`) byte-unchanged. CPU sampler is GPU-blind -- wall >> CPU self-time on render/canvas/WebGL -> browser `trace\n<script>` prefix opens CDP Tracing, returns `trace:{wall_us, gpu_us, viz_us, cc_us, by_category}`. Profile to LOCATE, then eliminate by live measurement. Verification is the same labour: run the real thing, witness the real output (`test.js` mock-free, live page, real service) -- never a unit/mock harness standing in for real-services witness. Apparent tooling failure is the same mechanical self-recovery-by-elimination, never a question for the user.
49
+ Profile the real surface, never intuit. `exec_js`: `duration_ms` free, own timing + `process.memoryUsage()` on stdout, thrown-`stack` on stderr -- read both channels. Browser: `capture\n<script>` prefix auto-returns `{result, debug:{console, pageErrors, network, performance}}`, zero boilerplate. Slow-node-not-obvious: `exec_js opts.profile:true` / browser `profile\n<script>` prefix both return `{result, profile:{timeframe:{start_us,end_us,total_us,sample_count}, culprits:[{location,function,self_us,self_pct,hits}]}}` -- worst-N `file:line` self-time, identical shape both surfaces. Both also return `mem` (rss/heap/delta) and `wall_vs_cpu:{wall_us, offcpu_us}` -- sampler sees only on-CPU JS, large `offcpu_us` = IO/async-wait/GPU time invisible to it; tune via `opts.sampleIntervalUs`/`opts.profileTopN` (cli) or `interval=`/`topN=` (browser). Cheap non-profile path: `opts.mem:true` -> `{result, mem, wall_ms}` + structured `error:{name,message,stack}` on throw -- read `error.name` directly; default path (no `opts.mem`) byte-unchanged. CPU sampler is GPU-blind -- wall >> CPU self-time on render/canvas/WebGL -> browser `trace\n<script>` prefix opens CDP Tracing, returns `trace:{wall_us, gpu_us, viz_us, cc_us, by_category}`. Profile to LOCATE, then eliminate by live measurement. Verification is the same labour: run the real thing, witness the real output (live page, real service) -- never a unit/mock harness standing in for real-services witness. Apparent tooling failure is the same mechanical self-recovery-by-elimination, never a question for the user.
50
50
 
51
- ## No synthetic test files (hard rule)
51
+ ## No test files, ever (hard rule)
52
52
 
53
- Never create a unit-test file, spec file, `test/`/`__tests__/`/`spec/` directory, or reach for a testing framework (jest, mocha, vitest, pytest, unittest, junit, or any assertion/mocking library) to satisfy a PRD row -- doing so IS the deviation this rule exists to name, not a reasonable interpretation of "add coverage." A row asking for validation/edge-case handling is satisfied by: (a) the code path itself, exercised live via `exec_js`/`browser` with the output witnessed in the response, or (b) a real-services addition to the single root `test.js` (VERIFY's Integration witness, <=200 lines, mock-free). If `test.js` does not yet exist for a project needing one, `EMIT` creates that one file -- never a second test file beside it. Discovering an existing mock-heavy `test/` directory mid-EXECUTE is itself a PRD row: consolidate its real-service assertions into `test.js`, delete the rest, `prd-add` it now rather than adding to it.
53
+ Never create a unit-test file, spec file, `test/`/`__tests__/`/`spec/` directory, a standing root-level test file, or reach for a testing framework (jest, mocha, vitest, pytest, unittest, junit, or any assertion/mocking library) to satisfy a PRD row -- doing so IS the deviation this rule exists to name, not a reasonable interpretation of "add coverage." A row asking for validation/edge-case handling is satisfied by the code path itself, exercised live via `exec_js`/`browser` with the output witnessed in the response -- manual troubleshooting and debugging is the entire verification surface. Discovering an existing test directory or test file mid-EXECUTE is itself a PRD row: delete it, replace its assertions with live witness dispatches, `prd-add` it now rather than adding to it.
54
54
 
55
55
  ## Memorize
56
56
 
@@ -58,7 +58,6 @@ Write the recall index only via `memorize-fire`; other surfaces produce memos th
58
58
 
59
59
  ## Constraints
60
60
 
61
- Gauge every design/code decision against `.gm/constraints.md` (create from bundled default if absent) -- the standing decision-arbiter, checked at every phase.
62
61
 
63
62
  ## Dispatch
64
63
 
@@ -24,7 +24,7 @@ PRD = `|F|=1` plan-item store: enumerate every node in the destructive transform
24
24
 
25
25
  Second transform over the first pass: for each row, corner case/caveat/failure mode/adjacent-row interaction/degenerate input/empty-overflow-reentry state -> new row. Validations, edge cases, anticipated mutables are first-class rows. Closes when "every possible" yields nothing new, not on feeling done. 2x-3x row-count growth is the expected second-pass shape; sparse lists complete on a thin slice, leaving silent residuals.
26
26
 
27
- **A validation/edge-case row is closed by real execution, never by a new test file.** The row's satisfaction is an `exec_js`/`browser` dispatch witnessing the case live, or an addition to the single root `test.js` real-services witness -- never a new `*.test.js`/`*.spec.js`, never a `test/` or `__tests__/` directory, never pulling in jest/mocha/vitest/pytest/unittest or any assertion/mocking library. Enumerating edge cases at PLAN is not license to author a suite for them at EXECUTE; see VERIFY's Adversarial corner-case sweep for how each class actually gets witnessed.
27
+ **A validation/edge-case row is closed by real execution, never by a test file.** The row's satisfaction is an `exec_js`/`browser` dispatch witnessing the case live -- never a `*.test.js`/`*.spec.js` file, never a `test/` or `__tests__/` directory, never pulling in jest/mocha/vitest/pytest/unittest or any assertion/mocking library, and never a standing test file of any kind. Enumerating edge cases at PLAN is not license to author a suite for them at EXECUTE; see VERIFY's Adversarial corner-case sweep for how each class actually gets witnessed.
28
28
 
29
29
  Cut the cover hardest-node-first: the row exercising the most failure modes at once (concurrency + partial failure + real input, colliding) proves the design early, while re-cutting is still cheap -- schedule it last and you validate nothing until reshaping is too late.
30
30
 
@@ -38,7 +38,6 @@ Unknowns -> `.gm/mutables.yml` via `mutable-add`, `status: unknown`, witness = `
38
38
 
39
39
  ## Constraints
40
40
 
41
- Gauge every design/code decision against `.gm/constraints.md` (create from bundled default if absent) -- the standing decision-arbiter, checked at every phase.
42
41
 
43
42
  ## Dispatch
44
43
 
@@ -33,11 +33,11 @@ VERIFY is adversarial, never confirmatory: hunt every way EMIT's write breaks, v
33
33
 
34
34
  Each class exercised = exec_js/browser dispatch + witness (pass or fix-then-rewitness), same turn, before `transition`. A happy-path-only VERIFY has not verified.
35
35
 
36
- ## Integration witness
36
+ ## Real-execution witness
37
37
 
38
- `test.js` at root, 200-line ceiling, real services only (mock-free) -- the single witness IS the test surface, proving a full real session end-to-end. Not one gate beside a conventional unit suite: a growing mock-heavy multi-file `test/` is the pattern gm replaces, never a coexisting exemption; the cap does not bless a parallel suite. More than the single real-services witness needs justifying, never default. Pass = integration witness; fail -> `transition` back to EXECUTE. `recursive` classifier = incomplete cover -- snake back, do not narrate past signal.
38
+ Every claim of correctness is proven by a live `exec_js`/`browser` dispatch witnessing the real output, same turn, real services only (mock-free) -- manual troubleshooting and debugging is the entire verification surface, never a standing test file or suite. Pass = the live witness matches expectation; fail -> `transition` back to EXECUTE. `recursive` classifier = incomplete cover -- snake back, do not narrate past signal.
39
39
 
40
- **No unit tests, no exceptions.** A `deviation.synthetic-test-file` at VERIFY (new `*.test.*`/`*.spec.*`, a `test/`/`__tests__/` directory, or a testing-framework import found in the diff) blocks `transition` exactly like an unwitnessed mutable -- fold its assertions into `test.js` or replace them with a live `exec_js`/`browser` witness, then re-verify. This is manual legwork, not framework legwork: the adversarial corner-case sweep above is how every class gets exercised, by running the real thing, never by writing a test case that runs it later.
40
+ **No test files, no exceptions.** A `deviation.synthetic-test-file` at VERIFY (new `*.test.*`/`*.spec.*`, a `test/`/`__tests__/` directory, a testing-framework import, or any standing root-level test file found in the diff) blocks `transition` exactly like an unwitnessed mutable -- delete it and replace its assertions with a live `exec_js`/`browser` witness, then re-verify. This is manual legwork, not framework legwork: the adversarial corner-case sweep above is how every class gets exercised, by running the real thing, never by writing a test case that runs it later.
41
41
 
42
42
  ## Residual-scan
43
43
 
@@ -75,7 +75,6 @@ rs-learn never calls a model; it emits the need, you supply the answer. Skipping
75
75
 
76
76
  ## Constraints
77
77
 
78
- Gauge every design/code decision against `.gm/constraints.md` (create from bundled default if absent) -- the standing decision-arbiter, checked at every phase.
79
78
 
80
79
  ## Dispatch
81
80
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gm-plugkit",
3
- "version": "2.0.1799",
3
+ "version": "2.0.1818",
4
4
  "description": "Bootstrap and daemon-spawn tool for gm plugkit binary. Downloads the correct platform binary, verifies SHA256, and starts the spool watcher daemon. Includes plugkit-wasm-wrapper for WASM-based spool watching.",
5
5
  "main": "index.js",
6
6
  "bin": {
package/plugkit.version CHANGED
@@ -1 +1 @@
1
- 0.1.823
1
+ 0.1.832