gm-skill 2.0.1180 → 2.0.1188
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 +1 -1
- package/bin/plugkit.version +1 -1
- package/bin/plugkit.wasm +0 -0
- package/bin/plugkit.wasm.sha256 +1 -1
- package/gm-plugkit/bootstrap.js +4 -136
- package/gm.json +2 -2
- package/lib/skill-bootstrap.js +10 -2
- package/lib/spool-dispatch.js +14 -4
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -35,7 +35,7 @@ An earlier generation fanned out fifteen per-platform downstream repos (gm-cc, g
|
|
|
35
35
|
|
|
36
36
|
## Version
|
|
37
37
|
|
|
38
|
-
`2.0.
|
|
38
|
+
`2.0.1188` — auto-bumped from the canonical `gm` repo. Every push to `AnEntrypoint/gm` (or any cascading sibling crate) republishes this package.
|
|
39
39
|
|
|
40
40
|
## Source of truth
|
|
41
41
|
|
package/bin/plugkit.version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.1.
|
|
1
|
+
0.1.431
|
package/bin/plugkit.wasm
CHANGED
|
Binary file
|
package/bin/plugkit.wasm.sha256
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
cce5625d938fff3d9c726b7ae3bb8b96a3ee6b0ecc616a2854fddbca4c4e464e plugkit.wasm
|
package/gm-plugkit/bootstrap.js
CHANGED
|
@@ -295,26 +295,6 @@ function platformKey() {
|
|
|
295
295
|
return (a === 'arm64' || a === 'aarch64') ? 'linux-arm64' : 'linux-x64';
|
|
296
296
|
}
|
|
297
297
|
|
|
298
|
-
function rtkBinaryName() {
|
|
299
|
-
const key = platformKey();
|
|
300
|
-
return key.startsWith('win32') ? `rtk-${key}.exe` : `rtk-${key}`;
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
function readRtkVersion() {
|
|
304
|
-
const p = path.join(wrapperDir, 'rtk.version');
|
|
305
|
-
if (!fs.existsSync(p)) return null;
|
|
306
|
-
const v = fs.readFileSync(p, 'utf8').trim();
|
|
307
|
-
return v || null;
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
function rtkCacheDir(root, plugkitVerDir) {
|
|
311
|
-
const rtkVer = readRtkVersion();
|
|
312
|
-
if (!rtkVer) return plugkitVerDir;
|
|
313
|
-
const dir = path.join(root, `rtk-v${rtkVer}`);
|
|
314
|
-
ensureDir(dir);
|
|
315
|
-
return dir;
|
|
316
|
-
}
|
|
317
|
-
|
|
318
298
|
function healIfShaMatches(binPath, expectedSha, sentinelPath, partialPath, kind) {
|
|
319
299
|
if (!fs.existsSync(binPath)) return false;
|
|
320
300
|
if (partialPath) { try { if (fs.existsSync(partialPath)) fs.unlinkSync(partialPath); } catch (_) {} }
|
|
@@ -402,7 +382,7 @@ function isLockStale(lockPath) {
|
|
|
402
382
|
return false;
|
|
403
383
|
}
|
|
404
384
|
|
|
405
|
-
function pruneOldVersions(root, keepVersion
|
|
385
|
+
function pruneOldVersions(root, keepVersion) {
|
|
406
386
|
try {
|
|
407
387
|
const entries = fs.readdirSync(root);
|
|
408
388
|
for (const e of entries) {
|
|
@@ -410,7 +390,6 @@ function pruneOldVersions(root, keepVersion, keepRtkVersion) {
|
|
|
410
390
|
const isRtk = e.startsWith('rtk-v');
|
|
411
391
|
if (!isPlugkit && !isRtk) continue;
|
|
412
392
|
if (isPlugkit && e === `v${keepVersion}`) continue;
|
|
413
|
-
if (isRtk && keepRtkVersion && e === `rtk-v${keepRtkVersion}`) continue;
|
|
414
393
|
const dir = path.join(root, e);
|
|
415
394
|
const lock = path.join(dir, '.lock');
|
|
416
395
|
if (fs.existsSync(lock) && !isLockStale(lock)) continue;
|
|
@@ -447,101 +426,6 @@ function killStaleDaemonIfVersionChanged() {
|
|
|
447
426
|
}
|
|
448
427
|
|
|
449
428
|
|
|
450
|
-
function resolveCachedRtk() {
|
|
451
|
-
const version = readVersionFile();
|
|
452
|
-
const root = (() => {
|
|
453
|
-
try { const r = cacheRoot(); ensureDir(r); return r; }
|
|
454
|
-
catch (_) { const r = fallbackCacheRoot(); ensureDir(r); return r; }
|
|
455
|
-
})();
|
|
456
|
-
const plugkitVerDir = path.join(root, `v${version}`);
|
|
457
|
-
const cacheDir = rtkCacheDir(root, plugkitVerDir);
|
|
458
|
-
const rtkPath = path.join(cacheDir, rtkBinaryName());
|
|
459
|
-
const rtkOk = path.join(cacheDir, '.rtk-ok');
|
|
460
|
-
if (fs.existsSync(rtkPath) && fs.existsSync(rtkOk)) return rtkPath;
|
|
461
|
-
return null;
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
async function bootstrapRtk(plugkitVerDir, plugkitVersion, silent, root) {
|
|
465
|
-
const rtkName = rtkBinaryName();
|
|
466
|
-
const cacheDir = rtkCacheDir(root || cacheRoot(), plugkitVerDir);
|
|
467
|
-
const rtkPath = path.join(cacheDir, rtkName);
|
|
468
|
-
const rtkOk = path.join(cacheDir, '.rtk-ok');
|
|
469
|
-
if (fs.existsSync(rtkPath) && fs.existsSync(rtkOk)) {
|
|
470
|
-
if (!silent) log(`rtk cache hit: ${rtkPath}`);
|
|
471
|
-
return rtkPath;
|
|
472
|
-
}
|
|
473
|
-
const rtkSha = readShaManifest();
|
|
474
|
-
// rtk.sha256 may be in a separate file
|
|
475
|
-
const rtkShaPath = path.join(wrapperDir, 'rtk.sha256');
|
|
476
|
-
let expected = null;
|
|
477
|
-
if (fs.existsSync(rtkShaPath)) {
|
|
478
|
-
expected = fs.readFileSync(rtkShaPath, 'utf8').trim();
|
|
479
|
-
}
|
|
480
|
-
const tmp = `${rtkPath}.partial`;
|
|
481
|
-
if (healIfShaMatches(rtkPath, expected, rtkOk, tmp, 'rtk')) {
|
|
482
|
-
if (!silent) log(`rtk cache heal (sha match): ${rtkPath}`);
|
|
483
|
-
return rtkPath;
|
|
484
|
-
}
|
|
485
|
-
const RTKS_RELEASE_REPO = 'AnEntrypoint/plugkit-bin';
|
|
486
|
-
const url = `https://github.com/${RTKS_RELEASE_REPO}/releases/download/v${plugkitVersion}/${rtkName}`;
|
|
487
|
-
const startMs = Date.now();
|
|
488
|
-
let lastErr;
|
|
489
|
-
for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {
|
|
490
|
-
try {
|
|
491
|
-
log(`rtk download attempt ${attempt}/${MAX_ATTEMPTS}: ${url}`);
|
|
492
|
-
const result = spawnSync(
|
|
493
|
-
'curl',
|
|
494
|
-
['-fSL', '--max-time', String(Math.floor(ATTEMPT_TIMEOUT_MS / 1000)), '-o', tmp, url],
|
|
495
|
-
{ stdio: 'pipe', timeout: ATTEMPT_TIMEOUT_MS + 5000, windowsHide: true }
|
|
496
|
-
);
|
|
497
|
-
if (result.error) throw result.error;
|
|
498
|
-
if (result.status !== 0) throw new Error(`curl failed with status ${result.status}`);
|
|
499
|
-
break;
|
|
500
|
-
} catch (err) {
|
|
501
|
-
lastErr = err;
|
|
502
|
-
log(`rtk attempt ${attempt} failed: ${err.message}`);
|
|
503
|
-
obsEvent('bootstrap', 'rtk.download.attempt_failed', { attempt, max: MAX_ATTEMPTS, err: String(err.message || err) });
|
|
504
|
-
if (attempt < MAX_ATTEMPTS) {
|
|
505
|
-
const wait = BACKOFF_MS[attempt - 1] || 120000;
|
|
506
|
-
log(`backing off ${wait}ms`);
|
|
507
|
-
await new Promise(r => setTimeout(r, wait));
|
|
508
|
-
}
|
|
509
|
-
}
|
|
510
|
-
}
|
|
511
|
-
if (lastErr) throw lastErr;
|
|
512
|
-
if (expected) {
|
|
513
|
-
const got = await sha256OfFile(tmp);
|
|
514
|
-
if (got !== expected) {
|
|
515
|
-
try { fs.unlinkSync(tmp); } catch (_) {}
|
|
516
|
-
throw new Error(`rtk sha256 mismatch: expected ${expected}, got ${got}`);
|
|
517
|
-
}
|
|
518
|
-
}
|
|
519
|
-
try { fs.renameSync(tmp, rtkPath); }
|
|
520
|
-
catch (err) {
|
|
521
|
-
if (err.code === 'EEXIST' || err.code === 'EPERM') {
|
|
522
|
-
try { fs.unlinkSync(rtkPath); } catch (_) {}
|
|
523
|
-
fs.renameSync(tmp, rtkPath);
|
|
524
|
-
} else throw err;
|
|
525
|
-
}
|
|
526
|
-
if (os.platform() !== 'win32') { try { fs.chmodSync(rtkPath, 0o755); } catch (_) {} }
|
|
527
|
-
fs.writeFileSync(rtkOk, new Date().toISOString());
|
|
528
|
-
log(`installed ${rtkPath}`);
|
|
529
|
-
obsEvent('bootstrap', 'install.done', { path: rtkPath, plugkit_version: plugkitVersion, rtk_version: readRtkVersion() || plugkitVersion, kind: 'rtk', dur_ms: Date.now() - startMs });
|
|
530
|
-
return rtkPath;
|
|
531
|
-
}
|
|
532
|
-
|
|
533
|
-
function spawnDetachedRtkFetch() {
|
|
534
|
-
try {
|
|
535
|
-
const child = spawn(process.execPath, [__filename, '--rtk-only'], {
|
|
536
|
-
detached: true, stdio: 'ignore', windowsHide: true,
|
|
537
|
-
});
|
|
538
|
-
child.unref();
|
|
539
|
-
obsEvent('bootstrap', 'rtk.detached.spawned', { pid: child.pid });
|
|
540
|
-
} catch (err) {
|
|
541
|
-
log(`rtk detach spawn failed: ${err.message}`);
|
|
542
|
-
}
|
|
543
|
-
}
|
|
544
|
-
|
|
545
429
|
async function bootstrap(opts) {
|
|
546
430
|
opts = opts || {};
|
|
547
431
|
const version = readVersionFile();
|
|
@@ -587,7 +471,6 @@ async function bootstrap(opts) {
|
|
|
587
471
|
|
|
588
472
|
if (healIfShaMatches(finalPath, expectedSha, okSentinel, partialPath, 'plugkit-wasm')) {
|
|
589
473
|
obsEvent('bootstrap', 'decision.heal', { reason: 'sha-match', path: finalPath });
|
|
590
|
-
spawnDetachedRtkFetch();
|
|
591
474
|
copyWasmToGmTools(finalPath, version);
|
|
592
475
|
clearBootstrapError();
|
|
593
476
|
return finalPath;
|
|
@@ -604,8 +487,7 @@ async function bootstrap(opts) {
|
|
|
604
487
|
}
|
|
605
488
|
if (healIfShaMatches(finalPath, expectedSha, okSentinel, partialPath, 'plugkit-wasm')) {
|
|
606
489
|
obsEvent('bootstrap', 'decision.heal', { reason: 'sha-match-under-lock', path: finalPath });
|
|
607
|
-
|
|
608
|
-
copyWasmToGmTools(finalPath, version);
|
|
490
|
+
copyWasmToGmTools(finalPath, version);
|
|
609
491
|
clearBootstrapError();
|
|
610
492
|
return finalPath;
|
|
611
493
|
}
|
|
@@ -663,8 +545,7 @@ async function bootstrap(opts) {
|
|
|
663
545
|
log(`decision: fetch reason: install-complete (${finalPath})`);
|
|
664
546
|
obsEvent('bootstrap', 'install.done', { path: finalPath, version, kind: 'plugkit-wasm' });
|
|
665
547
|
proactiveKillForNewInstall(version);
|
|
666
|
-
pruneOldVersions(root, version
|
|
667
|
-
spawnDetachedRtkFetch();
|
|
548
|
+
pruneOldVersions(root, version);
|
|
668
549
|
copyWasmToGmTools(finalPath, version);
|
|
669
550
|
clearBootstrapError();
|
|
670
551
|
return finalPath;
|
|
@@ -901,15 +782,12 @@ module.exports = {
|
|
|
901
782
|
getBinaryPath,
|
|
902
783
|
startSpoolDaemon,
|
|
903
784
|
isReady,
|
|
904
|
-
rtkBinaryName,
|
|
905
785
|
cacheRoot,
|
|
906
786
|
obsEvent,
|
|
907
787
|
killRunningDaemons,
|
|
908
788
|
killStaleDaemonIfVersionChanged,
|
|
909
789
|
killSpoolWatcherInCwd,
|
|
910
790
|
proactiveKillForNewInstall,
|
|
911
|
-
resolveCachedRtk,
|
|
912
|
-
bootstrapRtk,
|
|
913
791
|
readDaemonVersion,
|
|
914
792
|
writeDaemonVersion,
|
|
915
793
|
daemonVersionSentinel,
|
|
@@ -919,21 +797,11 @@ if (require.main === module) {
|
|
|
919
797
|
(async () => {
|
|
920
798
|
try {
|
|
921
799
|
const args = process.argv.slice(2);
|
|
922
|
-
if (args.includes('--
|
|
923
|
-
const version = readVersionFile();
|
|
924
|
-
let root = cacheRoot();
|
|
925
|
-
try { ensureDir(root); }
|
|
926
|
-
catch (_) { root = fallbackCacheRoot(); ensureDir(root); }
|
|
927
|
-
const verDir = path.join(root, `v${version}`);
|
|
928
|
-
ensureDir(verDir);
|
|
929
|
-
await bootstrapRtk(verDir, version, true, root);
|
|
930
|
-
process.exit(0);
|
|
931
|
-
} else if (args.includes('--status')) {
|
|
800
|
+
if (args.includes('--status')) {
|
|
932
801
|
console.log(JSON.stringify({
|
|
933
802
|
ready: isReady(),
|
|
934
803
|
wasmPath: getWasmPath(),
|
|
935
804
|
daemonVersion: readDaemonVersion(),
|
|
936
|
-
cachedRtk: resolveCachedRtk(),
|
|
937
805
|
}));
|
|
938
806
|
process.exit(0);
|
|
939
807
|
} else {
|
package/gm.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gm",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.1188",
|
|
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.431"
|
|
21
21
|
}
|
package/lib/skill-bootstrap.js
CHANGED
|
@@ -322,10 +322,18 @@ function ensureBuildToolIgnores(cwd) {
|
|
|
322
322
|
|
|
323
323
|
function writeSessionSidecar(sessionId) {
|
|
324
324
|
try {
|
|
325
|
-
const sess = sessionId || process.env.CLAUDE_SESSION_ID || process.env.GM_SESSION_ID || '';
|
|
326
|
-
if (!sess) return;
|
|
327
325
|
const spool = path.join(process.cwd(), '.gm', 'exec-spool');
|
|
328
326
|
fs.mkdirSync(spool, { recursive: true });
|
|
327
|
+
let sess = sessionId || process.env.CLAUDE_SESSION_ID || process.env.GM_SESSION_ID || '';
|
|
328
|
+
if (!sess) {
|
|
329
|
+
const fallbackFile = path.join(spool, '.session-fallback');
|
|
330
|
+
try { sess = fs.readFileSync(fallbackFile, 'utf8').trim(); } catch (_) {}
|
|
331
|
+
if (!sess) {
|
|
332
|
+
const cwdHash = require('crypto').createHash('sha1').update(process.cwd()).digest('hex').slice(0, 8);
|
|
333
|
+
sess = `machine-${cwdHash}-${Date.now().toString(36)}`;
|
|
334
|
+
try { fs.writeFileSync(fallbackFile, sess); } catch (_) {}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
329
337
|
fs.writeFileSync(path.join(spool, '.session-current'), sess);
|
|
330
338
|
} catch (_) {}
|
|
331
339
|
}
|
package/lib/spool-dispatch.js
CHANGED
|
@@ -101,10 +101,20 @@ async function dispatchSpool(cmd, lang, body, timeoutMs, sessionId) {
|
|
|
101
101
|
fs.mkdirSync(inDir, { recursive: true });
|
|
102
102
|
fs.mkdirSync(outDir, { recursive: true });
|
|
103
103
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
104
|
+
let sess = sessionId || process.env.CLAUDE_SESSION_ID || process.env.GM_SESSION_ID || '';
|
|
105
|
+
try {
|
|
106
|
+
const spoolDir = path.join(process.cwd(), '.gm', 'exec-spool');
|
|
107
|
+
if (!sess) {
|
|
108
|
+
const fallbackFile = path.join(spoolDir, '.session-fallback');
|
|
109
|
+
try { sess = fs.readFileSync(fallbackFile, 'utf8').trim(); } catch (_) {}
|
|
110
|
+
if (!sess) {
|
|
111
|
+
const cwdHash = require('crypto').createHash('sha1').update(process.cwd()).digest('hex').slice(0, 8);
|
|
112
|
+
sess = `machine-${cwdHash}-${Date.now().toString(36)}`;
|
|
113
|
+
try { fs.writeFileSync(fallbackFile, sess); } catch (_) {}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
fs.writeFileSync(path.join(spoolDir, '.session-current'), sess);
|
|
117
|
+
} catch (_) {}
|
|
108
118
|
|
|
109
119
|
const code = sessionId ? `const SESSION_ID = '${sessionId}';\n${body}` : body;
|
|
110
120
|
fs.writeFileSync(inFile, code, 'utf8');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gm-skill",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.1188",
|
|
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.1188"
|
|
43
43
|
},
|
|
44
44
|
"engines": {
|
|
45
45
|
"node": ">=16.0.0"
|