gm-plugkit 2.0.1824 → 2.0.1826
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-gm-continue.md +32 -0
- package/SKILL-wfgy-method.md +91 -0
- package/bootstrap.js +61 -59
- package/cli.js +4 -1
- package/instructions/verify.md +4 -0
- package/package.json +3 -1
|
@@ -0,0 +1,32 @@
|
|
|
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
|
+
## What this skill does
|
|
12
|
+
|
|
13
|
+
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).
|
|
14
|
+
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.
|
|
15
|
+
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.
|
|
16
|
+
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.
|
|
17
|
+
5. Two outcomes, decided by what steps 2-4 actually find:
|
|
18
|
+
- **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.
|
|
19
|
+
- **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.
|
|
20
|
+
- **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.
|
|
21
|
+
|
|
22
|
+
## When to load `wfgy-method` instead of `gm`
|
|
23
|
+
|
|
24
|
+
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.
|
|
25
|
+
|
|
26
|
+
## Recursion bound
|
|
27
|
+
|
|
28
|
+
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.
|
|
29
|
+
|
|
30
|
+
## Never a substitute for `gm`
|
|
31
|
+
|
|
32
|
+
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,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.
|
|
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, ΔS = 1 − cos(I, G) (I = current state, G = goal/anchor), and a trend classifier over consecutive ΔS 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 ΔS, 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 ΔS**: absent a real embedding call, any numeric ΔS you produce is your own qualitative estimate, not a measurement. Use the label ("ΔS is climbing," "ΔS looks high here") as shorthand for "this step is drifting from the stated goal" — never present a specific decimal (e.g. "ΔS = 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`; most gm-managed repos have one), a real `similarity` verb is available: dispatch `{"text_a": "<G>", "text_b": "<current state>"}` to it and read back `{"similarity", "distance"}` — `distance` is a genuine `1 - cos(I, G)` computed from real BGE-small-en-v1.5 embeddings, not a self-estimate. When available, use this real value as ΔS directly and say so explicitly ("ΔS = 0.31, computed"). When not available, fall back to the qualitative label above and say so explicitly too ("ΔS 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 ΔS 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 ΔS 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 ΔS 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/bootstrap.js
CHANGED
|
@@ -774,71 +774,72 @@ function ensureGmPlugkitVersionFresh() {
|
|
|
774
774
|
} catch (_) { return false; }
|
|
775
775
|
}
|
|
776
776
|
|
|
777
|
+
const BOOTSTRAP_JS_BUNDLED_SKILLS = ['gm', 'gm-continue', 'wfgy-method'];
|
|
778
|
+
|
|
777
779
|
function ensureSkillMdFresh() {
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
for (const target of targets) {
|
|
811
|
-
try {
|
|
812
|
-
let needsWrite = true;
|
|
813
|
-
if (fs.existsSync(target)) {
|
|
814
|
-
const existing = fs.readFileSync(target, 'utf-8');
|
|
815
|
-
const existingHash = crypto.createHash('sha256').update(_norm(existing)).digest('hex');
|
|
816
|
-
if (existingHash === bundledHash) needsWrite = false;
|
|
817
|
-
}
|
|
818
|
-
if (needsWrite) {
|
|
819
|
-
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
820
|
-
const tmp = target + '.tmp';
|
|
821
|
-
fs.writeFileSync(tmp, bundled);
|
|
822
|
-
fs.renameSync(tmp, target);
|
|
823
|
-
refreshed.push(target);
|
|
780
|
+
const home = process.env.HOME || process.env.USERPROFILE || require('os').homedir();
|
|
781
|
+
const crypto = require('crypto');
|
|
782
|
+
const _norm = s => s.replace(/\r\n/g, '\n');
|
|
783
|
+
const allRefreshed = [];
|
|
784
|
+
const sources = {};
|
|
785
|
+
for (const skillName of BOOTSTRAP_JS_BUNDLED_SKILLS) {
|
|
786
|
+
try {
|
|
787
|
+
const candidates = [
|
|
788
|
+
path.join(__dirname, skillName === 'gm' ? 'SKILL.md' : `SKILL-${skillName}.md`),
|
|
789
|
+
path.join(__dirname, '..', 'gm-skill', 'skills', skillName, 'SKILL.md'),
|
|
790
|
+
path.join(__dirname, '..', '..', 'gm-skill', 'skills', skillName, 'SKILL.md'),
|
|
791
|
+
path.join(__dirname, '..', 'skills', skillName, 'SKILL.md'),
|
|
792
|
+
];
|
|
793
|
+
const bundledPath = candidates.find(p => {
|
|
794
|
+
try { return fs.existsSync(p); } catch (_) { return false; }
|
|
795
|
+
});
|
|
796
|
+
if (!bundledPath) {
|
|
797
|
+
try { obsEvent('bootstrap', 'skill-md.refresh.bundled-not-found', { skillName, searched: candidates }); } catch (_) {}
|
|
798
|
+
continue;
|
|
799
|
+
}
|
|
800
|
+
const bundled = fs.readFileSync(bundledPath, 'utf-8');
|
|
801
|
+
const bundledHash = crypto.createHash('sha256').update(_norm(bundled)).digest('hex');
|
|
802
|
+
const targets = [
|
|
803
|
+
path.join(home, '.agents', 'skills', skillName, 'SKILL.md'),
|
|
804
|
+
path.join(home, '.claude', 'skills', skillName, 'SKILL.md'),
|
|
805
|
+
];
|
|
806
|
+
if (skillName === 'gm') {
|
|
807
|
+
for (const legacy of [
|
|
808
|
+
path.join(home, '.agents', 'skills', 'gm-skill'),
|
|
809
|
+
path.join(home, '.claude', 'skills', 'gm-skill'),
|
|
810
|
+
]) {
|
|
811
|
+
try { if (fs.existsSync(legacy)) fs.rmSync(legacy, { recursive: true, force: true }); } catch (_) {}
|
|
824
812
|
}
|
|
825
|
-
}
|
|
813
|
+
}
|
|
814
|
+
sources[skillName] = bundledPath;
|
|
815
|
+
for (const target of targets) {
|
|
826
816
|
try {
|
|
827
|
-
|
|
828
|
-
|
|
817
|
+
let needsWrite = true;
|
|
818
|
+
if (fs.existsSync(target)) {
|
|
819
|
+
const existing = fs.readFileSync(target, 'utf-8');
|
|
820
|
+
const existingHash = crypto.createHash('sha256').update(_norm(existing)).digest('hex');
|
|
821
|
+
if (existingHash === bundledHash) needsWrite = false;
|
|
822
|
+
}
|
|
823
|
+
if (needsWrite) {
|
|
824
|
+
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
825
|
+
const tmp = target + '.tmp';
|
|
826
|
+
fs.writeFileSync(tmp, bundled);
|
|
827
|
+
fs.renameSync(tmp, target);
|
|
828
|
+
allRefreshed.push(target);
|
|
829
|
+
}
|
|
830
|
+
} catch (e) {
|
|
831
|
+
try { obsEvent('bootstrap', 'skill-md.refresh.target-failed', { target, error: e.message }); } catch (_) {}
|
|
832
|
+
}
|
|
829
833
|
}
|
|
834
|
+
} catch (e) {
|
|
835
|
+
try { obsEvent('bootstrap', 'skill-md.refresh.failed', { skillName, error: e.message }); } catch (_) {}
|
|
830
836
|
}
|
|
831
|
-
if (refreshed.length > 0) {
|
|
832
|
-
log(`SKILL.md refreshed (sha=${bundledHash.slice(0, 12)}): ${refreshed.length} target(s)`);
|
|
833
|
-
try {
|
|
834
|
-
obsEvent('bootstrap', 'skill-md.refreshed', { hash: bundledHash.slice(0, 12), targets: refreshed, source: bundledPath });
|
|
835
|
-
} catch (_) {}
|
|
836
|
-
}
|
|
837
|
-
return { refreshed, bundledHash, source: bundledPath };
|
|
838
|
-
} catch (e) {
|
|
839
|
-
try { obsEvent('bootstrap', 'skill-md.refresh.failed', { error: e.message }); } catch (_) {}
|
|
840
|
-
return { error: e.message };
|
|
841
837
|
}
|
|
838
|
+
if (allRefreshed.length > 0) {
|
|
839
|
+
log(`SKILL.md refreshed: ${allRefreshed.length} target(s)`);
|
|
840
|
+
try { obsEvent('bootstrap', 'skill-md.refreshed', { targets: allRefreshed, sources }); } catch (_) {}
|
|
841
|
+
}
|
|
842
|
+
return { refreshed: allRefreshed, sources };
|
|
842
843
|
}
|
|
843
844
|
|
|
844
845
|
function installedVersionAtTools() {
|
|
@@ -1103,6 +1104,7 @@ module.exports = {
|
|
|
1103
1104
|
daemonVersionSentinel,
|
|
1104
1105
|
readVersionFile,
|
|
1105
1106
|
ensureGmPlugkitVersionFresh,
|
|
1107
|
+
ensureSkillMdFresh,
|
|
1106
1108
|
};
|
|
1107
1109
|
|
|
1108
1110
|
if (require.main === module) {
|
package/cli.js
CHANGED
|
@@ -5,7 +5,7 @@ const fs = require('fs');
|
|
|
5
5
|
const os = require('os');
|
|
6
6
|
const path = require('path');
|
|
7
7
|
const cp = require('child_process');
|
|
8
|
-
const { ensureReady, startSpoolDaemon, gmToolsDir, readVersionFile, ensureGmPlugkitVersionFresh } = require('./bootstrap');
|
|
8
|
+
const { ensureReady, startSpoolDaemon, gmToolsDir, readVersionFile, ensureGmPlugkitVersionFresh, ensureSkillMdFresh } = require('./bootstrap');
|
|
9
9
|
|
|
10
10
|
function readUpdateAvailableMarker(dir) {
|
|
11
11
|
try {
|
|
@@ -215,12 +215,15 @@ function writeCliError(phase, err) {
|
|
|
215
215
|
const versionDrifted = localVersionDrifted || remoteVersionDrifted;
|
|
216
216
|
if (statusServing(already, 12000) && !versionDrifted) {
|
|
217
217
|
try { ensureGmPlugkitVersionFresh(); } catch (_) {}
|
|
218
|
+
let skillRefresh = null;
|
|
219
|
+
try { skillRefresh = ensureSkillMdFresh(); } catch (_) {}
|
|
218
220
|
writeCliStatus({ phase: 'ready', already_serving: true, watcher_pid: already.pid });
|
|
219
221
|
console.log(JSON.stringify({
|
|
220
222
|
ok: true,
|
|
221
223
|
already_serving: true,
|
|
222
224
|
watcher_pid: already.pid,
|
|
223
225
|
version: already.version,
|
|
226
|
+
skills_refreshed: skillRefresh && skillRefresh.refreshed || [],
|
|
224
227
|
message: 'plugkit already serving, no bootstrap/spawn needed',
|
|
225
228
|
}));
|
|
226
229
|
process.exit(0);
|
package/instructions/verify.md
CHANGED
|
@@ -39,6 +39,10 @@ Every claim of correctness is proven by a live `exec_js`/`browser` dispatch witn
|
|
|
39
39
|
|
|
40
40
|
**No test files, no exceptions.** A `deviation.synthetic-test-file` at VERIFY (new `*.test.*`/`*.spec.*`, a `test/`/`__tests__/` directory, a testing-framework import, or any standing root-level test file found in the diff) blocks `transition` exactly like an unwitnessed mutable -- delete it and replace its assertions with a live `exec_js`/`browser` witness, then re-verify. This is manual legwork, not framework legwork: the adversarial corner-case sweep above is how every class gets exercised, by running the real thing, never by writing a test case that runs it later.
|
|
41
41
|
|
|
42
|
+
**No fake shipped code, checked at VERIFY too, not only at EMIT.** A `Mock*`/`Fake*`/`Stub*` class or a hardcoded always-succeeds/input-invariant short-circuit anywhere in the diff is the same class of deviation as a test file -- grep the diff for these names before transitioning; a mock network/service/client shipped as if it were the real integration is exactly what "nothing fake in source" forbids, whether or not it lives in a `test/` directory. Real input through real code into real output is the only acceptance shape.
|
|
43
|
+
|
|
44
|
+
**Documenting a hard row instead of implementing it is a false completion, not a resolution.** `prd-resolve` refuses two identical/near-identical `witness_evidence` strings across different PRD ids (`deviation.prd-resolve-duplicate-witness`) -- generic copy-pasted witness text ("code written and tested") across structurally distinct rows is the rubber-stamp tell: a row that got a README section titled "Future Optimizations"/"Not Yet Implemented" and a `status: completed` in the same turn was NOT solved, it was deferred with different words. If a row is genuinely out of reach this turn, it stays open or gets `blockedBy: [external]` with a real, specific reason -- it does not get marked completed because a design doc for it now exists. Each row's witness must name the specific file:line/exec-output/browser-read proving THAT row's own distinct deliverable, not a shared paragraph.
|
|
45
|
+
|
|
42
46
|
## Residual-scan
|
|
43
47
|
|
|
44
48
|
`residual-scan` is dispatched BEFORE `transition to=CONSOLIDATE` -- the CONSOLIDATE entry gate refuses without its fired marker, and the denial names `residual-scan` as the next dispatch. It examines the open surface -- PRD pending, browser sessions, dirty tree, untracked artifacts, browser-witness coverage for session-modified client-side files -- non-empty = non-convergent -> expand PRD with the reachable in-spirit residual, re-execute. One-shot per stop window via marker. `reason: "browser sessions still open"` -> close each (`browser` `session close <id>`; `session list` enumerates); rescanning without closing is idle-mid-chain/polling deviation -- the denial names the next verb, dispatch it.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gm-plugkit",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.1826",
|
|
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": {
|
|
@@ -17,6 +17,8 @@
|
|
|
17
17
|
"plugkit.version",
|
|
18
18
|
"plugkit.sha256",
|
|
19
19
|
"SKILL.md",
|
|
20
|
+
"SKILL-gm-continue.md",
|
|
21
|
+
"SKILL-wfgy-method.md",
|
|
20
22
|
"instructions/"
|
|
21
23
|
],
|
|
22
24
|
"keywords": [
|