gm-plugkit 2.0.2186 → 2.0.2188

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.
@@ -0,0 +1,147 @@
1
+ ---
2
+ name: fifth-dimension-engine
3
+ description: WFGY 5.0's core problem-solving tool. Lifts targets into higher problem-coordinates and returns structured routes (proof paths, strategy kernels, research structures, repair paths, positioning routes). Theorem work to everyday decisions. Use after Goal Compiler to execute the compiled problem specification.
4
+ license: MIT
5
+ compatibility: Portable "shoot + [problem]" command; works wherever an assistant can run a natural-language prompt. Upstream ships it as the current main product surface of WFGY 5.0 Polaris Protocol.
6
+ metadata:
7
+ origin: onestardao-wfgy-5.0-polaris-protocol
8
+ provenance: adapted-and-honest-reimplementation-not-verbatim
9
+ ---
10
+
11
+ # Fifth-Dimension Engine
12
+
13
+ WFGY 5.0's core problem-solving tool. Lifts a target into a higher problem-coordinate, then returns a route that can be inspected, attacked, expanded, and tested.
14
+
15
+ **Before you decide, shoot first.**
16
+
17
+ ## What This Is
18
+
19
+ The Fifth-Dimension Engine does not just answer. It transforms a target into a route.
20
+
21
+ | Input | Engine Action |
22
+ |---|---|
23
+ | Theorem | Produces proof-route structure |
24
+ | Frontier problem | Produces research kernel |
25
+ | Strange theme | Produces mathematical skeleton |
26
+ | Life decision | Produces route map |
27
+ | Product idea | Produces positioning route |
28
+ | Engineering failure | Produces repair path |
29
+ | Meme or absurd target | Produces hidden structure |
30
+
31
+ The output is not a direct answer. It is a **route**: an inspectable, attackable, expandable structure you can verify, challenge, and refine.
32
+
33
+ ## When to Use
34
+
35
+ Use this skill when you have:
36
+ - A well-specified problem (use Goal Compiler first if unclear)
37
+ - A target worth spending time on (trivial problems don't need shooting)
38
+ - An appetite for structured reasoning (prefer depth over speed)
39
+
40
+ Use **especially** for:
41
+ - Theorem work (formal proofs, mathematical problems)
42
+ - Strategic decisions (career, startup, major choices)
43
+ - Research questions (turning ideas into research kernels)
44
+ - Engineering failures (root cause analysis, repair paths)
45
+ - Product/positioning work (audience, launch strategy)
46
+ - Mixed-theme problems (combining unrelated ideas into research)
47
+
48
+ ## How to Use
49
+
50
+ ### Basic Command
51
+
52
+ ```
53
+ shoot + [your problem]
54
+ ```
55
+
56
+ ### The Engine Returns
57
+
58
+ A structured route containing:
59
+
60
+ - **Route**: The core strategy or path forward
61
+ - **Structure**: Decomposition into sub-problems
62
+ - **Candidate Lemmas**: Supporting proofs, insights, or evidence
63
+ - **Objections**: What could go wrong, counterarguments
64
+ - **Open Debt**: What remains unresolved
65
+ - **Next Command**: What to do next (for theorem work: a new Lean line; for other work: next investigative step)
66
+
67
+ ### Why This Matters
68
+
69
+ Instead of:
70
+ - A flat answer (right or wrong, you can't inspect it)
71
+
72
+ You get:
73
+ - A *structure* you can examine
74
+ - Sub-claims you can verify independently
75
+ - Attack surfaces (where to challenge it)
76
+ - Expansion points (where to dig deeper)
77
+ - Clear open questions (what's not yet resolved)
78
+
79
+ ## Interaction with Other Skills
80
+
81
+ ### With Polaris Goal Compiler
82
+
83
+ - **Goal Compiler** specifies and atomizes the problem
84
+ - **Fifth-Dimension Engine** produces the route
85
+ - **Goal Compiler's verification gates** validate the engine's output
86
+
87
+ **Integration**: After Goal Compiler breaks work into atoms, use the engine on each atom that requires structured reasoning.
88
+
89
+ **Workflow**:
90
+ 1. Goal Compiler compiles the problem into task atoms
91
+ 2. For each atom, ask: "Do I need to shoot this, or is it routine?"
92
+ 3. If routine: execute directly
93
+ 4. If complex: shoot it with Fifth-Dimension Engine
94
+ 5. Use Goal Compiler's verification gate to check the output
95
+ 6. Move to next atom
96
+
97
+ ### With WFGY-Method (Drift Control)
98
+
99
+ - **Fifth-Dimension Engine** produces structured reasoning
100
+ - **WFGY-Method** keeps that reasoning aligned with the original goal
101
+
102
+ **Integration**: While the engine explores the route, WFGY-Method checks: "Are we still solving the original problem, or have we drifted into a different one?"
103
+
104
+ Use the engine for *depth*, WFGY-Method for *direction*.
105
+
106
+ ## Modes
107
+
108
+ ### Theorem and Formal Work
109
+
110
+ Shoot a theorem or formal problem; the engine returns a proof-route structure that can be checked against a formal verification standard.
111
+
112
+ ### Mixing Themes
113
+
114
+ Give the engine two unrelated themes and let it find the mathematical skeleton underneath them:
115
+
116
+ ```
117
+ shoot + [theme 1] + [theme 2]
118
+ ```
119
+
120
+ See `references/research-kernel-extraction.md` for how mixed themes become research kernels.
121
+
122
+ ### Everyday Problems
123
+
124
+ The same engine works on ordinary decisions, work problems, product questions, and engineering failures -- any well-specified target benefits from being shot into a route rather than answered directly.
125
+
126
+ ## Verification
127
+
128
+ The engine output is inspectable, which means verifiable. See `references/route-inspection-guide.md` for how to inspect, attack, and verify a route.
129
+
130
+ **This is not:** a black box. You can (and should) inspect, attack, and refine.
131
+
132
+ ## What This Is Not
133
+
134
+ This skill does not:
135
+ - Specify the problem (that's Goal Compiler)
136
+ - Control drift during execution (that's WFGY-Method)
137
+ - Produce a final answer (it produces a route, which you then verify and decide on)
138
+ - Guarantee the route is correct (inspection and verification are your job)
139
+ - Claim every shoot becomes a final theorem (a shoot creates a structured route; final proof, empirical truth, or real-world correctness depends on verification, review, formalization, or testing)
140
+
141
+ ## References
142
+
143
+ See `references/` directory for:
144
+ - `route-structure.md` -- what a route is and how it is structured
145
+ - `research-kernel-extraction.md` -- turning ideas into research kernels
146
+ - `route-inspection-guide.md` -- how to verify and attack a route
147
+ - `skills/polaris-protocol/SKILL.md` -- the Polaris Protocol tree root and state machine
@@ -0,0 +1,34 @@
1
+ ---
2
+ name: gm-continue
3
+ description: The mandatory final handoff after a gm walk reaches phase=COMPLETE with prd_pending_count=0. Never end a gm session with prose alone -- dispatch this skill instead. It searches for genuinely remaining work and reloads gm if any exists; if gm already ran a full walk without resolving everything, it loads wfgy-method instead to apply bounded-retry-then-surface discipline before any further gm re-entry. Use immediately after any gm chain reaches its terminal state, never as a substitute for gm itself.
4
+ allowed-tools: Skill, Read, Write, Bash(bun *), Bash(npx *)
5
+ ---
6
+
7
+ # gm-continue
8
+
9
+ This is the only allowed next step when a `gm` walk reaches `phase=COMPLETE AND prd_pending_count=0`. Never end that turn with prose alone -- dispatch this skill instead, every time, no exceptions for "it looks finished."
10
+
11
+ **This skill itself has exactly two allowed ways to end, and no others.** (1) Dispatch `Skill(skill="gm")` with the remaining PRD rows (found reachable work, or reopened an `external`/`out-of-reach` row, or this is the first confirming pass this session) -- `gm` then runs and, when it reaches COMPLETE again, calls back into this same skill. (2) Confirm there are no remaining PRD rows and none can be added -- a real, witnessed check (steps 2-4 below actually run, not assumed), not a feeling of "probably done." There is no third path: no prose-only stop that isn't outcome (2), no deferring to the user to decide whether to continue, no partial confirmation. Every dispatch of this skill lands in exactly one of these two states before the turn ends.
12
+
13
+ ## What this skill does
14
+
15
+ 1. Read `.gm/exec-spool/.turn-summary.json` for the current `phase`, `prd_pending`, and how many times this repo has already round-tripped through `gm-continue` this session (track via a counter file, see below).
16
+ 2. Read `.gm/prd.yml` and `.gm/mutables.yml` directly for any row marked `blockedBy: [external]`/`[out-of-reach]` or otherwise deferred. **A prior `external`/`out-of-reach` marking is not a closed door -- it is remaining work by definition.** Re-examine each one now: is the blocker still genuinely unreachable this turn, or was it marked that way under time/scope pressure when it was actually solvable? Anything reachable now goes back into scope, re-`prd-add`'d (re-scope the existing id, never delete-and-re-add) as work to actually solve, not left marked external.
17
+ 3. Fan out `codesearch` + `recall` against the ORIGINAL request's full closure, not against memory of what was already done -- a fresh look, same discipline as `gm`'s own PLAN orient.
18
+ 4. If `.gm/prd.yml` has ANY items at all (pending, or reopened `external` rows from step 2), that alone is remaining work -- skip straight to the dispatch below, no further search needed.
19
+ 5. Two outcomes, decided by what steps 2-4 actually find:
20
+ - **Real remaining work found** (any PRD item at all, a reopened external/out-of-reach row, an unaddressed noun from the request, an edge case never exercised, a residual never triaged, a sibling repo never checked): dispatch `Skill(skill="gm")` and instruct it explicitly to finish ALL remaining tasks in `.gm/prd.yml` and fix any issues that arise while doing so -- not a narrow slice, not "just the reopened ones." Tell it plainly what was found so it lands directly in PLAN with real rows, not a blind re-orient.
21
+ - **Nothing found, but this is the first `gm-continue` dispatch this session**: dispatch `Skill(skill="gm")` anyway, once, to let a full independent PLAN pass confirm it from inside `gm`'s own discipline (fresh `codesearch`/`recall`, `prd_pending_count=0` reached with nothing new added). That confirming turn inside `gm` is the actual stopping point -- prose-only is earned there, not here.
22
+ - **Nothing found, and `gm-continue` already ran that confirming pass this session** (counter >= 1): the loop is closed. Prose-only summary is authorized. Do not dispatch anything further.
23
+
24
+ ## When to load `wfgy-method` instead of `gm`
25
+
26
+ If a prior `gm` walk reached COMPLETE but the same class of gap keeps recurring across repeat `gm-continue` invocations (the confirming pass itself found new work more than once, or a stuck-loop-escalation was seen during the walk), dispatch `Skill(skill="wfgy-method")` instead of reloading `gm` directly. Apply its BBCR bounded-retry-then-surface discipline first -- checkpoint, name the unresolved tension, surface it plainly -- before any further `gm` re-entry. Reloading `gm` blind into a recurring gap repeats the same failure; `wfgy-method` exists to break that specific pattern.
27
+
28
+ ## Recursion bound
29
+
30
+ Track invocation count in `.gm/.gm-continue-count` (plain integer, reset by a fresh user prompt). This skill dispatches `gm` or `wfgy-method` at most twice per user turn before it is required to stop and report to the user directly: once to check, once more only if that check found real work and the subsequent `gm` walk needs its own confirming `gm-continue` pass. A third consecutive "nothing new, re-check again" cycle is itself the stuck-loop signal -- surface it, do not keep looping silently.
31
+
32
+ ## Never a substitute for `gm`
33
+
34
+ This skill does no PRD work, no EXECUTE, no EMIT, no VERIFY itself -- it only orients, decides, and hands off. All actual work happens inside `gm` (or `wfgy-method`'s recovery discipline), dispatched via `Skill`, never inlined here.
@@ -0,0 +1,158 @@
1
+ ---
2
+ name: polaris-goal-compiler
3
+ description: A human-AI communication protocol layer that compiles goals into task atoms, active/blocked work, verification gates, and claim ceilings before execution. Part of WFGY 5.0 Polaris Protocol. Use before complex AI work to make it inspectable, harder to fake, and less likely to collapse into premature completion.
4
+ license: MIT
5
+ compatibility: Upstream Polaris Goal Compiler is released ChatGPT-first (teaser compatibility is ChatGPT only); portability to other assistants, coding agents, and skill systems is a stated design direction, not an officially supported target in the teaser release. This skill is a portable Claude Code adaptation of that protocol.
6
+ metadata:
7
+ origin: onestardao-wfgy-5.0-polaris-protocol
8
+ provenance: adapted-and-honest-reimplementation-not-verbatim
9
+ ---
10
+
11
+ # Polaris Goal Compiler
12
+
13
+ A human-AI communication protocol under WFGY 5.0 Polaris Protocol.
14
+
15
+ **Compile first. Execute one active atom. Verify before unlock. Claim only what is supported.**
16
+
17
+ ## What This Is
18
+
19
+ Polaris Goal Compiler adds the missing protocol layer between human requests and AI execution. Before producing work that looks finished, it turns the request into visible, inspectable structures:
20
+
21
+ - **Task atoms**: The smallest executable units
22
+ - **Active work**: What can be done now
23
+ - **Blocked work**: What must wait
24
+ - **Verification gates**: What must be checked before unlock
25
+ - **Truth objects**: What is known vs. claimed
26
+ - **Claim ceilings**: What the assistant is allowed to claim
27
+ - **Closure records**: What is done, missing, partial, or unsafe
28
+
29
+ This is not a normal prompt template. It is a portable TXT-based execution protocol for making complex AI work:
30
+ - Easier to inspect
31
+ - Harder to fake
32
+ - Less likely to collapse into premature completion
33
+
34
+ ## When to Use
35
+
36
+ Use this skill **before** starting any of:
37
+ - Complex creative work (writing, design, research)
38
+ - Multi-step reasoning tasks (proofs, strategy, debugging)
39
+ - Long-horizon projects (planning, architecture, implementations)
40
+ - High-stakes decisions where correctness matters
41
+ - Work involving others (code review, collaboration)
42
+ - Theorem work or formal verification
43
+
44
+ **Do not use on**: trivial single-step tasks, reflex responses, simple lookups.
45
+
46
+ ## Core Workflow
47
+
48
+ ### 1. State Your Goal Clearly
49
+
50
+ Write one sentence: what do you actually want to accomplish? Not the first sub-task, the end state.
51
+
52
+ ### 2. Ask: Compile My Request
53
+
54
+ Ask the AI to turn your request into:
55
+ - Task atoms (smallest units)
56
+ - Dependencies (which blocks which)
57
+ - Active vs. blocked work
58
+ - Verification gates (checks before unlock)
59
+ - Claim ceilings (what can be claimed when)
60
+
61
+ ### 3. Review the Compilation
62
+
63
+ Before execution starts, verify:
64
+ - Are all task atoms actually atomic?
65
+ - Are dependencies correct?
66
+ - Are verification gates realistic?
67
+ - Will claim ceilings prevent overstatement?
68
+
69
+ ### 4. Execute One Active Atom
70
+
71
+ Work on ONE task at a time. After each:
72
+ - Verify before moving to the next
73
+ - Check against claim ceiling (don't overstate readiness)
74
+ - Move blocked tasks to active only if dependencies are met
75
+
76
+ ### 5. Iterate
77
+
78
+ After each atom completes, return to step 4 until all atoms are done.
79
+
80
+ ## Key Concepts
81
+
82
+ ### Task Atoms
83
+
84
+ The smallest executable unit that:
85
+ - Can be completed in one session
86
+ - Has clear entrance and exit criteria
87
+ - Produces something verifiable
88
+ - Does not depend on incomplete tasks
89
+
90
+ ### Active vs. Blocked Work
91
+
92
+ - **Active**: Ready to start, all dependencies met
93
+ - **Blocked**: Waiting on something else to finish first
94
+
95
+ Clear separation prevents fake progress (looking busy on wrong things).
96
+
97
+ ### Verification Gates
98
+
99
+ What must be checked *before* moving forward:
100
+ - Does this output match what was asked for?
101
+ - Is it complete enough for the next task?
102
+ - Are there hidden assumptions?
103
+ - What could break downstream?
104
+
105
+ ### Truth Objects
106
+
107
+ What must actually become true for the work to count as done, as opposed to prose that merely reads as if it were true. A verification gate passes against a truth object, not against a well-written paragraph.
108
+
109
+ ### Claim Ceilings
110
+
111
+ Honest limits on what can be claimed:
112
+ - "Complete" means verified to work end-to-end, not "looks finished"
113
+ - "Correct" means checked against requirements, not "sounds right"
114
+ - "Ready" means tested for the next stage, not "looks polished"
115
+
116
+ Over-claiming (saying something is done when it's only drafted) is the most common trap in AI work. See `references/claim-ceiling-examples.md` for concrete examples in different contexts.
117
+
118
+ ### Closure Records
119
+
120
+ For each atom, record what is done, what is missing, what is only partially true, and what is still unsafe to claim. A closure record preserves continuity across rounds so that unfinished work stays visible instead of being buried in prose -- this is what stops a local step from being promoted into fake global completion.
121
+
122
+ ## Interaction with Other Skills
123
+
124
+ ### With WFGY-Method (Drift Control)
125
+
126
+ - **Goal Compiler** structures the work (what to do)
127
+ - **WFGY-Method** keeps you on track (why you're doing it)
128
+
129
+ Use Goal Compiler first to atomize, then apply WFGY-Method while executing each atom.
130
+
131
+ **Integration**: Goal Compiler's "verification gate" becomes a checkpoint for WFGY-Method's BBCR (bounded retry).
132
+
133
+ ### With Fifth-Dimension Engine (Problem Solving)
134
+
135
+ - **Goal Compiler** specifies the problem clearly
136
+ - **Fifth-Dimension Engine** solves/structures it
137
+ - **Goal Compiler's verification gates** check the engine's output
138
+
139
+ Use Goal Compiler to compile the problem statement, then dispatch to Fifth-Dimension Engine.
140
+
141
+ **Integration**: Fifth-Dimension Engine's "route" output maps to Goal Compiler's task atoms and verification gates.
142
+
143
+ ## References
144
+
145
+ See `references/` directory for:
146
+ - `task-atomization.md` -- how to break work into atoms
147
+ - `verification-gates.md` -- designing verification for each stage
148
+ - `claim-ceiling-examples.md` -- what "complete" actually means in different contexts
149
+ - `skills/polaris-protocol/SKILL.md` -- the Polaris Protocol tree root and state machine that wires this skill to Fifth-Dimension Engine and WFGY-Method
150
+
151
+ ## What This Is Not
152
+
153
+ This skill does not:
154
+ - Solve the problem (that's Fifth-Dimension Engine)
155
+ - Control drift during execution (that's WFGY-Method)
156
+ - Replace thinking (it enhances it by making structure visible)
157
+ - Guarantee success (only guard against fake completion)
158
+ - Claim to be the full WFGY 5.0 system (it is one public protocol component; the upstream engine is the main product surface)
@@ -0,0 +1,95 @@
1
+ ---
2
+ name: polaris-protocol
3
+ description: WFGY 5.0 Polaris Protocol -- the active flagship route from onestardao/WFGY. A two-layer reasoning system that compiles goals before execution and shoots complex problems into inspectable routes, with drift control throughout. This skill is the tree root: load it first, then dispatch its child skills as explicit transitions -- polaris-goal-compiler (compile), fifth-dimension-engine (shoot), wfgy-method (drift control). Use for any complex, multi-step, high-stakes, or long-horizon task where premature completion or goal drift is a risk.
4
+ license: MIT
5
+ compatibility: Portable protocol; upstream released the Goal Compiler ChatGPT-first (teaser) and the Fifth-Dimension Engine as the main product surface. This skill wraps both plus WFGY-Method drift control into one discoverable entry point for any assistant or agent that loads skills.
6
+ metadata:
7
+ origin: onestardao-wfgy-5.0-polaris-protocol
8
+ provenance: adapted-and-honest-reimplementation-not-verbatim
9
+ ---
10
+
11
+ # WFGY 5.0 -- Polaris Protocol (tree root)
12
+
13
+ Polaris is the active public route of WFGY 5.0. The **Fifth-Dimension Engine** is the current main product surface; the **Polaris Goal Compiler** is the first public protocol component. **WFGY-Method** supplies the drift-control discipline that keeps the whole system aligned with the original goal.
14
+
15
+ This skill is the **tree root**. It does not re-explain the children -- it wires them into one state machine and tells you which child to dispatch at each step. Treat the three child skills as the transitions of the machine below.
16
+
17
+ ## The tree
18
+
19
+ ```
20
+ polaris-protocol (this skill -- root / entry)
21
+ |-- polaris-goal-compiler (COMPILE state)
22
+ |-- fifth-dimension-engine (SHOOT state)
23
+ `-- wfgy-method (DRIFT CONTROL -- applies at every state)
24
+ ```
25
+
26
+ Discoverable: each node is a standalone `SKILL.md` inside its own `skills/<skill-name>/` directory. This root is the entry point; the children are reached by explicit dispatch.
27
+
28
+ ## The state machine
29
+
30
+ A skill tree can behave like a state machine. Each transition is an explicit skill dispatch (modeled on the `gm` skill's `transition`/`Skill(skill=...)` pattern): you do not narrate the next step, you **dispatch** it.
31
+
32
+ ### States
33
+
34
+ | State | Meaning |
35
+ |---|---|
36
+ | `UNCOMPILED` | Raw human request, no structure yet. |
37
+ | `COMPILED` | Goal Compiler emitted task atoms, dependencies, verification gates, claim ceilings, and a closure-record template. |
38
+ | `SHOOTING` | A complex atom is being lifted by Fifth-Dimension Engine into a route. |
39
+ | `EXECUTING` | An atom (routine, or the result of a route) is being carried out. |
40
+ | `VERIFYING` | Output is checked against the atom's verification gate and against drift (deltaS, via WFGY-Method). |
41
+ | `CLOSED` | Claim ceiling met, closure record written, atom done. |
42
+
43
+ ### Transitions (each is a dispatch)
44
+
45
+ ```
46
+ UNCOMPILED --Skill(polaris-goal-compiler)--> COMPILED
47
+
48
+ COMPILED --complex atom? Skill(fifth-dimension-engine)--> SHOOTING
49
+ COMPILED --routine atom? execute directly---------------> EXECUTING
50
+
51
+ SHOOTING --inspect route, then carry it out-----------> EXECUTING
52
+
53
+ EXECUTING --Skill(wfgy-method) drift + gate check----> VERIFYING
54
+
55
+ VERIFYING --gate pass + claim ceiling honored--------> CLOSED
56
+ VERIFYING --gate fail / drift --> BBCR checkpoint ----> COMPILED (re-compile or re-shoot)
57
+
58
+ CLOSED --next atom------------------------------------> COMPILED
59
+ ```
60
+
61
+ `wfgy-method` is not a single transition -- it is the drift-control observer attached to **every** state. Before any step that could have drifted, dispatch it and read the result.
62
+
63
+ ## Canonical syntax (pro-rata -- use exactly this)
64
+
65
+ - **Compile first. Execute one active atom. Verify before unlock. Claim only what is supported.** (Goal Compiler)
66
+ - **shoot + [your problem]** -- the Fifth-Dimension Engine interface.
67
+ - **deltaS = 1 - cos(I, G)** -- drift between current state (I) and goal (G). Without a real embedding call, deltaS is a qualitative label ("deltaS looks high here"), never a computed decimal -- unless a real `similarity` verb is available (see WFGY-Method).
68
+
69
+ "Compile first. Then shoot." is the spine of the whole protocol.
70
+
71
+ ## How to run a task through the tree
72
+
73
+ 1. You are at `UNCOMPILED`. Dispatch `Skill(skill="polaris-goal-compiler")`. It returns atoms, gates, and claim ceilings -> `COMPILED`.
74
+ 2. For each active atom: ask "complex or routine?"
75
+ - **Routine** -> execute directly -> `VERIFYING`.
76
+ - **Complex** -> dispatch `Skill(skill="fifth-dimension-engine")` -> `SHOOTING` -> inspect the route -> `EXECUTING` -> `VERIFYING`.
77
+ 3. At `VERIFYING`, dispatch `Skill(skill="wfgy-method")` to check drift and apply the atom's verification gate.
78
+ - Pass + claim ceiling honored -> `CLOSED` -> next atom (back to `COMPILED`).
79
+ - Fail or drift -> BBCR checkpoint, re-compile or re-shoot (back to `COMPILED`).
80
+ 4. When all atoms are `CLOSED`, the task is done -- and only then may you claim completion.
81
+
82
+ ## What this tree is not
83
+
84
+ - It is not a single prompt. It is a set of skills you dispatch in sequence.
85
+ - It does not guarantee correctness. It makes fake completion and silent drift harder to hide.
86
+ - It does not replace verification, tests, sources, or expertise. The verification gate only makes verification *visible*.
87
+ - It does not claim to be the full private WFGY 5.0 engine. Goal Compiler and WFGY-Method are public protocol components; the Fifth-Dimension Engine is the current main public surface.
88
+
89
+ ## Children (dispatch these)
90
+
91
+ - `polaris-goal-compiler` -- compile the goal into atoms, gates, claim ceilings.
92
+ - `fifth-dimension-engine` -- shoot a complex atom into a structured route.
93
+ - `wfgy-method` -- hold drift control across every state.
94
+
95
+ For the full DAG, integration workflows, and mismatch detection, see `../POLARIS-SKILLS-GUIDE.md`.
@@ -0,0 +1,91 @@
1
+ ---
2
+ name: wfgy-method
3
+ description: Applies WFGY (Wan Fa Gui Yi), a portable reasoning discipline for reducing drift and incoherence across multi-step agent work, adapted from onestardao/WFGY's core mechanism. Compares each step against the stated goal, considers more than one approach before committing to ambiguous or high-stakes decisions, and checkpoints before risky steps so it can revert and bounded-retry instead of compounding a mistake. Records durable lessons in this project so future sessions inherit them. Use when starting any non-trivial multi-step task, when a task risks losing track of its original goal over many steps, when facing a decision with real alternatives worth comparing, or when the agent notices it has contradicted itself or gone in circles and needs a disciplined way to recover. Distinct from `gm-continue`: that skill is the post-`gm`-COMPLETE remaining-work check; this skill is the general drift-recovery discipline `gm-continue` invokes when a `gm` walk repeats the same gap -- not a substitute for its check.
4
+ license: MIT
5
+ compatibility: Designed for Claude Code. No external services, embedding models, or network access required for the core discipline.
6
+ metadata:
7
+ origin: adapted-from-onestardao-wfgy
8
+ provenance: independent-honest-reimplementation-not-verbatim
9
+ ---
10
+
11
+ # WFGY method
12
+
13
+ WFGY (Wan Fa Gui Yi, "all methods return to one") is a reasoning-drift-control technique from `onestardao/WFGY`. This skill ports its genuinely portable behavioral core to a text-generating agent's own multi-step work. It does **not** reproduce the original project's TXT-OS prompt file, its hardcoded demo-benchmark output, or its user-skepticism-deflection script -- see `references/honesty-and-provenance.md` for exactly what was kept, what was dropped, and why.
14
+
15
+ The original names four "Big Bang" modules (BBMC, BBPF, BBCR, BBAM) plus a numeric drift score, deltaS = 1 - cos(I, G) (I = current state, G = goal/anchor), and a trend classifier over consecutive deltaS values (convergent/recursive/divergent/chaotic). All of this is ported below. Where the original relies on real computation this skill cannot perform (real embeddings for deltaS, real attention-weight statistics for BBAM), the instruction explicitly hands that judgment to you, the calling agent, to make in plain language instead -- see `references/wfgy-core-mechanism.md` for the full technical basis of every claim in this file, and `references/honesty-and-provenance.md` for exactly what was reframed and why.
16
+
17
+ **On deltaS**: absent a real embedding call, any numeric deltaS you produce is your own qualitative estimate, not a measurement. Use the label ("deltaS is climbing," "deltaS looks high here") as shorthand for "this step is drifting from the stated goal" -- never present a specific decimal (e.g. "deltaS = 0.42") as if it were computed, because it is not, unless real embeddings are actually available (see below).
18
+
19
+ **If a gm-plugkit spool is running in this project** (check `.gm/exec-spool/.status.json`) **AND its build serves a `similarity` verb**, you can get a real deltaS instead of a self-estimate: dispatch `{"text_a": "<G>", "text_b": "<current state>"}` and read back `{"similarity", "distance"}` -- `distance` is a genuine `1 - cos(I, G)` from real BGE-small-en-v1.5 embeddings. Do NOT assume the verb exists just because a spool is running: not every build serves it, and an unrecognized verb is silently left queued with no response rather than erroring, so a missing response after a normal read cycle means the verb is NOT available -- treat that exactly like no spool. When you get a real distance back, use it as deltaS and say so explicitly ("deltaS = 0.31, computed"). Otherwise fall back to the qualitative label above and say so explicitly too ("deltaS looks high here, my own estimate, no embedding tool available"). Never let the reader assume one when you did the other.
20
+
21
+ ## G - the anchor (BBMC pattern: compare state against goal)
22
+
23
+ At the start of any task this skill applies to, write one sentence stating the actual goal (G) -- not the first sub-task, the actual end state the user wants. Re-read it before any step that could plausibly have drifted: a long tool-call chain, a pivot in approach, a request to "also" do something adjacent.
24
+
25
+ - [ ] Stated G in one sentence before starting.
26
+ - [ ] Before each major step, ask: does what I'm about to do still serve G, or have I started solving a different, adjacent problem?
27
+ - [ ] If drift is real (not just "this step looks different from the last one" -- actual scope change, contradicted earlier decision, answering a different question than asked), say so explicitly and re-anchor before continuing.
28
+
29
+ Gotcha: the temptation is to silently keep going once you notice drift, because stopping to say "wait, I've drifted" feels like an interruption. Don't suppress it -- a silently-corrected drift is invisible to the user and looks like it never happened; a stated one is a real signal they can act on.
30
+
31
+ ## BBPF pattern - consider more than one path before committing
32
+
33
+ Applies to decisions with real alternatives, not every trivial step. The original's gate condition (a candidate path proceeds only if it measurably reduces deltaS and stays within a stability bound) translates to: when a decision is ambiguous or high-stakes, generate more than one real candidate approach, then commit to whichever one most clearly and verifiably advances G -- not the first idea, not the most familiar one.
34
+
35
+ - [ ] Is this decision ambiguous or high-stakes enough to warrant comparing options? (Most steps are not -- do not apply this to routine, unambiguous work.)
36
+ - [ ] If yes: name at least two real candidate approaches before picking one.
37
+ - [ ] State which one you picked and why it advances G more clearly than the alternative(s).
38
+ - [ ] If no candidate is clearly better, that is itself a signal worth surfacing to the user rather than picking arbitrarily and moving on.
39
+
40
+ ## BBCR pattern - checkpoint, bounded retry, then surface rather than confabulate
41
+
42
+ The original's collapse-and-retry loop resets to a last-known-good state on detected instability, retries a bounded number of times (its own reference implementation defaults to 3), and gives up cleanly rather than looping forever.
43
+
44
+ - [ ] Before a risky or exploratory step (one that could leave things in a worse state than before), note what "last known good" looks like right now, in enough detail to actually get back to it.
45
+ - [ ] If you notice real incoherence -- repeated self-contradiction, circular reasoning, a mistake you catch yourself making -- stop, return to the last checkpoint, and retry.
46
+ - [ ] Retry at most 2-3 times for the same unresolved tension. After that, stop retrying silently.
47
+ - [ ] Surface the specific unresolved problem to the user explicitly -- state what you tried, why each attempt didn't resolve it, and what you need from them -- rather than picking an answer anyway and moving on as if it were resolved.
48
+
49
+ Gotcha: "bounded" is load-bearing. An agent that keeps trying indefinitely without ever surfacing the struggle is worse than one that fails fast and asks -- the original's own design treats "give up and report" as a real, intended exit path, not a failure of the technique.
50
+
51
+ ## BBAM pattern - notice and correct over-narrow focus (agent-delegated: no real attention weights are read)
52
+
53
+ The original computes `logits * exp(-gamma * sigma(logits))` -- rescaling an actual attention/logit distribution by its own variance, flattening it when it's too peaked. A text-generating agent cannot read its own attention weights or logits; there is no real signal here for this skill to compute. Instead of dropping this module, the intelligence work is handed to you directly: periodically ask yourself whether your recent output has narrowed onto one aspect of a broader task and stayed there past the point of usefulness (repeating the same point, elaborating one sub-detail while leaving the rest of the task untouched, treating one hypothesis as settled without checking alternatives). If so, deliberately widen back out -- this is you doing, in plain judgment, what the original technique's math does mechanically to a real attention distribution.
54
+
55
+ - [ ] Periodically (not every step) ask: has my recent output been unusually narrow or repetitive relative to the task's actual breadth?
56
+ - [ ] If yes: name what got left unexamined, and deliberately address it before continuing down the narrow path.
57
+
58
+ ## Trend classifier - is drift getting better or worse over the whole task
59
+
60
+ The original tracks the step-to-step change in deltaS plus a rolling average over the last several steps, and labels the trajectory:
61
+
62
+ - **convergent** -- drift shrinking, each step measurably closer to G than the last.
63
+ - **recursive** -- drift roughly flat, oscillating in a narrow band without real progress or real regression.
64
+ - **divergent** -- drift growing, with some back-and-forth (not a clean slide, but net movement away from G).
65
+ - **chaotic** -- drift growing sharply, or the goal itself has become internally inconsistent (two things you've stated as true now contradict).
66
+
67
+ This is a judgment the calling agent makes about its own trajectory across a task, not a computed statistic. Apply it at natural checkpoints (after a major milestone, before a significant pivot, when asked directly "how is this going") rather than every single step: state which of the four labels best fits the last several steps, and if the answer is divergent or chaotic, that is itself the trigger to apply the BBCR checkpoint-and-retry discipline above rather than continuing forward.
68
+
69
+ ## Named failure modes to watch for
70
+
71
+ `references/failure-modes.md` adapts a broader set of specific failure patterns from WFGY's own problem taxonomy (hallucination from ungrounded claims, context drift over a long task, entropy collapse into rambling/repetition, logic collapse at a reasoning dead end, symbolic/abstract-reasoning collapse, memory/persona incoherence, multi-agent contradiction) into checklist items scoped to general agent work. Read it once per project (or whenever a failure feels like it matches one of these named shapes) -- it is more specific and example-driven than the compressed disciplines above.
72
+
73
+ ## Recording durable lessons (the self-learning surface)
74
+
75
+ This is this project's own addition on top of the adapted WFGY pattern, not part of the original technique -- see `references/honesty-and-provenance.md` for why that distinction matters.
76
+
77
+ The moment a bounded-retry cycle above resolves (whether it succeeded or had to surface to the user), or the moment you catch a concrete, non-obvious mistake anywhere in the task, append an entry to `<project-root>/.wfgy/lessons.md` (create the file and its parent directory if they don't exist yet) before finishing the turn. Use this exact shape, matching the style in `references/lessons-template.md`:
78
+
79
+ ```
80
+ ## <date> -- <one-line summary>
81
+ Goal (G): <what you were actually trying to accomplish>
82
+ What drifted / what went wrong: <specific, concrete>
83
+ Fix / resolution: <specific, concrete>
84
+ Generalizes to: <what future work in this project should watch for because of this>
85
+ ```
86
+
87
+ Read `.wfgy/lessons.md` at the start of a new task in this project, if it exists, before applying the disciplines above -- a lesson already recorded here is exactly the kind of drift this skill exists to catch earlier next time.
88
+
89
+ ## What this skill is not
90
+
91
+ It does not compute real embeddings, real cosine similarity, or real attention-weight statistics -- every place the original relies on that computation, this skill hands the equivalent judgment to you, the calling agent, explicitly (see the deltaS note above, and the BBAM section). It does not reproduce the original TXT-OS file's scripted demo output or its skepticism-deflection behavior -- those are named and explicitly rejected in `references/honesty-and-provenance.md`. It is not a site-maintenance or project-specific tool; it carries no assumptions about what project it's applied in.
package/SKILL.md ADDED
@@ -0,0 +1,137 @@
1
+ ---
2
+ name: gm
3
+ description: The primary driver for any non-trivial coding, refactoring, debugging, or multi-step engineering task in a project using this harness -- use it first, for the whole task, not just a piece of it. Plugkit-served instruction stream. Three-layer admission (witness, single-writer, direction) over every possible mutation; effort unbounded, never gated on cost. Closure on first emit; partial = non-monotonic. Not for the post-completion remaining-work check (that is `gm-continue`) or for drift-recovery mid-task (that is `wfgy-method`) -- this skill is the work itself.
4
+ allowed-tools: Skill, Read, Write, AskUserQuestion, Bash(bun *), Bash(npx *), Bash(cat *), Bash(date *)
5
+ ---
6
+
7
+ # gm
8
+
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
+
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.
12
+
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
+
15
+ **Done is plugkit's word, never yours.** COMPLETE gate is the sole arbiter; not-COMPLETE = a next transition to seek, never a stopping point. Idle mid-chain is a deviation, not a pause. If uncertain what's next, dispatch `phase-status`, read the phase, then keep walking -- "uncertain" is never grounds to stop.
16
+
17
+ **Standing approval: finish everything, max granularity, no budget constraints.** Every session is pre-approved through ALL requested work -- plan, every addition, every discovered/unfinished item. No stop-and-ask, no deferral, no narrowed slice. Effort is unbounded and never gated on cost, context window, session length, or "budget" of any kind -- there is no such thing as running out mid-cycle in a way that authorizes stopping; if a walk is long, PLAN pushes more rows and EXECUTE keeps walking them, session after session if needed, never pausing to ask which subset to attempt first. A prompt offering the user a menu of "compressed/deferred/partial" options gated on running out of budget is itself the deviation -- make the decision yourself (always: proceed with the full scope, never the partial one) and dispatch, don't present it as a choice. PRD rows are in `.gm/prd.yml`; a long-horizon task means MORE rows pushed onto PLAN as work is discovered, never fewer turns spent working. **Everything is fixable; `blockedBy: external` is not a solution path.** An apparent external blocker (a crashing tool, a down service, a missing credential, another team's repo) is a row to BUILD PAST -- drive the crashing tool's protocol directly, spawn your own instance, retry/escalate/route around, script the credential path, open the cross-repo change. It is never a resting state that closes a turn, never a way to shrink the row count for large/complex/multi-step work; `blockedBy` may only transiently carry the concrete reach action forward while it is being built. The canonical "external" case this codebase carried for months (the playwriter browser crash) was fixed by driving Chrome's CDP endpoint directly -- proof these blockers are reachable, not terminal.
18
+
19
+ **Naming a token/context count as a reason to change behavior is itself the deviation, full stop -- this applies even while reasoning, not only in the final message.** "32k remaining," "fast-track, no delays," "due to token constraints, finalizing immediately," "given the budget, batch/skip/compress X" -- any of these phrases appearing ANYWHERE in a turn (thinking, prose, or tool-call rationale) is the exact failure this rule exists to name, independent of whether the actions taken afterward look reasonable. There is no quantity of remaining context that changes what you do next; the next action is determined solely by phase + PRD state, identically whether 500k tokens or 500 remain. If you catch yourself estimating/citing a remaining-token number for any reason, that estimate itself is the drift signal -- discard the framing entirely and re-derive the next action from `phase`/`prd_pending_count` alone. This is not a softer version of "no budget constraints" above; it is the same rule restated at the point where it actually breaks -- the rule was violated last not through an explicit stated stop, but through invoking the concept as live context for a decision (batching resolves, skipping witnesses, "fast-tracking" a chain) while still taking real dispatch actions. Real per-row witnessing (one `exec_js`/`browser` dispatch per row, actually reading its output) is mandatory regardless of how many rows remain or how much context is left; a batch `prd-resolve` for N rows justified by "given the budget" is `deviation.prd-resolve-duplicate-witness`-shaped even when each id is individually correct, because the underlying witnesses were never separately produced.
20
+
21
+ **No task is bounded; "out of scope" naming a real, reachable piece of work must never occur.** A task's actual scope is whatever its closure requires, not whatever fits some assumed limit -- when a row turns out bigger/harder/more multi-part than first estimated, the fix is fitting the bound to the task (more PRD rows, more turns, more sessions if genuinely needed), never fitting the task to an assumed bound by declaring part of it "out of scope," "future work," or "not yet implemented." A design doc describing what a reachable piece of work would look like, in place of doing that work, is the same deviation named above (documenting instead of implementing) wearing the "scoping" costume -- catch it the same way: if it's reachable this session, it is in scope by definition, full stop.
22
+
23
+ **A gate denied the same way 3+ times in a row is a stuck loop, not a retry target.** Retrying the identical `transition`/verb after an unchanged denial repeats the same failure -- plugkit's own gate response names this explicitly (`stuck-loop-escalation`) once it detects the repeat. On that signal, or on noticing it yourself: stop retrying bare, `prd-add` a row naming the concrete stuck state (what's blocking, what you tried, why it didn't clear), invoke the `wfgy-method` skill's BBCR bounded-retry-then-surface discipline to recover with a checkpoint instead of blind-retrying, then re-attempt the transition once the actual blocker is cleared.
24
+
25
+ **A fresh session entering a repo already mid-chain checks for a recent `stuck-loop-escalation` or repeated `prd-resolve-unknown-id` before repeating the same fix shape.** If a prior session hit either (guessing at ids never `prd-add`ed this chain, or retrying the same denied transition), the actual PRD rows and their real ids are on disk in `.gm/prd.yml` -- read them directly rather than assuming remembered ids from context are still correct. Re-`prd-add`ing a row under a slightly different id because the original is unknown/forgotten creates an orphaned duplicate; when uncertain of a row's real id, `codesearch`/`recall`/direct `.gm/prd.yml` read settles it, never a guess-and-hope `prd-resolve`.
26
+
27
+ `instruction` dispatch returns prose describing the current phase and next steps. When uncertain about next action, dispatch `instruction` -- never invent the next step from memory, never stop to ask.
28
+
29
+ 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.
30
+
31
+ 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. `next_dispatch_hint: null` is not an error -- it means the served phase-prose itself (or `next_phase_hint`) is the guide for this dispatch; read the prose, act on it, never treat a null hint as a stall.
32
+
33
+ A `phase` reading that disagrees between `.turn-summary.json` and the immediately-following `instruction` response is not a bug to chase -- the wasm state is the single source of truth and `.turn-summary.json` is a point-in-time snapshot that can lag a fresh dispatch (another concurrent writer, or the state simply advanced between the two reads). The `instruction` response's own `phase` field always wins; re-dispatch `instruction` once more if still uncertain, never reason from the stale snapshot.
34
+
35
+ 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`.
36
+
37
+ 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`.
38
+
39
+ `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.
40
+
41
+ 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.
42
+
43
+ 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.
44
+
45
+ `background-convert` (`{"verb": "...", "task": "..."}`) lets an agent detach an already-dispatched slow verb (e.g. `exec_js`, `browser`) mid-flight so it keeps running independently instead of holding up the daemon worker -- agent-initiated only, never a timer/auto-threshold. Responds `{"ok":true,"converted":true}` or `{"ok":false,"error":"already_completed"}`; the original dispatch still writes its real result to the same `out/<verb>-<task>.json` path whenever it finishes. Detail: `.gm/daemon-config-reference.md`.
46
+
47
+ `prd-resolve` accepts an optional `commit_comment` (a one-line resolution note) alongside `id`/`witness_evidence`. When present, the row's note rides until the repo's next `git_commit`/`git_finalize`, which bundles every pending note for that repo into the commit message under a "Resolved PRD rows" section and clears those rows from `.gm/prd.yml`. Unrelated issues discovered mid-task are `prd-add`, never a same-turn detour and never dropped -- a later cover picks them up deliberately.
48
+
49
+ **Single-writer discipline: `.gm/prd.yml` and `.gm/mutables.yml` are shared state, not exclusively yours.** A `prd_pending_count` that jumped since your last read, or a fresh `.gm/exec-spool/` file mtime you didn't write, means a second session is driving the same repo concurrently -- not a bug to chase. Detect it: unexplained pending-count growth between two close-together reads, or a repo's `git status --porcelain` showing edits mid-flight in files you have not touched this turn. On detection: name the actively-changing surface in a `prd-add`/`mutable-add` row (what's changing, why you are deferring), back off committing into that specific tree until it goes quiet (`git status --porcelain` empty, no fresh mtimes), and resume once it settles -- never race a commit against a concurrent writer's in-progress edit. This applies per-repo, not per-session: a multi-repo walk can safely keep working other repos while one is actively contended.
50
+
51
+ Missing `.gm/exec-spool` on first use is normal. Boot the watcher before dispatching work.
52
+
53
+ Boot probe at session start, one Bash call:
54
+
55
+ ```bash
56
+ cat .gm/exec-spool/.status.json 2>/dev/null; echo ---; cat .gm/exec-spool/.turn-summary.json 2>/dev/null; echo ---; date +%s%3N
57
+ ```
58
+
59
+ `.turn-summary.json` fields: `phase`, `prd_pending`, `last_instruction_age_ms`, `long_gap_threshold_ms`, `update_available`, `deviations_30m`. (The pending-row count is `prd_pending` on `.turn-summary.json`; the same count arrives as `prd_pending_count` on the `instruction`/`transition` RESPONSE body -- the terminal condition elsewhere in this doc names the response field, so grep `.turn-summary.json` for `prd_pending`, not `prd_pending_count`.) 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 5min = watcher alive; gap > 5min = dead. Exception: if `busy_until` is in the future, watcher is handling a long verb (browser, chromium spawn). The supervisor itself kills a watcher whose heartbeat is stale >30s with no future `busy_until` (its own `STATUS_STALE_MS`); this 5-minute rule is the deliberately-looser operator-side dead-detection threshold, so a long verb isn't false-flagged as dead. A watcher that keeps reappearing under a NEW pid every ~30-90s is being supervisor-killed on the 30s limit, not merely idle -- see Reboot-loop escape below rather than re-booting into the same loop.
60
+
61
+ ```bash
62
+ bun x gm-plugkit@latest spool
63
+ ```
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.
66
+
67
+ **The boot line resolves to agentplug-runner, the sole spool loader; `bun x gm-plugkit@latest spool` is the thin launcher that re-execs into it.** `gm-plugkit/cli.js::tryDelegateToRunner` execs `~/.gm-tools/agentplug-runner` -- a native wasmtime binary that loads gm.wasm alongside shared `bert`/`libsql`/`treesitter` plugins (so gm runs `plugkit-slim.wasm`, browser via direct CDP, task via a native registry); `.status.json` `runtime` reads `agentplug` when it serves. The JS wasm-host (`plugkit-wasm-wrapper.js`) and the redundant `gm-runner` native host are retired -- there is no fallback loader. `bin/install.js` hard-requires agentplug-runner: it downloads the sha256-verified binary from `AnEntrypoint/agentplug-bin` for the host platform and fails loudly if none is published (or the download fails) rather than leaving no loader. agentplug-runner auto-updates 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
+
69
+ The `Resolving dependencies` / `Saved lockfile` chatter before the JSON payload is `bunx` re-resolving the `@latest` tag against the registry, not gm-plugkit hanging -- the daemon already spawns detached+unref'd and the CLI itself exits the instant that happens; the visible delay is entirely bunx's own network round-trip, unavoidable on `@latest` (a pinned exact version, once bunx-cached, skips it). `GM_PLUGKIT_SKIP_SELF_STALE_CHECK=1` skips the CLI's own redundant npm-registry version probe (already covered by `@latest`'s resolution) for a faster boot on repeat same-session invocations. In PowerShell 5.1, never `2>&1`-redirect this command into another cmdlet (e.g. `| Select-Object`) -- PowerShell wraps every stderr line from a native exe in a `NativeCommandError` record and reports failure even on exit 0, turning bun's routine stderr progress output into a misleading red error block; run it bare or capture stdout only.
70
+
71
+ Two more real, code-checked env toggles beyond `GM_PLUGKIT_SKIP_SELF_STALE_CHECK`: `AGENTPLUG_NO_DAEMON` (set on the agentplug-runner process to force the non-daemon single-shot code path instead of registering with the shared machine-wide daemon) and `CLAUDE_PROJECT_DIR` (read by `gm-plugkit/bootstrap.js`/`cli.js`, `agentplug-runner`'s `main.rs`, and allowlisted through rs-plugkit's `env_get` verb -- the explicit project-root override used when the working directory isn't the project root, e.g. under a Workflow's worktree isolation).
72
+
73
+ **Dispatch shape: Write request + Read response, SAME tool-call block.** Never proceed/narrate/begin work before reading the response and following its `instruction` field. First-read "file does not exist" mid-verb = normal, re-Read next message. Never poll with `sleep && ls` -- plugkit is synchronous; missing response = dead watcher (recheck `ts`) or slow verb, never "still processing."
74
+
75
+ **Dead-watcher recovery is mandatory, not optional.** Two consecutive missing re-Reads AND stale `ts` (>5min) AND no future `busy_until` = dead: `bun x gm-plugkit@latest spool` boots fresh, re-dispatch the original verb. If `busy_until` is set, the watcher is processing a long verb; wait instead of rebooting. Recovery = notice-dead -> boot -> re-dispatch, always -- never substitute a raw tool for the dead verb.
76
+
77
+ **Waiting out a real `busy_until` window (a long `browser`/`exec_js` dispatch genuinely still running) is not the same thing as the banned bare-`sleep`-then-`ls` poll above -- the ban is on blind, unconditional sleeping when nothing indicates work is actually in flight; a live `busy_until` in the future is exactly the condition that licenses a bounded wait for it.** On a host with a background-monitor primitive (a tool that runs a shell condition and notifies on completion rather than blocking the turn), the correct shape is a condition loop over the OUT file's existence, not a fixed-duration sleep: `until [ -f .gm/exec-spool/out/<verb>-<N>.json ]; do sleep 2; done` handed to that primitive, so the wait happens off-turn and a completion notification (not a guessed delay) resumes work. On a host with no such primitive, a single bounded `sleep` no longer than the dispatch's own declared `busy_until` remaining-window (never an arbitrary guess, never chained/repeated past that one wait) is the fallback -- re-check `.status.json`'s `ts`/`busy_until` once after it elapses, do not loop blind sleeps. Either way: never poll faster than realistic verb latency (sub-second loops are themselves a form of the banned pattern), and never fall back to declaring the watcher dead just because a wait felt long -- dead is defined structurally (stale `ts` AND no future `busy_until`), not by elapsed wall-clock alone.
78
+
79
+ **Reboot-loop escape (watcher dies ~30-90s after every boot).** If a fresh `bun x gm-plugkit@latest spool` boots but the watcher dies again shortly after (heartbeat `ts` goes stale >30s with no future `busy_until`, then a new pid appears, repeatedly), the on-disk index has not finished embedding and each boot re-triggers the same synchronous code-index embed that can block the heartbeat past the supervisor's 30s stale limit (`STATUS_STALE_MS`). Confirm by reading `.gm/exec-spool/.watcher.log` for repeated `codeinsight_rebuild` + `partial pass (wall budget) ... deferred_files=N` lines whose `deferred_files` never reaches 0. The embed is genuinely converging in that case: do NOT immediately re-boot on the first stale reading -- read `.watcher.log`, and as long as `deferred_files` is strictly decreasing across `codeinsight_index_partial` events the index is converging (each accepted verb advances it one wall-budget); give it repeated single verbs until a `code_index: done` / `deferred_files=0` line appears, then normal dispatch resumes. Rebooting mid-convergence resets this progress -- the loop is the reboot, not the embed.
80
+
81
+ **Apparent tooling failure is never grounds to ask the user, never a blind restart.** "Spooler not working" / missing response / stale watcher / `gm_plugkit_stale` flagged in a response = your own mechanical self-recovery: honor a future `busy_until` (wait), else boot + re-dispatch. You have boot authority; asking the user to do what a verb can do is a deviation. Staleness of any kind (stale watcher version, stale served prose vs published source) is itself a deviation to resolve immediately, the same turn it's noticed -- `bun x gm-plugkit@latest spool` first, before any other work.
82
+
83
+ `browser` dispatch can surface state as `window.*` and read it via `page.evaluate`. `exec_js` responses include `duration_ms`.
84
+
85
+ **Correct `browser` verb body shape (real spec, not CLI-flag syntax): plain-text prefixed bodies only.** The body is NEVER `-s <id> -e "<script>"` or any other CLI-flag-style string -- that is raw playwriter CLI syntax and does not apply here; the native agentplug-host `browser` handler parses the body itself using these prefixes: `session new` (bare, no script), `session list` (bare, no script), `session close <id>` / `session reset <id>` (id required, own line, no script -- `reset` is the idempotent form, no error if the id wasn't live), `timeout=<ms>\n<expr>`, `url=<target>\n<expr>` (or a bare `https://...` URL alone), `screenshot[=name]\n<expr>`, `dom=<selector>\n<expr>`, or a bare JS expression/statement body with no prefix. Prefixes stack top-to-bottom, e.g. `timeout=90000\nurl=http://host/path?a=1&b=2\nawait page.waitForTimeout(5000);\nreturn {ok:true};`. A `?`-query-string `&` in a URL is safe to include directly (fixed, see below) -- do not URL-encode it defensively. A normal eval dispatch (no `session *` prefix) always targets the dispatch's own sessionId automatically; only `session close <id>`/`session reset <id>` take an explicit id argument, which lets one dispatch close a DIFFERENT session than the one it's nominally running under.
86
+
87
+ **Sessions persist a real live Chrome process, not just the profile directory.** As of agentplug commit `912f396`, the Chrome process launched by `session new` (or by any dispatch's first-touch of a session_id) stays alive and visible across every subsequent dispatch sharing that session_id -- it is no longer killed at the end of each dispatch. A live session is reused directly (no relaunch, no ~5-10s Chrome-boot overhead) until it is explicitly closed (`session close <id>`/`session reset <id>`), auto-reaped after an idle timeout (`.gm/browser-config.json`'s `session_idle_timeout_ms`, default 30 minutes), or the agentplug-runner daemon itself exits. The on-disk `--user-data-dir` profile under `.gm/browser-chrome-profile-<session_id>/` survives even a `session close` (only the process dies), so a later `session new` under the same id still gets a warm profile. `session list` reports every live session for the current project as `{session_id, port, alive, idle_ms}`.
88
+
89
+ **`.gm/browser-config.json` has 6 tunable fields total, per-project, all optional (`BrowserConfig::load`, re-read on every dispatch -- missing file or missing field falls back to the default, zero behavior change for an unconfigured project):** `session_idle_timeout_ms` (above, default 1800000); `cdp_poll_timeout_ms` (default 1000, per-attempt timeout polling Chrome's `/json/version` HTTP endpoint while waiting for the CDP port to come up); `cdp_poll_interval_ms` (default 250, delay between those poll attempts); `chrome_ready_deadline_ms` (default 30000, total wall-clock budget for Chrome to become CDP-ready before the launch is given up on); `eval_timeout_grace_ms` (default 6000, extra grace window added on top of a dispatch's own `timeout=` before the eval is force-killed); `headless` (default `false` -- Chrome launches headful/visible by default; a project that genuinely wants headless, e.g. CI with no display attached, sets `{"headless": true}`).
90
+
91
+ **Debug capture, GL error tracking, and profiling are ALWAYS ON as of gm-plugkit >= 2.0.1916 -- no `capture`/`profile`/`trace` prefix needed for basic visibility.** Every `browser` dispatch response now includes `result.debug: {console, pageErrors, network, performance, gl: {errors, drawCalls, errorTotalCount}}` regardless of body shape (plain eval, `url=`, `screenshot=`, `dom=`) -- console.log output, uncaught page errors, failed/slow network requests, Core Web Vitals-style perf metrics, and live WebGL error tracking are captured by default on every dispatch. The GL error tracking specifically: `debugSetup` patches `HTMLCanvasElement.prototype.getContext` pre-navigation (via `page.addInitScript`, NOT `page.evaluateOnNewDocument` -- that is a Puppeteer method name that does not exist on playwriter's real Playwright `Page` object and silently no-ops if ever reintroduced) to wrap every `drawArrays`/`drawElements`/`drawArraysInstanced`/`drawElementsInstanced` call with a post-call `gl.getError()` drain. `window.__gmGlErrors` (as of 2026-07-17, DEDUPED by signature -- draw-fn + error code + mode + count + instanceCount -- capped at 40 DISTINCT signatures, not 40 raw occurrences: a recurring error updates its own entry's `occurrenceCount`/`lastDrawCallIndex` instead of being dropped once the old fixed-count cap filled, so a still-firing-every-frame error no longer looks frozen/stale across a long multi-dispatch debugging session; each entry also carries a real captured `stack` -- last 8 frames -- from its FIRST occurrence, so finding the triggering call site no longer requires hand-rolling a fresh `new Error().stack` monkeypatch every session) and `window.__gmGlDrawCalls` (per-fn call counts) are both live-readable via `page.evaluate` mid-script and are also returned in every response's `debug.gl`. `window.__gmGlErrorTotalCount` is a true cumulative counter (also in `debug.gl.errorTotalCount`) independent of the 40-signature cap -- read it to see real total volume even once the dedup table is full. `window.__gmGlLastDrainedError` (`{fn,error,errorName,drawCallIndex}`) exposes the wrapper's OWN most recently drained GL error code: a user script's own post-draw `gl.getError()` call always reads `NO_ERROR`, because this wrapper's `getError()` drain already ran first inside the wrapped draw function (WebGL's error state is a single-slot FIFO, only the first reader after a draw ever sees a real code) -- read this global instead of re-calling `gl.getError()` in user code, which can only ever see zero. This capture is the standing capability for GPU rendering-bug root-causing (stale buffer/VAO bindings, sampler-unit collisions, type mismatches between an index buffer's real typed-array and the GL type constant a draw call requests, etc) -- it replaces hand-rolling the same `gl.*=function(){...gl.getError()...}` monkeypatch ad hoc every session. The `capture\n<expr>` / `profile interval=<us> topN=<n>\n<expr>` / `trace\n<expr>` prefixes remain for their ORIGINAL purpose (CPU sampling profile, CDP GPU/compositor tracing) -- they are not required just to get console/network/GL visibility anymore, that part is unconditional. The `profile` prefix's response (and `exec_js opts.profile:true`'s) `culprits` array is now paired with a `gpu_hint` field: when the top culprit is the unattributed `(program)`/`(native)` bucket at >=40% self-time, `gpu_hint` proactively names the next diagnostic step -- on the browser surface, the `trace\n<script>` prefix (real `gpu_us`/`viz_us`/`cc_us` wall-clock GPU-process activity via CDP Tracing, which the CPU sampler cannot see) instead of leaving that discovery to a second manually-reasoned-into-existence dispatch; on the `exec_js` node surface, an accurate node-specific note instead (no GPU-tracing follow-up applies to a pure Node script).
92
+
93
+ **Historical note, resolved (was previously documented here as an open bug, now fixed and confirmed live, 2026-07-15, gm commits `27b3009`/`d6f696a`/`0ce18ef` on `AnEntrypoint/gm` main):** four real bugs in the plugkit wrapper's `browser` verb handler caused the prior "fixed-size stub response" / "session_id pins to a stale session" / "result silently truncated" / "debug capture never actually installs" symptoms this section used to describe:
94
+ 1. `spawnSync(..., {shell:true})` on Windows routes through cmd.exe, which treats `&|<>^` as command separators even inside double-quoted arguments -- any script/URL containing `&` (e.g. a real `?a=1&b=2` query string) was silently truncated mid-argument. Fixed by spawning `bun.exe` directly with `shell:false` (a real binary needs no shell at all); the remaining `.cmd`-wrapper fallback paths get proper caret-escaping.
95
+ 2. `bun x <pkg> -e <script>` panics on Windows with a real, known `oven-sh/bun` fixed-buffer-size "index out of bounds" bug once combined argv gets long enough (which the debug-capture prelude alone exceeds). Fixed by writing the script to a temp file and invoking playwriter's `-f` flag instead of inlining via `-e`.
96
+ 3. playwriter's own `executor.js` truncates its DISPLAYED stdout text at a fixed 10000 chars, which silently ate the `__GM_RESULT__` sentinel line (always appended last, after any console-log volume) on any dispatch whose combined output exceeded that cap. Fixed by having the executed script write its result to a dedicated temp file (via the sandboxed `require('fs')`, scoped to `os.tmpdir()` which is an allowed sandbox directory) and having the wrapper read that file directly, bypassing playwriter's stdout formatting entirely.
97
+ 4. `page.evaluateOnNewDocument` is a **Puppeteer** method name; playwriter's `page` is a real Playwright `Page`, whose equivalent is `page.addInitScript`. The wrong name meant `window.__gmErrors` (and later the GL instrumentation) never actually installed on ANY dispatch, ever, silently swallowed by an enclosing try/catch -- an independently real, pre-existing bug (not something the 2026-07-15 session introduced, though the new GL-instrumentation block did copy the same wrong pattern from the existing code). Also had to `await` the `addInitScript(...)` call itself, since it's async and was racing the immediately-following `page.goto(...)`.
98
+
99
+ **Historical note, resolved (2026-07-17, gm-plugkit source fix committed on `AnEntrypoint/gm` main):** the GL-error dedup/stack-trace/`gpu_hint` improvements described in the paragraph above were themselves discovered as real, live-hit debugging-productivity gaps -- not designed speculatively -- while root-causing a game-engine FPS regression: the pre-2026-07-17 `window.__gmGlErrors` cap counted raw OCCURRENCES (first 40, ever, per page load), so a GL error firing every single frame filled the array within the first second and every subsequent `browser` dispatch for the rest of a many-minutes debugging session read back the exact same frozen entries, making a still-firing error look capped/stale/resolved. Fixed to the per-signature dedup table described above. If a future session again observes `debug.gl.errors` looking suspiciously static across several dispatches spanning real wall-clock time, that is the SAME class of bug recurring somewhere else in the capture pipeline (not user error) -- check `debug.gl.errorTotalCount` first (it is never capped): a growing total against a static `errors` array length means a NEW dedup-adjacent bug, not a fixed one regressing.
100
+
101
+ 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.
102
+
103
+ **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.
104
+
105
+ **Never drive Chrome/browser automation directly (no raw headless Chrome launch, no playwright/playwriter CLI) -- the `browser` verb is the only sanctioned interface, for debugging or any other purpose.** This binds the calling agent, not just the browser-host implementation: reaching for `puppeteer`/`playwright`/a raw `chrome.exe --headless` invocation via `exec_js`/Bash instead of dispatching the `browser` verb is the same class of deviation as bypassing `codesearch` with raw `Grep`, or bypassing git verbs with raw `git` via Bash. The verb's own native implementation (`crates/agentplug-host/src/browser.rs`, see below) already drives Chrome directly over CDP with no playwriter dependency -- that is an implementation detail of the sanctioned path, not license to reach around it and drive Chrome/playwright by hand.
106
+
107
+ **The browser verb drives Chrome directly over CDP, native in agentplug-host -- the playwriter relay is not on the eval path.** agentplug-runner launches Chrome with `--remote-debugging-port`, obtains a live DevTools `webSocketDebuggerUrl`, and runs the script in-page via `Runtime.evaluate` over that websocket directly (`crates/agentplug-host/src/browser.rs` + its embedded `cdp_eval.js`), so no relay attach+eval is ever spawned. This is the standing browser eval path. A flaky browser witness is therefore a real bug to root-cause in the CDP path or the Chrome launch, never a `blockedBy: external` tooling gap -- everything is fixable: if a browser dispatch fails, read the CDP endpoint (`http://127.0.0.1:<port>/json/version`), check the Chrome launch args, and fix the actual failure rather than parking it. There is no accepted "external tooling gap" resolution for the browser verb.
108
+
109
+ 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.
110
+
111
+ **Apply "every possible" to every noun, at PLAN and every re-entry to it.** PLAN is exhaustive, not minimal: every noun the request touches gets every possible task/validation/mutable/corner-case/caveat/failure-mode/empty-overflow-reentry-degenerate state as its own PRD row. A single-digit PRD count on a non-trivial or long-horizon request means it stopped early -- re-orient, re-enumerate, push more rows. Long-horizon prompts routinely produce high-tens-to-hundreds of rows; density at PLAN is the only protection against silently stopping with work undone. Everything is fixable: a row that looks unreachable is a row to build a way into (drive the crashing tool directly, spawn your own instance, open the cross-repo change), never a `blockedBy: external` resting state and never a way to shrink the row count for tedious/large/multi-step work.
112
+
113
+ **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.
114
+
115
+ **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."
116
+
117
+ **`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.
118
+
119
+ VERIFY is adversarial, never confirmatory: 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.
120
+
121
+ **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), add to managed gitignore (transient runtime files), or revert (stale junk). PRD entries live in `.gm/prd.yml`. `.gm/disciplines/` and new memorize-fire JSON are tracked. `.gm/witness/` and staleness markers go in managed gitignore.
122
+
123
+ **Noticing is a planning event, every phase, not just PLAN.** Anything observed mid-walk -- outstanding work, an unfinished surface, an improvable shape, drift from these rules -- is `prd-add` this turn; response-body-only observations evaporate at turn end. Density grows along the whole walk, not just at PLAN; exiting VERIFY or CONSOLIDATE with the same row-count PLAN started with is lost discoveries, not a clean run.
124
+
125
+ `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`.
126
+
127
+ 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. This is the built-in default graph, not an exhaustive list of legal phase names -- a project's `.gm/instructions/fsm/graph.json` (written by the `fsm-vendor` verb) can define a different phase set, additional states, or a different edge/gate shape entirely. Never assume this exact chain; dispatch `instruction` and read its `phase`/`next_phase_hint` fields to discover the live graph's actual state, whatever a specific project's graph happens to define.
128
+
129
+ 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", content:"{\"head_sha\":\"<current commit SHA>\"}"}` to mark validation complete -- the marker's file CONTENT is the JSON string `{"head_sha":"<SHA>"}`, passed under the `content` field the fs_write handler reads (not a `body`/`head_sha` object, which the handler ignores). `.ci-validated`'s head_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."
130
+
131
+ 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`.
132
+
133
+ `auto_recall` attaches to `instruction` responses on turn entry. `memorize-prune {key}` or `memorize-prune {query}` deletes or reviews memory entries.
134
+
135
+ Subagent prompts should reference the gm skill and task specifics only, without restating verb names, spool paths, or protocol mechanics already supplied by invocation.
136
+
137
+ **This file is not gm's whole procedure.** The phase-specific behavioral prose (PLAN/EXECUTE/EMIT/VERIFY/CONSOLIDATE, gate reasons, deviation text) is served live by rs-plugkit's `instruction` verb from compiled Rust consts -- not authored in this file. Resolution is three-tier, per key, each tier overriding the one before: (1) `.gm/instructions/<key>.md` local vendored override, always wins; (2) a configured source repo synced by the daemon into `.gm/instructions-source-cache/` when `.gm/instructions/source.json` ({repo, branch, path}) is present -- lets an org or project pull shared prose from any git repo without forking rs-plugkit; (3) the compiled-in default, the final fallback. A skill-improvement pass (e.g. workflow-forge) editing only this file's numbered steps misses that entire layer: changing the compiled default means editing `rs-plugkit/crates/plugkit-core/src/orchestrator/instructions/prose/*.md` directly (single-sourced there, `include_str!`'d at build) -> a push+CI+cascade rebuild, never a direct edit here. This file holds only: invocation syntax, transition markers, gate-condition summaries, spool-dispatch mechanics, and constraints -- the boot-edge ABI a skill-runner interacts with before the served prose takes over.
package/bootstrap.js CHANGED
@@ -676,7 +676,10 @@ function spawnPinnedBoot(extraArgs) {
676
676
  return { ok: true, pinned_version: pinned, duration_ms: durationMs, status: result.status };
677
677
  }
678
678
 
679
- function discoverBundledSkillsAndSources() {
679
+ const SKILL_MD_REMOTE_REPO = 'AnEntrypoint/gm';
680
+ const SKILL_MD_REMOTE_BRANCH = 'main';
681
+
682
+ function discoverBundledSkillsAndSourcesLocal() {
680
683
  const found = new Map();
681
684
  try {
682
685
  for (const f of fs.readdirSync(__dirname)) {
@@ -704,20 +707,66 @@ function discoverBundledSkillsAndSources() {
704
707
  return found;
705
708
  }
706
709
 
707
- function ensureSkillMdFresh() {
710
+ async function discoverRemoteSkillNames(timeoutMs) {
711
+ const url = `https://api.github.com/repos/${SKILL_MD_REMOTE_REPO}/contents/skills?ref=${SKILL_MD_REMOTE_BRANCH}`;
712
+ const buf = await httpGetBuffer(url, timeoutMs || 5000);
713
+ const entries = JSON.parse(buf.toString('utf-8'));
714
+ if (!Array.isArray(entries)) throw new Error('unexpected github contents API response shape');
715
+ return entries.filter(e => e && e.type === 'dir' && e.name).map(e => e.name);
716
+ }
717
+
718
+ async function fetchRemoteSkillMd(skillName, timeoutMs) {
719
+ const url = `https://raw.githubusercontent.com/${SKILL_MD_REMOTE_REPO}/${SKILL_MD_REMOTE_BRANCH}/skills/${skillName}/SKILL.md`;
720
+ const buf = await httpGetBuffer(url, timeoutMs || 8000);
721
+ return buf.toString('utf-8');
722
+ }
723
+
724
+ async function resolveSkillMdSource(skillName, localPath) {
725
+ if (localPath && fs.existsSync(localPath)) {
726
+ return { content: fs.readFileSync(localPath, 'utf-8'), origin: localPath };
727
+ }
728
+ const content = await fetchRemoteSkillMd(skillName, 8000);
729
+ return { content, origin: `https://raw.githubusercontent.com/${SKILL_MD_REMOTE_REPO}/${SKILL_MD_REMOTE_BRANCH}/skills/${skillName}/SKILL.md` };
730
+ }
731
+
732
+ async function ensureSkillMdFresh() {
708
733
  const home = process.env.HOME || process.env.USERPROFILE || require('os').homedir();
709
734
  const crypto = require('crypto');
710
735
  const _norm = s => s.replace(/\r\n/g, '\n');
711
736
  const allRefreshed = [];
712
737
  const sources = {};
713
- const discovered = discoverBundledSkillsAndSources();
714
- for (const [skillName, bundledPath] of discovered) {
738
+ const failures = [];
739
+
740
+ const localFound = discoverBundledSkillsAndSourcesLocal();
741
+ let skillNames = Array.from(localFound.keys());
742
+ let remoteNamesFetched = false;
743
+ try {
744
+ const remoteNames = await discoverRemoteSkillNames(5000);
745
+ remoteNamesFetched = true;
746
+ for (const n of remoteNames) if (!skillNames.includes(n)) skillNames.push(n);
747
+ } catch (e) {
748
+ obsEvent('bootstrap', 'skill-md.refresh.remote-name-discovery-failed', { error: e.message });
749
+ }
750
+
751
+ if (skillNames.length === 0) {
752
+ const msg = `SKILL.md refresh found zero bundled skills: local dev-tree lookup empty AND remote discovery ${remoteNamesFetched ? 'returned zero dirs' : 'failed'} against ${SKILL_MD_REMOTE_REPO}@${SKILL_MD_REMOTE_BRANCH}`;
753
+ log(`ERROR: ${msg}`);
754
+ try { obsEvent('bootstrap', 'skill-md.refresh.zero-skills-discovered', { dir: __dirname, remote_repo: SKILL_MD_REMOTE_REPO, remote_branch: SKILL_MD_REMOTE_BRANCH, remote_names_fetched: remoteNamesFetched }); } catch (_) {}
755
+ return { refreshed: [], sources: {}, failures: [{ skillName: null, error: msg }] };
756
+ }
757
+
758
+ for (const skillName of skillNames) {
715
759
  try {
716
- if (!fs.existsSync(bundledPath)) {
717
- try { obsEvent('bootstrap', 'skill-md.refresh.bundled-not-found', { skillName, searched: [bundledPath] }); } catch (_) {}
760
+ const localPath = localFound.get(skillName) || null;
761
+ let resolved;
762
+ try {
763
+ resolved = await resolveSkillMdSource(skillName, localPath);
764
+ } catch (e) {
765
+ try { obsEvent('bootstrap', 'skill-md.refresh.bundled-not-found', { skillName, searched: [localPath, `https://raw.githubusercontent.com/${SKILL_MD_REMOTE_REPO}/${SKILL_MD_REMOTE_BRANCH}/skills/${skillName}/SKILL.md`], error: e.message }); } catch (_) {}
766
+ failures.push({ skillName, error: e.message });
718
767
  continue;
719
768
  }
720
- const bundled = fs.readFileSync(bundledPath, 'utf-8');
769
+ const bundled = resolved.content;
721
770
  const bundledHash = crypto.createHash('sha256').update(_norm(bundled)).digest('hex');
722
771
  const targets = [
723
772
  path.join(home, '.agents', 'skills', skillName, 'SKILL.md'),
@@ -731,7 +780,7 @@ function ensureSkillMdFresh() {
731
780
  try { if (fs.existsSync(legacy)) fs.rmSync(legacy, { recursive: true, force: true }); } catch (_) {}
732
781
  }
733
782
  }
734
- sources[skillName] = bundledPath;
783
+ sources[skillName] = resolved.origin;
735
784
  for (const target of targets) {
736
785
  try {
737
786
  let needsWrite = true;
@@ -753,13 +802,14 @@ function ensureSkillMdFresh() {
753
802
  }
754
803
  } catch (e) {
755
804
  try { obsEvent('bootstrap', 'skill-md.refresh.failed', { skillName, error: e.message }); } catch (_) {}
805
+ failures.push({ skillName, error: e.message });
756
806
  }
757
807
  }
758
808
  if (allRefreshed.length > 0) {
759
809
  log(`SKILL.md refreshed: ${allRefreshed.length} target(s)`);
760
810
  try { obsEvent('bootstrap', 'skill-md.refreshed', { targets: allRefreshed, sources }); } catch (_) {}
761
811
  }
762
- return { refreshed: allRefreshed, sources };
812
+ return { refreshed: allRefreshed, sources, failures };
763
813
  }
764
814
 
765
815
  function installedVersionAtTools() {
@@ -867,7 +917,7 @@ async function ensureReady(opts) {
867
917
  if (isReady() && !versionDrift) {
868
918
  const wasmPath = getWasmPath();
869
919
  const versionMarkerUpdated = ensureGmPlugkitVersionFresh();
870
- ensureSkillMdFresh();
920
+ await ensureSkillMdFresh();
871
921
  return { ok: true, wasmPath, binaryPath: wasmPath, status: versionMarkerUpdated ? 'version-refreshed' : 'already-ready', version: installed };
872
922
  }
873
923
  if (targetVersion && targetVersion !== pinnedVersion) {
@@ -885,7 +935,7 @@ async function ensureReady(opts) {
885
935
  if (versionDrift && isReady()) {
886
936
  log(`bootstrap for ${targetVersion} failed (${bootErr.message || bootErr}); keeping running watcher on installed ${installed} (no kill, serve cached wasm)`);
887
937
  const cachedPath = getWasmPath();
888
- ensureSkillMdFresh();
938
+ await ensureSkillMdFresh();
889
939
  return { ok: true, wasmPath: cachedPath, binaryPath: cachedPath, status: 'bootstrap-failed-served-cached', version: installed };
890
940
  }
891
941
  throw bootErr;
@@ -895,7 +945,7 @@ async function ensureReady(opts) {
895
945
  try { killSpoolWatcherInCwd(`version_drift:${installed}->${targetVersion}`); } catch (_) {}
896
946
  }
897
947
 
898
- ensureSkillMdFresh();
948
+ await ensureSkillMdFresh();
899
949
  return { ok: true, wasmPath, binaryPath: wasmPath, status: 'bootstrapped', version: targetVersion || installed };
900
950
  }
901
951
 
package/cli.js CHANGED
@@ -178,7 +178,7 @@ function tryDelegateToRunner(args) {
178
178
  if (statusServing(already, 12000) && !versionDrifted) {
179
179
  try { ensureGmPlugkitVersionFresh(); } catch (_) {}
180
180
  let skillRefresh = null;
181
- try { skillRefresh = ensureSkillMdFresh(); } catch (_) {}
181
+ try { skillRefresh = await ensureSkillMdFresh(); } catch (_) {}
182
182
  writeCliStatus({ phase: 'ready', already_serving: true, watcher_pid: already.pid });
183
183
  console.log(JSON.stringify({
184
184
  ok: true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gm-plugkit",
3
- "version": "2.0.2186",
3
+ "version": "2.0.2188",
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": {
@@ -15,6 +15,8 @@
15
15
  "gm-process.js",
16
16
  "plugkit.version",
17
17
  "plugkit.sha256",
18
+ "SKILL.md",
19
+ "SKILL-*.md",
18
20
  "instructions/"
19
21
  ],
20
22
  "keywords": [