gm-plugkit 2.0.1863 → 2.0.1864
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/SKILL-fifth-dimension-engine.md +5 -5
- package/SKILL-polaris-goal-compiler.md +5 -5
- package/SKILL-polaris-protocol.md +16 -16
- package/SKILL-wfgy-method.md +28 -28
- package/SKILL.md +2 -2
- package/instructions/residual/browser-open.md +1 -1
- package/instructions/residual/dirty-tree.md +1 -1
- package/instructions/residual/imperative.md +1 -1
- package/instructions/residual/tasks-running.md +1 -1
- package/package.json +1 -1
- package/plugkit-wasm-wrapper.js +60 -8
- package/supervisor.js +20 -13
|
@@ -121,7 +121,7 @@ See `references/research-kernel-extraction.md` for how mixed themes become resea
|
|
|
121
121
|
|
|
122
122
|
### Everyday Problems
|
|
123
123
|
|
|
124
|
-
The same engine works on ordinary decisions, work problems, product questions, and engineering failures
|
|
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
125
|
|
|
126
126
|
## Verification
|
|
127
127
|
|
|
@@ -141,7 +141,7 @@ This skill does not:
|
|
|
141
141
|
## References
|
|
142
142
|
|
|
143
143
|
See `references/` directory for:
|
|
144
|
-
- `route-structure.md`
|
|
145
|
-
- `research-kernel-extraction.md`
|
|
146
|
-
- `route-inspection-guide.md`
|
|
147
|
-
- `skills/polaris-protocol/SKILL.md`
|
|
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
|
|
@@ -117,7 +117,7 @@ Over-claiming (saying something is done when it's only drafted) is the most comm
|
|
|
117
117
|
|
|
118
118
|
### Closure Records
|
|
119
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
|
|
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
121
|
|
|
122
122
|
## Interaction with Other Skills
|
|
123
123
|
|
|
@@ -143,10 +143,10 @@ Use Goal Compiler to compile the problem statement, then dispatch to Fifth-Dimen
|
|
|
143
143
|
## References
|
|
144
144
|
|
|
145
145
|
See `references/` directory for:
|
|
146
|
-
- `task-atomization.md`
|
|
147
|
-
- `verification-gates.md`
|
|
148
|
-
- `claim-ceiling-examples.md`
|
|
149
|
-
- `skills/polaris-protocol/SKILL.md`
|
|
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
150
|
|
|
151
151
|
## What This Is Not
|
|
152
152
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: polaris-protocol
|
|
3
|
-
description: WFGY 5.0 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
4
|
license: MIT
|
|
5
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
6
|
metadata:
|
|
@@ -8,19 +8,19 @@ metadata:
|
|
|
8
8
|
provenance: adapted-and-honest-reimplementation-not-verbatim
|
|
9
9
|
---
|
|
10
10
|
|
|
11
|
-
# WFGY 5.0
|
|
11
|
+
# WFGY 5.0 -- Polaris Protocol (tree root)
|
|
12
12
|
|
|
13
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
14
|
|
|
15
|
-
This skill is the **tree root**. It does not re-explain the children
|
|
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
16
|
|
|
17
17
|
## The tree
|
|
18
18
|
|
|
19
19
|
```
|
|
20
|
-
polaris-protocol (this skill
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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
24
|
```
|
|
25
25
|
|
|
26
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.
|
|
@@ -37,7 +37,7 @@ A skill tree can behave like a state machine. Each transition is an explicit ski
|
|
|
37
37
|
| `COMPILED` | Goal Compiler emitted task atoms, dependencies, verification gates, claim ceilings, and a closure-record template. |
|
|
38
38
|
| `SHOOTING` | A complex atom is being lifted by Fifth-Dimension Engine into a route. |
|
|
39
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 (
|
|
40
|
+
| `VERIFYING` | Output is checked against the atom's verification gate and against drift (deltaS, via WFGY-Method). |
|
|
41
41
|
| `CLOSED` | Claim ceiling met, closure record written, atom done. |
|
|
42
42
|
|
|
43
43
|
### Transitions (each is a dispatch)
|
|
@@ -58,13 +58,13 @@ VERIFYING --gate fail / drift --> BBCR checkpoint ----> COMPILED (re-compile or
|
|
|
58
58
|
CLOSED --next atom------------------------------------> COMPILED
|
|
59
59
|
```
|
|
60
60
|
|
|
61
|
-
`wfgy-method` is not a single transition
|
|
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
62
|
|
|
63
|
-
## Canonical syntax (pro-rata
|
|
63
|
+
## Canonical syntax (pro-rata -- use exactly this)
|
|
64
64
|
|
|
65
65
|
- **Compile first. Execute one active atom. Verify before unlock. Claim only what is supported.** (Goal Compiler)
|
|
66
|
-
- **shoot + [your problem]**
|
|
67
|
-
-
|
|
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
68
|
|
|
69
69
|
"Compile first. Then shoot." is the spine of the whole protocol.
|
|
70
70
|
|
|
@@ -77,7 +77,7 @@ CLOSED --next atom------------------------------------> COMPILED
|
|
|
77
77
|
3. At `VERIFYING`, dispatch `Skill(skill="wfgy-method")` to check drift and apply the atom's verification gate.
|
|
78
78
|
- Pass + claim ceiling honored -> `CLOSED` -> next atom (back to `COMPILED`).
|
|
79
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
|
|
80
|
+
4. When all atoms are `CLOSED`, the task is done -- and only then may you claim completion.
|
|
81
81
|
|
|
82
82
|
## What this tree is not
|
|
83
83
|
|
|
@@ -88,8 +88,8 @@ CLOSED --next atom------------------------------------> COMPILED
|
|
|
88
88
|
|
|
89
89
|
## Children (dispatch these)
|
|
90
90
|
|
|
91
|
-
- `polaris-goal-compiler`
|
|
92
|
-
- `fifth-dimension-engine`
|
|
93
|
-
- `wfgy-method`
|
|
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
94
|
|
|
95
95
|
For the full DAG, integration workflows, and mismatch detection, see `../POLARIS-SKILLS-GUIDE.md`.
|
package/SKILL-wfgy-method.md
CHANGED
|
@@ -10,82 +10,82 @@ metadata:
|
|
|
10
10
|
|
|
11
11
|
# WFGY method
|
|
12
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
|
|
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
14
|
|
|
15
|
-
The original names four "Big Bang" modules (BBMC, BBPF, BBCR, BBAM) plus a numeric drift score,
|
|
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
16
|
|
|
17
|
-
**On
|
|
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
18
|
|
|
19
|
-
**If a gm-plugkit spool is running in this project** (check `.gm/exec-spool/.status.json
|
|
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
20
|
|
|
21
|
-
## G
|
|
21
|
+
## G - the anchor (BBMC pattern: compare state against goal)
|
|
22
22
|
|
|
23
|
-
At the start of any task this skill applies to, write one sentence stating the actual goal (G)
|
|
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
24
|
|
|
25
25
|
- [ ] Stated G in one sentence before starting.
|
|
26
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"
|
|
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
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
|
|
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
30
|
|
|
31
|
-
## BBPF pattern
|
|
31
|
+
## BBPF pattern - consider more than one path before committing
|
|
32
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
|
|
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
34
|
|
|
35
|
-
- [ ] Is this decision ambiguous or high-stakes enough to warrant comparing options? (Most steps are not
|
|
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
36
|
- [ ] If yes: name at least two real candidate approaches before picking one.
|
|
37
37
|
- [ ] State which one you picked and why it advances G more clearly than the alternative(s).
|
|
38
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
39
|
|
|
40
|
-
## BBCR pattern
|
|
40
|
+
## BBCR pattern - checkpoint, bounded retry, then surface rather than confabulate
|
|
41
41
|
|
|
42
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
43
|
|
|
44
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
|
|
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
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
|
|
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
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
|
|
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
50
|
|
|
51
|
-
## BBAM pattern
|
|
51
|
+
## BBAM pattern - notice and correct over-narrow focus (agent-delegated: no real attention weights are read)
|
|
52
52
|
|
|
53
|
-
The original computes `logits * exp(-gamma * sigma(logits))`
|
|
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
54
|
|
|
55
55
|
- [ ] Periodically (not every step) ask: has my recent output been unusually narrow or repetitive relative to the task's actual breadth?
|
|
56
56
|
- [ ] If yes: name what got left unexamined, and deliberately address it before continuing down the narrow path.
|
|
57
57
|
|
|
58
|
-
## Trend classifier
|
|
58
|
+
## Trend classifier - is drift getting better or worse over the whole task
|
|
59
59
|
|
|
60
|
-
The original tracks the step-to-step change in
|
|
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
61
|
|
|
62
|
-
- **convergent**
|
|
63
|
-
- **recursive**
|
|
64
|
-
- **divergent**
|
|
65
|
-
- **chaotic**
|
|
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
66
|
|
|
67
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
68
|
|
|
69
69
|
## Named failure modes to watch for
|
|
70
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)
|
|
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
72
|
|
|
73
73
|
## Recording durable lessons (the self-learning surface)
|
|
74
74
|
|
|
75
|
-
This is this project's own addition on top of the adapted WFGY pattern, not part of the original technique
|
|
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
76
|
|
|
77
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
78
|
|
|
79
79
|
```
|
|
80
|
-
## <date>
|
|
80
|
+
## <date> -- <one-line summary>
|
|
81
81
|
Goal (G): <what you were actually trying to accomplish>
|
|
82
82
|
What drifted / what went wrong: <specific, concrete>
|
|
83
83
|
Fix / resolution: <specific, concrete>
|
|
84
84
|
Generalizes to: <what future work in this project should watch for because of this>
|
|
85
85
|
```
|
|
86
86
|
|
|
87
|
-
Read `.wfgy/lessons.md` at the start of a new task in this project, if it exists, before applying the disciplines above
|
|
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
88
|
|
|
89
89
|
## What this skill is not
|
|
90
90
|
|
|
91
|
-
It does not compute real embeddings, real cosine similarity, or real attention-weight statistics
|
|
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
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: gm
|
|
3
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, Bash(bun *), Bash(npx *)
|
|
4
|
+
allowed-tools: Skill, Read, Write, Bash(bun *), Bash(npx *), Bash(cat *), Bash(date *)
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# gm
|
|
@@ -84,7 +84,7 @@ VERIFY is adversarial, never confirmatory: run the real code path and read its a
|
|
|
84
84
|
|
|
85
85
|
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.
|
|
86
86
|
|
|
87
|
-
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",
|
|
87
|
+
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."
|
|
88
88
|
|
|
89
89
|
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`.
|
|
90
90
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
browser sessions still open
|
|
1
|
+
browser sessions still open -- dispatch `browser` with `session list` body to enumerate open ids, then `session close <id>` for each before retrying residual-scan
|
|
@@ -1 +1 @@
|
|
|
1
|
-
worktree dirty
|
|
1
|
+
worktree dirty -- modified={modified} untracked={untracked} -- commit or revert before residual scan; a push from a dirty tree orphans the unstaged delta
|
|
@@ -1 +1 @@
|
|
|
1
|
-
Residual scan. Worktree clean, remote pushed, PRD empty, mutables witnessed
|
|
1
|
+
Residual scan. Worktree clean, remote pushed, PRD empty, mutables witnessed -- the four checks. Anything reachable and in-spirit expands the PRD and runs. Out-of-reach is credentials, down service, product decision.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
background tasks still running
|
|
1
|
+
background tasks still running -- wait for completion or kill them via the host_exec_js interface before retrying residual-scan
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gm-plugkit",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.1864",
|
|
4
4
|
"description": "Bootstrap and daemon-spawn tool for gm plugkit binary. Downloads the correct platform binary, verifies SHA256, and starts the spool watcher daemon. Includes plugkit-wasm-wrapper for WASM-based spool watching.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
package/plugkit-wasm-wrapper.js
CHANGED
|
@@ -2728,7 +2728,24 @@ function makeHostFunctions(instanceRef) {
|
|
|
2728
2728
|
+ `})();\n`;
|
|
2729
2729
|
cmd = process.execPath; args = ['-e', memRunner];
|
|
2730
2730
|
} else {
|
|
2731
|
-
|
|
2731
|
+
// Wrap in an async IIFE so top-level `return` (and top-level
|
|
2732
|
+
// `await`) work -- `node/bun -e "return 2+2;"` is a SyntaxError
|
|
2733
|
+
// at top level, but the gm exec_js contract lets code `return` a
|
|
2734
|
+
// result. This mirrors the mem/profile paths and the browser verb.
|
|
2735
|
+
// The returned value is emitted via a __GM_RESULT__ sentinel so the
|
|
2736
|
+
// user's own stdout stays clean; a throw still prints its stack to
|
|
2737
|
+
// stderr and exits 1, preserving the documented error channel.
|
|
2738
|
+
const defRunner = `(async () => {\n`
|
|
2739
|
+
+ ` try {\n`
|
|
2740
|
+
+ ` const __r = await (async () => {\n${code}\n})();\n`
|
|
2741
|
+
+ ` try { console.log('__GM_RESULT__' + JSON.stringify(__r === undefined ? null : __r)); }\n`
|
|
2742
|
+
+ ` catch (__se) { console.log('__GM_RESULT__' + JSON.stringify({ __unserializable: String(__se && __se.message || __se) })); }\n`
|
|
2743
|
+
+ ` } catch (__e) {\n`
|
|
2744
|
+
+ ` console.error(String(__e && __e.stack || __e));\n`
|
|
2745
|
+
+ ` process.exitCode = 1;\n`
|
|
2746
|
+
+ ` }\n`
|
|
2747
|
+
+ `})();\n`;
|
|
2748
|
+
cmd = process.execPath; args = ['-e', defRunner];
|
|
2732
2749
|
}
|
|
2733
2750
|
}
|
|
2734
2751
|
else if (lang === 'python') { cmd = 'python'; args = ['-c', code]; }
|
|
@@ -2742,6 +2759,20 @@ function makeHostFunctions(instanceRef) {
|
|
|
2742
2759
|
} finally {
|
|
2743
2760
|
if (profileUserFile) { try { fs.unlinkSync(profileUserFile); } catch (_) {} }
|
|
2744
2761
|
}
|
|
2762
|
+
// Shared across all result branches: a genuine timeout kills the child
|
|
2763
|
+
// near the deadline. A SIGTERM far under timeoutMs is a spurious /
|
|
2764
|
+
// host-injected kill (e.g. the stale-watcher SIGTERM-at-28ms), not a
|
|
2765
|
+
// timeout -- do not mislabel it as timed_out.
|
|
2766
|
+
const __execDurMs = Date.now() - __execT0;
|
|
2767
|
+
const __execTimedOut = result.signal === 'SIGTERM' && __execDurMs >= Math.floor(timeoutMs * 0.9);
|
|
2768
|
+
// spawnSync sets result.error (and leaves status/signal null) when the
|
|
2769
|
+
// child could NOT be started or was reaped abnormally (spawn race
|
|
2770
|
+
// during watcher boot, ETIMEDOUT, EBADF, ENOENT for a missing runtime).
|
|
2771
|
+
// Surface it so a status:-1 is diagnosable instead of a silent empty
|
|
2772
|
+
// failure -- the caller sees WHY, not just exit_code:-1.
|
|
2773
|
+
const __spawnError = result.error
|
|
2774
|
+
? { code: result.error.code || null, errno: result.error.errno || null, syscall: result.error.syscall || null, message: String(result.error.message || result.error) }
|
|
2775
|
+
: null;
|
|
2745
2776
|
if (wantProfile) {
|
|
2746
2777
|
const raw = result.stdout || '';
|
|
2747
2778
|
const idx = raw.indexOf('__GM_PROFILE__');
|
|
@@ -2752,14 +2783,15 @@ function makeHostFunctions(instanceRef) {
|
|
|
2752
2783
|
stdout: idx >= 0 ? raw.slice(0, idx) : raw,
|
|
2753
2784
|
stderr: result.stderr || '',
|
|
2754
2785
|
exit_code: result.status === null ? -1 : result.status,
|
|
2755
|
-
timed_out:
|
|
2756
|
-
duration_ms:
|
|
2786
|
+
timed_out: __execTimedOut,
|
|
2787
|
+
duration_ms: __execDurMs,
|
|
2757
2788
|
result: parsed ? parsed.result : null,
|
|
2758
2789
|
profile: parsed ? parsed.profile : { timeframe: null, culprits: [] },
|
|
2759
2790
|
profile_error: parsed ? parsed.profile_error : 'profile sentinel not found in stdout',
|
|
2760
2791
|
user_error: parsed ? parsed.user_error : null,
|
|
2761
2792
|
mem: parsed ? parsed.mem : null,
|
|
2762
2793
|
wall_vs_cpu: parsed ? parsed.wall_vs_cpu : null,
|
|
2794
|
+
...(__spawnError ? { spawn_error: __spawnError } : {}),
|
|
2763
2795
|
});
|
|
2764
2796
|
}
|
|
2765
2797
|
if (opts.mem === true && isJsLang) {
|
|
@@ -2772,21 +2804,41 @@ function makeHostFunctions(instanceRef) {
|
|
|
2772
2804
|
stdout: idx >= 0 ? raw.slice(0, idx) : raw,
|
|
2773
2805
|
stderr: result.stderr || '',
|
|
2774
2806
|
exit_code: result.status === null ? -1 : result.status,
|
|
2775
|
-
timed_out:
|
|
2776
|
-
duration_ms:
|
|
2807
|
+
timed_out: __execTimedOut,
|
|
2808
|
+
duration_ms: __execDurMs,
|
|
2777
2809
|
result: meta ? meta.result : null,
|
|
2778
2810
|
mem: meta ? meta.mem : null,
|
|
2779
2811
|
wall_ms: meta ? meta.wall_ms : null,
|
|
2780
2812
|
...(meta && meta.error ? { error: meta.error } : {}),
|
|
2813
|
+
...(__spawnError ? { spawn_error: __spawnError } : {}),
|
|
2781
2814
|
});
|
|
2782
2815
|
}
|
|
2816
|
+
let __defStdout = result.stdout || '';
|
|
2817
|
+
let __defResult = null;
|
|
2818
|
+
let __defHasResult = false;
|
|
2819
|
+
if (isJsLang) {
|
|
2820
|
+
const __ri = __defStdout.lastIndexOf('__GM_RESULT__');
|
|
2821
|
+
if (__ri >= 0) {
|
|
2822
|
+
const __tail = __defStdout.slice(__ri + '__GM_RESULT__'.length);
|
|
2823
|
+
const __nl = __tail.indexOf('\n');
|
|
2824
|
+
const __jsonStr = __nl >= 0 ? __tail.slice(0, __nl) : __tail;
|
|
2825
|
+
try { __defResult = JSON.parse(__jsonStr); __defHasResult = true; } catch (_) {}
|
|
2826
|
+
// Strip the sentinel (and the leading newline we prepended) so the
|
|
2827
|
+
// caller's own stdout is returned clean.
|
|
2828
|
+
let __clean = __defStdout.slice(0, __ri) + (__nl >= 0 ? __tail.slice(__nl + 1) : '');
|
|
2829
|
+
if (__clean.endsWith('\n')) __clean = __clean.slice(0, -1);
|
|
2830
|
+
__defStdout = __clean;
|
|
2831
|
+
}
|
|
2832
|
+
}
|
|
2783
2833
|
return writeWasmJson(instanceRef.value, {
|
|
2784
2834
|
ok: result.status === 0,
|
|
2785
|
-
stdout:
|
|
2835
|
+
stdout: __defStdout,
|
|
2786
2836
|
stderr: result.stderr || '',
|
|
2787
2837
|
exit_code: result.status === null ? -1 : result.status,
|
|
2788
|
-
timed_out:
|
|
2789
|
-
duration_ms:
|
|
2838
|
+
timed_out: __execTimedOut,
|
|
2839
|
+
duration_ms: __execDurMs,
|
|
2840
|
+
...(__defHasResult ? { result: __defResult } : {}),
|
|
2841
|
+
...(__spawnError ? { spawn_error: __spawnError } : {}),
|
|
2790
2842
|
...(profileSkipped ? { profile_skipped: profileSkipped } : {}),
|
|
2791
2843
|
});
|
|
2792
2844
|
} catch (e) {
|
package/supervisor.js
CHANGED
|
@@ -159,6 +159,22 @@ function readShutdownReason() {
|
|
|
159
159
|
try { return JSON.parse(fs.readFileSync(SHUTDOWN_REASON_PATH, 'utf-8')); } catch (_) { return null; }
|
|
160
160
|
}
|
|
161
161
|
|
|
162
|
+
// A supervisor-initiated kill is PLANNED (version/wrapper drift, heartbeat-stale),
|
|
163
|
+
// but on Windows process.kill(pid,'SIGTERM') terminates the child immediately with
|
|
164
|
+
// no catchable signal, so the child never writes its own .shutdown-reason.json and
|
|
165
|
+
// the taskkill /F that follows leaves none either -- the NEXT boot then mislabels a
|
|
166
|
+
// deliberate upgrade recycle as a SILENT ABORT / unplanned-restart critical. Write
|
|
167
|
+
// the planned reason on the child's behalf BEFORE killing, so the next boot reads a
|
|
168
|
+
// fresh planned shutdown reason and classifies the restart correctly.
|
|
169
|
+
function killChild(reason) {
|
|
170
|
+
if (!currentChildPid) return;
|
|
171
|
+
try { fs.writeFileSync(SHUTDOWN_REASON_PATH, JSON.stringify({ reason, ts: Date.now(), pid: currentChildPid, killed_by_supervisor: true })); } catch (_) {}
|
|
172
|
+
try { process.kill(currentChildPid, 'SIGTERM'); } catch (_) {}
|
|
173
|
+
if (process.platform === 'win32') {
|
|
174
|
+
try { spawnSync('taskkill', ['/F', '/T', '/PID', String(currentChildPid)], { stdio: 'ignore', windowsHide: true, timeout: 3000 }); } catch (_) {}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
162
178
|
let lastSpawnedAt = 0;
|
|
163
179
|
let lastVersionDriftActionAt = 0;
|
|
164
180
|
let restartTimestamps = [];
|
|
@@ -258,7 +274,7 @@ function spawnWatcher(bootReason) {
|
|
|
258
274
|
const idleClean = reason === 'idle';
|
|
259
275
|
const lockRejected = code === 75;
|
|
260
276
|
const cleanExit = code === 0;
|
|
261
|
-
const plannedReasons = new Set(['idle', 'sigterm', 'version-change', 'wrapper-change', 'peer-stale-takeover', 'external-planned', 'process-exit']);
|
|
277
|
+
const plannedReasons = new Set(['idle', 'sigterm', 'version-change', 'wrapper-change', 'heartbeat-stale', 'peer-stale-takeover', 'external-planned', 'process-exit']);
|
|
262
278
|
const isPlanned = plannedReasons.has(reason) || lockRejected || cleanExit;
|
|
263
279
|
const eventName = idleClean
|
|
264
280
|
? 'supervisor.watcher-exited-idle'
|
|
@@ -335,10 +351,7 @@ function checkWatcherHealth() {
|
|
|
335
351
|
stale_limit_ms: STATUS_STALE_MS,
|
|
336
352
|
severity: 'critical',
|
|
337
353
|
});
|
|
338
|
-
|
|
339
|
-
if (process.platform === 'win32') {
|
|
340
|
-
try { spawnSync('taskkill', ['/F', '/T', '/PID', String(currentChildPid)], { stdio: 'ignore', windowsHide: true, timeout: 3000 }); } catch (_) {}
|
|
341
|
-
}
|
|
354
|
+
killChild('heartbeat-stale');
|
|
342
355
|
return;
|
|
343
356
|
}
|
|
344
357
|
const reported = status.wrapper_sha || null;
|
|
@@ -350,10 +363,7 @@ function checkWatcherHealth() {
|
|
|
350
363
|
on_disk_sha: onDisk,
|
|
351
364
|
severity: 'info',
|
|
352
365
|
});
|
|
353
|
-
|
|
354
|
-
if (process.platform === 'win32') {
|
|
355
|
-
try { spawnSync('taskkill', ['/F', '/T', '/PID', String(currentChildPid)], { stdio: 'ignore', windowsHide: true, timeout: 3000 }); } catch (_) {}
|
|
356
|
-
}
|
|
366
|
+
killChild('wrapper-change');
|
|
357
367
|
return;
|
|
358
368
|
}
|
|
359
369
|
if (status.version_drifted === true) {
|
|
@@ -377,10 +387,7 @@ function checkWatcherHealth() {
|
|
|
377
387
|
try { fs.unlinkSync(path.join(gmTools, f)); } catch (_) {}
|
|
378
388
|
}
|
|
379
389
|
} catch (_) {}
|
|
380
|
-
|
|
381
|
-
if (process.platform === 'win32') {
|
|
382
|
-
try { spawnSync('taskkill', ['/F', '/T', '/PID', String(currentChildPid)], { stdio: 'ignore', windowsHide: true, timeout: 3000 }); } catch (_) {}
|
|
383
|
-
}
|
|
390
|
+
killChild('version-change');
|
|
384
391
|
}
|
|
385
392
|
}
|
|
386
393
|
|