gm-skill 2.0.1624 → 2.0.1626

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/bin/install.js CHANGED
@@ -7,7 +7,6 @@ const os = require('os');
7
7
  const readline = require('readline');
8
8
 
9
9
  const SKILL_NAME = 'gm';
10
- const AUTOCOMPACT_WINDOW = 380000;
11
10
 
12
11
  function out(msg) { process.stdout.write(msg + '\n'); }
13
12
  function err(msg) { process.stderr.write(msg + '\n'); }
@@ -102,8 +101,6 @@ function applyClaudeSettings(home) {
102
101
  const backup = settingsPath + '.bak';
103
102
  try { fs.copyFileSync(settingsPath, backup); err(`existing settings.json was malformed; backed up to ${backup}`); } catch (_) {}
104
103
  }
105
- obj.autoCompactEnabled = true;
106
- obj.autoCompactWindow = AUTOCOMPACT_WINDOW;
107
104
  obj.effortLevel = 'low';
108
105
  obj.alwaysThinkingEnabled = false;
109
106
  fs.mkdirSync(path.dirname(settingsPath), { recursive: true });
@@ -116,8 +113,6 @@ function applyClaudeSettings(home) {
116
113
 
117
114
  const SETTINGS_EXPLAINER = [
118
115
  'Claude Code settings applied:',
119
- ' autoCompactEnabled = true keep long sessions coherent by auto-compacting context',
120
- ` autoCompactWindow = ${AUTOCOMPACT_WINDOW} absolute token count (38% of a 1M window), not a percentage`,
121
116
  " effortLevel = low thinking effort lowered",
122
117
  ' alwaysThinkingEnabled = false explicit thinking turned off',
123
118
  '',
@@ -136,7 +131,7 @@ async function offerClaudeSettings(home) {
136
131
  try {
137
132
  out('');
138
133
  out('Claude Code detected. gm works best with reasoning-in-code rather than hidden thinking tokens.');
139
- out('Offer to set: autoCompactEnabled=true, autoCompactWindow=' + AUTOCOMPACT_WINDOW + ', effortLevel=low, alwaysThinkingEnabled=false.');
134
+ out('Offer to set: effortLevel=low, alwaysThinkingEnabled=false.');
140
135
  const ans = (await ask(rl, 'Apply these Claude Code settings now? [y/N] ')).trim().toLowerCase();
141
136
  if (ans === 'y' || ans === 'yes') {
142
137
  const r = applyClaudeSettings(home);
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gm-plugkit",
3
- "version": "2.0.1624",
3
+ "version": "2.0.1626",
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": {
@@ -163,7 +163,6 @@ function dispatchVerbToWasmInternal(instance, verb, body) {
163
163
  if (!dispatch) return null;
164
164
  const verbBytes = new TextEncoder().encode(verb);
165
165
  const bodyBytes = new TextEncoder().encode(body || '');
166
- // writeWasmInput re-reads memory.buffer fresh after each alloc (avoids the detached-buffer write bug).
167
166
  let verbPtr = 0, bodyPtr = 0;
168
167
  try { verbPtr = writeWasmInput(instance, verbBytes, `dispatch_verb(${verb}).verb`); }
169
168
  catch (e) { throw new Error(`wasm-alloc-failed for dispatch_verb(${verb}): ${e.message}`); }
@@ -1054,10 +1053,6 @@ function startManagedBrowser(pw, profileDir) {
1054
1053
  '--disable-default-apps',
1055
1054
  '--disable-gpu-process-crash-limit',
1056
1055
  ];
1057
- // In containers where unprivileged user namespaces are disabled, Chromium's
1058
- // sandbox cannot initialize and the remote-debugging port never binds (the CDP
1059
- // "did not become ready" failure). Opt in to running without the sandbox (plus
1060
- // the small-/dev/shm workaround common in containers) via GM_BROWSER_NO_SANDBOX=1.
1061
1056
  if (process.env.GM_BROWSER_NO_SANDBOX === '1') {
1062
1057
  args.push('--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage');
1063
1058
  }
@@ -1375,33 +1370,18 @@ function guardWasmRange(buffer, ptr, len, where) {
1375
1370
  }
1376
1371
  }
1377
1372
 
1378
- // Decode a packed (ptr,len) i64 dispatch result into a JS string, the ONE correct way.
1379
- // Two bugs this consolidates (they only surface once the wasm memory grows past a threshold --
1380
- // e.g. a large .gm state file -> a big plugkit_alloc -> the memory grows past ~2GB / the linear
1381
- // memory is re-grown mid-dispatch):
1382
- // 1. SIGNED i64 result. dispatch_verb returns an i64; a high bit set (large ptr or a packed
1383
- // len in the top 32 bits) makes `result` a NEGATIVE BigInt. `result >> 32n` on a negative
1384
- // BigInt arithmetic-shifts in sign bits -> a garbage/negative len, and the low-word mask can
1385
- // misread too. Normalize to unsigned 64-bit FIRST: BigInt.asUintN(64, result).
1386
- // 2. DETACHED buffer. `instance.exports.memory.buffer` captured before plugkit_alloc/dispatch is
1387
- // a STALE ArrayBuffer once the wasm linear memory grows (the old buffer detaches). Reading the
1388
- // result against it throws 'Start offset N is outside the bounds of the buffer'. Always re-read
1389
- // instance.exports.memory.buffer FRESH at the moment of the view, never reuse a captured one.
1390
1373
  function decodeWasmResult(instance, result, where) {
1391
- const u = BigInt.asUintN(64, BigInt(result)); // (1) normalize the i64 to unsigned before splitting
1374
+ const u = BigInt.asUintN(64, BigInt(result));
1392
1375
  const ptr = Number(u & 0xffffffffn);
1393
1376
  const len = Number(u >> 32n);
1394
1377
  if (ptr === 0 || len === 0) return '';
1395
- const buffer = instance.exports.memory.buffer; // (2) FRESH buffer (post-grow), never a stale capture
1378
+ const buffer = instance.exports.memory.buffer;
1396
1379
  guardWasmRange(buffer, ptr, len, where);
1397
1380
  const out = new TextDecoder().decode(new Uint8Array(buffer, ptr, len));
1398
1381
  try { instance.exports.plugkit_free(ptr, len); } catch (_) {}
1399
1382
  return out;
1400
1383
  }
1401
1384
 
1402
- // Write input bytes into wasm memory, re-reading memory.buffer FRESH after the alloc so a memory
1403
- // grow during plugkit_alloc never leaves us writing into a detached buffer (the write-side half of
1404
- // the detached-buffer bug). Returns the ptr (caller frees) or throws on alloc failure.
1405
1385
  function writeWasmInput(instance, bytes, where) {
1406
1386
  if (bytes.length === 0) return 0;
1407
1387
  const ptr = instance.exports.plugkit_alloc(bytes.length);
@@ -2151,8 +2131,12 @@ function makeHostFunctions(instanceRef) {
2151
2131
  const modeMatch = evalBody.match(/^(capture|profile)[ \t]*\n([\s\S]*)$/);
2152
2132
  const debugSetup = `const __logs=[],__errs=[],__net=[];\n`
2153
2133
  + `try{page.on('console',m=>{try{__logs.push({type:m.type(),text:m.text()});}catch(_){}});`
2154
- + `page.on('pageerror',e=>{try{__errs.push(String(e&&e.message||e));}catch(_){}});`
2155
- + `page.on('requestfinished',r=>{try{const t=r.timing();__net.push({url:String(r.url()).slice(0,120),dur_ms:Math.round(t.responseEnd),ttfb_ms:Math.round(t.responseStart)});}catch(_){}});}catch(_){}\n`;
2134
+ + `page.on('pageerror',e=>{try{__errs.push({type:'pageerror',msg:String(e&&e.message||e)});}catch(_){}});`
2135
+ + `page.on('error',e=>{try{__errs.push({type:'uncaught',msg:String(e&&e.message||e),stack:String(e&&e.stack||'')});}catch(_){}});`
2136
+ + `page.on('requestfinished',r=>{try{const t=r.timing();__net.push({url:String(r.url()).slice(0,120),dur_ms:Math.round(t.responseEnd),ttfb_ms:Math.round(t.responseStart)});}catch(_){}});`
2137
+ + `page.on('requestfailed',r=>{try{const err=r.failure();__errs.push({type:'fetch',msg:String(err&&err.errorText||'request failed'),url:String(r.url()).slice(0,120)});}catch(_){}});`
2138
+ + `page.evaluateOnNewDocument(()=>{window.__gmErrors=[];window.onerror=(msg,src,line,col,err)=>{try{window.__gmErrors.push({type:'error',msg:String(msg),src:String(src).slice(0,80),line,col,stack:String(err&&err.stack||'')});}catch(_){};return false;};window.onunhandledrejection=(e)=>{try{window.__gmErrors.push({type:'unhandledRejection',msg:String(e.reason&&e.reason.message||e.reason),stack:String(e.reason&&e.reason.stack||'')});}catch(_){}};});`
2139
+ + `}catch(_){}\n`;
2156
2140
  const perfRead = `let __perf=null;try{__perf=await page.evaluate(()=>{const n=performance.getEntriesByType('navigation')[0];return n?{load_ms:Math.round(n.loadEventEnd||0),dcl_ms:Math.round(n.domContentLoadedEventEnd||0),resources:performance.getEntriesByType('resource').length,now:Math.round(performance.now())}:null;});}catch(_){}\n`;
2157
2141
  const blankProbe = startUrl ? '' : `try{const __u=page.url();if(__u==='about:blank'||__u===''){console.error('__GM_BLANK__');}}catch(_){}\n`;
2158
2142
  if (modeMatch && modeMatch[1] === 'profile') {
@@ -2162,18 +2146,22 @@ function makeHostFunctions(instanceRef) {
2162
2146
  + `let __profile=null,__profileError=null;\n`
2163
2147
  + `let __cdp=null;\n`
2164
2148
  + `try{__cdp=await page.context().newCDPSession(page);await __cdp.send('Profiler.enable');await __cdp.send('Profiler.setSamplingInterval',{interval:${intervalUs}});await __cdp.send('Profiler.start');}catch(e){__profileError=String(e&&e.message||e);__cdp=null;}\n`
2165
- + `const __result = await (async () => {\n${blankProbe}${gotoPrefix}${userScript}\n})();\n`
2149
+ + `const __result = await (async () => {\n${blankProbe}${gotoPrefix}try{${userScript}}catch(e){__errs.push({type:'exec',msg:String(e&&e.message||e),stack:String(e&&e.stack||'')});throw e;}\n})();\n`
2166
2150
  + `if(__cdp){try{const __r=await __cdp.send('Profiler.stop');__profile=__r&&__r.profile||null;}catch(e){__profileError=String(e&&e.message||e);}}\n`
2151
+ + `const __wmErrors=await page.evaluate(()=>window.__gmErrors||[]);\n`
2167
2152
  + perfRead
2168
2153
  + AGGREGATE_CPU_PROFILE_SRC + `\n`
2169
2154
  + `const __agg = __profile ? aggregateCpuProfile(__profile) : {timeframe:null,culprits:[]};\n`
2170
- + `return {result:__result,profile:__agg,profile_error:__profileError,debug:{console:__logs,pageErrors:__errs,network:__net.slice(0,30),performance:__perf}};`;
2155
+ + `const __allErrors=[...__errs,...__wmErrors];\n`
2156
+ + `return {result:__result,profile:__agg,profile_error:__profileError,debug:{console:__logs,pageErrors:__allErrors,network:__net.slice(0,30),performance:__perf}};`;
2171
2157
  } else if (modeMatch && modeMatch[1] === 'capture') {
2172
2158
  const userScript = modeMatch[2];
2173
2159
  evalBody = debugSetup
2174
- + `const __result = await (async () => {\n${blankProbe}${gotoPrefix}${userScript}\n})();\n`
2160
+ + `const __result = await (async () => {\n${blankProbe}${gotoPrefix}try{${userScript}}catch(e){__errs.push({type:'exec',msg:String(e&&e.message||e),stack:String(e&&e.stack||'')});throw e;}\n})();\n`
2161
+ + `const __wmErrors=await page.evaluate(()=>window.__gmErrors||[]);\n`
2175
2162
  + perfRead
2176
- + `return {result:__result,debug:{console:__logs,pageErrors:__errs,network:__net.slice(0,30),performance:__perf}};`;
2163
+ + `const __allErrors=[...__errs,...__wmErrors];\n`
2164
+ + `return {result:__result,debug:{console:__logs,pageErrors:__allErrors,network:__net.slice(0,30),performance:__perf}};`;
2177
2165
  } else if (startUrl) {
2178
2166
  evalBody = `${gotoPrefix}${evalBody}`;
2179
2167
  } else if (blankProbe) {
@@ -3275,7 +3263,6 @@ async function runSpoolWatcher(instance, spoolDir) {
3275
3263
  }
3276
3264
  }
3277
3265
 
3278
- // writeWasmInput re-reads memory.buffer fresh after each alloc (detached-buffer write fix).
3279
3266
  const verbPtr = writeWasmInput(instance, verbBytes, `spool-dispatch:${verb}.verb`);
3280
3267
  const bodyPtr = writeWasmInput(instance, bodyBytes, `spool-dispatch:${verb}.body`);
3281
3268
 
@@ -3283,8 +3270,6 @@ async function runSpoolWatcher(instance, spoolDir) {
3283
3270
  const result = dispatch(verbPtr, verbBytes.length, bodyPtr, bodyBytes.length);
3284
3271
  clearVerbActive();
3285
3272
 
3286
- // decodeWasmResult normalizes the i64 (BigInt.asUintN), re-reads the buffer FRESH (post-grow),
3287
- // guards the range, AND frees the result ptr -- so the (ptr,len) free below is dropped.
3288
3273
  let resultStr = decodeWasmResult(instance, result, `spool-dispatch:${verb}`);
3289
3274
 
3290
3275
  if (autoRecallPayload) {
@@ -3338,7 +3323,6 @@ async function runSpoolWatcher(instance, spoolDir) {
3338
3323
 
3339
3324
  try { instance.exports.plugkit_free(verbPtr, verbBytes.length); } catch (_) {}
3340
3325
  try { instance.exports.plugkit_free(bodyPtr, bodyBytes.length); } catch (_) {}
3341
- // (the result ptr is freed inside decodeWasmResult above)
3342
3326
 
3343
3327
  try { if (fs.existsSync(filePath)) fs.unlinkSync(filePath); } catch (_) {}
3344
3328
  unmarkProcessed(key);
package/gm.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gm",
3
- "version": "2.0.1624",
3
+ "version": "2.0.1626",
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.1624",
3
+ "version": "2.0.1626",
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",
@@ -57,7 +57,9 @@
57
57
  "gm.json"
58
58
  ],
59
59
  "dependencies": {
60
- "gm-plugkit": "^2.0.1310"
60
+ "gm-plugkit": "^2.0.1310",
61
+ "gmsniff": "^1.0.0",
62
+ "ccsniff": "^1.1.0"
61
63
  },
62
64
  "engines": {
63
65
  "node": ">=16.0.0"