gm-skill 2.0.1526 → 2.0.1527
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 +1 -3
- package/gm-plugkit/package.json +1 -1
- package/gm-plugkit/plugkit-wasm-wrapper.js +5 -77
- package/gm.json +1 -1
- package/lib/skill-bootstrap.js +7 -8
- package/package.json +1 -1
package/AGENTS.md
CHANGED
|
@@ -32,9 +32,7 @@ The plugkit stack runs as a wasm cdylib loaded by `plugkit-wasm-wrapper.js` unde
|
|
|
32
32
|
|
|
33
33
|
**`plugkit-wasm-wrapper.js` is ESM; never use inline `require()` for a node builtin -- import it at module scope.** The wrapper runs under both node and bun, and the supervisor's `resolveRuntime()` prefers bun. Under bun's ESM, `require` is not a global, so an inline `const x = require('crypto'|'net'|'http'|'https'|'child_process')` throws `require is not defined` -- and because those calls sit in `catch(_){}` blocks, the failure is silent: it broke `_ownWrapperSha12` (status.wrapper_sha stayed null, leaving the supervisor wrapper-sha-drift recycle inert), `_wrapperShaAtBoot` and its self-drift-restart, the synthetic-session cwd-hash, and the file-index sha -- all only under the bun watcher, which is why it hid for so long (node-run watchers have `require` via CJS interop). Every node builtin is imported once at the top (`import crypto from 'crypto'`, etc.); inline `require` of a builtin is forbidden. Full incident in rs-learn (`recall: wrapper require not defined under bun`).
|
|
34
34
|
|
|
35
|
-
**Every single-instance / lock guard is atomic
|
|
36
|
-
|
|
37
|
-
**Count plugkit processes by executable Name, never by command-line substring.** A `Get-CimInstance Win32_Process | Where-Object { $_.CommandLine -like '*plugkit-wasm-wrapper*' }` (or `-match 'plugkit-supervisor'`) also matches the bash/powershell command running the query itself -- its eval string contains those literals -- so it fabricates phantom processes and inflates the count (it reported `8 watchers + 4 supervisors` when the truth was `4 watchers, 0 supervisors`). Always constrain to the real runtime: `Where-Object { ($_.Name -eq 'node.exe' -or $_.Name -eq 'bun.exe') -and $_.CommandLine -match 'plugkit-wasm-wrapper\.js' }`. The phantom count made a working atomic-guard fix look unconverged across two fires; a wrong measurement is as costly as a wrong diagnosis. Full incident in rs-learn (`recall: supervisor churn TOCTOU atomic guard`).
|
|
35
|
+
**Every single-instance / lock guard is atomic (`fs.openSync(path,'wx')` O_EXCL or atomic-rename), never check-then-act; count plugkit processes by executable Name not command-line substring.** Both are Windows concurrency mechanics whose full incident lives in rs-learn (`recall: supervisor churn TOCTOU atomic guard`).
|
|
38
36
|
|
|
39
37
|
## Spool dispatch ABI
|
|
40
38
|
|
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.1527",
|
|
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": {
|
|
@@ -3472,78 +3472,7 @@ async function runSpoolWatcher(instance, spoolDir) {
|
|
|
3472
3472
|
applyUpdateCheckResult(installed, cached.latest, cached.status || 200);
|
|
3473
3473
|
return;
|
|
3474
3474
|
}
|
|
3475
|
-
|
|
3476
|
-
host: 'api.github.com',
|
|
3477
|
-
path: '/repos/AnEntrypoint/plugkit-bin/releases/latest',
|
|
3478
|
-
headers: { 'user-agent': 'plugkit-watcher', 'accept': 'application/json' },
|
|
3479
|
-
timeout: 5000,
|
|
3480
|
-
}, (res) => {
|
|
3481
|
-
if (res.statusCode !== 200) {
|
|
3482
|
-
res.resume();
|
|
3483
|
-
writeSharedUpdateCache(null, res.statusCode);
|
|
3484
|
-
applyUpdateCheckResult(installed, null, res.statusCode);
|
|
3485
|
-
checkUpdateViaNpm(installed);
|
|
3486
|
-
return;
|
|
3487
|
-
}
|
|
3488
|
-
const chunks = [];
|
|
3489
|
-
res.on('data', c => chunks.push(c));
|
|
3490
|
-
res.on('end', () => {
|
|
3491
|
-
try {
|
|
3492
|
-
const rel = JSON.parse(Buffer.concat(chunks).toString('utf-8'));
|
|
3493
|
-
const tag = rel && rel.tag_name;
|
|
3494
|
-
if (!tag) return;
|
|
3495
|
-
const latest = tag.replace(/^v/, '');
|
|
3496
|
-
writeSharedUpdateCache(latest, 200);
|
|
3497
|
-
if (latest === installed) {
|
|
3498
|
-
try { fs.unlinkSync(UPDATE_AVAILABLE_PATH); } catch (_) {}
|
|
3499
|
-
if (_lastKnownDrift) {
|
|
3500
|
-
logEvent('plugkit', 'update.cleared', { installed, was: _lastKnownDrift });
|
|
3501
|
-
_lastKnownDrift = null;
|
|
3502
|
-
}
|
|
3503
|
-
return;
|
|
3504
|
-
}
|
|
3505
|
-
const update_url = `https://github.com/AnEntrypoint/plugkit-bin/releases/tag/v${latest}`;
|
|
3506
|
-
fs.writeFileSync(UPDATE_AVAILABLE_PATH, JSON.stringify({
|
|
3507
|
-
installed,
|
|
3508
|
-
latest,
|
|
3509
|
-
checked_at_ms: Date.now(),
|
|
3510
|
-
instruction: 'plugkit is out of date. Update with: bun x gm-plugkit@latest --kill-stale-watchers; bun x gm-plugkit@latest spool. A fresh boot downloads the new wasm and respawns; an in-place running watcher does not self-download.',
|
|
3511
|
-
update_url,
|
|
3512
|
-
}, null, 2));
|
|
3513
|
-
console.log(`[update] available: installed=${installed} latest=${latest} -> wrote ${UPDATE_AVAILABLE_PATH}`);
|
|
3514
|
-
if (_lastKnownDrift !== latest) {
|
|
3515
|
-
logEvent('plugkit', 'update.available', { installed, latest, update_url });
|
|
3516
|
-
_lastKnownDrift = latest;
|
|
3517
|
-
}
|
|
3518
|
-
// NOTE: do NOT bump the disk version file here to "arm" a drift-respawn. installedVersionAtTools()
|
|
3519
|
-
// reads that file as the source of truth for the installed version; bumping it ahead of the actual
|
|
3520
|
-
// wasm download makes ensureReady compute versionDrift=false (file==target) and isReady()=true, so it
|
|
3521
|
-
// returns already-ready WITHOUT downloading the new binary -- while the running instance is still the
|
|
3522
|
-
// old version. The drift-check then sees instance(old) != file(new) forever and self-respawns in an
|
|
3523
|
-
// infinite loop, each respawn reloading the same old wasm. The version file must only advance AFTER
|
|
3524
|
-
// a verified binary download (bootstrap's job). Auto-update stays notify-only until ensureReady gains
|
|
3525
|
-
// a sha-verified force-download path; see PRD watcher-autoupdate-thrash-fix.
|
|
3526
|
-
} catch (e) {
|
|
3527
|
-
logUpdateCheckError({ error: String(e && e.message || e) });
|
|
3528
|
-
}
|
|
3529
|
-
});
|
|
3530
|
-
});
|
|
3531
|
-
let _checkErrored = false;
|
|
3532
|
-
req.on('timeout', () => {
|
|
3533
|
-
if (_checkErrored) { try { req.destroy(); } catch (_) {} return; }
|
|
3534
|
-
_checkErrored = true;
|
|
3535
|
-
try { req.destroy(); } catch (_) {}
|
|
3536
|
-
writeSharedUpdateCache(null, -1);
|
|
3537
|
-
logUpdateCheckError({ error: 'timeout' });
|
|
3538
|
-
checkUpdateViaNpm(installed);
|
|
3539
|
-
});
|
|
3540
|
-
req.on('error', (e) => {
|
|
3541
|
-
if (_checkErrored) return;
|
|
3542
|
-
_checkErrored = true;
|
|
3543
|
-
writeSharedUpdateCache(null, -2);
|
|
3544
|
-
logUpdateCheckError({ error: String(e && e.message || e) });
|
|
3545
|
-
checkUpdateViaNpm(installed);
|
|
3546
|
-
});
|
|
3475
|
+
checkUpdateViaNpm(installed);
|
|
3547
3476
|
}
|
|
3548
3477
|
setTimeout(checkForUpdate, 10_000);
|
|
3549
3478
|
setInterval(checkForUpdate, UPDATE_CHECK_INTERVAL_MS);
|
|
@@ -3739,11 +3668,10 @@ async function selfHealFromGithubReleases() {
|
|
|
3739
3668
|
});
|
|
3740
3669
|
(async () => {
|
|
3741
3670
|
try {
|
|
3742
|
-
const
|
|
3743
|
-
const
|
|
3744
|
-
if (!
|
|
3745
|
-
const
|
|
3746
|
-
const base = `https://github.com/AnEntrypoint/plugkit-bin/releases/download/${tag}`;
|
|
3671
|
+
const meta = await fetchJson('https://registry.npmjs.org/plugkit-wasm/latest');
|
|
3672
|
+
const version = meta && meta.version;
|
|
3673
|
+
if (!version) throw new Error('no version from npm plugkit-wasm');
|
|
3674
|
+
const base = `https://github.com/AnEntrypoint/plugkit-bin/releases/download/v${version}`;
|
|
3747
3675
|
const [wasm, sha] = await Promise.all([
|
|
3748
3676
|
fetchBuf(`${base}/plugkit.wasm`),
|
|
3749
3677
|
fetchBuf(`${base}/plugkit.wasm.sha256`).then(b => b.toString('utf-8').trim().split(/\s+/)[0]).catch(() => ''),
|
package/gm.json
CHANGED
package/lib/skill-bootstrap.js
CHANGED
|
@@ -132,15 +132,14 @@ async function getLatestRemoteVersion() {
|
|
|
132
132
|
let version = null;
|
|
133
133
|
let source = null;
|
|
134
134
|
try {
|
|
135
|
-
const buf = await httpGet('https://
|
|
136
|
-
const
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
source = 'github-releases';
|
|
135
|
+
const buf = await httpGet('https://registry.npmjs.org/plugkit-wasm/latest', 3000);
|
|
136
|
+
const pkg = JSON.parse(buf.toString('utf-8'));
|
|
137
|
+
if (pkg && pkg.version) {
|
|
138
|
+
version = pkg.version;
|
|
139
|
+
source = 'npm-plugkit-wasm';
|
|
141
140
|
}
|
|
142
141
|
} catch (e) {
|
|
143
|
-
emitBootstrapEvent('warn', '
|
|
142
|
+
emitBootstrapEvent('warn', 'npm plugkit-wasm lookup failed', { error: e.message });
|
|
144
143
|
}
|
|
145
144
|
if (!version) {
|
|
146
145
|
try {
|
|
@@ -154,7 +153,7 @@ async function getLatestRemoteVersion() {
|
|
|
154
153
|
source = 'npm-gm-plugkit-fallback';
|
|
155
154
|
}
|
|
156
155
|
} catch (e) {
|
|
157
|
-
emitBootstrapEvent('warn', 'npm fallback lookup failed', { error: e.message });
|
|
156
|
+
emitBootstrapEvent('warn', 'npm gm-plugkit fallback lookup failed', { error: e.message });
|
|
158
157
|
}
|
|
159
158
|
}
|
|
160
159
|
if (!version) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gm-skill",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.1527",
|
|
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",
|