gm-skill 2.0.1127 → 2.0.1129
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/README.md +15 -10
- package/gm-plugkit/plugkit-wasm-wrapper.js +6 -4
- package/gm.json +1 -1
- package/lib/skill-bootstrap.js +126 -2
- package/package.json +2 -2
- package/skills/gm-skill/SKILL.md +2 -2
package/README.md
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
# gm-skill — Canonical Universal Harness
|
|
2
2
|
|
|
3
|
-
The single
|
|
3
|
+
The single shipped skill for gm. Install into any harness that loads Claude-style skill directories — Claude Code, OpenCode, Cursor, Zed, VS Code, Codex, Kilo, JetBrains, Copilot CLI, Antigravity, Windsurf, Gemini CLI — and plugkit serves every phase instruction, mutables row, and guardrail on demand via the spool.
|
|
4
4
|
|
|
5
5
|
## What this is
|
|
6
6
|
|
|
7
|
-
AI-native software engineering orchestrated as a
|
|
7
|
+
AI-native software engineering orchestrated as a state machine — PLAN → EXECUTE → EMIT → VERIFY → COMPLETE — backed by the `plugkit` WASM orchestrator. Spool-driven dispatch, no daemon, no native binaries.
|
|
8
8
|
|
|
9
9
|
## Install
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
|
-
npm install gm-skill
|
|
12
|
+
npm install -g gm-skill
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
-
Then point your AI coding agent host
|
|
15
|
+
Then point your AI coding agent host at the included `skills/` directory, or invoke the bootstrap directly:
|
|
16
16
|
|
|
17
17
|
```bash
|
|
18
18
|
npx gm-skill-bootstrap
|
|
@@ -20,15 +20,20 @@ npx gm-skill-bootstrap
|
|
|
20
20
|
|
|
21
21
|
## What's inside
|
|
22
22
|
|
|
23
|
-
- `skills/` —
|
|
24
|
-
- `
|
|
25
|
-
- `
|
|
26
|
-
- `
|
|
27
|
-
|
|
23
|
+
- `skills/gm-skill/` — the canonical universal harness (`SKILL.md` is the ~12-line entry point)
|
|
24
|
+
- `gm-plugkit/` — WASM bootstrap and spool watcher wrapper
|
|
25
|
+
- `lib/` — skill-bootstrap, spool-dispatch, daemon-bootstrap, git, codeinsight modules
|
|
26
|
+
- `bin/plugkit.wasm.sha256` — pinned hash of the plugkit WASM artifact
|
|
27
|
+
|
|
28
|
+
## Architecture
|
|
29
|
+
|
|
30
|
+
All orchestration lives in `rs-plugkit/src/orchestrator/` as native Rust, compiled to a single `plugkit.wasm` (~<200KB). The agent dispatches verbs by writing to `.gm/exec-spool/in/<verb>/<N>.txt` and reading responses from `.gm/exec-spool/out/`. See [AGENTS.md](https://github.com/AnEntrypoint/gm/blob/main/AGENTS.md) for the full design.
|
|
31
|
+
|
|
32
|
+
An earlier generation fanned out fifteen per-platform downstream repos (gm-cc, gm-gc, gm-oc, gm-kilo, gm-codex, gm-qwen, gm-copilot-cli, gm-hermes, gm-thebird, gm-vscode, gm-cursor, gm-zed, gm-jetbrains, gm-antigravity, gm-windsurf). Those are archived; `gm-skill` is the single source of truth.
|
|
28
33
|
|
|
29
34
|
## Version
|
|
30
35
|
|
|
31
|
-
`2.0.
|
|
36
|
+
`2.0.1129` — auto-bumped from the canonical `gm` repo. Every push to `AnEntrypoint/gm` (or any cascading sibling crate) republishes this package.
|
|
32
37
|
|
|
33
38
|
## Source of truth
|
|
34
39
|
|
|
@@ -90,12 +90,14 @@ function isProfileLocked(profileDir) {
|
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
function acquireProfileDir(cwd) {
|
|
93
|
-
const
|
|
94
|
-
|
|
95
|
-
|
|
93
|
+
const gmDir = path.join(cwd, '.gm');
|
|
94
|
+
try { fs.mkdirSync(gmDir, { recursive: true }); } catch (_) {}
|
|
95
|
+
const primary = path.join(gmDir, 'browser-profile');
|
|
96
|
+
ensureGitignored(cwd, '.gm/browser-profile/');
|
|
97
|
+
ensureGitignored(cwd, '.gm/browser-profile-*/');
|
|
96
98
|
try { fs.mkdirSync(primary, { recursive: true }); } catch (_) {}
|
|
97
99
|
if (!isProfileLocked(primary)) return primary;
|
|
98
|
-
const fallback = path.join(
|
|
100
|
+
const fallback = path.join(gmDir, `browser-profile-${process.pid}`);
|
|
99
101
|
try { fs.mkdirSync(fallback, { recursive: true }); } catch (_) {}
|
|
100
102
|
return fallback;
|
|
101
103
|
}
|
package/gm.json
CHANGED
package/lib/skill-bootstrap.js
CHANGED
|
@@ -182,6 +182,9 @@ function getManagedGitignoreEntries() {
|
|
|
182
182
|
'.gm/ingest-drafts/',
|
|
183
183
|
'.gm/prd-state.json',
|
|
184
184
|
'.gm/subagent-*.json',
|
|
185
|
+
'.gm/browser-profile/',
|
|
186
|
+
'.gm/browser-profile-*/',
|
|
187
|
+
'.gm/build-tool-ignores.md',
|
|
185
188
|
'.plugkit-browser-profile/',
|
|
186
189
|
'.plugkit-browser-profile-*/',
|
|
187
190
|
];
|
|
@@ -200,6 +203,123 @@ function getMustStayTracked() {
|
|
|
200
203
|
];
|
|
201
204
|
}
|
|
202
205
|
|
|
206
|
+
function detectBuildToolConfigs(cwd) {
|
|
207
|
+
const detectors = [
|
|
208
|
+
{ tool: 'vite', patterns: ['vite.config.js', 'vite.config.ts', 'vite.config.mjs', 'vite.config.cjs'] },
|
|
209
|
+
{ tool: 'vitest', patterns: ['vitest.config.js', 'vitest.config.ts', 'vitest.config.mjs'] },
|
|
210
|
+
{ tool: 'astro', patterns: ['astro.config.js', 'astro.config.ts', 'astro.config.mjs'] },
|
|
211
|
+
{ tool: 'next', patterns: ['next.config.js', 'next.config.ts', 'next.config.mjs', 'next.config.cjs'] },
|
|
212
|
+
{ tool: 'jest', patterns: ['jest.config.js', 'jest.config.ts', 'jest.config.mjs', 'jest.config.cjs', 'jest.config.json'] },
|
|
213
|
+
{ tool: 'webpack', patterns: ['webpack.config.js', 'webpack.config.ts', 'webpack.config.cjs', 'webpack.config.mjs'] },
|
|
214
|
+
{ tool: 'rollup', patterns: ['rollup.config.js', 'rollup.config.ts', 'rollup.config.mjs'] },
|
|
215
|
+
{ tool: 'nuxt', patterns: ['nuxt.config.js', 'nuxt.config.ts', 'nuxt.config.mjs'] },
|
|
216
|
+
];
|
|
217
|
+
const found = [];
|
|
218
|
+
for (const d of detectors) {
|
|
219
|
+
for (const p of d.patterns) {
|
|
220
|
+
const fp = path.join(cwd, p);
|
|
221
|
+
if (fs.existsSync(fp)) {
|
|
222
|
+
found.push({ tool: d.tool, file: p, fullPath: fp });
|
|
223
|
+
break;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
return found;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
function patchJestJsonConfig(filePath) {
|
|
231
|
+
const raw = fs.readFileSync(filePath, 'utf-8');
|
|
232
|
+
const cfg = JSON.parse(raw);
|
|
233
|
+
const want = '<rootDir>/.gm/';
|
|
234
|
+
const existing = Array.isArray(cfg.watchPathIgnorePatterns) ? cfg.watchPathIgnorePatterns : [];
|
|
235
|
+
if (existing.includes(want)) return false;
|
|
236
|
+
cfg.watchPathIgnorePatterns = [...existing, want];
|
|
237
|
+
fs.writeFileSync(filePath, JSON.stringify(cfg, null, 2) + '\n');
|
|
238
|
+
return true;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function patchPackageJsonJest(cwd) {
|
|
242
|
+
const pkgPath = path.join(cwd, 'package.json');
|
|
243
|
+
if (!fs.existsSync(pkgPath)) return null;
|
|
244
|
+
const raw = fs.readFileSync(pkgPath, 'utf-8');
|
|
245
|
+
let pkg;
|
|
246
|
+
try { pkg = JSON.parse(raw); } catch (_) { return null; }
|
|
247
|
+
if (!pkg.jest || typeof pkg.jest !== 'object') return null;
|
|
248
|
+
const want = '<rootDir>/.gm/';
|
|
249
|
+
const existing = Array.isArray(pkg.jest.watchPathIgnorePatterns) ? pkg.jest.watchPathIgnorePatterns : [];
|
|
250
|
+
if (existing.includes(want)) return false;
|
|
251
|
+
pkg.jest.watchPathIgnorePatterns = [...existing, want];
|
|
252
|
+
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n');
|
|
253
|
+
return true;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
function ensureBuildToolIgnores(cwd) {
|
|
257
|
+
try {
|
|
258
|
+
const found = detectBuildToolConfigs(cwd);
|
|
259
|
+
const automated = [];
|
|
260
|
+
const advisory = [];
|
|
261
|
+
|
|
262
|
+
for (const f of found) {
|
|
263
|
+
if (f.tool === 'jest' && f.file.endsWith('.json')) {
|
|
264
|
+
try {
|
|
265
|
+
const changed = patchJestJsonConfig(f.fullPath);
|
|
266
|
+
automated.push({ tool: 'jest', file: f.file, changed });
|
|
267
|
+
} catch (e) {
|
|
268
|
+
advisory.push({ ...f, reason: `patch failed: ${e.message}` });
|
|
269
|
+
}
|
|
270
|
+
} else {
|
|
271
|
+
advisory.push(f);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
try {
|
|
276
|
+
const pkgChanged = patchPackageJsonJest(cwd);
|
|
277
|
+
if (pkgChanged !== null) automated.push({ tool: 'jest', file: 'package.json#jest', changed: pkgChanged });
|
|
278
|
+
} catch (_) {}
|
|
279
|
+
|
|
280
|
+
const snippets = {
|
|
281
|
+
vite: "server: { watch: { ignored: ['**/.gm/**'] } }",
|
|
282
|
+
vitest: "test: { watchExclude: ['**/.gm/**'] }",
|
|
283
|
+
astro: "vite: { server: { watch: { ignored: ['**/.gm/**'] } } }",
|
|
284
|
+
next: "webpack: (config) => { config.watchOptions = { ...config.watchOptions, ignored: ['**/.gm/**', ...(config.watchOptions?.ignored || [])] }; return config; }",
|
|
285
|
+
jest: "watchPathIgnorePatterns: ['<rootDir>/.gm/']",
|
|
286
|
+
webpack: "watchOptions: { ignored: ['**/.gm/**', '**/node_modules/**'] }",
|
|
287
|
+
rollup: "watch: { exclude: ['.gm/**'] }",
|
|
288
|
+
nuxt: "vite: { server: { watch: { ignored: ['**/.gm/**'] } } }",
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
const gmDir = path.join(cwd, '.gm');
|
|
292
|
+
const advisoryPath = path.join(gmDir, 'build-tool-ignores.md');
|
|
293
|
+
if (advisory.length === 0) {
|
|
294
|
+
try { if (fs.existsSync(advisoryPath)) fs.unlinkSync(advisoryPath); } catch (_) {}
|
|
295
|
+
} else {
|
|
296
|
+
fs.mkdirSync(gmDir, { recursive: true });
|
|
297
|
+
const lines = [
|
|
298
|
+
'# Build-tool ignore advisories',
|
|
299
|
+
'',
|
|
300
|
+
'`.gitignore` already excludes `.gm/`. Tools whose watchers honor `.gitignore` (vite, vitest, astro, nuxt with chokidar defaults) need no further action.',
|
|
301
|
+
'',
|
|
302
|
+
'For watchers that do NOT honor `.gitignore` automatically, paste these snippets into the corresponding config file:',
|
|
303
|
+
'',
|
|
304
|
+
];
|
|
305
|
+
for (const f of advisory) {
|
|
306
|
+
const snip = snippets[f.tool];
|
|
307
|
+
if (!snip) continue;
|
|
308
|
+
lines.push(`## ${f.tool} (\`${f.file}\`)`, '', '```', snip, '```', '');
|
|
309
|
+
}
|
|
310
|
+
lines.push('---', '', 'Regenerated each bootstrap. Delete after applying — file is gitignored.');
|
|
311
|
+
fs.writeFileSync(advisoryPath, lines.join('\n'));
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
emitBootstrapEvent('info', 'Build-tool ignore handling complete', {
|
|
315
|
+
automated: automated.map(a => ({ tool: a.tool, file: a.file, changed: a.changed })),
|
|
316
|
+
advisory: advisory.map(a => ({ tool: a.tool, file: a.file })),
|
|
317
|
+
});
|
|
318
|
+
} catch (e) {
|
|
319
|
+
emitBootstrapEvent('warn', 'ensureBuildToolIgnores failed', { error: e.message });
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
203
323
|
function ensureManagedGitignore(cwd) {
|
|
204
324
|
try {
|
|
205
325
|
const gi = gitignorePath(cwd);
|
|
@@ -429,6 +549,7 @@ async function bootstrapPlugkit(sessionId, options) {
|
|
|
429
549
|
emitBootstrapEvent('info', 'Bootstrap started', { forceLatest });
|
|
430
550
|
|
|
431
551
|
ensureManagedGitignore(process.cwd());
|
|
552
|
+
ensureBuildToolIgnores(process.cwd());
|
|
432
553
|
|
|
433
554
|
const manifest = readManifest();
|
|
434
555
|
let targetVersion = manifest.version;
|
|
@@ -616,9 +737,12 @@ async function getSnapshot(sessionId, cwd) {
|
|
|
616
737
|
}
|
|
617
738
|
}
|
|
618
739
|
|
|
619
|
-
module.exports = {
|
|
740
|
+
module.exports = {
|
|
620
741
|
bootstrapPlugkit,
|
|
621
742
|
bootstrapAcptoapi,
|
|
622
743
|
getSnapshot,
|
|
623
|
-
checkPortReachable
|
|
744
|
+
checkPortReachable,
|
|
745
|
+
ensureBuildToolIgnores,
|
|
746
|
+
detectBuildToolConfigs,
|
|
747
|
+
ensureManagedGitignore,
|
|
624
748
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gm-skill",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.1129",
|
|
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",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"gm.json"
|
|
40
40
|
],
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"gm-plugkit": "^2.0.
|
|
42
|
+
"gm-plugkit": "^2.0.1129"
|
|
43
43
|
},
|
|
44
44
|
"engines": {
|
|
45
45
|
"node": ">=16.0.0"
|
package/skills/gm-skill/SKILL.md
CHANGED
|
@@ -100,8 +100,8 @@ Stop when `next_phase_hint` is null or phase is `COMPLETE`.
|
|
|
100
100
|
|
|
101
101
|
### Browser
|
|
102
102
|
|
|
103
|
-
Dispatch `.gm/exec-spool/in/browser/<N>.txt` with raw JavaScript as the body. The wrapper spawns Chrome (managed profile at `<cwd>/.
|
|
103
|
+
Dispatch `.gm/exec-spool/in/browser/<N>.txt` with raw JavaScript as the body. The wrapper spawns Chrome (managed profile at `<cwd>/.gm/browser-profile/`) and runs the JS via playwriter. Globals available inside the body: `page` (playwright Page), `snapshot` (accessibility snapshot), `screenshotWithAccessibilityLabels` (screenshot helper), `state` (per-session state object).
|
|
104
104
|
|
|
105
105
|
Special commands (body starts with `session `): `session new`, `session list`, `session close <id>` pass through to playwriter directly.
|
|
106
106
|
|
|
107
|
-
Chrome is detected from system install paths; profile dir is project-scoped so cookies/login persist per project. The wrapper
|
|
107
|
+
Chrome is detected from system install paths; profile dir is project-scoped so cookies/login persist per project. The wrapper writes the managed gitignore block (which includes `.gm/browser-profile/`) on first launch.
|