gm-skill 2.0.1779 → 2.0.1793
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 +3 -5
- package/bin/bootstrap.js +29 -0
- package/bin/plugkit.version +1 -1
- package/bin/plugkit.wasm.sha256 +1 -1
- package/gm-plugkit/bootstrap.js +28 -0
- package/gm-plugkit/package.json +1 -1
- package/gm-plugkit/plugkit-wasm-wrapper.js +48 -2
- package/gm-plugkit/plugkit.version +1 -1
- package/gm-plugkit/supervisor.js +30 -3
- package/gm.json +2 -2
- package/lib/skill-bootstrap.js +28 -1
- package/package.json +1 -1
package/AGENTS.md
CHANGED
|
@@ -66,9 +66,7 @@ Record only non-obvious multi-run-cost caveats; prune stale; never document the
|
|
|
66
66
|
|
|
67
67
|
**No graphical symbols; convert to industry-standard text on sight.** Any non-ASCII decorative glyph (arrows, box/geometric glyphs, stars, dots, bullets, checks/crosses, emojis) is forbidden in all output and source -- convert it to its plain-ASCII equivalent the same turn (the word, `->`, `-`/`*`, `[x]`/`[ ]`, done/todo/pass/fail). Tell-tale-AI class: one sighting spawns the full-codebase sweep, never a one-off edit. Exempt: functional code operators (`=>`, `??`, `?.`, comparison/math), frozen changelog/git-log entries, binary stores, intentional icon-font/CSS-content product glyphs, and canonical CS/formal-logic notation in `.gm/constraints.md` / `gm-plugkit/constraints-default.md` (`.`, `->` as function-space, `|-`, set/quantifier symbols) -- these are semantic operators in a formal constraints spec, not decorative flourish. `ccsniff --glyph-discipline` flags decorative glyphs post-hoc (run each audit, like `--git-discipline`/`--search-discipline`).
|
|
68
68
|
|
|
69
|
-
**
|
|
70
|
-
|
|
71
|
-
**Implicit, not explicit, in skill prose.** Skill files (and prompt-submit.txt) elicit, never describe: terse imperatives triggering already-learned dispositions, not numbered procedures. Describes = agent could re-derive from the goal (recipe, do-X-then-Y, trigger-instance list, over-explained rationale, restated mechanism) -- convert. Elicits = constructs a predicament where the wrong move is structurally incoherent -- keep. Exception: boot-edge ABI (exact spool paths, JSON fields, verb names, globs, deviation ids, gate names) is non-derivable, stays explicit regardless. Forbidden: step-by-step recipes, "see paper section X", site/paper citations, multi-step manuals -- manual-shaped skill gets imitated as script, breaks at first edge case. Papers/site are discipline OUTPUTS, never link from a skill into docs. Cross-cutting rules needing citation belong here, not in skills.
|
|
69
|
+
**Implicit, not explicit, in skill prose**: skill files elicit, never describe -- terse imperatives, no recipes/citations/manuals; boot-edge ABI (spool paths, JSON fields, verb names, deviation ids, gate names) stays explicit; SKILL.md keeps only invocation syntax, transition markers, gate conditions, constraints, exact-usage examples. Full criteria: rs-learn (`recall: implicit-not-explicit skill prose criteria`).
|
|
72
70
|
|
|
73
71
|
## Build
|
|
74
72
|
|
|
@@ -92,9 +90,9 @@ Every skill's `allowed-tools:` reduced to `Skill, Read, Write` (plus SKILL.md bo
|
|
|
92
90
|
|
|
93
91
|
## Core Rules
|
|
94
92
|
|
|
95
|
-
**
|
|
93
|
+
**Memory is human-readable md, tracked; derived stores are transient, never tracked**: canonical memory = `.gm/memories/<key>.md` (project facts) + `.gm/disciplines/<name>/memories/<key>.md` (transferable discipline knowledge), frontmatter `key/ns/created/updated`, UTF-8 no BOM, LF -- text shares cross-machine/session/CI as reviewable diffs. Legacy flat-JSON KV (`.gm/disciplines/<ns>/*.json`) remains the live recall read path until rs-plugkit's md read-path cutover lands; it stays tracked until then, then retires. Derived state (embeddings/`*-vec`, codeinsight manifests/digests, local sqlite/index dbs) is rebuildable-from-corpus, listed one-by-one between managed gitignore markers (parent-re-include caveat). Entry list + `ensureGitignored` mechanics: rs-learn (`recall: gm managed-gitignore mechanics`). Project-local persistent state -> `.gm/<name>/`, never top-level dotfile/dotdir.
|
|
96
94
|
|
|
97
|
-
**Disciplines are isolated knowledge stores**: per-project `<project>/.gm/disciplines/<name>/{
|
|
95
|
+
**Disciplines are isolated knowledge stores**: per-project `<project>/.gm/disciplines/<name>/{memories/, code-search/}`, own corpus+index each; memorize-time routing auto-creates a not-previously-known discipline's store rather than mixing it into project memories. `@<name>` sigil = strict isolation (cross-discipline reads forbidden). Sigil-less reads (recall/codesearch) fan across `default` + every `enabled.txt` line, merge-ranked `[discipline:<name>]`-prefixed; sigil-less writes -> project store only. Tracked, never ignored (`ensureGitignored` excludes `.gm/disciplines`); derived per-discipline caches follow the transient rule above. Harness + every spool verb propagate `@<name>` verbatim.
|
|
98
96
|
|
|
99
97
|
**Nothing fake in source the user runs**: stub/mock/placeholder-return/fixture-only-path/demo-mode-short-circuit/"TODO: implement" forbidden in shipped code. Scaffolds/shims permitted only delegating to real behavior (upstream API, subprocess, disk); check for an existing library before adding a shim. Detection = behavioral: always-succeeds, input-invariant, or type-signature-satisfying short-circuit = stub. Acceptance = real input through real code into real output, witnessed.
|
|
100
98
|
|
package/bin/bootstrap.js
CHANGED
|
@@ -606,6 +606,29 @@ function writeDaemonVersion(v) {
|
|
|
606
606
|
try { fs.writeFileSync(daemonVersionSentinel(), String(v)); } catch (_) {}
|
|
607
607
|
}
|
|
608
608
|
|
|
609
|
+
function pidCommandLineForKillGuard(pid) {
|
|
610
|
+
try {
|
|
611
|
+
const { spawnSync } = require('child_process');
|
|
612
|
+
if (process.platform === 'win32') {
|
|
613
|
+
const r = spawnSync('powershell.exe', ['-NoProfile', '-NonInteractive', '-Command', `(Get-CimInstance Win32_Process -Filter "ProcessId=${Number(pid)}").CommandLine`], { encoding: 'utf8', windowsHide: true, timeout: 5000 });
|
|
614
|
+
return String((r && r.stdout) || '');
|
|
615
|
+
}
|
|
616
|
+
const r = spawnSync('ps', ['-p', String(pid), '-o', 'args='], { encoding: 'utf8', timeout: 5000 });
|
|
617
|
+
return String((r && r.stdout) || '');
|
|
618
|
+
} catch (_) { return ''; }
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
function pidIsPlugkitProcess(pid) {
|
|
622
|
+
return /plugkit-wasm-wrapper\.js|plugkit-supervisor\.js|gm-plugkit[\\\/]supervisor\.js/i.test(pidCommandLineForKillGuard(pid));
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
function writeKillAttribution(targetSpoolDir, info) {
|
|
626
|
+
try {
|
|
627
|
+
fs.mkdirSync(targetSpoolDir, { recursive: true });
|
|
628
|
+
fs.writeFileSync(path.join(targetSpoolDir, '.kill-attribution.json'), JSON.stringify({ killer_pid: process.pid, killer_cwd: process.cwd(), killer_script: __filename, ts: Date.now(), ...info }, null, 2));
|
|
629
|
+
} catch (_) {}
|
|
630
|
+
}
|
|
631
|
+
|
|
609
632
|
function killPid(pid) {
|
|
610
633
|
if (!Number.isFinite(pid) || pid === process.pid || !pidAlive(pid)) return false;
|
|
611
634
|
try { process.kill(pid, 'SIGTERM'); }
|
|
@@ -624,6 +647,12 @@ function killSpoolWatcherInCwd(reason) {
|
|
|
624
647
|
const pidPath = path.join(process.cwd(), '.gm', 'exec-spool', '.watcher.pid');
|
|
625
648
|
if (!fs.existsSync(pidPath)) return null;
|
|
626
649
|
const pid = parseInt(fs.readFileSync(pidPath, 'utf8').trim(), 10);
|
|
650
|
+
if (pidAlive(pid) && !pidIsPlugkitProcess(pid)) {
|
|
651
|
+
obsEvent('bootstrap', 'watcher.kill-skipped-pid-reused', { pid, reason });
|
|
652
|
+
try { fs.unlinkSync(pidPath); } catch (_) {}
|
|
653
|
+
return null;
|
|
654
|
+
}
|
|
655
|
+
writeKillAttribution(path.join(process.cwd(), '.gm', 'exec-spool'), { reason, target_pid: pid, via: 'killSpoolWatcherInCwd' });
|
|
627
656
|
if (killPid(pid)) {
|
|
628
657
|
obsEvent('bootstrap', 'watcher.killed', { pid, reason });
|
|
629
658
|
try { fs.unlinkSync(pidPath); } catch (_) {}
|
package/bin/plugkit.version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.1.
|
|
1
|
+
0.1.818
|
package/bin/plugkit.wasm.sha256
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
5cfcad879b84f2443f28e5ce9182d725bc6ebfeae1bf2c84a5b21d5a84a55a1e plugkit.wasm
|
package/gm-plugkit/bootstrap.js
CHANGED
|
@@ -450,6 +450,28 @@ function writeDaemonVersion(v) {
|
|
|
450
450
|
try { fs.writeFileSync(daemonVersionSentinel(), String(v)); } catch (_) {}
|
|
451
451
|
}
|
|
452
452
|
|
|
453
|
+
function pidCommandLineForKillGuard(pid) {
|
|
454
|
+
try {
|
|
455
|
+
if (process.platform === 'win32') {
|
|
456
|
+
const r = spawnSync('powershell.exe', ['-NoProfile', '-NonInteractive', '-Command', `(Get-CimInstance Win32_Process -Filter "ProcessId=${Number(pid)}").CommandLine`], { encoding: 'utf8', windowsHide: true, timeout: 5000 });
|
|
457
|
+
return String((r && r.stdout) || '');
|
|
458
|
+
}
|
|
459
|
+
const r = spawnSync('ps', ['-p', String(pid), '-o', 'args='], { encoding: 'utf8', timeout: 5000 });
|
|
460
|
+
return String((r && r.stdout) || '');
|
|
461
|
+
} catch (_) { return ''; }
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
function pidIsPlugkitProcess(pid) {
|
|
465
|
+
return /plugkit-wasm-wrapper\.js|plugkit-supervisor\.js|gm-plugkit[\\\/]supervisor\.js/i.test(pidCommandLineForKillGuard(pid));
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
function writeKillAttribution(targetSpoolDir, info) {
|
|
469
|
+
try {
|
|
470
|
+
fs.mkdirSync(targetSpoolDir, { recursive: true });
|
|
471
|
+
fs.writeFileSync(path.join(targetSpoolDir, '.kill-attribution.json'), JSON.stringify({ killer_pid: process.pid, killer_cwd: process.cwd(), killer_script: __filename, ts: Date.now(), ...info }, null, 2));
|
|
472
|
+
} catch (_) {}
|
|
473
|
+
}
|
|
474
|
+
|
|
453
475
|
function killPid(pid) {
|
|
454
476
|
if (!Number.isFinite(pid) || pid === process.pid || !pidAlive(pid)) return false;
|
|
455
477
|
try { process.kill(pid, 'SIGTERM'); }
|
|
@@ -465,6 +487,12 @@ function killSpoolWatcherInCwd(reason) {
|
|
|
465
487
|
const pidPath = path.join(process.cwd(), '.gm', 'exec-spool', '.watcher.pid');
|
|
466
488
|
if (!fs.existsSync(pidPath)) return null;
|
|
467
489
|
const pid = parseInt(fs.readFileSync(pidPath, 'utf8').trim(), 10);
|
|
490
|
+
if (pidAlive(pid) && !pidIsPlugkitProcess(pid)) {
|
|
491
|
+
obsEvent('bootstrap', 'watcher.kill-skipped-pid-reused', { pid, reason });
|
|
492
|
+
try { fs.unlinkSync(pidPath); } catch (_) {}
|
|
493
|
+
return null;
|
|
494
|
+
}
|
|
495
|
+
writeKillAttribution(path.join(process.cwd(), '.gm', 'exec-spool'), { reason, target_pid: pid, via: 'killSpoolWatcherInCwd' });
|
|
468
496
|
if (killPid(pid)) {
|
|
469
497
|
obsEvent('bootstrap', 'watcher.killed', { pid, reason });
|
|
470
498
|
try { fs.unlinkSync(pidPath); } catch (_) {}
|
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.1793",
|
|
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": {
|
|
@@ -74,6 +74,28 @@ function emitShutdownReason(reason, err) {
|
|
|
74
74
|
} catch (_) {}
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
+
function pidCommandLineForKillGuard(pid) {
|
|
78
|
+
try {
|
|
79
|
+
if (process.platform === 'win32') {
|
|
80
|
+
const r = spawnSync('powershell.exe', ['-NoProfile', '-NonInteractive', '-Command', `(Get-CimInstance Win32_Process -Filter "ProcessId=${Number(pid)}").CommandLine`], { encoding: 'utf8', windowsHide: true, timeout: 5000 });
|
|
81
|
+
return String((r && r.stdout) || '');
|
|
82
|
+
}
|
|
83
|
+
const r = spawnSync('ps', ['-p', String(pid), '-o', 'args='], { encoding: 'utf8', timeout: 5000 });
|
|
84
|
+
return String((r && r.stdout) || '');
|
|
85
|
+
} catch (_) { return ''; }
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function pidIsPlugkitProcess(pid) {
|
|
89
|
+
return /plugkit-wasm-wrapper\.js|plugkit-supervisor\.js|gm-plugkit[\\\/]supervisor\.js/i.test(pidCommandLineForKillGuard(pid));
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function writeKillAttribution(targetSpoolDir, info) {
|
|
93
|
+
try {
|
|
94
|
+
fs.mkdirSync(targetSpoolDir, { recursive: true });
|
|
95
|
+
fs.writeFileSync(path.join(targetSpoolDir, '.kill-attribution.json'), JSON.stringify({ killer_pid: process.pid, killer_cwd: process.cwd(), killer_script: 'plugkit-wasm-wrapper', ts: Date.now(), ...info }, null, 2));
|
|
96
|
+
} catch (_) {}
|
|
97
|
+
}
|
|
98
|
+
|
|
77
99
|
function writeVerbActive(verb, task) {
|
|
78
100
|
__currentVerbContext = { verb, task, started_at_ms: Date.now(), pid: process.pid };
|
|
79
101
|
try {
|
|
@@ -1558,7 +1580,8 @@ function cosineSim(a, b) {
|
|
|
1558
1580
|
}
|
|
1559
1581
|
|
|
1560
1582
|
let __wasmAbortFlag = { aborted: false, code: 0 };
|
|
1561
|
-
const
|
|
1583
|
+
const WASI_PROJECT_SLUG = crypto.createHash('sha256').update(String(process.env.CLAUDE_PROJECT_DIR || process.cwd()).toLowerCase().replace(/\\/g, '/')).digest('hex').slice(0, 16);
|
|
1584
|
+
const WASI_FILESYSTEM_ROOT = path.join(GM_TOOLS_ROOT, 'wasi-fs', WASI_PROJECT_SLUG);
|
|
1562
1585
|
const wasiOpenFiles = new Map();
|
|
1563
1586
|
let wasiNextFd = 100;
|
|
1564
1587
|
|
|
@@ -2256,6 +2279,19 @@ function makeHostFunctions(instanceRef) {
|
|
|
2256
2279
|
}
|
|
2257
2280
|
},
|
|
2258
2281
|
|
|
2282
|
+
host_fs_remove: (pathPtr, pathLen) => {
|
|
2283
|
+
try {
|
|
2284
|
+
const filePath = readWasmStr(instanceRef.value, pathPtr, pathLen);
|
|
2285
|
+
if (!filePath) return 0;
|
|
2286
|
+
const st = fs.statSync(filePath);
|
|
2287
|
+
if (st.isDirectory()) return 0;
|
|
2288
|
+
fs.unlinkSync(filePath);
|
|
2289
|
+
return 1;
|
|
2290
|
+
} catch (e) {
|
|
2291
|
+
return 0;
|
|
2292
|
+
}
|
|
2293
|
+
},
|
|
2294
|
+
|
|
2259
2295
|
host_fs_readdir: (pathPtr, pathLen) => {
|
|
2260
2296
|
try {
|
|
2261
2297
|
const dirPath = readWasmStr(instanceRef.value, pathPtr, pathLen);
|
|
@@ -3038,7 +3074,12 @@ async function runSpoolWatcher(instance, spoolDir) {
|
|
|
3038
3074
|
holder_sha: holderSha,
|
|
3039
3075
|
}));
|
|
3040
3076
|
} catch (_) {}
|
|
3041
|
-
|
|
3077
|
+
if (pidIsPlugkitProcess(holderPidNum)) {
|
|
3078
|
+
writeKillAttribution(spoolDir, { reason: 'peer-stale-takeover', target_pid: holderPidNum, via: 'lock-takeover', holder_sha: holderSha });
|
|
3079
|
+
try { process.kill(holderPidNum, 'SIGTERM'); } catch (_) {}
|
|
3080
|
+
} else {
|
|
3081
|
+
try { logEvent('plugkit', 'takeover-kill-skipped-pid-reused', { holder_pid: pidStr }); } catch (_) {}
|
|
3082
|
+
}
|
|
3042
3083
|
return 'takeover';
|
|
3043
3084
|
} else {
|
|
3044
3085
|
const msg = JSON.stringify({ ok: false, reason: 'another-watcher-active', pid: pidStr, age_ms: age });
|
|
@@ -3249,6 +3290,11 @@ async function runSpoolWatcher(instance, spoolDir) {
|
|
|
3249
3290
|
try {
|
|
3250
3291
|
process.kill(peerPid, 0);
|
|
3251
3292
|
} catch (_) { continue; }
|
|
3293
|
+
if (!pidIsPlugkitProcess(peerPid)) {
|
|
3294
|
+
logEvent('plugkit', 'peer.kill-skipped-pid-reused', { peer_cwd: peerCwd, peer_pid: peerPid });
|
|
3295
|
+
continue;
|
|
3296
|
+
}
|
|
3297
|
+
writeKillAttribution(path.join(peerCwd, '.gm', 'exec-spool'), { reason: 'peer-stale-takeover', target_pid: peerPid, via: 'peer-sweep', peer_sha: peerSha, own_sha: _ownWrapperSha12 });
|
|
3252
3298
|
logEvent('plugkit', 'peer.stale-wrapper-killed', { peer_cwd: peerCwd, peer_pid: peerPid, peer_sha: peerSha, own_sha: _ownWrapperSha12, lock_age_ms: age });
|
|
3253
3299
|
console.error(`[plugkit-wasm] peer-sweep killing stale-wrapper watcher pid=${peerPid} cwd=${peerCwd} sha=${peerSha} (own=${_ownWrapperSha12})`);
|
|
3254
3300
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
0.1.
|
|
1
|
+
0.1.818
|
package/gm-plugkit/supervisor.js
CHANGED
|
@@ -64,6 +64,28 @@ function writeSupervisorStatus(state, extra) {
|
|
|
64
64
|
} catch (_) {}
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
+
function pidCommandLineForKillGuard(pid) {
|
|
68
|
+
try {
|
|
69
|
+
if (process.platform === 'win32') {
|
|
70
|
+
const r = spawnSync('powershell.exe', ['-NoProfile', '-NonInteractive', '-Command', `(Get-CimInstance Win32_Process -Filter "ProcessId=${Number(pid)}").CommandLine`], { encoding: 'utf8', windowsHide: true, timeout: 5000 });
|
|
71
|
+
return String((r && r.stdout) || '');
|
|
72
|
+
}
|
|
73
|
+
const r = spawnSync('ps', ['-p', String(pid), '-o', 'args='], { encoding: 'utf8', timeout: 5000 });
|
|
74
|
+
return String((r && r.stdout) || '');
|
|
75
|
+
} catch (_) { return ''; }
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function pidIsPlugkitProcess(pid) {
|
|
79
|
+
return /plugkit-wasm-wrapper\.js|plugkit-supervisor\.js|gm-plugkit[\\\/]supervisor\.js/i.test(pidCommandLineForKillGuard(pid));
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function writeKillAttribution(targetSpoolDir, info) {
|
|
83
|
+
try {
|
|
84
|
+
fs.mkdirSync(targetSpoolDir, { recursive: true });
|
|
85
|
+
fs.writeFileSync(path.join(targetSpoolDir, '.kill-attribution.json'), JSON.stringify({ killer_pid: process.pid, killer_cwd: process.cwd(), killer_script: __filename, ts: Date.now(), ...info }, null, 2));
|
|
86
|
+
} catch (_) {}
|
|
87
|
+
}
|
|
88
|
+
|
|
67
89
|
function pidAlive(pid) {
|
|
68
90
|
if (!Number.isFinite(pid) || pid <= 0) return false;
|
|
69
91
|
try { process.kill(pid, 0); return true; } catch (_) { return false; }
|
|
@@ -100,9 +122,14 @@ function acquireSingleInstance() {
|
|
|
100
122
|
spool_status_age_ms: now - spoolTs,
|
|
101
123
|
severity: 'critical',
|
|
102
124
|
});
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
try {
|
|
125
|
+
if (pidIsPlugkitProcess(other)) {
|
|
126
|
+
writeKillAttribution(spoolDir, { reason: 'supervisor-takeover-wedged', target_pid: other, via: 'supervisor-duel' });
|
|
127
|
+
try { process.kill(other, 'SIGTERM'); } catch (_) {}
|
|
128
|
+
if (process.platform === 'win32') {
|
|
129
|
+
try { spawnSync('taskkill', ['/F', '/T', '/PID', String(other)], { stdio: 'ignore', windowsHide: true, timeout: 3000 }); } catch (_) {}
|
|
130
|
+
}
|
|
131
|
+
} else {
|
|
132
|
+
logEvent('supervisor.takeover-kill-skipped-pid-reused', { existing_pid: other, severity: 'warn' });
|
|
106
133
|
}
|
|
107
134
|
}
|
|
108
135
|
try { fs.unlinkSync(SUPERVISOR_PID_PATH); } catch (_) {}
|
package/gm.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gm",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.1793",
|
|
4
4
|
"description": "Spool-dispatch orchestration engine with unified state machine, skills, and automated git enforcement",
|
|
5
5
|
"author": "AnEntrypoint",
|
|
6
6
|
"license": "MIT",
|
|
@@ -17,5 +17,5 @@
|
|
|
17
17
|
"publishConfig": {
|
|
18
18
|
"access": "public"
|
|
19
19
|
},
|
|
20
|
-
"plugkitVersion": "0.1.
|
|
20
|
+
"plugkitVersion": "0.1.818"
|
|
21
21
|
}
|
package/lib/skill-bootstrap.js
CHANGED
|
@@ -406,6 +406,26 @@ function isProcessRunning() {
|
|
|
406
406
|
return findPlugkitWasmPids().length > 0;
|
|
407
407
|
}
|
|
408
408
|
|
|
409
|
+
function pidCommandLineForKillGuard(pid) {
|
|
410
|
+
try {
|
|
411
|
+
if (process.platform === 'win32') {
|
|
412
|
+
return execFileSync('powershell.exe', ['-NoProfile', '-NonInteractive', '-Command', `(Get-CimInstance Win32_Process -Filter "ProcessId=${Number(pid)}").CommandLine`], { encoding: 'utf8', windowsHide: true, timeout: 5000 }) || '';
|
|
413
|
+
}
|
|
414
|
+
return execFileSync('ps', ['-p', String(pid), '-o', 'args='], { encoding: 'utf8', timeout: 5000 }) || '';
|
|
415
|
+
} catch (_) { return ''; }
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
function pidIsPlugkitProcess(pid) {
|
|
419
|
+
return /plugkit-wasm-wrapper\.js|plugkit-supervisor\.js|gm-plugkit[\\\/]supervisor\.js/i.test(pidCommandLineForKillGuard(pid));
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
function writeKillAttribution(targetSpoolDir, info) {
|
|
423
|
+
try {
|
|
424
|
+
fs.mkdirSync(targetSpoolDir, { recursive: true });
|
|
425
|
+
fs.writeFileSync(path.join(targetSpoolDir, '.kill-attribution.json'), JSON.stringify({ killer_pid: process.pid, killer_cwd: process.cwd(), killer_script: __filename, ts: Date.now(), ...info }, null, 2));
|
|
426
|
+
} catch (_) {}
|
|
427
|
+
}
|
|
428
|
+
|
|
409
429
|
function killExistingPlugkit() {
|
|
410
430
|
try {
|
|
411
431
|
const pids = findPlugkitWasmPids();
|
|
@@ -413,17 +433,24 @@ function killExistingPlugkit() {
|
|
|
413
433
|
emitBootstrapEvent('info', 'No existing plugkit WASM watcher to kill');
|
|
414
434
|
return;
|
|
415
435
|
}
|
|
436
|
+
const killed = [];
|
|
416
437
|
for (const pid of pids) {
|
|
438
|
+
if (!pidIsPlugkitProcess(pid)) {
|
|
439
|
+
emitBootstrapEvent('warn', 'Kill skipped: pid is not a plugkit process (stale or reused pid)', { pid });
|
|
440
|
+
continue;
|
|
441
|
+
}
|
|
442
|
+
writeKillAttribution(path.join(process.cwd(), '.gm', 'exec-spool'), { reason: 'bootstrap-refresh', target_pid: Number(pid), via: 'killExistingPlugkit' });
|
|
417
443
|
try {
|
|
418
444
|
if (process.platform === 'win32') {
|
|
419
445
|
execFileSync('taskkill', ['/F', '/T', '/PID', String(pid)], { stdio: 'ignore', windowsHide: true });
|
|
420
446
|
} else {
|
|
421
447
|
execFileSync('kill', ['-9', String(pid)], { stdio: 'ignore' });
|
|
422
448
|
}
|
|
449
|
+
killed.push(pid);
|
|
423
450
|
} catch (e) {
|
|
424
451
|
}
|
|
425
452
|
}
|
|
426
|
-
emitBootstrapEvent('info', 'Killed existing plugkit WASM watcher', { pids });
|
|
453
|
+
emitBootstrapEvent('info', 'Killed existing plugkit WASM watcher', { pids: killed });
|
|
427
454
|
} catch (e) {
|
|
428
455
|
emitBootstrapEvent('warn', 'Failed to kill existing plugkit', { error: e.message });
|
|
429
456
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gm-skill",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.1793",
|
|
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",
|