gm-skill 2.0.1292 → 2.0.1294

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.1292` — auto-bumped from the canonical `gm` repo. Every push to `AnEntrypoint/gm` (or any cascading sibling crate) republishes this package.
38
+ `2.0.1294` — 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
 
@@ -709,7 +709,9 @@ function findInstalledChromiumBinary() {
709
709
  }
710
710
 
711
711
  function startManagedBrowser(pw, profileDir) {
712
- const args = [...pw.baseArgs, 'browser', 'start', '--user-data-dir', profileDir, '--headless'];
712
+ const headless = process.env.GM_BROWSER_HEADLESS === '1';
713
+ const args = [...pw.baseArgs, 'browser', 'start', '--user-data-dir', profileDir];
714
+ if (headless) args.push('--headless');
713
715
  const env = { ...process.env };
714
716
  if (!env.GM_BROWSER_RUNNER_PATH && !env.PLAYWRITER_BROWSER_PATH) {
715
717
  const browserBin = findInstalledChromiumBinary();
@@ -875,10 +877,25 @@ function cosineSim(a, b) {
875
877
  return dot / (Math.sqrt(na) * Math.sqrt(nb));
876
878
  }
877
879
 
880
+ let __wasmAbortFlag = { aborted: false, code: 0 };
878
881
  function createWasiShim(instanceRef) {
879
882
  const getMemory = () => instanceRef.value.exports.memory.buffer;
880
883
  const shim = {
881
- proc_exit: (code) => process.exit(code),
884
+ proc_exit: (code) => {
885
+ __wasmAbortFlag.aborted = true;
886
+ __wasmAbortFlag.code = code;
887
+ try {
888
+ const spoolDir = spoolDirForSentinel();
889
+ fs.mkdirSync(spoolDir, { recursive: true });
890
+ fs.writeFileSync(path.join(spoolDir, '.wasm-abort.json'), JSON.stringify({
891
+ ts: Date.now(),
892
+ exit_code: code,
893
+ verb_in_flight: __currentVerbContext,
894
+ }));
895
+ } catch (_) {}
896
+ try { console.error(`[plugkit-wasm] wasm proc_exit(${code}) intercepted; throwing to abort current verb without killing watcher`); } catch (_) {}
897
+ throw new Error(`wasm proc_exit(${code}) during verb ${__currentVerbContext && __currentVerbContext.verb}`);
898
+ },
882
899
  fd_write: (fd, iovs_ptr, iovs_len, nwritten_ptr) => {
883
900
  try {
884
901
  const buf = getMemory();
@@ -2022,6 +2039,27 @@ async function runSpoolWatcher(instance, spoolDir) {
2022
2039
  if (isProcessed(key)) return;
2023
2040
  markProcessed(key);
2024
2041
 
2042
+ if (__wasmAbortFlag.aborted) {
2043
+ try {
2044
+ const taskBase = path.basename(filePath, path.extname(filePath));
2045
+ const relPath = path.relative(inDir, filePath);
2046
+ const dir = path.dirname(relPath);
2047
+ const verb = dir === '.' ? taskBase : dir;
2048
+ const outName = dir === '.' ? `${taskBase}.json` : `${verb}-${taskBase}.json`;
2049
+ fs.writeFileSync(path.join(outDir, outName), JSON.stringify({
2050
+ ok: false,
2051
+ error: `wasm aborted earlier (exit_code=${__wasmAbortFlag.code}); watcher will respawn`,
2052
+ wasm_aborted: true,
2053
+ }));
2054
+ try { fs.unlinkSync(filePath); } catch (_) {}
2055
+ } catch (_) {}
2056
+ unmarkProcessed(key);
2057
+ emitShutdownReason('wasm-abort-graceful', new Error(`wasm proc_exit(${__wasmAbortFlag.code}) earlier; clean watcher restart`));
2058
+ try { console.error('[plugkit-wasm] exiting after wasm abort to allow supervisor respawn'); } catch (_) {}
2059
+ setTimeout(() => process.exit(2), 100).unref();
2060
+ return;
2061
+ }
2062
+
2025
2063
  try {
2026
2064
  const content = fs.readFileSync(filePath, 'utf8');
2027
2065
  const relPath = path.relative(inDir, filePath);
package/gm.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gm",
3
- "version": "2.0.1292",
3
+ "version": "2.0.1294",
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/lang/browser.js CHANGED
@@ -9,12 +9,9 @@ function findPlugkit() {
9
9
  const home = os.homedir();
10
10
  const candidates = [
11
11
  path.join(__dirname, '..', 'bin', 'plugkit.js'),
12
+ path.join(home, '.gm-tools', 'plugkit.js'),
12
13
  path.join(home, '.claude', 'gm-tools', 'plugkit.js'),
13
- path.join(home, '.claude', 'plugins', 'marketplaces', 'gm-cc', 'bin', 'plugkit.js'),
14
14
  ];
15
- if (process.env.CLAUDE_PLUGIN_ROOT) {
16
- candidates.push(path.join(process.env.CLAUDE_PLUGIN_ROOT, 'bin', 'plugkit.js'));
17
- }
18
15
  for (const p of candidates) {
19
16
  if (fsSync.existsSync(p)) return p;
20
17
  }
package/lang/ssh.js CHANGED
@@ -5,8 +5,12 @@ const fsSync = require('fs');
5
5
  const http = require('http');
6
6
 
7
7
  function loadTarget(targetName) {
8
- const cfgPath = path.join(os.homedir(), '.claude', 'ssh-targets.json');
9
- if (!fsSync.existsSync(cfgPath)) throw new Error('No ssh-targets.json found at ' + cfgPath);
8
+ const candidatesCfg = [
9
+ path.join(os.homedir(), '.gm-tools', 'ssh-targets.json'),
10
+ path.join(os.homedir(), '.claude', 'ssh-targets.json'),
11
+ ];
12
+ const cfgPath = candidatesCfg.find(p => fsSync.existsSync(p));
13
+ if (!cfgPath) throw new Error('No ssh-targets.json found at ' + candidatesCfg.join(' or '));
10
14
  const cfg = JSON.parse(fsSync.readFileSync(cfgPath, 'utf8'));
11
15
  const name = targetName || 'default';
12
16
  if (!cfg[name]) throw new Error('No target \'' + name + '\' in ssh-targets.json. Available: ' + Object.keys(cfg).join(', '));
@@ -26,6 +30,7 @@ function parseCommand(code) {
26
30
 
27
31
  function resolveSsh2() {
28
32
  const candidates = [
33
+ path.join(os.homedir(), '.gm-tools', 'node_modules', 'ssh2'),
29
34
  path.join(os.homedir(), '.claude', 'gm-tools', 'node_modules', 'ssh2'),
30
35
  path.join(os.homedir(), '.claude', 'plugins', 'node_modules', 'ssh2'),
31
36
  'ssh2',
@@ -33,7 +38,7 @@ function resolveSsh2() {
33
38
  for (const p of candidates) {
34
39
  try { return require(p); } catch (_) {}
35
40
  }
36
- throw new Error('ssh2 not found. Run: cd ~/.claude/gm-tools && npm install ssh2');
41
+ throw new Error('ssh2 not found. Install into ~/.gm-tools/ with: mkdir -p ~/.gm-tools && cd ~/.gm-tools && npm install ssh2');
37
42
  }
38
43
 
39
44
  function getRunnerPort() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gm-skill",
3
- "version": "2.0.1292",
3
+ "version": "2.0.1294",
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",
@@ -41,7 +41,7 @@
41
41
  "gm.json"
42
42
  ],
43
43
  "dependencies": {
44
- "gm-plugkit": "^2.0.1292"
44
+ "gm-plugkit": "^2.0.1294"
45
45
  },
46
46
  "engines": {
47
47
  "node": ">=16.0.0"
@@ -1,166 +0,0 @@
1
- #!/usr/bin/env node
2
- 'use strict';
3
-
4
- const { execSync, spawnSync } = require('child_process');
5
-
6
- const REPOS = {
7
- 'rs-exec': 'AnEntrypoint/rs-exec',
8
- 'rs-codeinsight':'AnEntrypoint/rs-codeinsight',
9
- 'rs-search': 'AnEntrypoint/rs-search',
10
- 'rs-plugkit': 'AnEntrypoint/rs-plugkit',
11
- 'gm': 'AnEntrypoint/gm',
12
- 'gm-cc': 'AnEntrypoint/gm-cc',
13
- };
14
-
15
- const POLL_MS = 20000;
16
- const TIMEOUT_MS = 30 * 60 * 1000;
17
-
18
- function gh(args) {
19
- const r = spawnSync('gh', args, { encoding: 'utf8' });
20
- if (r.status !== 0) throw new Error(r.stderr.trim() || `gh ${args.join(' ')} failed`);
21
- return r.stdout.trim();
22
- }
23
-
24
- function latestRun(repo) {
25
- const out = gh(['run', 'list', '--repo', repo, '--limit', '1', '--json', 'databaseId,status,conclusion,name,headBranch,createdAt']);
26
- const rows = JSON.parse(out);
27
- return rows[0] || null;
28
- }
29
-
30
- function getGmCcSha() {
31
- return gh(['api', 'repos/AnEntrypoint/gm-cc/git/refs/heads/main', '--jq', '.object.sha']);
32
- }
33
-
34
- function getInstalledSha() {
35
- const os = require('os');
36
- const path = require('path');
37
- const fs = require('fs');
38
- const base = path.join(os.homedir(), '.claude/plugins/cache/gm-cc/gm');
39
- if (!fs.existsSync(base)) return null;
40
- const dirs = fs.readdirSync(base).filter(d => /^[0-9a-f]{12,}$/.test(d));
41
- dirs.sort((a, b) => {
42
- try {
43
- const av = JSON.parse(fs.readFileSync(path.join(base, a, 'gm.json'), 'utf8')).version || '0';
44
- const bv = JSON.parse(fs.readFileSync(path.join(base, b, 'gm.json'), 'utf8')).version || '0';
45
- return bv.localeCompare(av, undefined, { numeric: true });
46
- } catch { return 0; }
47
- });
48
- if (!dirs[0]) return null;
49
- const gm = JSON.parse(fs.readFileSync(path.join(base, dirs[0], 'gm.json'), 'utf8'));
50
- return { hash: dirs[0], version: gm.version, plugkitVersion: gm.plugkitVersion };
51
- }
52
-
53
- function getPlugkitVersion() {
54
- const fs = require('fs');
55
- const cargo = 'C:/dev/rs-plugkit/Cargo.toml';
56
- if (!fs.existsSync(cargo)) return null;
57
- const m = fs.readFileSync(cargo, 'utf8').match(/^version\s*=\s*"([^"]+)"/m);
58
- return m ? m[1] : null;
59
- }
60
-
61
- function validate(label, fn) {
62
- try {
63
- const result = fn();
64
- console.log(` ✓ ${label}: ${result}`);
65
- return true;
66
- } catch (e) {
67
- console.log(` ✗ ${label}: ${e.message}`);
68
- return false;
69
- }
70
- }
71
-
72
- async function watchRun(repo, runId, label) {
73
- const start = Date.now();
74
- while (Date.now() - start < TIMEOUT_MS) {
75
- const out = gh(['run', 'view', String(runId), '--repo', repo, '--json', 'status,conclusion']);
76
- const { status, conclusion } = JSON.parse(out);
77
- process.stdout.write(`\r ${label}: ${status} ${conclusion || ''} `);
78
- if (status === 'completed') {
79
- process.stdout.write('\n');
80
- if (conclusion !== 'success') throw new Error(`${label} concluded: ${conclusion}`);
81
- return;
82
- }
83
- await sleep(POLL_MS);
84
- }
85
- throw new Error(`${label} timed out after ${TIMEOUT_MS / 60000}min`);
86
- }
87
-
88
- function sleep(ms) { return new Promise(r => setTimeout(r, ms)); }
89
-
90
- async function waitForNewRun(repo, label, afterTime, maxWaitMs = 5 * 60 * 1000) {
91
- const start = Date.now();
92
- while (Date.now() - start < maxWaitMs) {
93
- const run = latestRun(repo);
94
- if (run && new Date(run.createdAt).getTime() > afterTime) return run;
95
- process.stdout.write(`\r Waiting for ${label} run to appear... `);
96
- await sleep(POLL_MS);
97
- }
98
- process.stdout.write('\n');
99
- throw new Error(`No new run appeared in ${repo} within ${maxWaitMs / 60000}min`);
100
- }
101
-
102
- async function main() {
103
- const triggerTime = Date.now();
104
-
105
- console.log('\n=== Cascade Watcher ===');
106
- console.log('Monitoring full pipeline: rs-{exec,codeinsight,search} → rs-plugkit → gm → gm-cc\n');
107
-
108
- console.log('[1] Baseline');
109
- const baseGmCcSha = getGmCcSha();
110
- const baseInstalled = getInstalledSha();
111
- const basePlugkitVersion = getPlugkitVersion();
112
- console.log(` gm-cc HEAD: ${baseGmCcSha}`);
113
- console.log(` installed hash: ${baseInstalled ? baseInstalled.hash : 'unknown'} (gm v${baseInstalled?.version}, plugkit v${baseInstalled?.plugkitVersion})`);
114
- console.log(` local plugkit: v${basePlugkitVersion}`);
115
-
116
- console.log('\n[2] rs-plugkit Release run');
117
- const plugkitRun = await waitForNewRun('AnEntrypoint/rs-plugkit', 'rs-plugkit Release', triggerTime - 10 * 60 * 1000);
118
- console.log(` Run #${plugkitRun.databaseId} "${plugkitRun.name}" on ${plugkitRun.headBranch}`);
119
- await watchRun('AnEntrypoint/rs-plugkit', plugkitRun.databaseId, 'rs-plugkit Release');
120
-
121
- console.log('\n[3] Validate rs-plugkit version bumped');
122
- validate('rs-plugkit Cargo.toml version', () => {
123
- const v = getPlugkitVersion();
124
- if (!v) throw new Error('Could not read');
125
- return `v${v}`;
126
- });
127
-
128
- validate('gm-starter/gm.json plugkitVersion', () => {
129
- const fs = require('fs');
130
- const p = 'C:/dev/plugforge/gm-starter/gm.json';
131
- if (!fs.existsSync(p)) throw new Error('file not found');
132
- const j = JSON.parse(fs.readFileSync(p, 'utf8'));
133
- return `v${j.plugkitVersion}`;
134
- });
135
-
136
- console.log('\n[4] gm Build & Publish run');
137
- const afterPlugkit = Date.now();
138
- const pfRun = await waitForNewRun('AnEntrypoint/gm', 'Build & Publish Plugins', afterPlugkit - 3 * 60 * 1000);
139
- console.log(` Run #${pfRun.databaseId} "${pfRun.name}" on ${pfRun.headBranch}`);
140
- await watchRun('AnEntrypoint/gm', pfRun.databaseId, 'Build & Publish Plugins');
141
-
142
- console.log('\n[5] Validate gm-cc updated');
143
- const newGmCcSha = getGmCcSha();
144
- validate('gm-cc HEAD changed', () => {
145
- if (newGmCcSha === baseGmCcSha) throw new Error(`still ${baseGmCcSha}`);
146
- return newGmCcSha;
147
- });
148
-
149
- console.log('\n[6] Validate local installed plugin (requires /plugin + /reload-plugins)');
150
- const installed = getInstalledSha();
151
- validate('installed hash matches gm-cc HEAD prefix', () => {
152
- if (!installed) throw new Error('no installed plugin found');
153
- if (!newGmCcSha.startsWith(installed.hash)) throw new Error(`installed ${installed.hash} != gm-cc ${newGmCcSha.slice(0, 12)}`);
154
- return `${installed.hash} (gm v${installed.version}, plugkit v${installed.plugkitVersion})`;
155
- });
156
-
157
- console.log('\n=== Cascade complete ===');
158
- console.log(` gm-cc: ${baseGmCcSha.slice(0, 12)} → ${newGmCcSha.slice(0, 12)}`);
159
- if (installed && newGmCcSha.startsWith(installed.hash)) {
160
- console.log(' Local plugin is up to date.');
161
- } else {
162
- console.log(' ⚠ Run /plugin then /reload-plugins to update local cache.');
163
- }
164
- }
165
-
166
- main().catch(e => { console.error('\nFATAL:', e.message); process.exit(1); });