gm-skill 2.0.1333 → 2.0.1335

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gm-plugkit",
3
- "version": "2.0.1333",
3
+ "version": "2.0.1335",
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": {
@@ -1752,17 +1752,8 @@ function resolveVersion(instance) {
1752
1752
  try {
1753
1753
  return fs.readFileSync(path.join(GM_TOOLS_ROOT, 'plugkit.version'), 'utf8').trim();
1754
1754
  } catch (_) {}
1755
- try {
1756
- const fn = instance && instance.exports && instance.exports.plugkit_version;
1757
- if (typeof fn === 'function') {
1758
- const result = fn();
1759
- const ptr = Number(result & 0xffffffffn);
1760
- const len = Number(result >> 32n);
1761
- const bytes = new Uint8Array(instance.exports.memory.buffer, ptr, len);
1762
- return new TextDecoder().decode(bytes).trim();
1763
- }
1764
- } catch (_) {}
1765
- return 'unknown';
1755
+ const fromInstance = readInstanceVersion(instance);
1756
+ return fromInstance || 'unknown';
1766
1757
  }
1767
1758
 
1768
1759
  function readFileVersionOnly() {
@@ -1774,10 +1765,22 @@ function readInstanceVersion(instance) {
1774
1765
  const fn = instance && instance.exports && instance.exports.plugkit_version;
1775
1766
  if (typeof fn !== 'function') return null;
1776
1767
  const result = fn();
1777
- const ptr = Number(result & 0xffffffffn);
1778
- const len = Number(result >> 32n);
1779
- const bytes = new Uint8Array(instance.exports.memory.buffer, ptr, len);
1780
- return new TextDecoder().decode(bytes).trim();
1768
+ let ptr, len;
1769
+ if (typeof result === 'bigint') {
1770
+ ptr = Number(result & 0xffffffffn);
1771
+ len = Number(result >> 32n);
1772
+ } else {
1773
+ ptr = Number(result) & 0xffffffff;
1774
+ len = 0;
1775
+ }
1776
+ const buf = new Uint8Array(instance.exports.memory.buffer, ptr, 64);
1777
+ if (len === 0) {
1778
+ let end = 0;
1779
+ while (end < buf.length && buf[end] !== 0) end++;
1780
+ len = end;
1781
+ }
1782
+ if (len === 0) return null;
1783
+ return new TextDecoder().decode(buf.subarray(0, len)).trim() || null;
1781
1784
  } catch (_) { return null; }
1782
1785
  }
1783
1786
 
@@ -2577,8 +2580,26 @@ async function runSpoolWatcher(instance, spoolDir) {
2577
2580
  }
2578
2581
  }, 5000);
2579
2582
 
2583
+ let _sweepErrLogged = false;
2580
2584
  setInterval(() => {
2581
2585
  try {
2586
+ if (!fs.existsSync(outDir)) {
2587
+ try {
2588
+ fs.mkdirSync(outDir, { recursive: true });
2589
+ fs.mkdirSync(inDir, { recursive: true });
2590
+ console.log(`[retention] recreated missing spool dirs: ${outDir}, ${inDir}`);
2591
+ logEvent('plugkit', 'spool.dirs-recreated', { outDir, inDir, reason: 'sweep-found-missing' });
2592
+ _sweepErrLogged = false;
2593
+ return;
2594
+ } catch (mke) {
2595
+ if (!_sweepErrLogged) {
2596
+ console.error(`[retention] cannot recreate ${outDir}: ${mke.message}`);
2597
+ logEvent('plugkit', 'spool.dirs-recreate-failed', { outDir, error: mke.message });
2598
+ _sweepErrLogged = true;
2599
+ }
2600
+ return;
2601
+ }
2602
+ }
2582
2603
  const cutoff = Date.now() - 3600_000;
2583
2604
  let swept = 0;
2584
2605
  for (const entry of fs.readdirSync(outDir)) {
@@ -2592,9 +2613,13 @@ async function runSpoolWatcher(instance, spoolDir) {
2592
2613
  console.log(`[retention] swept ${swept} out/ files older than 1h`);
2593
2614
  logEvent('plugkit', 'sweep.retention', { swept });
2594
2615
  }
2616
+ _sweepErrLogged = false;
2595
2617
  } catch (e) {
2596
- console.error(`[retention] sweep error: ${e.message}`);
2597
- logEvent('plugkit', 'sweep.retention.error', { error: String(e.message || e) });
2618
+ if (!_sweepErrLogged) {
2619
+ console.error(`[retention] sweep error: ${e.message}`);
2620
+ logEvent('plugkit', 'sweep.retention.error', { error: String(e.message || e) });
2621
+ _sweepErrLogged = true;
2622
+ }
2598
2623
  }
2599
2624
  }, 60_000);
2600
2625
 
package/gm.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gm",
3
- "version": "2.0.1333",
3
+ "version": "2.0.1335",
4
4
  "description": "Spool-dispatch orchestration engine with unified state machine, skills, and automated git enforcement",
5
5
  "author": "AnEntrypoint",
6
6
  "license": "MIT",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gm-skill",
3
- "version": "2.0.1333",
3
+ "version": "2.0.1335",
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",
@@ -38,6 +38,8 @@ bun x gm-plugkit@latest spool > /dev/null 2>&1 &
38
38
 
39
39
  Never poll the spool dir with `sleep && ls` or `Start-Sleep && Test-Path` — plugkit is synchronous from your view; if the response is not there, the watcher is dead (re-check `.status.json` mtime) or the verb is slow (check `.gm/exec-spool/.watcher.log`), not "still processing."
40
40
 
41
+ When writing the spool input from PowerShell, pass `-Encoding utf8` (or use `[System.IO.File]::WriteAllText($path, $body)` which defaults to UTF-8 no-BOM). PowerShell 5.1's default `Out-File` / `Set-Content` write UTF-16 LE with BOM, which the watcher detects and re-decodes (`spool.body-encoding-recoded` event in gmsniff), but the deviation is a fingerprint of an instruction you missed. Use `bash -c "echo -n '...' > ..."` or `Write` tool instead when the body is structured JSON.
42
+
41
43
  First turn body must be `{"prompt":"<user request>"}` so orient_nouns and recall_hits derive from the request; subsequent turns in the same conversation may use empty body `{}`.
42
44
 
43
45
  **Batch writes, waits, and reads together.** Each agent turn costs cycles; the dispatch shape `Write request → wait → Read response` is one logical step, not three. Issue all three in a single message — the Write tool call and the Read tool call go in the same `<function_calls>` block. The Read may return "file does not exist" if plugkit is mid-verb; that's fine, retry with one more Read in the next message rather than spreading the cycle across three turns. Fan-out is the same shape — dispatching three independent verbs (`prd-add g1`, `prd-add g2`, `prd-add g3`) means three Write tool calls in one block, then three Read tool calls in one block. Serial dispatch when you could be parallel is wasted cycles. The only sequencing constraint is real data dependency: if verb B needs the response of verb A, those go in separate turns; otherwise batch.