gm-skill 2.0.2087 → 2.0.2089
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 +9 -1
- package/bin/plugkit-slim.wasm.sha256 +1 -1
- package/bin/plugkit.version +1 -1
- package/bin/plugkit.wasm.sha256 +1 -1
- package/gm-plugkit/bootstrap.js +0 -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 +103 -106
package/README.md
CHANGED
|
@@ -87,7 +87,7 @@ Every tool the agent uses is a dispatch verb. No direct shell, no direct file wr
|
|
|
87
87
|
- **`recall`**: vector + KV recall against `rs-learn`, scored by cosine x recency, namespace-aware
|
|
88
88
|
- **`codesearch`**: semantic vector search across the project
|
|
89
89
|
- **`memorize`**: write to the recall index (with the BGE query/passage prefix asymmetry)
|
|
90
|
-
- **`browser`**: headful-by-default Chrome session driven natively by `agentplug` (CDP direct, no JS wrapper) -- a process-wide session registry keeps the launched Chrome child + CDP port alive across dispatches instead of relaunching per-call, profile persisted at `.gm/browser-chrome-profile-<session_id>/`; `session new|list|close|reset <id>` manages sessions explicitly
|
|
90
|
+
- **`browser`**: headful-by-default Chrome session driven natively by `agentplug` (CDP direct, no JS wrapper) -- a process-wide session registry keeps the launched Chrome child + CDP port alive across dispatches instead of relaunching per-call, profile persisted at `.gm/browser-chrome-profile-<session_id>/`; `session new|list|close|reset <id>` manages sessions explicitly; `screenshot[=name]`/`dom=<selector>`/`timeout=<ms>` body prefixes stack with a plain eval body for capture and DOM-scoped queries
|
|
91
91
|
- **`git_status` / `branch_status` / `git_push`**: git verbs that gate on porcelain
|
|
92
92
|
- **`filter`**: in-wasm stdout-compaction (grep/ls/tree/json/diff)
|
|
93
93
|
|
|
@@ -99,6 +99,10 @@ Orchestration state is tracked via `.gm/` marker files, not hook events. The gat
|
|
|
99
99
|
- **turn entry**: the `instruction` verb reminds the agent to dispatch first and attaches the per-prompt auto-recall pack
|
|
100
100
|
- **pre-tool-use**: blocks Write/Edit/git before the gm skill fires for the turn
|
|
101
101
|
- **stop**: blocks session end while `.gm/prd.yml` has open items, mutables are unresolved, residual-scan hasn't fired, or the worktree is dirty or unpushed
|
|
102
|
+
- **VERIFY -> CONSOLIDATE**: `residual-scan-fired`, `prd-all-closed`, `mutables-all-resolved`, `claim-audit-clean` (every AGENTS.md/recall claim naming a commit hash resolves against real git log), `submodules-clean` (every tracked submodule gitlink matches that submodule's own live HEAD)
|
|
103
|
+
- **CONSOLIDATE -> COMPLETE**: `prd-all-closed`, `mutables-all-resolved`, `worktree-clean`, `residual-scan-fired`, `ci-validated-fresh` (`.gm/exec-spool/.ci-validated` matches current HEAD sha), `browser-witness-coverage`, `submodules-clean`
|
|
104
|
+
|
|
105
|
+
The gate graph itself is data, not hardcoded Rust: a project's `.gm/instructions/fsm/graph.json` (written by the `fsm-vendor` verb) can add states, rewire edges, or swap which gates guard which transition, including a `policy` block that externalizes previously-hardcoded behavior (status vocabularies, witness-requirement toggles, CAS retry attempts) as project-overridable JSON.
|
|
102
106
|
|
|
103
107
|
### ground truth
|
|
104
108
|
|
|
@@ -143,3 +147,7 @@ Empty submodule directories after a normal `git clone` are expected, not a bug -
|
|
|
143
147
|
## license
|
|
144
148
|
|
|
145
149
|
MIT
|
|
150
|
+
|
|
151
|
+
## donations
|
|
152
|
+
|
|
153
|
+
BTC: `15FLMay4of9rk4jK2davzzL4HDdGQtscGX`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
679ca6886f25de4843570a38e52d153afae973ce0fa0837cdfdae85b60230fb9 plugkit-slim.wasm
|
package/bin/plugkit.version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.1.
|
|
1
|
+
0.1.962
|
package/bin/plugkit.wasm.sha256
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
12bf61f61d47fddffc6ad0d7d1ced8e6d2616959a2813547da00ee913abc50cd plugkit.wasm
|
package/gm-plugkit/bootstrap.js
CHANGED
|
@@ -659,7 +659,6 @@ function spawnPinnedBoot(extraArgs) {
|
|
|
659
659
|
|
|
660
660
|
function discoverBundledSkillsAndSources() {
|
|
661
661
|
const found = new Map();
|
|
662
|
-
found.set('gm', path.join(__dirname, 'SKILL.md'));
|
|
663
662
|
try {
|
|
664
663
|
for (const f of fs.readdirSync(__dirname)) {
|
|
665
664
|
const m = f.match(/^SKILL-(.+)\.md$/);
|
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.2089",
|
|
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
|
+
679ca6886f25de4843570a38e52d153afae973ce0fa0837cdfdae85b60230fb9 plugkit-slim.wasm
|
|
@@ -1 +1 @@
|
|
|
1
|
-
0.1.
|
|
1
|
+
0.1.962
|
package/gm.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gm",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.2089",
|
|
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.962"
|
|
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.2089",
|
|
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,142 +5,139 @@ 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 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
|
-
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
14
|
+
function validateBundleCompleteness() {
|
|
15
|
+
const missing = [];
|
|
16
|
+
const empty = [];
|
|
17
|
+
for (const key of GATE_AND_RESIDUAL_KEYS) {
|
|
18
|
+
const fp = path.join(bundleDir, `${key}.md`);
|
|
19
|
+
if (!fs.existsSync(fp)) { missing.push(key); continue; }
|
|
20
|
+
if (fs.readFileSync(fp, 'utf8').trim() === '') empty.push(key);
|
|
21
|
+
}
|
|
22
|
+
if (missing.length || empty.length) {
|
|
23
|
+
if (missing.length) console.error(`prose bundle missing entries: ${missing.join(', ')}`);
|
|
24
|
+
if (empty.length) console.error(`prose bundle empty entries: ${empty.join(', ')}`);
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
console.log(`prose bundle complete: ${GATE_AND_RESIDUAL_KEYS.length} keys present and non-empty`);
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function resolveConformancePaths() {
|
|
32
|
+
const proseSourceDir = path.join(root, 'rs-plugkit', 'crates', 'plugkit-core', 'src', 'orchestrator', 'instructions', 'prose');
|
|
33
|
+
return {
|
|
34
|
+
proseSourceDir,
|
|
35
|
+
browserMdPath: path.join(proseSourceDir, 'browser.md'),
|
|
36
|
+
executeMdPath: path.join(proseSourceDir, 'execute.md'),
|
|
37
|
+
browserRsPath: path.join(root, 'agentplug', 'crates', 'agentplug-host', 'src', 'browser.rs'),
|
|
38
|
+
cdpEvalJsPath: path.join(root, 'agentplug', 'crates', 'agentplug-host', 'src', 'cdp_eval.js'),
|
|
39
|
+
execJsRsPath: path.join(root, 'agentplug', 'crates', 'agentplug-host', 'src', 'exec_js.rs'),
|
|
40
|
+
};
|
|
20
41
|
}
|
|
21
42
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
bundleFailed = true;
|
|
25
|
-
if (missing.length) console.error(`prose bundle missing entries: ${missing.join(', ')}`);
|
|
26
|
-
if (empty.length) console.error(`prose bundle empty entries: ${empty.join(', ')}`);
|
|
27
|
-
} else {
|
|
28
|
-
console.log(`prose bundle complete: ${KEYS.length} keys present and non-empty`);
|
|
43
|
+
function checkEveryRequiredFileExists(requiredFiles) {
|
|
44
|
+
return requiredFiles.filter((p) => !fs.existsSync(p));
|
|
29
45
|
}
|
|
30
46
|
|
|
31
|
-
|
|
32
|
-
// exec_js `opts.*` field the served prose promises, and check that the
|
|
33
|
-
// implementing native source (agentplug-host, the sole loader per this
|
|
34
|
-
// repo's own architecture) actually references it. Static, not a live
|
|
35
|
-
// dispatch -- this is a "did anyone even write the code" check, not a
|
|
36
|
-
// behavioral one, but that is exactly what catches a "documented, zero
|
|
37
|
-
// implementing code" gap: this check is what found the browser.md
|
|
38
|
-
// screenshot/dom= gap live (agentplug-host/src/browser.rs had zero
|
|
39
|
-
// BrowserMode variant for either, confirmed by grep before this script
|
|
40
|
-
// was written). Runs against the checked-out submodules, so it only fires
|
|
41
|
-
// in CI/local contexts where they're actually populated (a plain `git
|
|
42
|
-
// clone` without --recurse-submodules leaves them empty per README.md's
|
|
43
|
-
// own documented note -- absence there is skipped, not failed, matching
|
|
44
|
-
// this repo's existing plain-clone tolerance).
|
|
45
|
-
const proseSourceDir = path.join(root, 'rs-plugkit', 'crates', 'plugkit-core', 'src', 'orchestrator', 'instructions', 'prose');
|
|
46
|
-
const browserMdPath = path.join(proseSourceDir, 'browser.md');
|
|
47
|
-
const executeMdPath = path.join(proseSourceDir, 'execute.md');
|
|
48
|
-
const browserRsPath = path.join(root, 'agentplug', 'crates', 'agentplug-host', 'src', 'browser.rs');
|
|
49
|
-
const cdpEvalJsPath = path.join(root, 'agentplug', 'crates', 'agentplug-host', 'src', 'cdp_eval.js');
|
|
50
|
-
const execJsRsPath = path.join(root, 'agentplug', 'crates', 'agentplug-host', 'src', 'exec_js.rs');
|
|
51
|
-
|
|
52
|
-
// Every INDIVIDUAL file this check reads, not just the containing
|
|
53
|
-
// directories -- a submodule can be present but shallow/partial (a
|
|
54
|
-
// degenerate state distinct from "not cloned at all"), and the directory-
|
|
55
|
-
// only check previously crashed with an unhandled ENOENT the moment any one
|
|
56
|
-
// file was individually missing (live-reproduced this session: temporarily
|
|
57
|
-
// removing browser.md alone, with every directory still present, crashed
|
|
58
|
-
// the script instead of skipping gracefully).
|
|
59
|
-
const requiredFiles = [browserMdPath, executeMdPath, browserRsPath, cdpEvalJsPath, execJsRsPath];
|
|
60
|
-
const missingFiles = requiredFiles.filter((p) => !fs.existsSync(p));
|
|
61
|
-
const submodulesPresent = missingFiles.length === 0;
|
|
62
|
-
|
|
63
|
-
let conformanceFailed = false;
|
|
64
|
-
if (!submodulesPresent) {
|
|
65
|
-
console.log(`prose-conformance: skipping -- missing file(s) (submodules not populated, or a partial/shallow checkout): ${missingFiles.map((p) => path.relative(root, p)).join(', ')}`);
|
|
66
|
-
} else {
|
|
67
|
-
const browserMd = fs.readFileSync(path.join(proseSourceDir, 'browser.md'), 'utf8');
|
|
68
|
-
const browserRs = fs.readFileSync(browserRsPath, 'utf8');
|
|
69
|
-
const cdpEvalJs = fs.readFileSync(cdpEvalJsPath, 'utf8');
|
|
70
|
-
const executeMd = fs.readFileSync(path.join(proseSourceDir, 'execute.md'), 'utf8');
|
|
71
|
-
const execJsRs = fs.readFileSync(execJsRsPath, 'utf8');
|
|
72
|
-
|
|
73
|
-
// Extract every backtick-quoted `<word>\n<expression>` / `<word>=` mode
|
|
74
|
-
// prefix from browser.md's "Body shapes" code block -- the exact syntax
|
|
75
|
-
// the served prose promises as a real body-shape prefix.
|
|
47
|
+
function extractBrowserModePrefixesFromProse(browserMd) {
|
|
76
48
|
const bodyShapesMatch = browserMd.match(/## Body shapes[\s\S]*?```\r?\n([\s\S]*?)```/);
|
|
77
49
|
const promisedPrefixes = [];
|
|
78
|
-
if (bodyShapesMatch)
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}
|
|
50
|
+
if (!bodyShapesMatch) return promisedPrefixes;
|
|
51
|
+
|
|
52
|
+
for (const line of bodyShapesMatch[1].split(/\r?\n/)) {
|
|
53
|
+
const t = line.trim();
|
|
54
|
+
if (!t) continue;
|
|
55
|
+
|
|
56
|
+
const sessionMatch = t.match(/^session (\w+)/);
|
|
57
|
+
if (sessionMatch) { promisedPrefixes.push({ kind: 'session', name: sessionMatch[1] }); continue; }
|
|
58
|
+
|
|
59
|
+
const modeMatch = t.match(/^(\w+)(?:\s+\w+=<[^>]+>)*\\n/);
|
|
60
|
+
if (modeMatch && !['url', 'timeout', 'dom'].includes(modeMatch[1])) { promisedPrefixes.push({ kind: 'mode', name: modeMatch[1] }); continue; }
|
|
61
|
+
|
|
62
|
+
const kvMatch = t.match(/^(\w+)=</);
|
|
63
|
+
if (kvMatch) { promisedPrefixes.push({ kind: 'kv', name: kvMatch[1] }); continue; }
|
|
92
64
|
}
|
|
65
|
+
return promisedPrefixes;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function checkPrefixInImplementingCode(kind, name, browserRs, cdpEvalJs) {
|
|
69
|
+
if (kind === 'session') return browserRs.includes(`"session ${name}`);
|
|
70
|
+
if (kind === 'kv') return browserRs.includes(`"${name}="`) || cdpEvalJs.includes(`${name}=`);
|
|
71
|
+
return browserRs.includes(`"${name}\\n"`) || browserRs.includes(`"${name}"`) || cdpEvalJs.includes(`'${name}'`) || cdpEvalJs.includes(`"${name}"`);
|
|
72
|
+
}
|
|
93
73
|
|
|
74
|
+
function crossReferenceBrowserPrefixes(browserMd, browserRs, cdpEvalJs) {
|
|
75
|
+
const promisedPrefixes = extractBrowserModePrefixesFromProse(browserMd);
|
|
94
76
|
const conformanceFindings = [];
|
|
77
|
+
|
|
95
78
|
for (const { kind, name } of promisedPrefixes) {
|
|
96
|
-
|
|
97
|
-
// the Rust prefix-stripping logic or the JS mode-dispatch logic -- one
|
|
98
|
-
// hit in either is sufficient (some prefixes are parsed Rust-side,
|
|
99
|
-
// others are only checked JS-side against the `mode` string agentplug
|
|
100
|
-
// passes through). `session <word>` prefixes are matched as the real
|
|
101
|
-
// "session <word>" literal parse_session_command uses, not the bare
|
|
102
|
-
// word alone (which would false-positive-pass on any incidental
|
|
103
|
-
// substring match).
|
|
104
|
-
let inRust, inJs;
|
|
105
|
-
if (kind === 'session') {
|
|
106
|
-
inRust = browserRs.includes(`"session ${name}`);
|
|
107
|
-
inJs = false;
|
|
108
|
-
} else if (kind === 'kv') {
|
|
109
|
-
inRust = browserRs.includes(`"${name}="`);
|
|
110
|
-
inJs = cdpEvalJs.includes(`${name}=`);
|
|
111
|
-
} else {
|
|
112
|
-
inRust = browserRs.includes(`"${name}\\n"`) || browserRs.includes(`"${name}"`);
|
|
113
|
-
inJs = cdpEvalJs.includes(`'${name}'`) || cdpEvalJs.includes(`"${name}"`);
|
|
114
|
-
}
|
|
115
|
-
if (!inRust && !inJs) {
|
|
79
|
+
if (!checkPrefixInImplementingCode(kind, name, browserRs, cdpEvalJs)) {
|
|
116
80
|
conformanceFindings.push(`browser.md promises ${kind} prefix "${name}" with zero implementing-code reference in browser.rs or cdp_eval.js`);
|
|
117
81
|
}
|
|
118
82
|
}
|
|
83
|
+
return { conformanceFindings, promisedPrefixCount: promisedPrefixes.length };
|
|
84
|
+
}
|
|
119
85
|
|
|
120
|
-
|
|
121
|
-
// in execute.md's prose and check exec_js.rs actually reads it via
|
|
122
|
-
// opts.get("<fieldName>").
|
|
86
|
+
function extractExecJsOptsFieldsFromProse(executeMd) {
|
|
123
87
|
const optsFieldRe = /opts\.([a-zA-Z][a-zA-Z0-9]*)/g;
|
|
124
88
|
const promisedOptsFields = new Set();
|
|
125
89
|
let m;
|
|
126
|
-
while ((m = optsFieldRe.exec(executeMd)) !== null)
|
|
90
|
+
while ((m = optsFieldRe.exec(executeMd)) !== null) {
|
|
91
|
+
if (m[1] !== 'true' && m[1] !== 'false') promisedOptsFields.add(m[1]);
|
|
92
|
+
}
|
|
93
|
+
return promisedOptsFields;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function crossReferenceExecJsOptsFields(executeMd, execJsRs) {
|
|
97
|
+
const promisedOptsFields = extractExecJsOptsFieldsFromProse(executeMd);
|
|
98
|
+
const conformanceFindings = [];
|
|
99
|
+
|
|
127
100
|
for (const field of promisedOptsFields) {
|
|
128
|
-
if (field
|
|
129
|
-
const needle = `opts.get("${field}")`;
|
|
130
|
-
if (!execJsRs.includes(needle)) {
|
|
101
|
+
if (!execJsRs.includes(`opts.get("${field}")`)) {
|
|
131
102
|
conformanceFindings.push(`execute.md promises exec_js opts.${field} with no matching opts.get("${field}") in exec_js.rs`);
|
|
132
103
|
}
|
|
133
104
|
}
|
|
105
|
+
return { conformanceFindings, promisedOptsFieldCount: promisedOptsFields.size };
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function runConformanceCheck() {
|
|
109
|
+
const paths = resolveConformancePaths();
|
|
110
|
+
const requiredFiles = [paths.browserMdPath, paths.executeMdPath, paths.browserRsPath, paths.cdpEvalJsPath, paths.execJsRsPath];
|
|
111
|
+
const missingFiles = checkEveryRequiredFileExists(requiredFiles);
|
|
112
|
+
|
|
113
|
+
if (missingFiles.length > 0) {
|
|
114
|
+
console.log(`prose-conformance: skipping -- missing file(s) (submodules not populated, or a partial/shallow checkout): ${missingFiles.map((p) => path.relative(root, p)).join(', ')}`);
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const browserMd = fs.readFileSync(paths.browserMdPath, 'utf8');
|
|
119
|
+
const browserRs = fs.readFileSync(paths.browserRsPath, 'utf8');
|
|
120
|
+
const cdpEvalJs = fs.readFileSync(paths.cdpEvalJsPath, 'utf8');
|
|
121
|
+
const executeMd = fs.readFileSync(paths.executeMdPath, 'utf8');
|
|
122
|
+
const execJsRs = fs.readFileSync(paths.execJsRsPath, 'utf8');
|
|
123
|
+
|
|
124
|
+
const browserResult = crossReferenceBrowserPrefixes(browserMd, browserRs, cdpEvalJs);
|
|
125
|
+
const execJsResult = crossReferenceExecJsOptsFields(executeMd, execJsRs);
|
|
126
|
+
const allFindings = [...browserResult.conformanceFindings, ...execJsResult.conformanceFindings];
|
|
134
127
|
|
|
135
|
-
if (
|
|
136
|
-
conformanceFailed = true;
|
|
128
|
+
if (allFindings.length) {
|
|
137
129
|
console.error('prose-conformance FAILED -- prose promises capabilities with no confirmed implementing-code reference:');
|
|
138
|
-
for (const f of
|
|
139
|
-
|
|
140
|
-
console.log(`prose-conformance: ${promisedPrefixes.length} browser mode-prefixes + ${promisedOptsFields.size} exec_js opts fields all have a matching implementing-code reference`);
|
|
130
|
+
for (const f of allFindings) console.error(` - ${f}`);
|
|
131
|
+
return true;
|
|
141
132
|
}
|
|
133
|
+
|
|
134
|
+
console.log(`prose-conformance: ${browserResult.promisedPrefixCount} browser mode-prefixes + ${execJsResult.promisedOptsFieldCount} exec_js opts fields all have a matching implementing-code reference`);
|
|
135
|
+
return false;
|
|
142
136
|
}
|
|
143
137
|
|
|
138
|
+
const bundleFailed = !validateBundleCompleteness();
|
|
139
|
+
const conformanceFailed = runConformanceCheck();
|
|
140
|
+
|
|
144
141
|
if (bundleFailed || conformanceFailed) {
|
|
145
142
|
process.exit(1);
|
|
146
|
-
}
|
|
143
|
+
}
|