gm-skill 2.0.1106 → 2.0.1108

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
@@ -28,7 +28,7 @@ npx gm-skill-bootstrap
28
28
 
29
29
  ## Version
30
30
 
31
- `2.0.1106` — auto-bumped from the canonical `gm` repo. Every push to `AnEntrypoint/gm` republishes this package alongside all 15 platform packages.
31
+ `2.0.1108` — auto-bumped from the canonical `gm` repo. Every push to `AnEntrypoint/gm` republishes this package alongside all 15 platform packages.
32
32
 
33
33
  ## Source of truth
34
34
 
@@ -1 +1 @@
1
- 0.1.387
1
+ 0.1.389
package/bin/plugkit.wasm CHANGED
Binary file
@@ -1 +1 @@
1
- 093c5d9e8cb80e6b12d13eb66c9561dbfc2af4e3424acc0c9f0bd7e0713b3575 plugkit.wasm
1
+ 00902ce26dd6e5079f84de5049adb0c6547d0b295610ba21beb250a7deda6607 plugkit.wasm
@@ -12,12 +12,6 @@ const VEC_K_DEFAULT = 10;
12
12
  const EMBED_MODEL_DEFAULT = process.env.EMBED_MODEL || 'mistral/mistral-embed';
13
13
  const INFERENCE_MODEL_DEFAULT = process.env.INFERENCE_MODEL || 'groq/llama-3.3-70b-versatile';
14
14
 
15
- function failLoud(verb, status, detail) {
16
- const msg = `[plugkit-wasm] ${verb} FAILED: ${detail}`;
17
- console.error(msg);
18
- return { ok: false, verb, error: detail, status: status || 0 };
19
- }
20
-
21
15
  function cosineSim(a, b) {
22
16
  if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) return 0;
23
17
  let dot = 0, na = 0, nb = 0;
@@ -383,14 +377,25 @@ async function runSpoolWatcher(instance, spoolDir) {
383
377
  console.log(`[plugkit-wasm] plugkit v${resolveVersion(instance)} (wasm)`);
384
378
  console.log(`[plugkit-wasm] watching ${inDir}`);
385
379
 
386
- const processed = new Set();
380
+ const PROCESSED_MAX = 10000;
381
+ const processed = new Map();
382
+ function markProcessed(key) {
383
+ processed.set(key, Date.now());
384
+ if (processed.size > PROCESSED_MAX) {
385
+ const oldest = processed.keys().next().value;
386
+ processed.delete(oldest);
387
+ }
388
+ }
389
+ function isProcessed(key) { return processed.has(key); }
390
+ function unmarkProcessed(key) { processed.delete(key); }
391
+
387
392
  const dispatch = instance.exports.dispatch_verb;
388
393
  if (!dispatch) throw new Error('dispatch_verb not exported');
389
394
 
390
395
  const processFile = async (filePath) => {
391
396
  const key = path.relative(inDir, filePath);
392
- if (processed.has(key)) return;
393
- processed.add(key);
397
+ if (isProcessed(key)) return;
398
+ markProcessed(key);
394
399
 
395
400
  try {
396
401
  const content = fs.readFileSync(filePath, 'utf8');
@@ -423,7 +428,7 @@ async function runSpoolWatcher(instance, spoolDir) {
423
428
  try { instance.exports.plugkit_free(ptr, len); } catch (_) {}
424
429
 
425
430
  try { if (fs.existsSync(filePath)) fs.unlinkSync(filePath); } catch (_) {}
426
- processed.delete(key);
431
+ unmarkProcessed(key);
427
432
  } catch (e) {
428
433
  console.error(`[plugkit-wasm] error processing ${key}: ${e.message}`);
429
434
  const taskBase = path.basename(filePath, path.extname(filePath));
@@ -435,7 +440,7 @@ async function runSpoolWatcher(instance, spoolDir) {
435
440
  fs.writeFileSync(path.join(outDir, outName), JSON.stringify({ ok: false, error: e.message }));
436
441
  } catch (_) {}
437
442
  try { fs.unlinkSync(filePath); } catch (_) {}
438
- processed.delete(key);
443
+ unmarkProcessed(key);
439
444
  }
440
445
  };
441
446
 
@@ -462,12 +467,51 @@ async function runSpoolWatcher(instance, spoolDir) {
462
467
  try { fs.writeFileSync(heartbeatPath, String(Date.now())); } catch (_) {}
463
468
  }, 5000);
464
469
 
465
- const pollDeadline = setInterval(async () => {
470
+ const pollInterval = setInterval(async () => {
466
471
  const existing = walkDir(inDir);
467
472
  for (const fullPath of existing) {
468
473
  await processFile(fullPath);
469
474
  }
470
- }, 250);
475
+ }, 5000);
476
+
477
+ setInterval(() => {
478
+ try {
479
+ const cutoff = Date.now() - 3600_000;
480
+ for (const entry of fs.readdirSync(outDir)) {
481
+ try {
482
+ const fp = path.join(outDir, entry);
483
+ const s = fs.statSync(fp);
484
+ if (s.mtimeMs < cutoff) fs.unlinkSync(fp);
485
+ } catch (_) {}
486
+ }
487
+ } catch (_) {}
488
+ }, 60_000);
489
+
490
+ setInterval(() => {
491
+ try {
492
+ const cutoff = Date.now() - 600_000;
493
+ const walk = (dir) => {
494
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
495
+ const fp = path.join(dir, entry.name);
496
+ if (entry.isDirectory()) walk(fp);
497
+ else if (entry.isFile()) {
498
+ const s = fs.statSync(fp);
499
+ if (s.mtimeMs < cutoff) {
500
+ const rel = path.relative(inDir, fp);
501
+ const verbDir = path.dirname(rel);
502
+ const base = path.basename(fp, path.extname(fp));
503
+ const outName = verbDir === '.' ? `${base}.json` : `${verbDir}-${base}.json`;
504
+ try {
505
+ fs.writeFileSync(path.join(outDir, outName), JSON.stringify({ ok: false, error: 'stale input — never dispatched or watcher crash mid-flight' }));
506
+ } catch (_) {}
507
+ try { fs.unlinkSync(fp); } catch (_) {}
508
+ }
509
+ }
510
+ }
511
+ };
512
+ walk(inDir);
513
+ } catch (_) {}
514
+ }, 300_000);
471
515
 
472
516
  const existing = walkDir(inDir);
473
517
  for (const fullPath of existing) {
@@ -523,7 +567,7 @@ async function runSpoolWatcher(instance, spoolDir) {
523
567
  await runSpoolWatcher(instance, spoolDir);
524
568
  } else if (args[0] === 'dispatch') {
525
569
  const verb = args[1] || '';
526
- const body = args[2] || '{}';
570
+ const body = args.length >= 3 ? args[2] : '';
527
571
  const dispatch = instance.exports.dispatch_verb;
528
572
  const verbBytes = new TextEncoder().encode(verb);
529
573
  const bodyBytes = new TextEncoder().encode(body);
@@ -536,7 +580,10 @@ async function runSpoolWatcher(instance, spoolDir) {
536
580
  const len = Number(result >> 32n);
537
581
  const out = new TextDecoder().decode(new Uint8Array(instance.exports.memory.buffer, ptr, len));
538
582
  process.stdout.write(out);
539
- process.exit(0);
583
+ let parsed;
584
+ try { parsed = JSON.parse(out); } catch (_) { parsed = null; }
585
+ const failed = parsed && parsed.ok === false;
586
+ process.exit(failed ? 2 : 0);
540
587
  } else {
541
588
  console.log('[plugkit-wasm] args:', args.join(' '));
542
589
  process.exit(0);
package/gm.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gm",
3
- "version": "2.0.1106",
3
+ "version": "2.0.1108",
4
4
  "description": "Spool-dispatch orchestration engine with unified state machine, skills, and automated git enforcement",
5
5
  "author": "AnEntrypoint",
6
6
  "license": "MIT",
@@ -23,5 +23,5 @@
23
23
  "publishConfig": {
24
24
  "access": "public"
25
25
  },
26
- "plugkitVersion": "0.1.387"
26
+ "plugkitVersion": "0.1.389"
27
27
  }
@@ -41,18 +41,38 @@ function emitBootstrapEvent(severity, message, details) {
41
41
  }
42
42
  }
43
43
 
44
+ function resolveFromCandidates(candidates, requireResolveId) {
45
+ for (const c of candidates) {
46
+ if (c && fs.existsSync(c)) return c;
47
+ }
48
+ if (requireResolveId) {
49
+ try {
50
+ const resolved = require.resolve(requireResolveId);
51
+ if (fs.existsSync(resolved)) return resolved;
52
+ } catch (e) {
53
+ }
54
+ }
55
+ return null;
56
+ }
57
+
44
58
  function readManifest() {
45
59
  try {
46
- const gmJsonPath = path.join(process.cwd(), 'gm-starter', 'gm.json');
47
- if (!fs.existsSync(gmJsonPath)) {
48
- throw new Error('gm-starter/gm.json not found');
60
+ const gmJsonPath = resolveFromCandidates([
61
+ path.join(__dirname, '..', 'gm.json'),
62
+ path.join(__dirname, '..', '..', 'gm.json'),
63
+ ], 'gm-skill/gm.json');
64
+ if (!gmJsonPath) {
65
+ throw new Error('gm.json not found relative to skill-bootstrap.js');
49
66
  }
50
67
  const gm = JSON.parse(fs.readFileSync(gmJsonPath, 'utf8'));
51
68
  const version = gm.plugkitVersion;
52
69
 
53
- const sha256Path = path.join(process.cwd(), 'gm-starter', 'bin', 'plugkit.wasm.sha256');
54
- if (!fs.existsSync(sha256Path)) {
55
- throw new Error('gm-starter/bin/plugkit.wasm.sha256 not found');
70
+ const sha256Path = resolveFromCandidates([
71
+ path.join(__dirname, '..', 'bin', 'plugkit.wasm.sha256'),
72
+ path.join(__dirname, '..', '..', 'bin', 'plugkit.wasm.sha256'),
73
+ ], 'gm-skill/bin/plugkit.wasm.sha256');
74
+ if (!sha256Path) {
75
+ throw new Error('bin/plugkit.wasm.sha256 not found relative to skill-bootstrap.js');
56
76
  }
57
77
  const sha256Content = fs.readFileSync(sha256Path, 'utf8').trim();
58
78
  const expectedHash = sha256Content.split(/\s+/)[0];
@@ -366,12 +386,26 @@ async function bootstrapPlugkit(sessionId) {
366
386
  }
367
387
 
368
388
  async function checkPortReachable(host, port, timeoutMs = 500) {
369
- try {
370
- const result = await spool.execSpool('health', 'health', { timeoutMs, sessionId: process.env.CLAUDE_SESSION_ID || 'unknown' });
371
- return !!(result && result.ok);
372
- } catch (e) {
373
- return false;
374
- }
389
+ const net = require('net');
390
+ return new Promise((resolve) => {
391
+ const socket = new net.Socket();
392
+ let done = false;
393
+ const finish = (ok) => {
394
+ if (done) return;
395
+ done = true;
396
+ try { socket.destroy(); } catch (e) {}
397
+ resolve(ok);
398
+ };
399
+ socket.setTimeout(timeoutMs);
400
+ socket.once('connect', () => finish(true));
401
+ socket.once('timeout', () => finish(false));
402
+ socket.once('error', () => finish(false));
403
+ try {
404
+ socket.connect(port, host);
405
+ } catch (e) {
406
+ finish(false);
407
+ }
408
+ });
375
409
  }
376
410
 
377
411
  async function bootstrapAcptoapi() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gm-skill",
3
- "version": "2.0.1106",
3
+ "version": "2.0.1108",
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.1106"
42
+ "gm-plugkit": "^2.0.1108"
43
43
  },
44
44
  "engines": {
45
45
  "node": ">=16.0.0"