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 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.1180` — auto-bumped from the canonical `gm` repo. Every push to `AnEntrypoint/gm` (or any cascading sibling crate) republishes this package.
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
 
@@ -1 +1 @@
1
- 0.1.426
1
+ 0.1.431
package/bin/plugkit.wasm CHANGED
Binary file
@@ -1 +1 @@
1
- 9dd65bfeb7037f9d883a3064d22fab4a34581e8fde962aa8dfe20141fbb2dd1c plugkit.wasm
1
+ cce5625d938fff3d9c726b7ae3bb8b96a3ee6b0ecc616a2854fddbca4c4e464e plugkit.wasm
@@ -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, keepRtkVersion) {
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
- spawnDetachedRtkFetch();
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, readRtkVersion());
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('--rtk-only')) {
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.1180",
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.426"
20
+ "plugkitVersion": "0.1.431"
21
21
  }
@@ -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
  }
@@ -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
- const sess = sessionId || process.env.CLAUDE_SESSION_ID || process.env.GM_SESSION_ID || '';
105
- if (sess) {
106
- try { fs.writeFileSync(path.join(process.cwd(), '.gm', 'exec-spool', '.session-current'), sess); } catch (_) {}
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.1180",
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.1180"
42
+ "gm-plugkit": "^2.0.1188"
43
43
  },
44
44
  "engines": {
45
45
  "node": ">=16.0.0"