gm-skill 2.0.1293 → 2.0.1295

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.1293` — auto-bumped from the canonical `gm` repo. Every push to `AnEntrypoint/gm` (or any cascading sibling crate) republishes this package.
38
+ `2.0.1295` — 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.479
1
+ 0.1.480
package/bin/plugkit.wasm CHANGED
Binary file
@@ -1 +1 @@
1
- d22156c2ef672875557c91649ddc0dfb86a403b431bbdb2b5048ab8870b95dd5 plugkit.wasm
1
+ 8d3e95567b644e3ad4429bfa1026220eaf3674afa317dc511997ec52fff5c8e8 plugkit.wasm
@@ -877,10 +877,25 @@ function cosineSim(a, b) {
877
877
  return dot / (Math.sqrt(na) * Math.sqrt(nb));
878
878
  }
879
879
 
880
+ let __wasmAbortFlag = { aborted: false, code: 0 };
880
881
  function createWasiShim(instanceRef) {
881
882
  const getMemory = () => instanceRef.value.exports.memory.buffer;
882
883
  const shim = {
883
- 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
+ },
884
899
  fd_write: (fd, iovs_ptr, iovs_len, nwritten_ptr) => {
885
900
  try {
886
901
  const buf = getMemory();
@@ -2024,6 +2039,27 @@ async function runSpoolWatcher(instance, spoolDir) {
2024
2039
  if (isProcessed(key)) return;
2025
2040
  markProcessed(key);
2026
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
+
2027
2063
  try {
2028
2064
  const content = fs.readFileSync(filePath, 'utf8');
2029
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.1293",
3
+ "version": "2.0.1295",
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.479"
20
+ "plugkitVersion": "0.1.480"
21
21
  }
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.1293",
3
+ "version": "2.0.1295",
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.1293"
44
+ "gm-plugkit": "^2.0.1295"
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); });