gm-skill 2.0.1617 → 2.0.1618
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/AGENTS.md +10 -8
- package/README.md +29 -8
- package/bin/bootstrap.js +14 -4
- package/bin/install.js +214 -0
- package/gm-plugkit/bootstrap.js +11 -5
- package/gm-plugkit/instructions/emit.md +1 -1
- package/gm-plugkit/instructions/entry.md +2 -2
- package/gm-plugkit/instructions/execute.md +4 -2
- package/gm-plugkit/instructions/plan.md +1 -1
- package/gm-plugkit/instructions/verify.md +1 -1
- package/gm-plugkit/package.json +1 -1
- package/gm-plugkit/plugkit-wasm-wrapper.js +5 -5
- package/gm.json +1 -1
- package/lib/skill-bootstrap.js +11 -5
- package/package.json +4 -2
- package/prompts/pre-compact.txt +1 -1
- package/prompts/prompt-submit.txt +1 -1
- package/prompts/session-start.txt +2 -2
- package/skills/{gm-skill → gm}/SKILL.md +1 -1
package/AGENTS.md
CHANGED
|
@@ -22,7 +22,7 @@ Skills encode environment-specific constraints that override general knowledge.
|
|
|
22
22
|
|
|
23
23
|
# Architecture & Philosophy
|
|
24
24
|
|
|
25
|
-
This repo IS the published `gm-skill` npm package: repo root = package root, no factory, no build step generating a separate output dir. `skills/gm
|
|
25
|
+
This repo IS the published `gm-skill` npm package: repo root = package root, no factory, no build step generating a separate output dir. `skills/gm/SKILL.md` is the entry point; orchestration logic lives in rs-plugkit, served on demand via the `instruction` verb. Agent-facing prose (phase instruction + gate/residual text) is externalized to an editable `gm-plugkit/instructions/` bundle, so editing prose is a gm-plugkit republish with no Rust rebuild. Mechanism (prose.rs per-key fallback to compiled const; sync-instruction-consts.mjs byte-aligns the .md and the rs-plugkit consts) in rs-learn (`recall: string-externalization project`).
|
|
26
26
|
|
|
27
27
|
## WASM-only
|
|
28
28
|
|
|
@@ -30,9 +30,9 @@ The plugkit stack runs as a wasm cdylib loaded by `plugkit-wasm-wrapper.js` unde
|
|
|
30
30
|
|
|
31
31
|
**Every wasm host-import `extern "C"` block carries `#[link(wasm_import_module = "env")]`** -- in rs-plugkit AND every dep crate linked into the cdylib (rs-learn) AND any sibling building wasm (rs-exec, rs-search); miss it anywhere and the cascade goes dark (local builds stay green, only Linux CI link fails). Incident + host-fn enumeration in rs-learn (`recall: cascade outage wasm import module link`, `recall: wasm host-import link-module trap`).
|
|
32
32
|
|
|
33
|
-
**`plugkit-wasm-wrapper.js` is ESM; import node builtins at module scope, never inline `require()`**
|
|
33
|
+
**`plugkit-wasm-wrapper.js` is ESM; import node builtins at module scope, never inline `require()`** (rs-learn: `recall: wrapper require not defined under bun`).
|
|
34
34
|
|
|
35
|
-
**Every single-instance/lock guard is atomic** (O_EXCL / atomic-rename), never check-then-act
|
|
35
|
+
**Every single-instance/lock guard is atomic** (O_EXCL / atomic-rename), never check-then-act (rs-learn: `recall: supervisor churn TOCTOU atomic guard`).
|
|
36
36
|
|
|
37
37
|
## Spool dispatch ABI
|
|
38
38
|
|
|
@@ -70,15 +70,17 @@ Record only non-obvious technical caveats that cost multiple runs to discover; r
|
|
|
70
70
|
|
|
71
71
|
## Build
|
|
72
72
|
|
|
73
|
-
No build step; the repo root is the published artifact. `npm publish` from root publishes `gm-skill
|
|
73
|
+
No build step; the repo root is the published artifact. `npm publish` from root publishes `gm-skill` (npm package id is permanent; only the skill DIRECTORY is `skills/gm`, so the command is `/gm`). `package.json` `files:` pins the shipped paths. `AnEntrypoint/gm-skill` is a back-compat mirror receiving only `skills/gm/SKILL.md` per release.
|
|
74
|
+
|
|
75
|
+
`bin/install.js` is the canonical installer -- no npx `skills` library, no marketplace. It copies `skills/gm` into `<home>/.claude/skills/gm/` (personal) or `.claude/skills/gm/` (`--project`); the dir name IS the `/command`. Non-interactive (`-y`/`--yes` or non-TTY) SETS four Claude Code settings (`autoCompactEnabled:true`, `autoCompactWindow:380000` -- an ABSOLUTE token count = 38% of 1M, not a percentage -- `effortLevel:"low"`, `alwaysThinkingEnabled:false`) and explains the revert; interactive OFFERS them. The reasoning-in-code framing it prints is load-bearing: the LLM still thinks, it tests its thoughts in code (execution as reasoning). `test.js checkRenameAndInstaller()` is the structural guard (asserts no `skills/gm-skill`, package id stays `gm-skill`, installer lands the skill + writes the four keys into an isolated temp HOME).
|
|
74
76
|
|
|
75
77
|
## The agent is the orchestrator; plugkit is the brain it drives
|
|
76
78
|
|
|
77
79
|
Plugkit is the stateful library the agent drives by dispatching verbs -- it does not act autonomously, advance phases in the background, or validate transitions while the agent waits. Every state change is a verb the agent writes into `.gm/exec-spool/in/<verb>/<N>.txt`; the dispatch ledger is ground truth, so zero dispatches with a narrated PLAN->COMPLETE walk = a fabricated walk. The PLAN -> EXECUTE -> EMIT -> VERIFY -> COMPLETE state machine lives natively in rs-plugkit (phase/mutables/memorize/transition-legality as data + gate checks), but the agent triggers every operation; plugkit is synchronous from the agent's view, so polling the output dir instead of reading the response file is the canonical misuse. File paths + verb enumeration in rs-learn (`recall: rs-plugkit state-machine internals`).
|
|
78
80
|
|
|
79
|
-
## gm
|
|
81
|
+
## gm is the canonical universal harness
|
|
80
82
|
|
|
81
|
-
`skills/gm
|
|
83
|
+
`skills/gm/SKILL.md` is the single source of truth; one skill shipped, legacy 15-platform fanout retired+archived. Canonical install: `bun x skills add AnEntrypoint/gm`. Detail in rs-learn (`recall: legacy gm-skill variants retired`).
|
|
82
84
|
|
|
83
85
|
## Tool surface is plugkit-only
|
|
84
86
|
|
|
@@ -152,9 +154,9 @@ Push to any rs-* sibling triggers `cascade.yml` -> rs-plugkit `release.yml` -> s
|
|
|
152
154
|
|
|
153
155
|
Orchestration state is tracked via `.gm/` marker files, not hook events; the CLI layer calls `checkDispatchGates()` before tool execution to gate Write/Edit/git. Marker set (`prd.yml, mutables.yml, needs-gm, gm-fired-<sessionId>, residual-check-fired`) + SpoolDispatcher mechanism in rs-learn (`recall: gate enforcement layer`, `recall: spool dispatch gates marker files`).
|
|
154
156
|
|
|
155
|
-
**gm
|
|
157
|
+
**gm tool-use sequencing**: `Skill(skill="gm")` clears the needs-gm gate. One shipped skill, no subagent variant. Marker mechanics in rs-learn (`recall: gm-skill tool-use sequencing mechanics`).
|
|
156
158
|
|
|
157
|
-
**The skill is the driver, not a post-hoc witness**: when a request carries the standing instruction to use gm
|
|
159
|
+
**The skill is the driver, not a post-hoc witness**: when a request carries the standing instruction to use the gm skill (every `/loop` fire, any prompt naming `/gm`), the FIRST working action is `Skill(skill="gm")`, and the skill prose drives the chain PLAN->COMPLETE. Dispatching spool verbs directly without first entering the skill executes the work outside the skill the user asked to drive it; entering only at the end to confirm terminal state does NOT satisfy the instruction. The boot probe (`cat .gm/exec-spool/.status.json` ...) is prescribed by the skill and may precede invocation; everything that mutates state happens inside the skill-driven session.
|
|
158
160
|
|
|
159
161
|
**Dead-watcher recovery uses `bun x gm-plugkit@latest spool`, never direct-node boot** (mechanism in rs-learn: `recall: dead-watcher recovery bun x not direct-node`).
|
|
160
162
|
|
package/README.md
CHANGED
|
@@ -14,19 +14,40 @@ disclaimer: this is extremely opinionated. it will block bash, redirect your too
|
|
|
14
14
|
|
|
15
15
|
## install
|
|
16
16
|
|
|
17
|
+
A Claude Code Agent Skill is just a directory at `~/.claude/skills/<name>/SKILL.md` (personal, all projects) or `.claude/skills/<name>/SKILL.md` (one project). The directory name becomes the slash command. No marketplace, no `npx skills` library -- the installer copies the directory into place.
|
|
18
|
+
|
|
19
|
+
Interactive (offers Claude Code settings):
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
npx gm-skill install
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Non-interactive (sets Claude Code settings outright, prints how to revert):
|
|
26
|
+
|
|
17
27
|
```
|
|
18
|
-
|
|
28
|
+
npx gm-skill install --yes
|
|
19
29
|
```
|
|
20
30
|
|
|
21
|
-
|
|
31
|
+
Project-local instead of home (`./.claude/skills/gm`):
|
|
22
32
|
|
|
23
33
|
```
|
|
24
|
-
|
|
34
|
+
npx gm-skill install --project
|
|
25
35
|
```
|
|
26
36
|
|
|
27
|
-
|
|
37
|
+
The skill installs as `/gm`. On Claude Code the installer also offers (interactive) or sets (`--yes`):
|
|
28
38
|
|
|
29
|
-
|
|
39
|
+
- `autoCompactEnabled: true`
|
|
40
|
+
- `autoCompactWindow: 380000` -- an absolute token count (38% of a 1M window), not a percentage
|
|
41
|
+
- `effortLevel: "low"`
|
|
42
|
+
- `alwaysThinkingEnabled: false`
|
|
43
|
+
|
|
44
|
+
The model still reasons -- gm replaces hidden thinking tokens with reasoning in code: form a hypothesis, run it as code or a browser probe, read the real result. Reasoning becomes a witnessed execution rather than an unverified internal monologue. Change any of these back in `~/.claude/settings.json` or via `/config` at any time.
|
|
45
|
+
|
|
46
|
+
then add this line to your agent's global memory / system prompt (the installer seeds it into `~/.claude/CLAUDE.md` for you):
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
always use the gm skill for everything, always fan out subagents
|
|
50
|
+
```
|
|
30
51
|
|
|
31
52
|
## what's in this repo
|
|
32
53
|
|
|
@@ -34,7 +55,7 @@ This repo IS the published `gm-skill` npm package. No build step, no factory. Th
|
|
|
34
55
|
|
|
35
56
|
```
|
|
36
57
|
gm/
|
|
37
|
-
|-- skills/gm
|
|
58
|
+
|-- skills/gm/ <- the skill (SKILL.md), installed as /gm
|
|
38
59
|
|-- bin/ <- bootstrap + plugkit launcher (gmsniff / ccsniff are separate npm packages, `bun x gmsniff`, `bun x ccsniff`)
|
|
39
60
|
|-- lib/ <- runtime: spool dispatch, skill bootstrap, daemon mgmt
|
|
40
61
|
|-- agents/ <- subagent prompts (gm, memorize, research-worker, textprocessing)
|
|
@@ -50,7 +71,7 @@ gm/
|
|
|
50
71
|
|
|
51
72
|
The two npm packages this repo publishes:
|
|
52
73
|
|
|
53
|
-
- **`gm-skill`**: the
|
|
74
|
+
- **`gm-skill`**: the npm package that bundles the `/gm` skill + installer (`npx gm-skill install`)
|
|
54
75
|
- **`gm-plugkit`**: the wasm-wrapper daemon, dependency of `gm-skill`
|
|
55
76
|
|
|
56
77
|
## how it works
|
|
@@ -92,7 +113,7 @@ A push to `main` triggers `.github/workflows/publish.yml`:
|
|
|
92
113
|
1. auto-bump `gm.json::version` + `package.json::version` + `gm-plugkit/package.json::version`
|
|
93
114
|
2. publish `gm-skill` to npm from repo root (no build step)
|
|
94
115
|
3. publish `gm-plugkit` to npm from `gm-plugkit/`
|
|
95
|
-
4. mirror `skills/gm
|
|
116
|
+
4. mirror `skills/gm/SKILL.md` to the `AnEntrypoint/gm-skill` repo (back-compat)
|
|
96
117
|
|
|
97
118
|
`.github/workflows/gh-pages.yml` builds the `site/` flatspace source to `dist/` and deploys to GitHub Pages.
|
|
98
119
|
|
package/bin/bootstrap.js
CHANGED
|
@@ -20,8 +20,8 @@ function log(msg) {
|
|
|
20
20
|
function ensureSkillMdCurrent(wrapperDir) {
|
|
21
21
|
try {
|
|
22
22
|
const candidates = [
|
|
23
|
-
path.join(wrapperDir, '..', 'skills', 'gm
|
|
24
|
-
path.join(wrapperDir, '..', '..', 'skills', 'gm
|
|
23
|
+
path.join(wrapperDir, '..', 'skills', 'gm', 'SKILL.md'),
|
|
24
|
+
path.join(wrapperDir, '..', '..', 'skills', 'gm', 'SKILL.md'),
|
|
25
25
|
path.join(wrapperDir, '..', 'SKILL.md'),
|
|
26
26
|
];
|
|
27
27
|
const bundledPath = candidates.find(p => { try { return fs.existsSync(p); } catch (_) { return false; } });
|
|
@@ -31,9 +31,15 @@ function ensureSkillMdCurrent(wrapperDir) {
|
|
|
31
31
|
const bundledHash = crypto.createHash('sha256').update(_norm(bundled)).digest('hex');
|
|
32
32
|
const home = os.homedir();
|
|
33
33
|
const targets = [
|
|
34
|
-
path.join(home, '.agents', 'skills', 'gm
|
|
35
|
-
path.join(home, '.claude', 'skills', 'gm
|
|
34
|
+
path.join(home, '.agents', 'skills', 'gm', 'SKILL.md'),
|
|
35
|
+
path.join(home, '.claude', 'skills', 'gm', 'SKILL.md'),
|
|
36
36
|
];
|
|
37
|
+
for (const legacy of [
|
|
38
|
+
path.join(home, '.agents', 'skills', 'gm-skill'),
|
|
39
|
+
path.join(home, '.claude', 'skills', 'gm-skill'),
|
|
40
|
+
]) {
|
|
41
|
+
try { if (fs.existsSync(legacy)) fs.rmSync(legacy, { recursive: true, force: true }); } catch (_) {}
|
|
42
|
+
}
|
|
37
43
|
const refreshed = [];
|
|
38
44
|
for (const target of targets) {
|
|
39
45
|
try {
|
|
@@ -663,6 +669,10 @@ module.exports = { bootstrap, getWasmPath, cacheRoot, obsEvent, killRunningDaemo
|
|
|
663
669
|
|
|
664
670
|
if (require.main === module) {
|
|
665
671
|
const argv = process.argv.slice(2);
|
|
672
|
+
if (argv[0] === 'install') {
|
|
673
|
+
require('./install.js');
|
|
674
|
+
return;
|
|
675
|
+
}
|
|
666
676
|
bootstrap({ silent: false })
|
|
667
677
|
.then(p => { process.stdout.write(p + '\n'); process.exit(0); })
|
|
668
678
|
.catch(err => {
|
package/bin/install.js
ADDED
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
const os = require('os');
|
|
7
|
+
const readline = require('readline');
|
|
8
|
+
|
|
9
|
+
const SKILL_NAME = 'gm';
|
|
10
|
+
const AUTOCOMPACT_WINDOW = 380000;
|
|
11
|
+
|
|
12
|
+
function out(msg) { process.stdout.write(msg + '\n'); }
|
|
13
|
+
function err(msg) { process.stderr.write(msg + '\n'); }
|
|
14
|
+
|
|
15
|
+
function parseArgs(argv) {
|
|
16
|
+
const flags = { yes: false, project: false, help: false };
|
|
17
|
+
for (const a of argv) {
|
|
18
|
+
if (a === '-y' || a === '--yes' || a === '--non-interactive') flags.yes = true;
|
|
19
|
+
else if (a === '--project') flags.project = true;
|
|
20
|
+
else if (a === '-h' || a === '--help') flags.help = true;
|
|
21
|
+
}
|
|
22
|
+
return flags;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function homeDir() {
|
|
26
|
+
return process.env.USERPROFILE || process.env.HOME || os.homedir();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function bundledSkillDir() {
|
|
30
|
+
const candidates = [
|
|
31
|
+
path.join(__dirname, '..', 'skills', SKILL_NAME),
|
|
32
|
+
path.join(__dirname, '..', '..', 'skills', SKILL_NAME),
|
|
33
|
+
];
|
|
34
|
+
return candidates.find(p => { try { return fs.existsSync(path.join(p, 'SKILL.md')); } catch (_) { return false; } }) || null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function detectClaudeCode(home) {
|
|
38
|
+
try { return fs.existsSync(path.join(home, '.claude')); } catch (_) { return false; }
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function detectAgentsHost(home) {
|
|
42
|
+
try { return fs.existsSync(path.join(home, '.agents')); } catch (_) { return false; }
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function copyTree(src, dst) {
|
|
46
|
+
fs.mkdirSync(dst, { recursive: true });
|
|
47
|
+
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
|
|
48
|
+
const s = path.join(src, entry.name);
|
|
49
|
+
const d = path.join(dst, entry.name);
|
|
50
|
+
if (entry.isDirectory()) copyTree(s, d);
|
|
51
|
+
else fs.copyFileSync(s, d);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function installSkillDir(skillSrc, home, projectScope) {
|
|
56
|
+
const installed = [];
|
|
57
|
+
const roots = projectScope
|
|
58
|
+
? [path.join(process.cwd(), '.claude', 'skills', SKILL_NAME)]
|
|
59
|
+
: [path.join(home, '.claude', 'skills', SKILL_NAME), path.join(home, '.agents', 'skills', SKILL_NAME)];
|
|
60
|
+
for (const root of roots) {
|
|
61
|
+
const legacy = path.join(path.dirname(root), 'gm-skill');
|
|
62
|
+
try { if (fs.existsSync(legacy)) fs.rmSync(legacy, { recursive: true, force: true }); } catch (_) {}
|
|
63
|
+
try {
|
|
64
|
+
if (fs.existsSync(root)) fs.rmSync(root, { recursive: true, force: true });
|
|
65
|
+
copyTree(skillSrc, root);
|
|
66
|
+
installed.push(root);
|
|
67
|
+
} catch (e) {
|
|
68
|
+
err(`failed to install skill to ${root}: ${e.message}`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return installed;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function seedGlobalMemory(home) {
|
|
75
|
+
const memPath = path.join(home, '.claude', 'CLAUDE.md');
|
|
76
|
+
const line = 'Always use the gm skill (/gm) to drive non-trivial coding tasks.';
|
|
77
|
+
try {
|
|
78
|
+
let cur = '';
|
|
79
|
+
if (fs.existsSync(memPath)) cur = fs.readFileSync(memPath, 'utf8');
|
|
80
|
+
if (cur.split(/\r?\n/).some(l => l.trim() === line)) return false;
|
|
81
|
+
fs.mkdirSync(path.dirname(memPath), { recursive: true });
|
|
82
|
+
const sep = cur && !cur.endsWith('\n') ? '\n' : '';
|
|
83
|
+
fs.writeFileSync(memPath, cur + sep + line + '\n');
|
|
84
|
+
return true;
|
|
85
|
+
} catch (_) { return false; }
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function readSettings(settingsPath) {
|
|
89
|
+
try {
|
|
90
|
+
const raw = fs.readFileSync(settingsPath, 'utf8');
|
|
91
|
+
return { obj: JSON.parse(raw), existed: true, corrupt: false };
|
|
92
|
+
} catch (e) {
|
|
93
|
+
if (e.code === 'ENOENT') return { obj: {}, existed: false, corrupt: false };
|
|
94
|
+
return { obj: {}, existed: true, corrupt: true };
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function applyClaudeSettings(home) {
|
|
99
|
+
const settingsPath = path.join(home, '.claude', 'settings.json');
|
|
100
|
+
const { obj, existed, corrupt } = readSettings(settingsPath);
|
|
101
|
+
if (corrupt) {
|
|
102
|
+
const backup = settingsPath + '.bak';
|
|
103
|
+
try { fs.copyFileSync(settingsPath, backup); err(`existing settings.json was malformed; backed up to ${backup}`); } catch (_) {}
|
|
104
|
+
}
|
|
105
|
+
obj.autoCompactEnabled = true;
|
|
106
|
+
obj.autoCompactWindow = AUTOCOMPACT_WINDOW;
|
|
107
|
+
obj.effortLevel = 'low';
|
|
108
|
+
obj.alwaysThinkingEnabled = false;
|
|
109
|
+
fs.mkdirSync(path.dirname(settingsPath), { recursive: true });
|
|
110
|
+
const tmp = settingsPath + '.tmp';
|
|
111
|
+
fs.writeFileSync(tmp, JSON.stringify(obj, null, 2) + '\n');
|
|
112
|
+
JSON.parse(fs.readFileSync(tmp, 'utf8'));
|
|
113
|
+
fs.renameSync(tmp, settingsPath);
|
|
114
|
+
return { settingsPath, existed };
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const SETTINGS_EXPLAINER = [
|
|
118
|
+
'Claude Code settings applied:',
|
|
119
|
+
' autoCompactEnabled = true keep long sessions coherent by auto-compacting context',
|
|
120
|
+
` autoCompactWindow = ${AUTOCOMPACT_WINDOW} absolute token count (38% of a 1M window), not a percentage`,
|
|
121
|
+
" effortLevel = low thinking effort lowered",
|
|
122
|
+
' alwaysThinkingEnabled = false explicit thinking turned off',
|
|
123
|
+
'',
|
|
124
|
+
'The model will still reason -- gm replaces hidden thinking tokens with reasoning in code:',
|
|
125
|
+
'it forms a hypothesis, runs it as code or a browser probe, and reads the real result.',
|
|
126
|
+
'Reasoning becomes a witnessed execution rather than an unverified internal monologue.',
|
|
127
|
+
'Change any of these back in ~/.claude/settings.json or via /config at any time.',
|
|
128
|
+
].join('\n');
|
|
129
|
+
|
|
130
|
+
function ask(rl, question) {
|
|
131
|
+
return new Promise(resolve => rl.question(question, ans => resolve(ans)));
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
async function offerClaudeSettings(home) {
|
|
135
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
136
|
+
try {
|
|
137
|
+
out('');
|
|
138
|
+
out('Claude Code detected. gm works best with reasoning-in-code rather than hidden thinking tokens.');
|
|
139
|
+
out('Offer to set: autoCompactEnabled=true, autoCompactWindow=' + AUTOCOMPACT_WINDOW + ', effortLevel=low, alwaysThinkingEnabled=false.');
|
|
140
|
+
const ans = (await ask(rl, 'Apply these Claude Code settings now? [y/N] ')).trim().toLowerCase();
|
|
141
|
+
if (ans === 'y' || ans === 'yes') {
|
|
142
|
+
const r = applyClaudeSettings(home);
|
|
143
|
+
out(`Wrote ${r.settingsPath}.`);
|
|
144
|
+
out(SETTINGS_EXPLAINER);
|
|
145
|
+
return true;
|
|
146
|
+
}
|
|
147
|
+
out('Skipped Claude Code settings.');
|
|
148
|
+
return false;
|
|
149
|
+
} finally {
|
|
150
|
+
rl.close();
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function runPlugkitBootstrap() {
|
|
155
|
+
try {
|
|
156
|
+
const boot = require('../gm-plugkit/bootstrap.js');
|
|
157
|
+
if (boot && typeof boot.bootstrap === 'function') return boot.bootstrap({ silent: true }).then(() => true).catch(() => false);
|
|
158
|
+
} catch (_) {}
|
|
159
|
+
return Promise.resolve(false);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function printHelp() {
|
|
163
|
+
out('gm installer');
|
|
164
|
+
out('');
|
|
165
|
+
out('Usage:');
|
|
166
|
+
out(' npx gm-skill install interactive install (offers Claude Code settings)');
|
|
167
|
+
out(' npx gm-skill install --yes non-interactive install (sets Claude Code settings)');
|
|
168
|
+
out(' npx gm-skill install --project install into ./.claude/skills/gm instead of the home dir');
|
|
169
|
+
out('');
|
|
170
|
+
out('Installs the gm skill (/gm) by copying its directory into ~/.claude/skills/gm and');
|
|
171
|
+
out('~/.agents/skills/gm -- no npx "skills" library required.');
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
async function main() {
|
|
175
|
+
const rawArgs = process.argv.slice(2).filter(a => a !== 'install');
|
|
176
|
+
const flags = parseArgs(rawArgs);
|
|
177
|
+
if (flags.help) { printHelp(); return 0; }
|
|
178
|
+
|
|
179
|
+
const home = homeDir();
|
|
180
|
+
if (!home) { err('cannot resolve home directory (HOME/USERPROFILE unset)'); return 1; }
|
|
181
|
+
|
|
182
|
+
const skillSrc = bundledSkillDir();
|
|
183
|
+
if (!skillSrc) { err('bundled skill directory skills/gm not found in package'); return 1; }
|
|
184
|
+
|
|
185
|
+
const nonInteractive = flags.yes || !process.stdin.isTTY;
|
|
186
|
+
|
|
187
|
+
const installed = installSkillDir(skillSrc, home, flags.project);
|
|
188
|
+
if (installed.length === 0) { err('skill installation failed'); return 1; }
|
|
189
|
+
out('Installed gm skill to:');
|
|
190
|
+
for (const p of installed) out(' ' + p);
|
|
191
|
+
|
|
192
|
+
if (!flags.project) {
|
|
193
|
+
if (seedGlobalMemory(home)) out('Seeded global memory line in ~/.claude/CLAUDE.md.');
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const isClaudeCode = detectClaudeCode(home) || (!detectAgentsHost(home));
|
|
197
|
+
if (isClaudeCode) {
|
|
198
|
+
if (nonInteractive) {
|
|
199
|
+
const r = applyClaudeSettings(home);
|
|
200
|
+
out(`Wrote ${r.settingsPath}.`);
|
|
201
|
+
out(SETTINGS_EXPLAINER);
|
|
202
|
+
} else {
|
|
203
|
+
await offerClaudeSettings(home);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
await runPlugkitBootstrap();
|
|
208
|
+
|
|
209
|
+
out('');
|
|
210
|
+
out('Done. Open Claude Code and run /gm. New top-level skill dirs may need one restart to register.');
|
|
211
|
+
return 0;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
main().then(code => process.exit(code)).catch(e => { err('install failed: ' + (e && e.message || e)); process.exit(1); });
|
package/gm-plugkit/bootstrap.js
CHANGED
|
@@ -768,9 +768,9 @@ function ensureSkillMdFresh() {
|
|
|
768
768
|
try {
|
|
769
769
|
const candidates = [
|
|
770
770
|
path.join(__dirname, 'SKILL.md'),
|
|
771
|
-
path.join(__dirname, '..', 'gm-skill', 'skills', 'gm
|
|
772
|
-
path.join(__dirname, '..', '..', 'gm-skill', 'skills', 'gm
|
|
773
|
-
path.join(__dirname, '..', 'skills', 'gm
|
|
771
|
+
path.join(__dirname, '..', 'gm-skill', 'skills', 'gm', 'SKILL.md'),
|
|
772
|
+
path.join(__dirname, '..', '..', 'gm-skill', 'skills', 'gm', 'SKILL.md'),
|
|
773
|
+
path.join(__dirname, '..', 'skills', 'gm', 'SKILL.md'),
|
|
774
774
|
];
|
|
775
775
|
const bundledPath = candidates.find(p => {
|
|
776
776
|
try { return fs.existsSync(p); } catch (_) { return false; }
|
|
@@ -787,9 +787,15 @@ function ensureSkillMdFresh() {
|
|
|
787
787
|
const bundledHash = crypto.createHash('sha256').update(_norm(bundled)).digest('hex');
|
|
788
788
|
const home = process.env.HOME || process.env.USERPROFILE || require('os').homedir();
|
|
789
789
|
const targets = [
|
|
790
|
-
path.join(home, '.agents', 'skills', 'gm
|
|
791
|
-
path.join(home, '.claude', 'skills', 'gm
|
|
790
|
+
path.join(home, '.agents', 'skills', 'gm', 'SKILL.md'),
|
|
791
|
+
path.join(home, '.claude', 'skills', 'gm', 'SKILL.md'),
|
|
792
792
|
];
|
|
793
|
+
for (const legacy of [
|
|
794
|
+
path.join(home, '.agents', 'skills', 'gm-skill'),
|
|
795
|
+
path.join(home, '.claude', 'skills', 'gm-skill'),
|
|
796
|
+
]) {
|
|
797
|
+
try { if (fs.existsSync(legacy)) fs.rmSync(legacy, { recursive: true, force: true }); } catch (_) {}
|
|
798
|
+
}
|
|
793
799
|
const refreshed = [];
|
|
794
800
|
for (const target of targets) {
|
|
795
801
|
try {
|
|
@@ -14,7 +14,7 @@ Feed search outputs into EMIT only when the digest matches the live filesystem;
|
|
|
14
14
|
|
|
15
15
|
## Write-then-verify
|
|
16
16
|
|
|
17
|
-
One write per artifact, then a disk Read against every touched path to assert the change --
|
|
17
|
+
One write per artifact, then a disk Read against every touched path to assert the change -- you do not reason that the write succeeded, you run the read and witness it. Verified disk state IS the witness, not the tool-call return. On discrepancy, regress to root cause, do not retry.
|
|
18
18
|
|
|
19
19
|
**Client-side artifacts: write-then-browser-witness, same turn.** If the artifact is `.html .js .jsx .ts .tsx .vue .svelte .mjs .css` or any browser-loaded path, the disk Read is necessary but not sufficient -- also dispatch a `browser` verb that `page.evaluate`s the invariant the artifact establishes (the page-side assertion is the real witness; the disk Read only witnesses serialization). Skipping it ships a green-checked stub. The COMPLETE gate refuses while any client-side file edited this session lacks its paired browser-witness (`deviation.client-edit-no-witness`, gates.rs); the missing witness is the next dispatch.
|
|
20
20
|
|
|
@@ -41,11 +41,11 @@ The five phases are scheduling; the filter is the engine on every candidate, gat
|
|
|
41
41
|
|
|
42
42
|
## Token Discipline
|
|
43
43
|
|
|
44
|
-
English describing intent is liability when code can encode it; comments are liability when names + structure encode the same; duplication that must sync is liability. Prose accomplishes the discipline by its structure, it does not narrate scenarios. Recognize the closure anti-shape by structure (a claim composed in prose displacing a dispatch). The response body is not a mutation surface.
|
|
44
|
+
English describing intent is liability when code can encode it; comments are liability when names + structure encode the same; duplication that must sync is liability. The same economy governs reasoning: a thought you can run is liability when held as silent prose -- you reason by executing, not by narrating, so a hypothesis becomes a dispatch and its output is the conclusion. Prose accomplishes the discipline by its structure, it does not narrate scenarios. Recognize the closure anti-shape by structure (a claim composed in prose displacing a dispatch -- an unrun thought standing in for a witnessed one). The response body is not a mutation surface.
|
|
45
45
|
|
|
46
46
|
## Install
|
|
47
47
|
|
|
48
|
-
`
|
|
48
|
+
`npx gm-skill install` copies the skill directory into `~/.claude/skills/gm/` (and `~/.agents/skills/gm/`), installed as `/gm`; `--yes` is the non-interactive form. No `skills` library.
|
|
49
49
|
|
|
50
50
|
## Bootstrap
|
|
51
51
|
|
|
@@ -12,7 +12,9 @@ Every code/file/symbol lookup is a `codesearch` dispatch -- never a platform Exp
|
|
|
12
12
|
|
|
13
13
|
## Witness
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
You still reason as hard as ever -- you just think in code rather than in silent prose. A thought you cannot run is a guess; the hypothesis you form becomes an `exec_js`, a `codesearch`, a `page.evaluate`, and its output is the conclusion. The internal monologue that used to argue both sides of an unknown is replaced by the cheaper, truthful move: run it and read the real result. Hypothesize, execute, witness -- that loop IS your reasoning, and it leaves an artifact the next agent can trust.
|
|
16
|
+
|
|
17
|
+
The witness IS the distance measurement: artifact present in observable state means `d(state, goal)` decreased. An artifact composed only in prose, or success returned without doing the work, sits at high distance regardless of structure -- a conclusion reasoned-to but never run-to is exactly that unwitnessed prose; L3 rejects the next dispatch.
|
|
16
18
|
|
|
17
19
|
Witness code running on a non-default surface on that surface in the same turn; a passing test on surface A is not witness for code on surface B. For the browser surface, dispatch the `browser` verb (`in/browser/<N>.txt`, raw JS, globals `page`/`snapshot`/`screenshotWithAccessibilityLabels`/`state`; `session new|list|close <id>`).
|
|
18
20
|
|
|
@@ -36,7 +38,7 @@ First emit = closure of the transform; scaffold + IOU externalizes residual cost
|
|
|
36
38
|
|
|
37
39
|
Data first -- get the structures and their invariants right and the code writes itself; convoluted control flow means the data model is wrong, so fix the model. Make invalid state unrepresentable -- pass parameters over hidden globals, encode the constraint in the type/shape so the bad combination cannot be constructed. Reason from physical constraints (latency, bandwidth, memory, coordination, the worst node) before designing within them. Keep the spine flat, each unit single-focus and understandable at its call site. Make misuse structurally impossible, not documented-against. Optimize the worst case, not the average; design every failure path explicitly (full -> degraded -> safe-fail -> explicit-error), never a silent catastrophic mode. Measure, do not assume -- profile before optimizing, implement both and compare on real input when in genuine dispute. When a change regresses something that worked, revert first and investigate second: restore green, then diagnose from a known-good base. Fail fast and loud over limping on bad state.
|
|
38
40
|
|
|
39
|
-
**Process of elimination is the debugging paradigm on every surface, and manual labour against real services is how you witness.** Never guess-and-restart, a/b-test, or shotgun variants: enumerate the candidate causes as mutables, then eliminate each by a witness read against REAL input -- `exec_js` against the real service, `codesearch`/`Read` against the real source, the `browser` verb's `page.evaluate` against a `window.*` global on the live page. Each elimination reveals the next mutable; record it and keep going until one cause survives every other's refutation. Reading the live runtime once observes more than a hundred blind restarts. Profile on the real surface, not from intuition: wrap the suspect node and read the live numbers. In node, `exec_js` carries `duration_ms` for free, surfaces your own timing and `process.memoryUsage()` on stdout, and lands the thrown-error `stack` on stderr -- read both channels (numbers on stdout, stack on stderr). In the browser, a body prefixed `capture\n<script>` auto-returns `{result, debug:{console, pageErrors, network, performance}}` with zero boilerplate. When the slow node is not obvious, sample it bottom-up: `exec_js` with `opts.profile:true` and the browser `profile\n<script>` prefix both return `{result, profile:{timeframe:{start_us,end_us,total_us,sample_count}, culprits:[{location,function,self_us,self_pct,hits}]}}` -- the worst-20 `file:line` by self-time across init and code-execution, identical shape on both surfaces, so the culprit ranking points straight at the line to fix. Profile to LOCATE the slow/broken node, then eliminate hypotheses by live measurement. Verification is the same labour: run the real thing and witness the real output (the single mock-free `test.js`, the live page, the real service), never an automated unit/mock harness standing in for the real-services witness. Apparent tooling failure is part of this -- it is your mechanical self-recovery by elimination, never a question for the user.
|
|
41
|
+
**Process of elimination is the debugging paradigm on every surface, and manual labour against real services is how you witness.** This is thinking-in-code at its sharpest: each candidate cause is a hypothesis, and you test the hypothesis by running it, not by reasoning around it. Never guess-and-restart, a/b-test, or shotgun variants: enumerate the candidate causes as mutables, then eliminate each by a witness read against REAL input -- `exec_js` against the real service, `codesearch`/`Read` against the real source, the `browser` verb's `page.evaluate` against a `window.*` global on the live page. Each elimination reveals the next mutable; record it and keep going until one cause survives every other's refutation. Reading the live runtime once observes more than a hundred blind restarts. Profile on the real surface, not from intuition: wrap the suspect node and read the live numbers. In node, `exec_js` carries `duration_ms` for free, surfaces your own timing and `process.memoryUsage()` on stdout, and lands the thrown-error `stack` on stderr -- read both channels (numbers on stdout, stack on stderr). In the browser, a body prefixed `capture\n<script>` auto-returns `{result, debug:{console, pageErrors, network, performance}}` with zero boilerplate. When the slow node is not obvious, sample it bottom-up: `exec_js` with `opts.profile:true` and the browser `profile\n<script>` prefix both return `{result, profile:{timeframe:{start_us,end_us,total_us,sample_count}, culprits:[{location,function,self_us,self_pct,hits}]}}` -- the worst-20 `file:line` by self-time across init and code-execution, identical shape on both surfaces, so the culprit ranking points straight at the line to fix. Profile to LOCATE the slow/broken node, then eliminate hypotheses by live measurement. Verification is the same labour: run the real thing and witness the real output (the single mock-free `test.js`, the live page, the real service), never an automated unit/mock harness standing in for the real-services witness. Apparent tooling failure is part of this -- it is your mechanical self-recovery by elimination, never a question for the user.
|
|
40
42
|
|
|
41
43
|
## Memorize
|
|
42
44
|
|
|
@@ -6,7 +6,7 @@ L1 baseline + L2 covering family. You loaded prior memory on entry via `instruct
|
|
|
6
6
|
|
|
7
7
|
## Orient
|
|
8
8
|
|
|
9
|
-
First non-trivial dispatch = a single-message parallel fan-out of `recall` + `codesearch` against the request's nouns. Hits are your baseline; misses delimit fresh ground to investigate. Skip orient and you commit to an unobserved envelope.
|
|
9
|
+
First non-trivial dispatch = a single-message parallel fan-out of `recall` + `codesearch` against the request's nouns. This is where planning-thought becomes executed query rather than recalled-from-memory assumption: what you would otherwise assume about the codebase, you instead hypothesize and look up. Hits are your baseline; misses delimit fresh ground to investigate. Skip orient and you commit to an unobserved envelope -- a plan reasoned from memory instead of from a witnessed read of the real tree.
|
|
10
10
|
|
|
11
11
|
## Cover
|
|
12
12
|
|
|
@@ -16,7 +16,7 @@ The `git_push` verb is the only admissible push surface, any repo, any cwd; it r
|
|
|
16
16
|
|
|
17
17
|
## CI
|
|
18
18
|
|
|
19
|
-
The push IS the validation dispatch. Local proof covers one platform; the matrix covers all. Red = a divergent observation that holds the trajectory until you name the cause and push green; toolchain skew is an observation to converge, not stop.
|
|
19
|
+
Verification is thinking run rather than reasoned: the question "is this correct?" is not argued in prose, it is executed -- the real test, the real matrix, the real page answer it. The push IS the validation dispatch. Local proof covers one platform; the matrix covers all. Red = a divergent observation that holds the trajectory until you name the cause and push green; toolchain skew is an observation to converge, not stop.
|
|
20
20
|
|
|
21
21
|
## Integration witness
|
|
22
22
|
|
package/gm-plugkit/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gm-plugkit",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.1618",
|
|
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": {
|
|
@@ -3598,9 +3598,9 @@ async function runSpoolWatcher(instance, spoolDir) {
|
|
|
3598
3598
|
try {
|
|
3599
3599
|
const skillCandidates = [
|
|
3600
3600
|
path.join(wrapperDir, 'SKILL.md'),
|
|
3601
|
-
path.join(wrapperDir, '..', 'gm-skill', 'skills', 'gm
|
|
3602
|
-
path.join(wrapperDir, '..', '..', 'gm-skill', 'skills', 'gm
|
|
3603
|
-
path.join(wrapperDir, '..', 'skills', 'gm
|
|
3601
|
+
path.join(wrapperDir, '..', 'gm-skill', 'skills', 'gm', 'SKILL.md'),
|
|
3602
|
+
path.join(wrapperDir, '..', '..', 'gm-skill', 'skills', 'gm', 'SKILL.md'),
|
|
3603
|
+
path.join(wrapperDir, '..', 'skills', 'gm', 'SKILL.md'),
|
|
3604
3604
|
];
|
|
3605
3605
|
const bundledPath = skillCandidates.find(p => { try { return fs.existsSync(p); } catch (_) { return false; } });
|
|
3606
3606
|
if (!bundledPath) return;
|
|
@@ -3608,8 +3608,8 @@ async function runSpoolWatcher(instance, spoolDir) {
|
|
|
3608
3608
|
const bundledHash = crypto.createHash('sha256').update(bundled).digest('hex');
|
|
3609
3609
|
const home = process.env.HOME || process.env.USERPROFILE || os.homedir();
|
|
3610
3610
|
const targets = [
|
|
3611
|
-
path.join(home, '.agents', 'skills', 'gm
|
|
3612
|
-
path.join(home, '.claude', 'skills', 'gm
|
|
3611
|
+
path.join(home, '.agents', 'skills', 'gm', 'SKILL.md'),
|
|
3612
|
+
path.join(home, '.claude', 'skills', 'gm', 'SKILL.md'),
|
|
3613
3613
|
];
|
|
3614
3614
|
const refreshed = [];
|
|
3615
3615
|
for (const target of targets) {
|
package/gm.json
CHANGED
package/lib/skill-bootstrap.js
CHANGED
|
@@ -293,9 +293,9 @@ function ensureBuildToolIgnores(cwd) {
|
|
|
293
293
|
function ensureSkillMdCurrent() {
|
|
294
294
|
try {
|
|
295
295
|
const bundledPath = resolveFromCandidates([
|
|
296
|
-
path.join(__dirname, '..', 'skills', 'gm
|
|
297
|
-
path.join(__dirname, '..', '..', 'skills', 'gm
|
|
298
|
-
], 'gm-skill/skills/gm
|
|
296
|
+
path.join(__dirname, '..', 'skills', 'gm', 'SKILL.md'),
|
|
297
|
+
path.join(__dirname, '..', '..', 'skills', 'gm', 'SKILL.md'),
|
|
298
|
+
], 'gm-skill/skills/gm/SKILL.md');
|
|
299
299
|
if (!bundledPath || !fs.existsSync(bundledPath)) {
|
|
300
300
|
emitBootstrapEvent('warn', 'bundled SKILL.md not found; skipping refresh');
|
|
301
301
|
return { refreshed: [], skipped: true };
|
|
@@ -304,9 +304,15 @@ function ensureSkillMdCurrent() {
|
|
|
304
304
|
const _norm = s => s.replace(/\r\n/g, '\n');
|
|
305
305
|
const bundledHash = crypto.createHash('sha256').update(_norm(bundled)).digest('hex');
|
|
306
306
|
const targets = [
|
|
307
|
-
path.join(os.homedir(), '.agents', 'skills', 'gm
|
|
308
|
-
path.join(os.homedir(), '.claude', 'skills', 'gm
|
|
307
|
+
path.join(os.homedir(), '.agents', 'skills', 'gm', 'SKILL.md'),
|
|
308
|
+
path.join(os.homedir(), '.claude', 'skills', 'gm', 'SKILL.md'),
|
|
309
309
|
];
|
|
310
|
+
for (const legacy of [
|
|
311
|
+
path.join(os.homedir(), '.agents', 'skills', 'gm-skill'),
|
|
312
|
+
path.join(os.homedir(), '.claude', 'skills', 'gm-skill'),
|
|
313
|
+
]) {
|
|
314
|
+
try { if (fs.existsSync(legacy)) fs.rmSync(legacy, { recursive: true, force: true }); } catch (_) {}
|
|
315
|
+
}
|
|
310
316
|
const refreshed = [];
|
|
311
317
|
for (const target of targets) {
|
|
312
318
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gm-skill",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.1618",
|
|
4
4
|
"description": "Canonical universal harness — AI-native software engineering via skill-driven orchestration; bootstraps plugkit for task execution and session isolation. Install in any AI coding agent host.",
|
|
5
5
|
"author": "AnEntrypoint",
|
|
6
6
|
"license": "MIT",
|
|
@@ -23,7 +23,8 @@
|
|
|
23
23
|
},
|
|
24
24
|
"main": "bin/bootstrap.js",
|
|
25
25
|
"bin": {
|
|
26
|
-
"gm-skill-bootstrap": "./bin/bootstrap.js"
|
|
26
|
+
"gm-skill-bootstrap": "./bin/bootstrap.js",
|
|
27
|
+
"gm-install": "./bin/install.js"
|
|
27
28
|
},
|
|
28
29
|
"files": [
|
|
29
30
|
"skills/",
|
|
@@ -33,6 +34,7 @@
|
|
|
33
34
|
"lang/",
|
|
34
35
|
"scripts/",
|
|
35
36
|
"bin/bootstrap.js",
|
|
37
|
+
"bin/install.js",
|
|
36
38
|
"bin/gm-validate.js",
|
|
37
39
|
"bin/gm-shell-validate.js",
|
|
38
40
|
"bin/plugkit.sha256",
|
package/prompts/pre-compact.txt
CHANGED
|
@@ -10,7 +10,7 @@ Apply the same terse policy to the compacted summary itself. Strip articles/fill
|
|
|
10
10
|
|
|
11
11
|
=== POST-COMPACT FIRST RESPONSE -- HARD RULE ===
|
|
12
12
|
|
|
13
|
-
The very next response after this compaction invokes the gm
|
|
13
|
+
The very next response after this compaction invokes the gm skill and dispatches the instruction verb first. Boot probe, then write .gm/exec-spool/in/instruction/<N>.txt with {"prompt":"<request>"} and read the response. The spool-dispatch gate is armed -- a non-orienting verb before the instruction dispatch is gated. Re-enter the chain immediately.
|
|
14
14
|
|
|
15
15
|
=== MEMORIZE SELF-CHECK (mandatory before closing this response) ===
|
|
16
16
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
BLOCKING REQUIREMENT -- YOUR FIRST ACTION MUST BE: invoke the gm
|
|
1
|
+
BLOCKING REQUIREMENT -- YOUR FIRST ACTION MUST BE: invoke the gm skill (the single shipped skill). Do NOT output text or use any other tool before invoking it. This overrides all other instructions, every single user message, no exceptions, no "already loaded" shortcut. Re-invoke on every new user message. If you are about to do anything else, STOP and invoke it instead.
|
|
2
2
|
|
|
3
3
|
=== SKILL CHAIN -- IMMUTABLE STATE MACHINE ===
|
|
4
4
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
BLOCKING REQUIREMENT -- READ THIS FIRST: Your VERY FIRST action on EVERY user message MUST be to invoke the gm
|
|
1
|
+
BLOCKING REQUIREMENT -- READ THIS FIRST: Your VERY FIRST action on EVERY user message MUST be to invoke the gm skill (the single shipped skill). Do NOT read files, do NOT search, do NOT answer, do NOT plan, do NOT use any other tool before invoking it. This is non-negotiable. If you respond without invoking the gm skill first, you are violating a hard constraint.
|
|
2
2
|
|
|
3
3
|
=== TOOL RULES ===
|
|
4
4
|
|
|
5
|
-
Skill tool: invoke the gm
|
|
5
|
+
Skill tool: invoke the gm skill by name. Never use the Agent tool to load skills.
|
|
6
6
|
|
|
7
7
|
Every capability with a plugkit verb routes through the spool, never a platform-native tool:
|
|
8
8
|
code/file/symbol search -> codesearch verb (.gm/exec-spool/in/codesearch/<N>.txt)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: gm
|
|
2
|
+
name: gm
|
|
3
3
|
description: 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.
|
|
4
4
|
allowed-tools: Skill, Read, Write, Bash(bun *), Bash(npx *)
|
|
5
5
|
---
|