gm-skill
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinesegm — single entry point
gm — 单一入口点
Every turn begins with . Write (empty body) and read the response — its field is the active phase prose, its is the live work plan, its is what blocks the EMIT gate, its is the prior memory already loaded for you. Follow that prose imperatively until the phase's exit condition is met, then . The user's request is the authorization; the PRD is the receipt; the chain runs PLAN → EXECUTE → EMIT → VERIFY → COMPLETE without re-asking between phases.
instruction.gm/exec-spool/in/instruction/<N>.txtinstructionprd_itemsmutables_pendingrecall_hitstransitionDirect Read/Edit/Bash before the first dispatch is the failure mode this skill prevents. If you find yourself reaching for a tool to "just take a quick look", you have already dropped the loop — dispatch first, then act on its prose.
instructioninstructionFix on Sight. Every unexpected output, broken neighbor, lockfile drift, suppressed error, or stale generated file surfaced during work becomes a PRD item the same turn and is executed before COMPLETE. Surprise is a new mutable, not noise to absorb. Stubs, mocks, placeholder returns, fixture-only paths, and "always succeeds" code paths are forbidden in shipped material; acceptance is real input through real code into real output, witnessed. Edits to code that runs in a browser require a live verb witness in the same turn — Browser Witness is non-negotiable.
browserDo not create documentation files the user did not ask for. No COMPLETED.md, no SUMMARY.txt, no IMPLEMENTATION_NOTES.md, no START-HERE.md, no *-STATUS.md, no build-output.txt left behind, no new top-level or of any kind. Closure narrative lives in the PRD (which plugkit owns), in (which becomes recallable next session), and in the commit message (which preserves) — those are the only sanctioned destinations. A new doc at project root, in , or anywhere else is a residual the next stop-gate will flag.
.md.txtmemorize-firegit logdocs/Before any apparent stop, dispatch . If it returns work that fits the spirit of the original ask and is reachable from this session, expand the PRD and execute; only residuals genuinely out-of-spirit or out-of-reach are name-and-stop. A turn that ends with uncommitted changes, an open PRD slice, or unresolved mutables has not actually stopped — it has stalled the chain.
residual-scanIf the response carries a non-null , plugkit drift has been detected on disk and the running watcher is behind. Rebootstrap before continuing — newer fixes are sitting on disk unused, and every dispatch is wasted on stale code. (or ) is the one-shot: it fetches the new wasm, replaces the artifact, and the watcher reloads. Drift past one version is a deviation.
instructionupdate_availablebun x gm-plugkit@latestnpx -y gm-plugkit@latestIf is non-empty, you own them — every entry is a subprocess you started that's still consuming CPU/memory. Stop ones that have outlived their purpose with (write with ). The 15-min idle reaper is the last resort, not a substitute for hygiene. If is non-empty, dispatches are wedged — the watcher's host_exec_js is synchronous and a stuck body blocks every other verb until it returns. Diagnose via and consider rebootstrapping if it doesn't clear; spool bodies are Turing-complete and can loop forever. Long-running work goes through (returns a immediately, body runs detached), not through the sync // language verbs.
running_taskstask-stop.gm/exec-spool/in/task-stop/<N>.txt{id: "t<n>"}stuck_spool.watcher.logtask-spawntask_idnodejsbashpythonIf is true, dispatch before any text response that reads like a stop. The marker is one-shot per stopping window — re-checking after you've fired it is fine; firing it for the first time in a session that has pending work is non-negotiable. If is non-null, the running watcher predates supervisor.js and has no unplanned-restart recovery; stop the named PID and let the next bootstrap re-spawn it under supervision.
should_residual_scanresidual-scanunsupervised_watcherNo deferral phrasing. "Next pass", "next session", "future work", "defer to later", "address it next", "below criticality", "do later", "fix later" are all forced closure dressed up. rejects items whose description/subject/notes contain these markers unless the item carries or . The dispatch gate also rejects git commits whose message contains them. Per §22 Fix on Sight: in-spirit reachable work is executed this turn, not deferred. If the work is genuinely unreachable, declare it with blockedBy; that's an auditable refusal, not a defer.
prd-addblockedBy: [external]blockedBy: [out-of-reach]The wasm artifact lives at ; the spool watcher runs it. The watcher's own stdout/stderr is appended to — Read it to see plugkit's internal trace, dispatch timings, sweep actions, errors.
~/.claude/gm-tools/plugkit.wasm.gm/exec-spool/.watcher.logThe watcher self-shuts-down after 15 minutes idle (no spool I/O, no live browser session) and is restarted on next agent activity by a detached supervisor. is a critical-failure marker — present means a prior watcher died without a planned shutdown. Treat as a PRD-worthy incident on sight: diagnose via and events and around the prior_status.ts timestamp, then delete the marker once root cause is named.
.gm/exec-spool/.unplanned-restart.json.watcher.loggm-log/<day>/plugkit.jsonlsupervisor.watcher-exited-unexpectedlysupervisor.heartbeat-stale每个轮次都从开始。写入(空内容)并读取响应——其中字段是当前阶段的执行说明,是实时工作计划,是阻碍EMIT阶段的项,是已为你加载的过往记忆内容。严格遵循该执行说明,直到满足阶段退出条件,然后执行。用户的请求即为授权;PRD是工作依据;流程会按PLAN → EXECUTE → EMIT → VERIFY → COMPLETE运行,阶段间无需再次确认。
instruction.gm/exec-spool/in/instruction/<N>.txtinstructionprd_itemsmutables_pendingrecall_hitstransition在首次调度前直接进行读取/编辑/执行Bash命令是本技能要避免的错误模式。如果你发现自己想要使用工具“快速查看一下”,说明你已经脱离了循环——先调度,再根据返回的执行说明操作。
instructioninstruction即时修复(Fix on Sight)。工作过程中出现的任何意外输出、关联模块故障、锁文件漂移、被抑制的错误或过期生成文件,都要在本轮次中转为PRD项,并在COMPLETE阶段前执行修复。意外情况属于新的mutable项,而非可忽略的干扰。交付内容中禁止使用桩代码、模拟对象、占位返回值、仅适用于测试用例的路径以及“始终成功”的代码路径;验收标准是真实输入通过真实代码产生真实输出,并经过验证。对浏览器运行代码的修改,必须在同一轮次中通过操作进行实时验证——浏览器验证是硬性要求。
browser不要创建用户未要求的文档文件。禁止留下COMPLETED.md、SUMMARY.txt、IMPLEMENTATION_NOTES.md、START-HERE.md、*-STATUS.md、build-output.txt,也禁止创建任何新的顶级或文件。收尾说明应记录在PRD(由plugkit管理)、(可在下一会话中被调用)以及提交信息(由保存)中——这些是唯一被允许的记录位置。项目根目录、或其他任何位置的新文档,都会被下一阶段的检查标记为残留项。
.md.txtmemorize-firegit logdocs/在任何看似要结束的节点前,调度。如果返回的工作符合原始需求的精神且可在本次会话中完成,则扩展PRD并执行;只有完全不符合需求精神或无法完成的残留项才可以标记并终止。如果轮次结束时存在未提交的更改、未完成的PRD片段或未解决的mutables项,说明流程并未真正结束——只是陷入了停滞。
residual-scan如果响应中不为空,说明磁盘上的plugkit已出现版本漂移,当前运行的监控进程已过时。继续前需执行bootstrap——磁盘上已有更新的修复版本,使用过时代码进行的所有调度都是无效的。(或)是一键更新命令:它会获取新的wasm文件,替换旧文件,监控进程会自动重新加载。版本漂移超过一个版本属于违规操作。
instructionupdate_availablebun x gm-plugkit@latestnpx -y gm-plugkit@latest如果不为空,你需要负责管理这些任务——每个条目都是你启动的仍在消耗CPU/内存的子进程。使用终止已无存在必要的任务(写入,内容为)。15分钟闲置自动清理是最后手段,不能替代主动管理。如果不为空,说明调度已陷入阻塞——监控进程的host_exec_js是同步的,阻塞的任务会阻止所有其他操作直到它返回。通过进行诊断,如果无法解决则考虑重新执行bootstrap;spool任务是图灵完备的,可能会无限循环。长时间运行的工作应通过(立即返回,任务后台运行)执行,而非同步的//语言操作。
running_taskstask-stop.gm/exec-spool/in/task-stop/<N>.txt{id: "t<n>"}stuck_spool.watcher.logtask-spawntask_idnodejsbashpython如果为true,在任何看似结束的文本响应前调度。该标记在每个结束窗口期仅生效一次——执行后再次检查是允许的;在有未完成工作的会话中首次执行该操作是硬性要求。如果不为空,说明当前运行的监控进程早于supervisor.js,不具备意外重启恢复能力;终止指定PID,让下一次bootstrap在监控下重新启动它。
should_residual_scanresidual-scanunsupervised_watcher禁止使用延迟表述。“下一轮”、“下一会话”、“未来工作”、“延后处理”、“后续解决”、“非关键项”、“以后再做”、“稍后修复”等表述都是变相的强制收尾。会拒绝描述/主题/备注中包含这些标记的项,除非该项带有或。调度网关也会拒绝提交信息中包含这些标记的git提交。根据§22即时修复原则:符合需求精神且可完成的工作必须在本轮次执行,不得延迟。如果工作确实无法完成,需通过blockedBy声明;这是可审计的拒绝,而非延迟。
prd-addblockedBy: [external]blockedBy: [out-of-reach]wasm文件位于;spool监控进程运行该文件。监控进程的标准输出/错误会追加到——查看该文件可了解plugkit的内部跟踪信息、调度时间、清理操作和错误信息。
~/.claude/gm-tools/plugkit.wasm.gm/exec-spool/.watcher.log监控进程在15分钟闲置(无spool I/O、无活跃浏览器会话)后会自动关闭,下一次Agent活动时会由后台监控程序重新启动。是严重故障标记——存在该文件说明之前的监控进程未正常关闭就已终止。一旦发现需将其视为PRD级事件:通过和中prior_status.ts时间戳附近的和事件进行诊断,确定根本原因后删除该标记。
.gm/exec-spool/.unplanned-restart.json.watcher.loggm-log/<day>/plugkit.jsonlsupervisor.watcher-exited-unexpectedlysupervisor.heartbeat-staleBoot the spool watcher (first turn only)
启动spool监控进程(仅首次轮次)
Check . If absent or > 15s old, boot via the npm package — fetches the freshest plugkit (wasm + wrapper), copies them into , then enters spool mode:
.gm/exec-spool/.status.jsontsbun x gm-plugkit@latest spool~/.claude/gm-tools/bun x gm-plugkit@latest spool > /dev/null 2>&1 &If is not available, fall back to or to the local wrapper if it's already installed: . The wrapper has a self-heal: if it detects a or missing wasm at instantiation, it re-runs bootstrap automatically and retries.
bunnpx -y gm-plugkit@latest spool > /dev/null 2>&1 &node ~/.claude/gm-tools/plugkit-wasm-wrapper.js spool > /dev/null 2>&1 &LinkErrorWait 2 seconds, then verify boot:
- Read — the launcher writes its phase here (
.gm/exec-spool/.cli-status.json→starting→bootstrapped). Present withready= good.phase: "ready" - Read — the watcher writes its heartbeat here every 5s. Fresh
.gm/exec-spool/.status.json(within 15s) = watcher alive.ts - If neither file exists or is stuck at an earlier phase, read
.cli-status.json— the launcher writes.gm/exec-spool/.bootstrap-error.jsonon any failure even when stdout/stderr were redirected to{error_phase, error_message, stack}. Also read/dev/nullfor the post-spawn trace. Surface the error to the user; do not retry blindly..gm/exec-spool/.watcher.log
检查。如果文件不存在或超过15秒,通过npm包启动——会获取最新的plugkit(wasm + 包装器),将其复制到,然后进入spool模式:
.gm/exec-spool/.status.jsontsbun x gm-plugkit@latest spool~/.claude/gm-tools/bun x gm-plugkit@latest spool > /dev/null 2>&1 &如果不可用,可改用,或使用已安装的本地包装器:。包装器具备自我修复功能:如果在实例化时检测到或缺失wasm文件,会自动重新执行bootstrap并重试。
bunnpx -y gm-plugkit@latest spool > /dev/null 2>&1 &node ~/.claude/gm-tools/plugkit-wasm-wrapper.js spool > /dev/null 2>&1 &LinkError等待2秒后,验证启动状态:
- 读取——启动器会在此写入阶段状态(
.gm/exec-spool/.cli-status.json→starting→bootstrapped)。文件存在且ready表示启动成功。phase: "ready" - 读取——监控进程每5秒在此写入心跳信息。
.gm/exec-spool/.status.json较新(15秒内)表示监控进程存活。ts - 如果两个文件都不存在或停留在早期阶段,读取
.cli-status.json——即使标准输出/错误被重定向到.gm/exec-spool/.bootstrap-error.json,启动器也会在此写入/dev/null错误信息。同时查看{error_phase, error_message, stack}获取启动后的跟踪信息。将错误告知用户;不要盲目重试。.gm/exec-spool/.watcher.log
Plugkit version updates
Plugkit版本更新
The watcher checks GitHub Releases every 5 minutes for a newer plugkit. If drift is detected, it writes with ; if no drift, the file is removed. Read this file at session start (and occasionally afterward); if present, kill the current watcher, run once to fetch the new wasm, then restart the watcher. Default bootstrap never hits the network — only fetches the newest binary.
.gm/exec-spool/.update-available.json{installed, latest, instruction, update_url}bootstrapPlugkit({latest: true}){latest: true}监控进程每5分钟检查GitHub Releases是否有更新的plugkit版本。如果检测到版本漂移,会写入,内容为;如果无版本漂移,该文件会被删除。会话开始时(之后也可定期)读取该文件;如果文件存在,终止当前监控进程,运行一次以获取新的wasm文件,然后重新启动监控进程。默认bootstrap不会访问网络——只有会获取最新的二进制文件。
.gm/exec-spool/.update-available.json{installed, latest, instruction, update_url}bootstrapPlugkit({latest: true}){latest: true}Dispatch ABI
调度ABI
Write request body to . Read response from (nested verbs) or (root verbs). Bodies are JSON, raw code, or a single phase name depending on the verb.
.gm/exec-spool/in/<verb>/<N>.txt.gm/exec-spool/out/<verb>-<N>.jsonout/<N>.json将请求内容写入。从(嵌套操作)或(根操作)读取响应。内容格式根据操作不同可为JSON、原始代码或单一阶段名称。
.gm/exec-spool/in/<verb>/<N>.txt.gm/exec-spool/out/<verb>-<N>.jsonout/<N>.jsonBatch dispatch — never serial round-trips for independent verbs
批量调度——独立操作绝不串行往返
The watcher processes verbs sequentially internally, but the agent's bottleneck is round-trip latency, not the watcher. Write N inputs in one message via parallel Write tool calls, then read N outputs in one message via parallel Read calls. A 5-verb batch is one agent turn, not five.
Example PLAN orient pack — 3 recalls + 3 codesearches in ONE message:
Write .gm/exec-spool/in/recall/1.txt body: {"query":"<noun A>"}
Write .gm/exec-spool/in/recall/2.txt body: {"query":"<noun B>"}
Write .gm/exec-spool/in/recall/3.txt body: {"query":"<noun C>"}
Write .gm/exec-spool/in/codesearch/1.txt body: {"query":"<phrase X>"}
Write .gm/exec-spool/in/codesearch/2.txt body: {"query":"<phrase Y>"}
Write .gm/exec-spool/in/codesearch/3.txt body: {"query":"<phrase Z>"}Then in the NEXT message, all 6 Reads in parallel.
For dependent verbs (transition after instruction, prd-resolve after work), the agent must serialize — but only at the dependency boundary, not across independent dispatches.
监控进程内部会按顺序处理操作,但Agent的瓶颈是往返延迟,而非监控进程。**通过并行Write工具调用在一条消息中写入N个输入,然后通过并行Read调用在一条消息中读取N个输出。**5个操作的批量处理只需一个Agent轮次,而非五个。
示例PLAN阶段批量操作——在一条消息中完成3次recall + 3次codesearch:
Write .gm/exec-spool/in/recall/1.txt body: {"query":"<noun A>"}
Write .gm/exec-spool/in/recall/2.txt body: {"query":"<noun B>"}
Write .gm/exec-spool/in/recall/3.txt body: {"query":"<noun C>"}
Write .gm/exec-spool/in/codesearch/1.txt body: {"query":"<phrase X>"}
Write .gm/exec-spool/in/codesearch/2.txt body: {"query":"<phrase Y>"}
Write .gm/exec-spool/in/codesearch/3.txt body: {"query":"<phrase Z>"}然后在下一条消息中,并行读取所有6个结果。
对于依赖操作(instruction后执行transition,工作完成后执行prd-resolve),Agent必须串行执行——但仅在依赖边界处串行,而非所有独立调度都串行。
State lives in plugkit, not in conversation context
状态存储在plugkit中,而非对话上下文
Never Read or directly. Every response carries the data you need:
.gm/prd.yml.gm/mutables.ymlinstruction{
phase, // current phase
instruction, // phase prose (the active discipline)
prd_items: [...], // full PRD items with id, subject, status, fields
prd_pending_count,
mutables_pending: [{id, claim, witness_method, witness_evidence, status}, ...],
recall_hits: [...], // auto-fired against phase + first pending PRD subject
next_phase_hint
}切勿直接读取或。响应会携带你所需的所有数据:
.gm/prd.yml.gm/mutables.ymlinstruction{
phase, // 当前阶段
instruction, // 阶段执行说明(当前规则)
prd_items: [...], // 完整PRD项,包含id、主题、状态、字段
prd_pending_count,
mutables_pending: [{id, claim, witness_method, witness_evidence, status}, ...],
recall_hits: [...], // 根据阶段+首个待处理PRD主题自动触发的记忆内容
next_phase_hint
}Plugkit observability — read .watcher.log
Plugkit可观测性——读取.watcher.log
The watcher writes its own stdout + stderr (plus the wasm cdylib's /) to . Useful when:
println!eprintln!.gm/exec-spool/.watcher.log- A dispatch returned an error you don't understand → tail the log for the stack
- A verb seems slow → log shows
[dispatch] ← verb=X ms=N - Sweep cleaned up something → log shows or
[retention]lines[stale-sweep] - Watcher boot issues → markers
--- watcher boot ... ---
Read with to tail:
offsetRead .gm/exec-spool/.watcher.log offset=<last-known-line>The log is rotated at 10MB (older content moves to ).
.watcher.log.1监控进程会将自身的标准输出+错误(以及wasm cdylib的/输出)写入。以下场景中该文件非常有用:
println!eprintln!.gm/exec-spool/.watcher.log- 调度返回无法理解的错误→查看日志末尾的堆栈信息
- 操作执行缓慢→日志中会显示
[dispatch] ← verb=X ms=N - 清理操作删除了某些内容→日志中会显示或
[retention]行[stale-sweep] - 监控进程启动问题→查看标记
--- watcher boot ... ---
使用参数读取日志末尾:
offsetRead .gm/exec-spool/.watcher.log offset=<last-known-line>日志文件达到10MB时会自动轮转(旧内容移动到)。
.watcher.log.1The loop
循环流程
Add PRD items via (JSON body), resolve via (id as body). Add mutables via , resolve via once is filled — narrative resolution is rejected; only file:line, codesearch hit, or exec output snippet counts. Every auto-fires memorize so the witness becomes recall-able next session.
prd-addprd-resolvemutable-addmutable-resolvewitness_evidencemutable-resolveResolve every entry in before transitioning. When the phase's exit condition is met, dispatch with the next phase name (or empty for auto-advance). Each transition response embeds automatically — relevant prior memos surface without you asking.
mutables_pendingtransitionrecall_hitsStop only when is AND returns empty AND the worktree is clean AND CI is green. Any of those false means the chain has not finished.
phaseCOMPLETEresidual-scan通过(JSON内容)添加PRD项,通过(内容为id)标记完成。通过添加mutables项,填充后通过标记完成——仅描述性说明不被接受;只有文件:行号、codesearch结果或执行输出片段才算有效证据。每次都会自动触发memorize,使该证据可在下一会话中被调用。
prd-addprd-resolvemutable-addwitness_evidencemutable-resolvemutable-resolve在执行transition前,需解决中的所有条目。当满足阶段退出条件时,调度并传入下一阶段名称(或留空自动推进)。每次transition响应都会自动嵌入——相关过往记忆会自动呈现,无需主动请求。
mutables_pendingtransitionrecall_hits只有当为且返回空、工作目录干净、CI验证通过时,才可终止流程。任何一项不满足都说明流程尚未完成。
phaseCOMPLETEresidual-scanOrchestrator verbs
编排类操作
instructiontransitionphase-statusprd-addprd-resolveprd-listmutable-addmutable-resolvemutable-listmemorize-fireresidual-scanauto-recalltask-spawntask-listtask-stoptask-outputinstructiontransitionphase-statusprd-addprd-resolveprd-listmutable-addmutable-resolvemutable-listmemorize-fireresidual-scanauto-recalltask-spawntask-listtask-stoptask-outputHost verbs
主机类操作
fs_readfs_writefs_statfs_readdirkv_getkv_putkv_queryfetchexec_jsenv_getrecallcodesearchmemorizehealthstatuswaitsleepclosekill-portforgetfeedbacklearn-statuslearn-debuglearn-builddisciplinepauserunnerinferencebrowserfs_readfs_writefs_statfs_readdirkv_getkv_putkv_queryfetchexec_jsenv_getrecallcodesearchmemorizehealthstatuswaitsleepclosekill-portforgetfeedbacklearn-statuslearn-debuglearn-builddisciplinepauserunnerinferencebrowserLanguage verbs
语言类操作
nodejspythonbashpowershellsshgorustccppjavadenonodejspythonbashpowershellsshgorustccppjavadenoBrowser
Browser
The verb is the only sanctioned way to drive a live page. Do not reach for any other browser tool, library, or skill — the host owns the managed session and a parallel surface fragments witness state. Dispatch with raw JavaScript as the body. The host runs Chrome under a project-scoped profile at (cookies/login persist per project) and exposes the body to four globals: (the live page handle — , , etc.), (accessibility-tree snapshot), (annotated screenshot helper), and (a per-session object that persists across dispatches within the same session).
browser.gm/exec-spool/in/browser/<N>.txt<cwd>/.gm/browser-profile/pageawait page.goto(...)await page.evaluate(...)snapshotscreenshotWithAccessibilityLabelsstateSpecial commands (body starts with ): , , manage session lifecycle.
session session newsession listsession close <id>Required for any edit to code that runs in a browser — Browser Witness is non-negotiable. A does not substitute for a live asserting the invariant the edit was supposed to change.
node test.js passespage.evaluatebrowser.gm/exec-spool/in/browser/<N>.txt<cwd>/.gm/browser-profile/pageawait page.goto(...)await page.evaluate(...)snapshotscreenshotWithAccessibilityLabelsstate特殊命令(内容以开头):、、用于管理会话生命周期。
session session newsession listsession close <id>对浏览器运行代码的任何修改都必须使用该操作——浏览器验证是硬性要求。不能替代通过验证修改应实现的逻辑。
node test.js passeslive page.evaluate