gm-skill 2.0.2195 → 2.0.2197
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/plugkit-slim.wasm.sha256 +1 -1
- package/bin/plugkit.version +1 -1
- package/bin/plugkit.wasm.sha256 +1 -1
- package/gm-plugkit/package.json +1 -1
- package/gm-plugkit/plugkit-slim.wasm.sha256 +1 -1
- package/gm-plugkit/plugkit.version +1 -1
- package/gm.json +2 -2
- package/package.json +1 -1
- package/scripts/check-prose-bundle.mjs +109 -6
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
8d37533c3fe69ed6627551aeb8fbbbe092c9ffa223abe42c0610d2339aeac4d2 plugkit-slim.wasm
|
package/bin/plugkit.version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.1.
|
|
1
|
+
0.1.1041
|
package/bin/plugkit.wasm.sha256
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
d0186237f4e0d691bd5f983ff729ffd62075c1b1c46c62f8be0b2edb6865784a plugkit.wasm
|
package/gm-plugkit/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gm-plugkit",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.2197",
|
|
4
4
|
"description": "Bootstrap and daemon-spawn tool for gm plugkit binary. Downloads the correct platform wasm, verifies SHA256, and launches agentplug-runner (the native wasm host) as the spool watcher daemon.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
8d37533c3fe69ed6627551aeb8fbbbe092c9ffa223abe42c0610d2339aeac4d2 plugkit-slim.wasm
|
|
@@ -1 +1 @@
|
|
|
1
|
-
0.1.
|
|
1
|
+
0.1.1041
|
package/gm.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gm",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.2197",
|
|
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.1041"
|
|
21
21
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gm-skill",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.2197",
|
|
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",
|
|
@@ -5,16 +5,78 @@ import process from 'node:process';
|
|
|
5
5
|
const root = path.resolve(path.dirname(new URL(import.meta.url).pathname.replace(/^\/([A-Za-z]:)/, '$1')), '..');
|
|
6
6
|
const bundleDir = path.join(root, 'gm-plugkit', 'instructions');
|
|
7
7
|
|
|
8
|
-
const
|
|
8
|
+
const FALLBACK_GATE_AND_RESIDUAL_KEYS = [
|
|
9
9
|
'gates/long-gap-no-instruction',
|
|
10
10
|
'residual/prd-open', 'residual/browser-open', 'residual/tasks-running',
|
|
11
11
|
'residual/dirty-tree', 'residual/imperative',
|
|
12
12
|
];
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
const coreSrcDir = path.join(root, 'rs-plugkit', 'crates', 'plugkit-core', 'src');
|
|
15
|
+
const fsmVendorPath = path.join(coreSrcDir, 'orchestrator', 'fsm_vendor.rs');
|
|
16
|
+
const gatesRsPath = path.join(coreSrcDir, 'gates.rs');
|
|
17
|
+
const residualRsPath = path.join(coreSrcDir, 'orchestrator', 'residual.rs');
|
|
18
|
+
|
|
19
|
+
function readIfPresent(p) {
|
|
20
|
+
return fs.existsSync(p) ? fs.readFileSync(p, 'utf8') : null;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function extractDefaultsTable(fsmVendorRs, tableName) {
|
|
24
|
+
const re = new RegExp(`const ${tableName}:\\s*&\\[\\(&str,\\s*&str\\)\\]\\s*=\\s*&\\[([\\s\\S]*?)\\];`);
|
|
25
|
+
const m = fsmVendorRs.match(re);
|
|
26
|
+
if (!m) return null;
|
|
27
|
+
const entries = [];
|
|
28
|
+
const rowRe = /\(\s*"([^"]+)"\s*,\s*([A-Za-z_][A-Za-z0-9_:]*)\s*\)/g;
|
|
29
|
+
let row;
|
|
30
|
+
while ((row = rowRe.exec(m[1])) !== null) {
|
|
31
|
+
entries.push({ key: row[1], constPath: row[2] });
|
|
32
|
+
}
|
|
33
|
+
return entries;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function extractConstText(sourceText, constName) {
|
|
37
|
+
const re = new RegExp(`const ${constName}:\\s*&str\\s*=\\s*"((?:[^"\\\\]|\\\\.)*)"\\s*;`);
|
|
38
|
+
const m = sourceText.match(re);
|
|
39
|
+
return m ? m[1] : null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function placeholdersIn(text) {
|
|
43
|
+
const found = new Set();
|
|
44
|
+
const re = /\{([a-z_]+)\}/g;
|
|
45
|
+
let m;
|
|
46
|
+
while ((m = re.exec(text)) !== null) found.add(`{${m[1]}}`);
|
|
47
|
+
return found;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function deriveKeySpecs() {
|
|
51
|
+
const fsmVendorRs = readIfPresent(fsmVendorPath);
|
|
52
|
+
const gatesRs = readIfPresent(gatesRsPath);
|
|
53
|
+
const residualRs = readIfPresent(residualRsPath);
|
|
54
|
+
if (!fsmVendorRs || !gatesRs || !residualRs) return null;
|
|
55
|
+
|
|
56
|
+
const gateRows = extractDefaultsTable(fsmVendorRs, 'GATE_DEFAULTS');
|
|
57
|
+
const residualRows = extractDefaultsTable(fsmVendorRs, 'RESIDUAL_DEFAULTS');
|
|
58
|
+
if (!gateRows || !residualRows || gateRows.length === 0 || residualRows.length === 0) return null;
|
|
59
|
+
|
|
60
|
+
const specs = [];
|
|
61
|
+
for (const { key, constPath } of gateRows) {
|
|
62
|
+
const constName = constPath.split('::').pop();
|
|
63
|
+
const text = extractConstText(gatesRs, constName) ?? extractConstText(residualRs, constName);
|
|
64
|
+
if (text === null) return null;
|
|
65
|
+
specs.push({ key: `gates/${key}`, constName, placeholders: placeholdersIn(text) });
|
|
66
|
+
}
|
|
67
|
+
for (const { key, constPath } of residualRows) {
|
|
68
|
+
const constName = constPath.split('::').pop();
|
|
69
|
+
const text = extractConstText(residualRs, constName) ?? extractConstText(gatesRs, constName);
|
|
70
|
+
if (text === null) return null;
|
|
71
|
+
specs.push({ key: `residual/${key}`, constName, placeholders: placeholdersIn(text) });
|
|
72
|
+
}
|
|
73
|
+
return specs;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function validateBundleCompleteness(keys) {
|
|
15
77
|
const missing = [];
|
|
16
78
|
const empty = [];
|
|
17
|
-
for (const key of
|
|
79
|
+
for (const key of keys) {
|
|
18
80
|
const fp = path.join(bundleDir, `${key}.md`);
|
|
19
81
|
if (!fs.existsSync(fp)) { missing.push(key); continue; }
|
|
20
82
|
if (fs.readFileSync(fp, 'utf8').trim() === '') empty.push(key);
|
|
@@ -24,10 +86,37 @@ function validateBundleCompleteness() {
|
|
|
24
86
|
if (empty.length) console.error(`prose bundle empty entries: ${empty.join(', ')}`);
|
|
25
87
|
return false;
|
|
26
88
|
}
|
|
27
|
-
console.log(`prose bundle complete: ${
|
|
89
|
+
console.log(`prose bundle complete: ${keys.length} keys present and non-empty`);
|
|
28
90
|
return true;
|
|
29
91
|
}
|
|
30
92
|
|
|
93
|
+
function validatePlaceholderParity(specs) {
|
|
94
|
+
const findings = [];
|
|
95
|
+
for (const { key, constName, placeholders } of specs) {
|
|
96
|
+
const fp = path.join(bundleDir, `${key}.md`);
|
|
97
|
+
if (!fs.existsSync(fp)) continue;
|
|
98
|
+
const mdPlaceholders = placeholdersIn(fs.readFileSync(fp, 'utf8'));
|
|
99
|
+
for (const tok of placeholders) {
|
|
100
|
+
if (!mdPlaceholders.has(tok)) {
|
|
101
|
+
findings.push(`${key}.md is missing placeholder ${tok} carried by the canonical Rust const ${constName}; the substituted value would be silently dropped at render time`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
for (const tok of mdPlaceholders) {
|
|
105
|
+
if (!placeholders.has(tok)) {
|
|
106
|
+
findings.push(`${key}.md carries placeholder ${tok} that the canonical Rust const ${constName} never substitutes; it would render literally`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
if (findings.length) {
|
|
111
|
+
console.error('prose-placeholder-parity FAILED -- .md overrides drifted from the substituting Rust consts:');
|
|
112
|
+
for (const f of findings) console.error(` - ${f}`);
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
115
|
+
const withTokens = specs.filter((s) => s.placeholders.size > 0).length;
|
|
116
|
+
console.log(`prose-placeholder-parity: ${specs.length} keys checked, ${withTokens} carrying placeholders, all matching their Rust consts`);
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
|
|
31
120
|
function resolveConformancePaths() {
|
|
32
121
|
const proseSourceDir = path.join(root, 'rs-plugkit', 'crates', 'plugkit-core', 'src', 'orchestrator', 'instructions', 'prose');
|
|
33
122
|
return {
|
|
@@ -135,9 +224,23 @@ function runConformanceCheck() {
|
|
|
135
224
|
return false;
|
|
136
225
|
}
|
|
137
226
|
|
|
138
|
-
const
|
|
227
|
+
const derivedSpecs = deriveKeySpecs();
|
|
228
|
+
const keys = derivedSpecs ? derivedSpecs.map((s) => s.key) : FALLBACK_GATE_AND_RESIDUAL_KEYS;
|
|
229
|
+
|
|
230
|
+
if (derivedSpecs) {
|
|
231
|
+
const missingFromDerived = FALLBACK_GATE_AND_RESIDUAL_KEYS.filter((k) => !keys.includes(k));
|
|
232
|
+
console.log(`prose bundle keys derived from fsm_vendor GATE_DEFAULTS + RESIDUAL_DEFAULTS: ${keys.length}`);
|
|
233
|
+
if (missingFromDerived.length) {
|
|
234
|
+
console.log(`note: previously-hardcoded keys no longer in the Rust tables: ${missingFromDerived.join(', ')}`);
|
|
235
|
+
}
|
|
236
|
+
} else {
|
|
237
|
+
console.log('prose bundle keys: falling back to the hardcoded list -- rs-plugkit sources unavailable (submodule not populated, or a partial/shallow checkout)');
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
const bundleFailed = !validateBundleCompleteness(keys);
|
|
241
|
+
const placeholderFailed = derivedSpecs ? validatePlaceholderParity(derivedSpecs) : false;
|
|
139
242
|
const conformanceFailed = runConformanceCheck();
|
|
140
243
|
|
|
141
|
-
if (bundleFailed || conformanceFailed) {
|
|
244
|
+
if (bundleFailed || placeholderFailed || conformanceFailed) {
|
|
142
245
|
process.exit(1);
|
|
143
246
|
}
|