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 +1 -1
- package/bin/plugkit.version +1 -1
- package/bin/plugkit.wasm +0 -0
- package/bin/plugkit.wasm.sha256 +1 -1
- package/gm-plugkit/plugkit-wasm-wrapper.js +37 -1
- package/gm.json +2 -2
- package/lang/browser.js +1 -4
- package/lang/ssh.js +8 -3
- package/package.json +2 -2
- package/scripts/watch-cascade.js +0 -166
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.
|
|
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
|
|
package/bin/plugkit.version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.1.
|
|
1
|
+
0.1.480
|
package/bin/plugkit.wasm
CHANGED
|
Binary file
|
package/bin/plugkit.wasm.sha256
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
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) =>
|
|
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.
|
|
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.
|
|
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
|
|
9
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
44
|
+
"gm-plugkit": "^2.0.1295"
|
|
45
45
|
},
|
|
46
46
|
"engines": {
|
|
47
47
|
"node": ">=16.0.0"
|
package/scripts/watch-cascade.js
DELETED
|
@@ -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); });
|