@vibe-agent-toolkit/cli 0.1.38 → 0.1.39-rc.10
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 +6 -3
- package/dist/commands/audit/git-url-clone.d.ts +1 -1
- package/dist/commands/audit/git-url-clone.d.ts.map +1 -1
- package/dist/commands/audit/git-url-clone.js +3 -67
- package/dist/commands/audit/git-url-clone.js.map +1 -1
- package/dist/commands/audit/hierarchical-output.d.ts +2 -1
- package/dist/commands/audit/hierarchical-output.d.ts.map +1 -1
- package/dist/commands/audit/hierarchical-output.js.map +1 -1
- package/dist/commands/audit.d.ts.map +1 -1
- package/dist/commands/audit.js +1 -2
- package/dist/commands/audit.js.map +1 -1
- package/dist/commands/claude/marketplace/git-publish.d.ts +5 -12
- package/dist/commands/claude/marketplace/git-publish.d.ts.map +1 -1
- package/dist/commands/claude/marketplace/git-publish.js +7 -80
- package/dist/commands/claude/marketplace/git-publish.js.map +1 -1
- package/dist/commands/claude/marketplace/publish-tree.d.ts +12 -4
- package/dist/commands/claude/marketplace/publish-tree.d.ts.map +1 -1
- package/dist/commands/claude/marketplace/publish-tree.js +54 -24
- package/dist/commands/claude/marketplace/publish-tree.js.map +1 -1
- package/dist/commands/claude/marketplace/publish.d.ts.map +1 -1
- package/dist/commands/claude/marketplace/publish.js +14 -39
- package/dist/commands/claude/marketplace/publish.js.map +1 -1
- package/dist/commands/claude/marketplace/validate.js.map +1 -1
- package/dist/commands/claude/plugin/build.d.ts.map +1 -1
- package/dist/commands/claude/plugin/build.js +68 -4
- package/dist/commands/claude/plugin/build.js.map +1 -1
- package/dist/commands/consistency-check.d.ts +13 -0
- package/dist/commands/consistency-check.d.ts.map +1 -1
- package/dist/commands/consistency-check.js +98 -1
- package/dist/commands/consistency-check.js.map +1 -1
- package/dist/commands/corpus/runner.d.ts.map +1 -1
- package/dist/commands/corpus/runner.js +1 -2
- package/dist/commands/corpus/runner.js.map +1 -1
- package/dist/commands/corpus/seed.d.ts +24 -0
- package/dist/commands/corpus/seed.d.ts.map +1 -1
- package/dist/commands/corpus/seed.js +5 -0
- package/dist/commands/corpus/seed.js.map +1 -1
- package/dist/commands/resources/index.d.ts.map +1 -1
- package/dist/commands/resources/index.js +4 -1
- package/dist/commands/resources/index.js.map +1 -1
- package/dist/commands/resources/validate.d.ts.map +1 -1
- package/dist/commands/resources/validate.js +155 -112
- package/dist/commands/resources/validate.js.map +1 -1
- package/dist/commands/skill/index.d.ts.map +1 -1
- package/dist/commands/skill/index.js +2 -0
- package/dist/commands/skill/index.js.map +1 -1
- package/dist/commands/skill/review.js.map +1 -1
- package/dist/commands/skill/test/configure.d.ts +22 -0
- package/dist/commands/skill/test/configure.d.ts.map +1 -0
- package/dist/commands/skill/test/configure.js +127 -0
- package/dist/commands/skill/test/configure.js.map +1 -0
- package/dist/commands/skill/test/index.d.ts +6 -0
- package/dist/commands/skill/test/index.d.ts.map +1 -0
- package/dist/commands/skill/test/index.js +16 -0
- package/dist/commands/skill/test/index.js.map +1 -0
- package/dist/commands/skill/test/run.d.ts +40 -0
- package/dist/commands/skill/test/run.d.ts.map +1 -0
- package/dist/commands/skill/test/run.js +381 -0
- package/dist/commands/skill/test/run.js.map +1 -0
- package/dist/commands/skills/skill-discovery.d.ts +9 -2
- package/dist/commands/skills/skill-discovery.d.ts.map +1 -1
- package/dist/commands/skills/skill-discovery.js +83 -18
- package/dist/commands/skills/skill-discovery.js.map +1 -1
- package/dist/utils/verdict-helpers.d.ts +2 -1
- package/dist/utils/verdict-helpers.d.ts.map +1 -1
- package/dist/utils/verdict-helpers.js +1 -1
- package/dist/utils/verdict-helpers.js.map +1 -1
- package/docs/resources.md +7 -3
- package/package.json +11 -11
- package/dist/commands/claude/marketplace/tag-utils.d.ts +0 -11
- package/dist/commands/claude/marketplace/tag-utils.d.ts.map +0 -1
- package/dist/commands/claude/marketplace/tag-utils.js +0 -17
- package/dist/commands/claude/marketplace/tag-utils.js.map +0 -1
- package/dist/utils/git-url.d.ts +0 -43
- package/dist/utils/git-url.d.ts.map +0 -1
- package/dist/utils/git-url.js +0 -135
- package/dist/utils/git-url.js.map +0 -1
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `vat skill test` command group — behavioral testing of packaged skills in isolation.
|
|
3
|
+
*/
|
|
4
|
+
import { Command } from 'commander';
|
|
5
|
+
import { createSkillTestConfigureCommand } from './configure.js';
|
|
6
|
+
import { createSkillTestRunCommand } from './run.js';
|
|
7
|
+
export function createSkillTestCommand() {
|
|
8
|
+
const command = new Command('test');
|
|
9
|
+
command
|
|
10
|
+
.description('Behaviorally test a packaged skill in isolation (run) or configure its test block (configure)')
|
|
11
|
+
.helpCommand(false);
|
|
12
|
+
command.addCommand(createSkillTestRunCommand());
|
|
13
|
+
command.addCommand(createSkillTestConfigureCommand());
|
|
14
|
+
return command;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/commands/skill/test/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,+BAA+B,EAAE,MAAM,gBAAgB,CAAC;AACjE,OAAO,EAAE,yBAAyB,EAAE,MAAM,UAAU,CAAC;AAErD,MAAM,UAAU,sBAAsB;IACpC,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IACpC,OAAO;SACJ,WAAW,CACV,+FAA+F,CAChG;SACA,WAAW,CAAC,KAAK,CAAC,CAAC;IACtB,OAAO,CAAC,UAAU,CAAC,yBAAyB,EAAE,CAAC,CAAC;IAChD,OAAO,CAAC,UAAU,CAAC,+BAA+B,EAAE,CAAC,CAAC;IACtD,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `vat skill test run <skill...>` — execute a packaged skill's eval suite in isolation.
|
|
3
|
+
*
|
|
4
|
+
* Thin orchestration layer: parse flags, resolve precedence (flag > config > default),
|
|
5
|
+
* print the §12 security warning, call runSkillTestHarness, map result/error to exit code.
|
|
6
|
+
* All domain logic lives in run-harness.ts (agent-skills package).
|
|
7
|
+
*/
|
|
8
|
+
import { Command } from 'commander';
|
|
9
|
+
export interface SkillTestRunOptions {
|
|
10
|
+
with?: string[];
|
|
11
|
+
withOptional?: string[];
|
|
12
|
+
refresh?: boolean;
|
|
13
|
+
workdir?: string;
|
|
14
|
+
out?: string;
|
|
15
|
+
keep?: boolean;
|
|
16
|
+
dryRun?: boolean;
|
|
17
|
+
auth?: string;
|
|
18
|
+
requireAuth?: string;
|
|
19
|
+
baseline?: boolean;
|
|
20
|
+
allowUnverifiedSkillSource?: boolean;
|
|
21
|
+
iUnderstandThisRunsSkillCode?: boolean;
|
|
22
|
+
model?: string;
|
|
23
|
+
maxTurns?: string;
|
|
24
|
+
maxBudgetUsd?: string;
|
|
25
|
+
timeout?: string;
|
|
26
|
+
stall?: string;
|
|
27
|
+
debug?: boolean;
|
|
28
|
+
env?: string[];
|
|
29
|
+
passEnv?: string[];
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* The unit-testable action for `vat skill test run`. Exported so tests can
|
|
33
|
+
* call it directly without parsing CLI args. Calls process.exit on completion.
|
|
34
|
+
*
|
|
35
|
+
* Note: the security ack enforcement lives inside runSkillTestHarness (domain),
|
|
36
|
+
* NOT here — this ensures the mock in tests can bypass it cleanly.
|
|
37
|
+
*/
|
|
38
|
+
export declare function runSkillTestRun(skills: string[], options: SkillTestRunOptions): Promise<void>;
|
|
39
|
+
export declare function createSkillTestRunCommand(): Command;
|
|
40
|
+
//# sourceMappingURL=run.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../../../src/commands/skill/test/run.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAOH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA4BpC,MAAM,WAAW,mBAAmB;IAClC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,0BAA0B,CAAC,EAAE,OAAO,CAAC;IACrC,4BAA4B,CAAC,EAAE,OAAO,CAAC;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAuSD;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,MAAM,EAAE,EAChB,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,IAAI,CAAC,CA0Bf;AAMD,wBAAgB,yBAAyB,IAAI,OAAO,CAkEnD"}
|
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `vat skill test run <skill...>` — execute a packaged skill's eval suite in isolation.
|
|
3
|
+
*
|
|
4
|
+
* Thin orchestration layer: parse flags, resolve precedence (flag > config > default),
|
|
5
|
+
* print the §12 security warning, call runSkillTestHarness, map result/error to exit code.
|
|
6
|
+
* All domain logic lives in run-harness.ts (agent-skills package).
|
|
7
|
+
*/
|
|
8
|
+
import { basename } from 'node:path';
|
|
9
|
+
import { BootstrapNeededError, mapErrorToExitCode, runSkillTestHarness } from '@vibe-agent-toolkit/agent-skills';
|
|
10
|
+
import { findProjectRoot, toForwardSlash } from '@vibe-agent-toolkit/utils';
|
|
11
|
+
import { Command } from 'commander';
|
|
12
|
+
import { loadConfig } from '../../../utils/config-loader.js';
|
|
13
|
+
/** Extract the trailing path segment (cross-platform) from a path-like string. */
|
|
14
|
+
function lastPathSegment(p) {
|
|
15
|
+
return basename(toForwardSlash(p));
|
|
16
|
+
}
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
// Security warning (§12)
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
const SECURITY_WARNING = `
|
|
21
|
+
WARNING: vat skill test run executes arbitrary skill code inside a headless
|
|
22
|
+
Claude session. The experimenter prompt and all staged skill files run with
|
|
23
|
+
bypassPermissions. Pass --i-understand-this-runs-skill-code to acknowledge
|
|
24
|
+
this and proceed.
|
|
25
|
+
`.trim();
|
|
26
|
+
function printSecurityWarning() {
|
|
27
|
+
process.stderr.write(SECURITY_WARNING + '\n\n');
|
|
28
|
+
}
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
// Knob coercion helpers
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
function coercePositiveInt(value, flagName) {
|
|
33
|
+
if (value === undefined)
|
|
34
|
+
return undefined;
|
|
35
|
+
const n = Number.parseInt(value, 10);
|
|
36
|
+
if (!Number.isInteger(n) || n <= 0) {
|
|
37
|
+
throw new Error(`${flagName} must be a positive integer. Got: ${value}`);
|
|
38
|
+
}
|
|
39
|
+
return n;
|
|
40
|
+
}
|
|
41
|
+
function coercePositiveFloat(value, flagName) {
|
|
42
|
+
if (value === undefined)
|
|
43
|
+
return undefined;
|
|
44
|
+
const n = Number.parseFloat(value);
|
|
45
|
+
if (!Number.isFinite(n) || n <= 0) {
|
|
46
|
+
throw new Error(`${flagName} must be a positive number. Got: ${value}`);
|
|
47
|
+
}
|
|
48
|
+
return n;
|
|
49
|
+
}
|
|
50
|
+
function coerceKnobs(options) {
|
|
51
|
+
const result = {};
|
|
52
|
+
const maxTurns = coercePositiveInt(options.maxTurns, '--max-turns');
|
|
53
|
+
if (maxTurns !== undefined)
|
|
54
|
+
result.maxTurns = maxTurns;
|
|
55
|
+
const maxBudgetUsd = coercePositiveFloat(options.maxBudgetUsd, '--max-budget-usd');
|
|
56
|
+
if (maxBudgetUsd !== undefined)
|
|
57
|
+
result.maxBudgetUsd = maxBudgetUsd;
|
|
58
|
+
const timeout = coercePositiveInt(options.timeout, '--timeout');
|
|
59
|
+
if (timeout !== undefined)
|
|
60
|
+
result.timeout = timeout;
|
|
61
|
+
const stall = coercePositiveInt(options.stall, '--stall');
|
|
62
|
+
if (stall !== undefined)
|
|
63
|
+
result.stall = stall;
|
|
64
|
+
return result;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Parse a single `name=src` pair into a [name, SkillSourceSpec] tuple. The
|
|
68
|
+
* source half uses a `kind:value` prefix:
|
|
69
|
+
* workspace:foo · npm:@scope/s@1.2.3 · url:https://… · path:../baz · vendored
|
|
70
|
+
* A bare value without `name=` is rejected — every injected dep needs a name so
|
|
71
|
+
* the domain can key it (and so the skill resolves under that name in staging).
|
|
72
|
+
*/
|
|
73
|
+
function parseWithPair(pair) {
|
|
74
|
+
const eq = pair.indexOf('=');
|
|
75
|
+
if (eq <= 0) {
|
|
76
|
+
throw new Error(`--with entries must be "name=<src>" (e.g. mydep=workspace:foo, bar=npm:@scope/s@1.2.3, baz=path:../baz). Got: ${pair}`);
|
|
77
|
+
}
|
|
78
|
+
const name = pair.slice(0, eq);
|
|
79
|
+
const src = pair.slice(eq + 1);
|
|
80
|
+
return [name, parseSourceSpec(src, pair)];
|
|
81
|
+
}
|
|
82
|
+
/** Parse the `kind:value` source half of a --with pair into a SkillSourceSpec. */
|
|
83
|
+
function parseSourceSpec(src, original) {
|
|
84
|
+
if (src === 'vendored')
|
|
85
|
+
return { vendored: true };
|
|
86
|
+
const colon = src.indexOf(':');
|
|
87
|
+
const kind = colon === -1 ? src : src.slice(0, colon);
|
|
88
|
+
const value = colon === -1 ? '' : src.slice(colon + 1);
|
|
89
|
+
switch (kind) {
|
|
90
|
+
case 'workspace': return requireValue(value, original, () => ({ workspace: value }));
|
|
91
|
+
case 'npm': return requireValue(value, original, () => ({ npm: value }));
|
|
92
|
+
case 'path': return requireValue(value, original, () => ({ path: value }));
|
|
93
|
+
case 'url': return requireValue(value, original, () => ({ url: value }));
|
|
94
|
+
default:
|
|
95
|
+
throw new Error(`--with source must start with workspace:|npm:|url:|path:|vendored. Got: ${original}`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
function requireValue(value, original, build) {
|
|
99
|
+
if (!value) {
|
|
100
|
+
throw new Error(`--with source is missing a value: ${original}`);
|
|
101
|
+
}
|
|
102
|
+
return build();
|
|
103
|
+
}
|
|
104
|
+
/** Parse an array of `name=src` flag values into a name→spec record. */
|
|
105
|
+
function parseWithFlags(pairs) {
|
|
106
|
+
if (pairs === undefined || pairs.length === 0)
|
|
107
|
+
return undefined;
|
|
108
|
+
const record = {};
|
|
109
|
+
for (const pair of pairs) {
|
|
110
|
+
const [name, spec] = parseWithPair(pair);
|
|
111
|
+
record[name] = spec;
|
|
112
|
+
}
|
|
113
|
+
return record;
|
|
114
|
+
}
|
|
115
|
+
/** Derive a stable name for a config-supplied (nameless) skill source descriptor. */
|
|
116
|
+
function descriptorName(d) {
|
|
117
|
+
if ('workspace' in d)
|
|
118
|
+
return d.workspace;
|
|
119
|
+
if ('npm' in d)
|
|
120
|
+
return d.npm.replace(/@[^@/]+$/, '');
|
|
121
|
+
if ('path' in d)
|
|
122
|
+
return lastPathSegment(d.path) || d.path;
|
|
123
|
+
if ('url' in d)
|
|
124
|
+
return 'url-dep';
|
|
125
|
+
return 'skill-creator';
|
|
126
|
+
}
|
|
127
|
+
/** Map a config descriptor array (with/optional) into a name→spec record. */
|
|
128
|
+
function descriptorsToRecord(list) {
|
|
129
|
+
if (list === undefined || list.length === 0)
|
|
130
|
+
return undefined;
|
|
131
|
+
const record = {};
|
|
132
|
+
for (const d of list)
|
|
133
|
+
record[descriptorName(d)] = d;
|
|
134
|
+
return record;
|
|
135
|
+
}
|
|
136
|
+
// ---------------------------------------------------------------------------
|
|
137
|
+
// Precedence resolution: flag > config > default
|
|
138
|
+
// ---------------------------------------------------------------------------
|
|
139
|
+
/**
|
|
140
|
+
* Load the persisted `skills.config.<skill>.test` block for the subject skill.
|
|
141
|
+
* The subject is the first positional skill name (a path or skill key). We key
|
|
142
|
+
* the config by its basename so `./dist/skills/my-skill/` matches `my-skill`.
|
|
143
|
+
* Missing config / missing file → undefined (defaults apply).
|
|
144
|
+
*/
|
|
145
|
+
function loadTestConfig(skills) {
|
|
146
|
+
const projectRoot = findProjectRoot(process.cwd());
|
|
147
|
+
if (projectRoot === null)
|
|
148
|
+
return undefined;
|
|
149
|
+
let config;
|
|
150
|
+
try {
|
|
151
|
+
config = loadConfig(projectRoot);
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
return undefined; // tolerate a broken/absent config → defaults
|
|
155
|
+
}
|
|
156
|
+
const perSkill = config?.skills?.config;
|
|
157
|
+
if (perSkill === undefined)
|
|
158
|
+
return undefined;
|
|
159
|
+
const subject = skills[0] ?? '';
|
|
160
|
+
const base = lastPathSegment(subject) || subject;
|
|
161
|
+
return perSkill[subject]?.test ?? perSkill[base]?.test;
|
|
162
|
+
}
|
|
163
|
+
/** Resolve the project root used as the harness repoRoot anchor. */
|
|
164
|
+
function resolveRepoRoot() {
|
|
165
|
+
return findProjectRoot(process.cwd()) ?? process.cwd();
|
|
166
|
+
}
|
|
167
|
+
/** Copy flag-only passthrough options (no config counterpart) onto opts. */
|
|
168
|
+
function applyFlagOnlyOptions(opts, options) {
|
|
169
|
+
if (options.refresh !== undefined)
|
|
170
|
+
opts.refresh = options.refresh;
|
|
171
|
+
if (options.workdir !== undefined)
|
|
172
|
+
opts.workdir = options.workdir;
|
|
173
|
+
if (options.out !== undefined)
|
|
174
|
+
opts.out = options.out;
|
|
175
|
+
if (options.keep !== undefined)
|
|
176
|
+
opts.keep = options.keep;
|
|
177
|
+
if (options.dryRun !== undefined)
|
|
178
|
+
opts.dryRun = options.dryRun;
|
|
179
|
+
if (options.allowUnverifiedSkillSource !== undefined)
|
|
180
|
+
opts.allowUnverifiedSkillSource = options.allowUnverifiedSkillSource;
|
|
181
|
+
if (options.iUnderstandThisRunsSkillCode !== undefined)
|
|
182
|
+
opts.acknowledgedRunsSkillCode = options.iUnderstandThisRunsSkillCode;
|
|
183
|
+
}
|
|
184
|
+
/** Apply flag>config merges for scalar knobs (auth, model, baseline, eval/prompt). */
|
|
185
|
+
function applyScalarMerges(opts, options, config) {
|
|
186
|
+
const authMode = options.auth ?? config?.auth;
|
|
187
|
+
if (authMode !== undefined)
|
|
188
|
+
opts.auth = authMode;
|
|
189
|
+
const authRequirement = options.requireAuth ?? config?.requireAuth;
|
|
190
|
+
if (authRequirement !== undefined)
|
|
191
|
+
opts.requireAuth = authRequirement;
|
|
192
|
+
const baseline = options.baseline ?? config?.baseline;
|
|
193
|
+
if (baseline !== undefined)
|
|
194
|
+
opts.baseline = baseline;
|
|
195
|
+
const model = options.model ?? config?.model;
|
|
196
|
+
if (model !== undefined)
|
|
197
|
+
opts.model = model;
|
|
198
|
+
if (config?.evals !== undefined)
|
|
199
|
+
opts.evalsSubpath = config.evals;
|
|
200
|
+
if (config?.experimenterPrompt !== undefined)
|
|
201
|
+
opts.promptOverride = config.experimenterPrompt;
|
|
202
|
+
if (config?.build !== undefined)
|
|
203
|
+
opts.build = config.build;
|
|
204
|
+
}
|
|
205
|
+
/** Apply flag>config merges for numeric knobs (turns/budget/timeout/stall). */
|
|
206
|
+
function applyKnobMerges(opts, knobs, config) {
|
|
207
|
+
const maxTurns = knobs.maxTurns ?? config?.maxTurns;
|
|
208
|
+
if (maxTurns !== undefined)
|
|
209
|
+
opts.maxTurns = maxTurns;
|
|
210
|
+
const maxBudgetUsd = knobs.maxBudgetUsd ?? config?.maxBudgetUsd;
|
|
211
|
+
if (maxBudgetUsd !== undefined)
|
|
212
|
+
opts.maxBudgetUsd = maxBudgetUsd;
|
|
213
|
+
const timeout = knobs.timeout ?? config?.timeout;
|
|
214
|
+
if (timeout !== undefined)
|
|
215
|
+
opts.timeout = timeout;
|
|
216
|
+
const stall = knobs.stall ?? config?.stall;
|
|
217
|
+
if (stall !== undefined)
|
|
218
|
+
opts.stall = stall;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Parse a single `KEY=VALUE` pair (split on the FIRST `=`, so values may contain
|
|
222
|
+
* `=`). The key must be non-empty; the value may be empty.
|
|
223
|
+
*/
|
|
224
|
+
function parseEnvPair(pair) {
|
|
225
|
+
const eq = pair.indexOf('=');
|
|
226
|
+
if (eq <= 0) {
|
|
227
|
+
throw new Error(`--env entries must be "KEY=VALUE" (e.g. CUSTOMER_SNAPSHOT_PATH=\${fixturesDir}/snapshot.json). Got: ${pair}`);
|
|
228
|
+
}
|
|
229
|
+
return [pair.slice(0, eq), pair.slice(eq + 1)];
|
|
230
|
+
}
|
|
231
|
+
/** Parse repeated `--env KEY=VALUE` flags into a record (undefined when none). */
|
|
232
|
+
function parseEnvFlags(pairs) {
|
|
233
|
+
if (pairs === undefined || pairs.length === 0)
|
|
234
|
+
return undefined;
|
|
235
|
+
const record = {};
|
|
236
|
+
for (const pair of pairs) {
|
|
237
|
+
const [key, value] = parseEnvPair(pair);
|
|
238
|
+
record[key] = value;
|
|
239
|
+
}
|
|
240
|
+
return record;
|
|
241
|
+
}
|
|
242
|
+
/** Merge config + CLI `env` maps; CLI wins per-key. undefined when both absent. */
|
|
243
|
+
function mergeEnv(configEnv, cliEnv) {
|
|
244
|
+
if (configEnv === undefined && cliEnv === undefined)
|
|
245
|
+
return undefined;
|
|
246
|
+
return { ...(configEnv ?? {}), ...(cliEnv ?? {}) };
|
|
247
|
+
}
|
|
248
|
+
/** Union config + CLI `passEnv` lists (config first), de-duplicated. */
|
|
249
|
+
function mergePassEnv(configPass, cliPass) {
|
|
250
|
+
if (configPass === undefined && cliPass === undefined)
|
|
251
|
+
return undefined;
|
|
252
|
+
return [...new Set([...(configPass ?? []), ...(cliPass ?? [])])];
|
|
253
|
+
}
|
|
254
|
+
/** Apply flag>config merges for the declared test env (Features A + B). */
|
|
255
|
+
function applyEnvMerges(opts, options, config) {
|
|
256
|
+
const env = mergeEnv(config?.env, parseEnvFlags(options.env));
|
|
257
|
+
if (env !== undefined)
|
|
258
|
+
opts.env = env;
|
|
259
|
+
const passEnv = mergePassEnv(config?.passEnv, options.passEnv);
|
|
260
|
+
if (passEnv !== undefined)
|
|
261
|
+
opts.passEnv = passEnv;
|
|
262
|
+
}
|
|
263
|
+
/** Apply flag>config merges for injected-dependency records. */
|
|
264
|
+
function applyDepMerges(opts, options, config) {
|
|
265
|
+
const withSources = parseWithFlags(options.with) ?? descriptorsToRecord(config?.with);
|
|
266
|
+
if (withSources !== undefined)
|
|
267
|
+
opts.withSources = withSources;
|
|
268
|
+
const withOptional = parseWithFlags(options.withOptional) ?? descriptorsToRecord(config?.optional);
|
|
269
|
+
if (withOptional !== undefined)
|
|
270
|
+
opts.withOptional = withOptional;
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Resolve CLI flags → RunHarnessOptions, applying flag > config > default
|
|
274
|
+
* precedence. CLI flags win; config (`skills.config.<skill>.test`) fills gaps;
|
|
275
|
+
* built-in defaults (inside the domain) are the final fallback.
|
|
276
|
+
*/
|
|
277
|
+
function buildHarnessOpts(skills, options, knobs, config) {
|
|
278
|
+
const repoRoot = resolveRepoRoot();
|
|
279
|
+
const opts = { skills, repoRoot };
|
|
280
|
+
// cwd for the pre-stage build hook. repoRoot comes from findProjectRoot, whose
|
|
281
|
+
// discovery ladder is config-anchored (vibe-agent-toolkit.config.yaml first, then
|
|
282
|
+
// .git), so the project root IS the directory holding the config — configRoot and
|
|
283
|
+
// repoRoot are the same dir by construction, not coincidence.
|
|
284
|
+
opts.configRoot = repoRoot;
|
|
285
|
+
applyFlagOnlyOptions(opts, options);
|
|
286
|
+
applyScalarMerges(opts, options, config);
|
|
287
|
+
applyKnobMerges(opts, knobs, config);
|
|
288
|
+
applyDepMerges(opts, options, config);
|
|
289
|
+
applyEnvMerges(opts, options, config);
|
|
290
|
+
return opts;
|
|
291
|
+
}
|
|
292
|
+
// ---------------------------------------------------------------------------
|
|
293
|
+
// Testable action
|
|
294
|
+
// ---------------------------------------------------------------------------
|
|
295
|
+
/**
|
|
296
|
+
* The unit-testable action for `vat skill test run`. Exported so tests can
|
|
297
|
+
* call it directly without parsing CLI args. Calls process.exit on completion.
|
|
298
|
+
*
|
|
299
|
+
* Note: the security ack enforcement lives inside runSkillTestHarness (domain),
|
|
300
|
+
* NOT here — this ensures the mock in tests can bypass it cleanly.
|
|
301
|
+
*/
|
|
302
|
+
export async function runSkillTestRun(skills, options) {
|
|
303
|
+
printSecurityWarning();
|
|
304
|
+
const knobs = coerceKnobs(options);
|
|
305
|
+
const config = loadTestConfig(skills);
|
|
306
|
+
const harnessOpts = buildHarnessOpts(skills, options, knobs, config);
|
|
307
|
+
try {
|
|
308
|
+
const result = await runSkillTestHarness(harnessOpts);
|
|
309
|
+
process.stderr.write(`Harness: ${result.harnessPath}\n`);
|
|
310
|
+
process.stdout.write(`Summary: ${result.summary}\n`);
|
|
311
|
+
process.exit(result.exitCode);
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
catch (err) {
|
|
315
|
+
const exitCode = mapErrorToExitCode(err);
|
|
316
|
+
// BootstrapNeededError (exit 3) is the happy "wrote a template, fill it in
|
|
317
|
+
// and re-run" path — surface its message plainly, not as a hard `Error:`.
|
|
318
|
+
if (err instanceof BootstrapNeededError) {
|
|
319
|
+
process.stderr.write(`${err.message}\n`);
|
|
320
|
+
}
|
|
321
|
+
else {
|
|
322
|
+
process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
323
|
+
}
|
|
324
|
+
process.exit(exitCode);
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
// ---------------------------------------------------------------------------
|
|
329
|
+
// Commander command builder
|
|
330
|
+
// ---------------------------------------------------------------------------
|
|
331
|
+
export function createSkillTestRunCommand() {
|
|
332
|
+
const command = new Command('run');
|
|
333
|
+
command
|
|
334
|
+
.description('Execute the eval suite for a packaged skill in a headless Claude sandbox')
|
|
335
|
+
.argument('<skill...>', 'Skill name(s) to test (primary subject set)')
|
|
336
|
+
.option('--with <pair...>', 'Inject a declared-dependency skill as name=<src>, where <src> is workspace:<pkg> | npm:<spec> | url:<u> | path:<dir> | vendored (e.g. mydep=npm:@scope/s@1.2.3)')
|
|
337
|
+
.option('--with-optional <pair...>', 'Inject an optional skill as name=<src> (same syntax as --with)')
|
|
338
|
+
.option('--env <pair...>', 'Inject an env var into the experimenter spawn as KEY=VALUE (repeatable). Values support ${fixturesDir}, ${stagedSkillDir}, ${harnessRoot}, ${resultsDir}. CLI overrides config for the same key.')
|
|
339
|
+
.option('--pass-env <key...>', 'Forward a host env var by NAME to the experimenter spawn if present (repeatable). Protected names (PATH, auth, model) are ignored.')
|
|
340
|
+
.option('--refresh', 'Force a full re-stage (ignore existing staged content)')
|
|
341
|
+
.option('--workdir <dir>', 'Override the harness working directory')
|
|
342
|
+
.option('--out <dir>', 'Override the harness output directory')
|
|
343
|
+
.option('--keep', 'Keep the harness directory after the run')
|
|
344
|
+
.option('--dry-run', 'Assemble the command without spawning Claude')
|
|
345
|
+
.option('--auth <mode>', 'Auth mechanism: inherit | subscription | api-key | auto')
|
|
346
|
+
.option('--require-auth <mech>', 'Require a specific auth mechanism: subscription | api-key')
|
|
347
|
+
.option('--baseline', 'Enable A/B baseline run (with/without skill)')
|
|
348
|
+
.option('--allow-unverified-skill-source', 'Skip the vendored manifest integrity check')
|
|
349
|
+
.option('--i-understand-this-runs-skill-code', 'Acknowledge this command executes skill code (required)')
|
|
350
|
+
.option('--model <id>', 'Pinned model ID override')
|
|
351
|
+
.option('--max-turns <n>', 'Cap on experimenter turns (positive integer)')
|
|
352
|
+
.option('--max-budget-usd <n>', 'Hard USD budget cap (positive number)')
|
|
353
|
+
.option('--timeout <s>', 'Wall-clock timeout in seconds (positive integer)')
|
|
354
|
+
.option('--stall <s>', 'Stall-watchdog in seconds (positive integer)')
|
|
355
|
+
.option('--debug', 'Enable debug logging')
|
|
356
|
+
.action(runSkillTestRun)
|
|
357
|
+
.addHelpText('after', `
|
|
358
|
+
Description:
|
|
359
|
+
Stages the named skill(s) into an isolated tmp directory, runs preflight
|
|
360
|
+
checks (claude binary, auth, eval inputs, budget), then spawns a headless
|
|
361
|
+
Claude session with a non-interactive experimenter prompt. The experimenter
|
|
362
|
+
grades each eval against the skill's expectations and writes grading.json.
|
|
363
|
+
|
|
364
|
+
IMPORTANT: This command executes arbitrary skill code. You MUST pass
|
|
365
|
+
--i-understand-this-runs-skill-code to acknowledge this and proceed.
|
|
366
|
+
|
|
367
|
+
Exit Codes:
|
|
368
|
+
0 - Harness ran to completion and produced a valid grading.json (check summary/grading.json for pass/fail counts)
|
|
369
|
+
1 - Internal error (grading.json absent/invalid, experimenter crash, stall/timeout)
|
|
370
|
+
2 - Preflight failed (missing binary, auth error, eval inputs absent, unsafe workdir, ack missing)
|
|
371
|
+
3 - Bootstrap needed: evals.json was absent, so VAT wrote a starter template next to the skill source. Fill it in and re-run.
|
|
372
|
+
|
|
373
|
+
Note: eval pass/fail is NOT reflected in the exit code. Read the printed summary
|
|
374
|
+
("PASS N/N" or "FAIL N/N") or grading.json to determine whether expectations passed.
|
|
375
|
+
|
|
376
|
+
Example:
|
|
377
|
+
$ vat skill test run my-skill --i-understand-this-runs-skill-code
|
|
378
|
+
`);
|
|
379
|
+
return command;
|
|
380
|
+
}
|
|
381
|
+
//# sourceMappingURL=run.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../../../src/commands/skill/test/run.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,8 +9,15 @@ import type { DiscoveredSkill } from './command-helpers.js';
|
|
|
9
9
|
/**
|
|
10
10
|
* Discover skills from config yaml skills section.
|
|
11
11
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
12
|
+
* Each include pattern is resolved against `projectRoot` and may step out of
|
|
13
|
+
* the package via `..` (e.g. `"../../docs/skills/*\/SKILL.md"` in a monorepo
|
|
14
|
+
* where SKILL.md files live alongside, not inside, the package). Patterns are
|
|
15
|
+
* grouped by their effective scan root so `crawlDirectory` is invoked once per
|
|
16
|
+
* root rather than blindly walking from `projectRoot`.
|
|
17
|
+
*
|
|
18
|
+
* User-supplied excludes are matched against paths relative to `projectRoot`
|
|
19
|
+
* so anchored excludes like `docs/private/**` keep their original meaning
|
|
20
|
+
* regardless of which scan root produced the candidate file.
|
|
14
21
|
*
|
|
15
22
|
* @param skillsConfig - The skills section from vibe-agent-toolkit.config.yaml
|
|
16
23
|
* @param projectRoot - Absolute path to project root (where config yaml lives)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skill-discovery.d.ts","sourceRoot":"","sources":["../../../src/commands/skills/skill-discovery.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"skill-discovery.d.ts","sourceRoot":"","sources":["../../../src/commands/skills/skill-discovery.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAIlE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AA2F5D;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,wBAAwB,CAC5C,YAAY,EAAE,YAAY,EAC1B,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,eAAe,EAAE,CAAC,CA0B5B"}
|
|
@@ -4,10 +4,12 @@
|
|
|
4
4
|
* Reads skills.include/exclude glob patterns from vibe-agent-toolkit.config.yaml,
|
|
5
5
|
* finds matching SKILL.md files, and extracts skill names from frontmatter.
|
|
6
6
|
*/
|
|
7
|
+
import { existsSync } from 'node:fs';
|
|
7
8
|
import { readFile } from 'node:fs/promises';
|
|
8
9
|
import { basename } from 'node:path';
|
|
9
10
|
import { parseMarkdown } from '@vibe-agent-toolkit/resources';
|
|
10
|
-
import { crawlDirectory } from '@vibe-agent-toolkit/utils';
|
|
11
|
+
import { crawlDirectory, safePath, toForwardSlash } from '@vibe-agent-toolkit/utils';
|
|
12
|
+
import picomatch from 'picomatch';
|
|
11
13
|
/**
|
|
12
14
|
* Directories that should always be excluded from skill discovery for performance.
|
|
13
15
|
*/
|
|
@@ -37,11 +39,70 @@ async function readSkillName(skillPath) {
|
|
|
37
39
|
}
|
|
38
40
|
return basename(skillPath, '.md');
|
|
39
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* Split an include pattern into its literal base directory and its glob
|
|
44
|
+
* remainder. `picomatch.scan` already does the heavy lifting for proper
|
|
45
|
+
* glob patterns; the manual split handles pure-literal paths so a single
|
|
46
|
+
* SKILL.md file is still crawlable from its parent directory.
|
|
47
|
+
*/
|
|
48
|
+
function splitIncludePattern(pattern) {
|
|
49
|
+
const scanned = picomatch.scan(pattern);
|
|
50
|
+
if (scanned.isGlob) {
|
|
51
|
+
return { base: scanned.base, glob: scanned.glob };
|
|
52
|
+
}
|
|
53
|
+
// Literal path (no glob metachars): match the file from its parent.
|
|
54
|
+
const slash = pattern.lastIndexOf('/');
|
|
55
|
+
if (slash === -1) {
|
|
56
|
+
return { base: '', glob: pattern };
|
|
57
|
+
}
|
|
58
|
+
return { base: pattern.slice(0, slash), glob: pattern.slice(slash + 1) };
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Group include patterns by their effective scan root. Each pattern's literal
|
|
62
|
+
* prefix (resolved against `projectRoot`) becomes the absolute scan root for
|
|
63
|
+
* its glob remainder, which is what lets `..` segments escape `projectRoot`.
|
|
64
|
+
*/
|
|
65
|
+
function groupIncludePatternsByBase(include, projectRoot) {
|
|
66
|
+
const patternsByBase = new Map();
|
|
67
|
+
for (const pattern of include) {
|
|
68
|
+
const { base, glob } = splitIncludePattern(pattern);
|
|
69
|
+
const absBase = safePath.resolve(projectRoot, base || '.');
|
|
70
|
+
const effectiveGlob = glob.length > 0 ? glob : '**/*';
|
|
71
|
+
const existing = patternsByBase.get(absBase) ?? [];
|
|
72
|
+
existing.push(effectiveGlob);
|
|
73
|
+
patternsByBase.set(absBase, existing);
|
|
74
|
+
}
|
|
75
|
+
return patternsByBase;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Crawl one effective scan root. Returns absolute paths, or an empty array if
|
|
79
|
+
* the root does not exist (mirrors audit's filesystem-first tolerance for
|
|
80
|
+
* patterns pointing at nothing).
|
|
81
|
+
*/
|
|
82
|
+
async function crawlOneBase(base, globs) {
|
|
83
|
+
// eslint-disable-next-line security/detect-non-literal-fs-filename -- base derived from validated config
|
|
84
|
+
if (!existsSync(base)) {
|
|
85
|
+
return [];
|
|
86
|
+
}
|
|
87
|
+
return crawlDirectory({
|
|
88
|
+
baseDir: base,
|
|
89
|
+
include: globs,
|
|
90
|
+
exclude: DISCOVERY_EXCLUDE,
|
|
91
|
+
dot: true,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
40
94
|
/**
|
|
41
95
|
* Discover skills from config yaml skills section.
|
|
42
96
|
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
97
|
+
* Each include pattern is resolved against `projectRoot` and may step out of
|
|
98
|
+
* the package via `..` (e.g. `"../../docs/skills/*\/SKILL.md"` in a monorepo
|
|
99
|
+
* where SKILL.md files live alongside, not inside, the package). Patterns are
|
|
100
|
+
* grouped by their effective scan root so `crawlDirectory` is invoked once per
|
|
101
|
+
* root rather than blindly walking from `projectRoot`.
|
|
102
|
+
*
|
|
103
|
+
* User-supplied excludes are matched against paths relative to `projectRoot`
|
|
104
|
+
* so anchored excludes like `docs/private/**` keep their original meaning
|
|
105
|
+
* regardless of which scan root produced the candidate file.
|
|
45
106
|
*
|
|
46
107
|
* @param skillsConfig - The skills section from vibe-agent-toolkit.config.yaml
|
|
47
108
|
* @param projectRoot - Absolute path to project root (where config yaml lives)
|
|
@@ -49,23 +110,27 @@ async function readSkillName(skillPath) {
|
|
|
49
110
|
*/
|
|
50
111
|
export async function discoverSkillsFromConfig(skillsConfig, projectRoot) {
|
|
51
112
|
const { include, exclude } = skillsConfig;
|
|
52
|
-
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
113
|
+
const patternsByBase = groupIncludePatternsByBase(include, projectRoot);
|
|
114
|
+
const userExcludeMatcher = exclude && exclude.length > 0
|
|
115
|
+
? picomatch(exclude, { dot: true })
|
|
116
|
+
: null;
|
|
117
|
+
const foundAbsPaths = new Set();
|
|
118
|
+
for (const [base, globs] of patternsByBase) {
|
|
119
|
+
const crawled = await crawlOneBase(base, globs);
|
|
120
|
+
for (const absPath of crawled) {
|
|
121
|
+
if (userExcludeMatcher) {
|
|
122
|
+
const relFromProject = toForwardSlash(safePath.relative(projectRoot, absPath));
|
|
123
|
+
if (userExcludeMatcher(relFromProject))
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
foundAbsPaths.add(safePath.resolve(absPath));
|
|
127
|
+
}
|
|
128
|
+
}
|
|
62
129
|
const discovered = [];
|
|
63
|
-
for (const skillPath of
|
|
130
|
+
for (const skillPath of foundAbsPaths) {
|
|
64
131
|
const name = await readSkillName(skillPath);
|
|
65
|
-
if (
|
|
66
|
-
|
|
67
|
-
}
|
|
68
|
-
discovered.push({ name, sourcePath: skillPath });
|
|
132
|
+
if (name)
|
|
133
|
+
discovered.push({ name, sourcePath: skillPath });
|
|
69
134
|
}
|
|
70
135
|
return discovered;
|
|
71
136
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skill-discovery.js","sourceRoot":"","sources":["../../../src/commands/skills/skill-discovery.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAErC,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAE9D,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"skill-discovery.js","sourceRoot":"","sources":["../../../src/commands/skills/skill-discovery.ts"],"names":[],"mappings":"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"}
|
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
* nor in marketplace (which knows nothing about config-level packaging
|
|
13
13
|
* options).
|
|
14
14
|
*/
|
|
15
|
-
import { type
|
|
15
|
+
import { type ValidationIssue } from '@vibe-agent-toolkit/agent-schema';
|
|
16
|
+
import { type Observation, type PackagingValidationResult } from '@vibe-agent-toolkit/agent-skills';
|
|
16
17
|
import { type Target, type Verdict } from '@vibe-agent-toolkit/claude-marketplace';
|
|
17
18
|
/**
|
|
18
19
|
* Convert a verdict into a ValidationIssue using CODE_REGISTRY for severity,
|