@vibe-agent-toolkit/agent-skills 0.1.39-rc.8 → 0.1.39
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/dist/files-config.d.ts +61 -0
- package/dist/files-config.d.ts.map +1 -1
- package/dist/files-config.js +262 -6
- package/dist/files-config.js.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/plugin-distribution-layout.d.ts +70 -0
- package/dist/plugin-distribution-layout.d.ts.map +1 -0
- package/dist/plugin-distribution-layout.js +97 -0
- package/dist/plugin-distribution-layout.js.map +1 -0
- package/dist/skill-packager.d.ts +43 -1
- package/dist/skill-packager.d.ts.map +1 -1
- package/dist/skill-packager.js +131 -53
- package/dist/skill-packager.js.map +1 -1
- package/dist/skill-source/git-clone.d.ts +2 -2
- package/dist/skill-source/git-clone.d.ts.map +1 -1
- package/dist/skill-source/git-clone.js +33 -10
- package/dist/skill-source/git-clone.js.map +1 -1
- package/dist/skill-source/sources/url-source.d.ts.map +1 -1
- package/dist/skill-source/sources/url-source.js +23 -8
- package/dist/skill-source/sources/url-source.js.map +1 -1
- package/dist/skill-source/sources/workspace-source.d.ts.map +1 -1
- package/dist/skill-source/sources/workspace-source.js +16 -8
- package/dist/skill-source/sources/workspace-source.js.map +1 -1
- package/dist/skill-source/stage.js +6 -2
- package/dist/skill-source/stage.js.map +1 -1
- package/dist/skill-test/build-hook.d.ts +58 -0
- package/dist/skill-test/build-hook.d.ts.map +1 -0
- package/dist/skill-test/build-hook.js +63 -0
- package/dist/skill-test/build-hook.js.map +1 -0
- package/dist/skill-test/configure-writer.d.ts +19 -11
- package/dist/skill-test/configure-writer.d.ts.map +1 -1
- package/dist/skill-test/configure-writer.js +23 -15
- package/dist/skill-test/configure-writer.js.map +1 -1
- package/dist/skill-test/declared-env.d.ts +72 -0
- package/dist/skill-test/declared-env.d.ts.map +1 -0
- package/dist/skill-test/declared-env.js +85 -0
- package/dist/skill-test/declared-env.js.map +1 -0
- package/dist/skill-test/eval-inputs.d.ts +159 -0
- package/dist/skill-test/eval-inputs.d.ts.map +1 -0
- package/dist/skill-test/eval-inputs.js +158 -0
- package/dist/skill-test/eval-inputs.js.map +1 -0
- package/dist/skill-test/evals-template.d.ts.map +1 -1
- package/dist/skill-test/evals-template.js +27 -10
- package/dist/skill-test/evals-template.js.map +1 -1
- package/dist/skill-test/exit-codes.d.ts +44 -5
- package/dist/skill-test/exit-codes.d.ts.map +1 -1
- package/dist/skill-test/exit-codes.js +63 -9
- package/dist/skill-test/exit-codes.js.map +1 -1
- package/dist/skill-test/experimenter-prompt.d.ts +22 -0
- package/dist/skill-test/experimenter-prompt.d.ts.map +1 -1
- package/dist/skill-test/experimenter-prompt.js +39 -2
- package/dist/skill-test/experimenter-prompt.js.map +1 -1
- package/dist/skill-test/grading-adapter.d.ts +42 -0
- package/dist/skill-test/grading-adapter.d.ts.map +1 -1
- package/dist/skill-test/grading-adapter.js +63 -1
- package/dist/skill-test/grading-adapter.js.map +1 -1
- package/dist/skill-test/grading-schema.d.ts +73 -5
- package/dist/skill-test/grading-schema.d.ts.map +1 -1
- package/dist/skill-test/grading-schema.js +20 -5
- package/dist/skill-test/grading-schema.js.map +1 -1
- package/dist/skill-test/harness-location.d.ts +35 -4
- package/dist/skill-test/harness-location.d.ts.map +1 -1
- package/dist/skill-test/harness-location.js +111 -16
- package/dist/skill-test/harness-location.js.map +1 -1
- package/dist/skill-test/index.d.ts +7 -4
- package/dist/skill-test/index.d.ts.map +1 -1
- package/dist/skill-test/index.js +7 -4
- package/dist/skill-test/index.js.map +1 -1
- package/dist/skill-test/lock.d.ts +23 -0
- package/dist/skill-test/lock.d.ts.map +1 -1
- package/dist/skill-test/lock.js +35 -1
- package/dist/skill-test/lock.js.map +1 -1
- package/dist/skill-test/plugin-env.d.ts +20 -0
- package/dist/skill-test/plugin-env.d.ts.map +1 -0
- package/dist/skill-test/plugin-env.js +24 -0
- package/dist/skill-test/plugin-env.js.map +1 -0
- package/dist/skill-test/plugin-layout.d.ts +41 -0
- package/dist/skill-test/plugin-layout.d.ts.map +1 -0
- package/dist/skill-test/plugin-layout.js +49 -0
- package/dist/skill-test/plugin-layout.js.map +1 -0
- package/dist/skill-test/preflight.d.ts.map +1 -1
- package/dist/skill-test/preflight.js +1 -2
- package/dist/skill-test/preflight.js.map +1 -1
- package/dist/skill-test/run-harness.d.ts +197 -11
- package/dist/skill-test/run-harness.d.ts.map +1 -1
- package/dist/skill-test/run-harness.js +401 -65
- package/dist/skill-test/run-harness.js.map +1 -1
- package/dist/skill-test/staging.d.ts +20 -1
- package/dist/skill-test/staging.d.ts.map +1 -1
- package/dist/skill-test/staging.js +71 -17
- package/dist/skill-test/staging.js.map +1 -1
- package/dist/skill-test/vendor-manifest.d.ts +3 -3
- package/dist/skill-test/vendor-manifest.d.ts.map +1 -1
- package/dist/skill-test/vendor-manifest.js +13 -3
- package/dist/skill-test/vendor-manifest.js.map +1 -1
- package/dist/validators/packaging-validator.d.ts.map +1 -1
- package/dist/validators/packaging-validator.js +134 -1
- package/dist/validators/packaging-validator.js.map +1 -1
- package/dist/validators/skill-validator.d.ts.map +1 -1
- package/dist/validators/skill-validator.js +18 -14
- package/dist/validators/skill-validator.js.map +1 -1
- package/dist/walk-link-graph.d.ts.map +1 -1
- package/dist/walk-link-graph.js +26 -1
- package/dist/walk-link-graph.js.map +1 -1
- package/package.json +6 -5
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* declared-env.ts — resolve and assemble the declared test environment
|
|
3
|
+
* (Features A + B) for the experimenter spawn.
|
|
4
|
+
*
|
|
5
|
+
* Feature A (passEnv): forward named host env vars if present.
|
|
6
|
+
* Feature B (env): inject explicit key→value pairs whose values support
|
|
7
|
+
* stage-time interpolation tokens. An unknown token is a hard preflight error.
|
|
8
|
+
*
|
|
9
|
+
* The security-critical union (protected-key collisions, redaction) lives in
|
|
10
|
+
* `applyDeclaredEnv`/`formatForwardedEnvLine` (utils); this module owns the
|
|
11
|
+
* agent-skills-specific concerns: token computation, interpolation, and gluing
|
|
12
|
+
* the result onto the plugin-root env.
|
|
13
|
+
*/
|
|
14
|
+
import { dirname } from 'node:path';
|
|
15
|
+
import { applyDeclaredEnv, formatForwardedEnvLine, safePath, toForwardSlash } from '@vibe-agent-toolkit/utils';
|
|
16
|
+
import { withPluginRootEnv } from './plugin-env.js';
|
|
17
|
+
/**
|
|
18
|
+
* A declared `env` value referenced an unknown `${token}`. Exit 2 (preflight):
|
|
19
|
+
* fail loud naming the offending token rather than forwarding a literal `${x}`.
|
|
20
|
+
*/
|
|
21
|
+
export class UnknownEnvTokenError extends Error {
|
|
22
|
+
token;
|
|
23
|
+
key;
|
|
24
|
+
exitCode = 2;
|
|
25
|
+
constructor(token, key) {
|
|
26
|
+
super(`Unknown interpolation token \${${token}} in env value for "${key}". ` +
|
|
27
|
+
`Known tokens: fixturesDir, stagedSkillDir, harnessRoot, resultsDir.`);
|
|
28
|
+
this.token = token;
|
|
29
|
+
this.key = key;
|
|
30
|
+
this.name = 'UnknownEnvTokenError';
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Compute the interpolation tokens from the known staged dirs. `fixturesDir`
|
|
35
|
+
* tracks the eval suite's directory (`<evalsDir>/fixtures`), so the default
|
|
36
|
+
* `evals/evals.json` yields `<staged>/evals/fixtures`.
|
|
37
|
+
*/
|
|
38
|
+
export function computeEnvTokens(inputs) {
|
|
39
|
+
const evalsDir = dirname(toForwardSlash(inputs.evalsSubpath));
|
|
40
|
+
return {
|
|
41
|
+
fixturesDir: safePath.join(inputs.subjectStagedDir, evalsDir, 'fixtures'),
|
|
42
|
+
stagedSkillDir: inputs.subjectStagedDir,
|
|
43
|
+
harnessRoot: inputs.harnessRoot,
|
|
44
|
+
resultsDir: inputs.resultsDir,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function lookupToken(name, key, tokens) {
|
|
48
|
+
switch (name) {
|
|
49
|
+
case 'fixturesDir': return tokens.fixturesDir;
|
|
50
|
+
case 'stagedSkillDir': return tokens.stagedSkillDir;
|
|
51
|
+
case 'harnessRoot': return tokens.harnessRoot;
|
|
52
|
+
case 'resultsDir': return tokens.resultsDir;
|
|
53
|
+
default: throw new UnknownEnvTokenError(name, key);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/** Interpolate every `${token}` in `value`. Throws UnknownEnvTokenError on an unknown token. */
|
|
57
|
+
export function interpolateEnvValue(value, key, tokens) {
|
|
58
|
+
return value.replaceAll(/\$\{([^}]*)\}/g, (_match, name) => lookupToken(name, key, tokens));
|
|
59
|
+
}
|
|
60
|
+
/** Resolve every value in a declared `env` map. undefined in → undefined out. */
|
|
61
|
+
export function resolveInjectEnv(injectEnv, tokens) {
|
|
62
|
+
if (injectEnv === undefined)
|
|
63
|
+
return undefined;
|
|
64
|
+
const out = {};
|
|
65
|
+
for (const [key, value] of Object.entries(injectEnv)) {
|
|
66
|
+
out[key] = interpolateEnvValue(value, key, tokens);
|
|
67
|
+
}
|
|
68
|
+
return out;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Union the declared test env onto `base`, add the plugin-root var, and render
|
|
72
|
+
* the transparency line. Protected-key collisions surface as warnings; secrets
|
|
73
|
+
* and pass-through values are redacted in the line.
|
|
74
|
+
*/
|
|
75
|
+
export function assembleChildEnv(input) {
|
|
76
|
+
const declared = applyDeclaredEnv(input.base, {
|
|
77
|
+
source: input.source,
|
|
78
|
+
...(input.passEnv ? { passEnv: input.passEnv } : {}),
|
|
79
|
+
...(input.injectEnv ? { injectEnv: input.injectEnv } : {}),
|
|
80
|
+
});
|
|
81
|
+
const env = withPluginRootEnv(declared.env, input.subjectPluginRoot);
|
|
82
|
+
const line = formatForwardedEnvLine(env, declared);
|
|
83
|
+
return { env, warnings: declared.warnings, line };
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=declared-env.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"declared-env.js","sourceRoot":"","sources":["../../src/skill-test/declared-env.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAE/G,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAUpD;;;GAGG;AACH,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IAEjB;IAA+B;IADlD,QAAQ,GAAG,CAAU,CAAC;IAC/B,YAA4B,KAAa,EAAkB,GAAW;QACpE,KAAK,CACH,kCAAkC,KAAK,uBAAuB,GAAG,KAAK;YACpE,qEAAqE,CACxE,CAAC;QAJwB,UAAK,GAAL,KAAK,CAAQ;QAAkB,QAAG,GAAH,GAAG,CAAQ;QAKpE,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;IACrC,CAAC;CACF;AAUD;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAsB;IACrD,MAAM,QAAQ,GAAG,OAAO,CAAC,cAAc,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC;IAC9D,OAAO;QACL,WAAW,EAAE,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE,QAAQ,EAAE,UAAU,CAAC;QACzE,cAAc,EAAE,MAAM,CAAC,gBAAgB;QACvC,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,UAAU,EAAE,MAAM,CAAC,UAAU;KAC9B,CAAC;AACJ,CAAC;AAED,SAAS,WAAW,CAAC,IAAY,EAAE,GAAW,EAAE,MAA8B;IAC5E,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,aAAa,CAAC,CAAC,OAAO,MAAM,CAAC,WAAW,CAAC;QAC9C,KAAK,gBAAgB,CAAC,CAAC,OAAO,MAAM,CAAC,cAAc,CAAC;QACpD,KAAK,aAAa,CAAC,CAAC,OAAO,MAAM,CAAC,WAAW,CAAC;QAC9C,KAAK,YAAY,CAAC,CAAC,OAAO,MAAM,CAAC,UAAU,CAAC;QAC5C,OAAO,CAAC,CAAC,MAAM,IAAI,oBAAoB,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACrD,CAAC;AACH,CAAC;AAED,gGAAgG;AAChG,MAAM,UAAU,mBAAmB,CAAC,KAAa,EAAE,GAAW,EAAE,MAA8B;IAC5F,OAAO,KAAK,CAAC,UAAU,CAAC,gBAAgB,EAAE,CAAC,MAAM,EAAE,IAAY,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC;AACtG,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,gBAAgB,CAC9B,SAA6C,EAC7C,MAA8B;IAE9B,IAAI,SAAS,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC9C,MAAM,GAAG,GAA2B,EAAE,CAAC;IACvC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;QACrD,GAAG,CAAC,GAAG,CAAC,GAAG,mBAAmB,CAAC,KAAK,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;IACrD,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAsBD;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAA4B;IAC3D,MAAM,QAAQ,GAAG,gBAAgB,CAAC,KAAK,CAAC,IAAI,EAAE;QAC5C,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACpD,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC3D,CAAC,CAAC;IACH,MAAM,GAAG,GAAG,iBAAiB,CAAC,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC,iBAAiB,CAAC,CAAC;IACrE,MAAM,IAAI,GAAG,sBAAsB,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IACnD,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,QAAQ,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC;AACpD,CAAC"}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/** Raised for any eval-input problem (bad JSON, schema failure, missing input file). Maps to exit 2. */
|
|
3
|
+
export declare class EvalInputError extends Error {
|
|
4
|
+
constructor(message: string);
|
|
5
|
+
}
|
|
6
|
+
export declare const EvalEntrySchema: z.ZodEffects<z.ZodObject<{
|
|
7
|
+
id: z.ZodUnion<[z.ZodNumber, z.ZodString]>;
|
|
8
|
+
prompt: z.ZodString;
|
|
9
|
+
expected_output: z.ZodOptional<z.ZodString>;
|
|
10
|
+
files: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
11
|
+
expectations: z.ZodArray<z.ZodString, "many">;
|
|
12
|
+
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
13
|
+
id: z.ZodUnion<[z.ZodNumber, z.ZodString]>;
|
|
14
|
+
prompt: z.ZodString;
|
|
15
|
+
expected_output: z.ZodOptional<z.ZodString>;
|
|
16
|
+
files: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
17
|
+
expectations: z.ZodArray<z.ZodString, "many">;
|
|
18
|
+
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
19
|
+
id: z.ZodUnion<[z.ZodNumber, z.ZodString]>;
|
|
20
|
+
prompt: z.ZodString;
|
|
21
|
+
expected_output: z.ZodOptional<z.ZodString>;
|
|
22
|
+
files: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
23
|
+
expectations: z.ZodArray<z.ZodString, "many">;
|
|
24
|
+
}, z.ZodTypeAny, "passthrough">>, z.objectOutputType<{
|
|
25
|
+
id: z.ZodUnion<[z.ZodNumber, z.ZodString]>;
|
|
26
|
+
prompt: z.ZodString;
|
|
27
|
+
expected_output: z.ZodOptional<z.ZodString>;
|
|
28
|
+
files: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
29
|
+
expectations: z.ZodArray<z.ZodString, "many">;
|
|
30
|
+
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
31
|
+
id: z.ZodUnion<[z.ZodNumber, z.ZodString]>;
|
|
32
|
+
prompt: z.ZodString;
|
|
33
|
+
expected_output: z.ZodOptional<z.ZodString>;
|
|
34
|
+
files: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
35
|
+
expectations: z.ZodArray<z.ZodString, "many">;
|
|
36
|
+
}, z.ZodTypeAny, "passthrough">>;
|
|
37
|
+
export declare const EvalSuiteSchema: z.ZodObject<{
|
|
38
|
+
_comment: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
39
|
+
skill_name: z.ZodString;
|
|
40
|
+
evals: z.ZodArray<z.ZodEffects<z.ZodObject<{
|
|
41
|
+
id: z.ZodUnion<[z.ZodNumber, z.ZodString]>;
|
|
42
|
+
prompt: z.ZodString;
|
|
43
|
+
expected_output: z.ZodOptional<z.ZodString>;
|
|
44
|
+
files: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
45
|
+
expectations: z.ZodArray<z.ZodString, "many">;
|
|
46
|
+
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
47
|
+
id: z.ZodUnion<[z.ZodNumber, z.ZodString]>;
|
|
48
|
+
prompt: z.ZodString;
|
|
49
|
+
expected_output: z.ZodOptional<z.ZodString>;
|
|
50
|
+
files: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
51
|
+
expectations: z.ZodArray<z.ZodString, "many">;
|
|
52
|
+
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
53
|
+
id: z.ZodUnion<[z.ZodNumber, z.ZodString]>;
|
|
54
|
+
prompt: z.ZodString;
|
|
55
|
+
expected_output: z.ZodOptional<z.ZodString>;
|
|
56
|
+
files: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
57
|
+
expectations: z.ZodArray<z.ZodString, "many">;
|
|
58
|
+
}, z.ZodTypeAny, "passthrough">>, z.objectOutputType<{
|
|
59
|
+
id: z.ZodUnion<[z.ZodNumber, z.ZodString]>;
|
|
60
|
+
prompt: z.ZodString;
|
|
61
|
+
expected_output: z.ZodOptional<z.ZodString>;
|
|
62
|
+
files: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
63
|
+
expectations: z.ZodArray<z.ZodString, "many">;
|
|
64
|
+
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
65
|
+
id: z.ZodUnion<[z.ZodNumber, z.ZodString]>;
|
|
66
|
+
prompt: z.ZodString;
|
|
67
|
+
expected_output: z.ZodOptional<z.ZodString>;
|
|
68
|
+
files: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
69
|
+
expectations: z.ZodArray<z.ZodString, "many">;
|
|
70
|
+
}, z.ZodTypeAny, "passthrough">>, "many">;
|
|
71
|
+
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
72
|
+
_comment: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
73
|
+
skill_name: z.ZodString;
|
|
74
|
+
evals: z.ZodArray<z.ZodEffects<z.ZodObject<{
|
|
75
|
+
id: z.ZodUnion<[z.ZodNumber, z.ZodString]>;
|
|
76
|
+
prompt: z.ZodString;
|
|
77
|
+
expected_output: z.ZodOptional<z.ZodString>;
|
|
78
|
+
files: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
79
|
+
expectations: z.ZodArray<z.ZodString, "many">;
|
|
80
|
+
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
81
|
+
id: z.ZodUnion<[z.ZodNumber, z.ZodString]>;
|
|
82
|
+
prompt: z.ZodString;
|
|
83
|
+
expected_output: z.ZodOptional<z.ZodString>;
|
|
84
|
+
files: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
85
|
+
expectations: z.ZodArray<z.ZodString, "many">;
|
|
86
|
+
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
87
|
+
id: z.ZodUnion<[z.ZodNumber, z.ZodString]>;
|
|
88
|
+
prompt: z.ZodString;
|
|
89
|
+
expected_output: z.ZodOptional<z.ZodString>;
|
|
90
|
+
files: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
91
|
+
expectations: z.ZodArray<z.ZodString, "many">;
|
|
92
|
+
}, z.ZodTypeAny, "passthrough">>, z.objectOutputType<{
|
|
93
|
+
id: z.ZodUnion<[z.ZodNumber, z.ZodString]>;
|
|
94
|
+
prompt: z.ZodString;
|
|
95
|
+
expected_output: z.ZodOptional<z.ZodString>;
|
|
96
|
+
files: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
97
|
+
expectations: z.ZodArray<z.ZodString, "many">;
|
|
98
|
+
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
99
|
+
id: z.ZodUnion<[z.ZodNumber, z.ZodString]>;
|
|
100
|
+
prompt: z.ZodString;
|
|
101
|
+
expected_output: z.ZodOptional<z.ZodString>;
|
|
102
|
+
files: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
103
|
+
expectations: z.ZodArray<z.ZodString, "many">;
|
|
104
|
+
}, z.ZodTypeAny, "passthrough">>, "many">;
|
|
105
|
+
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
106
|
+
_comment: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
107
|
+
skill_name: z.ZodString;
|
|
108
|
+
evals: z.ZodArray<z.ZodEffects<z.ZodObject<{
|
|
109
|
+
id: z.ZodUnion<[z.ZodNumber, z.ZodString]>;
|
|
110
|
+
prompt: z.ZodString;
|
|
111
|
+
expected_output: z.ZodOptional<z.ZodString>;
|
|
112
|
+
files: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
113
|
+
expectations: z.ZodArray<z.ZodString, "many">;
|
|
114
|
+
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
115
|
+
id: z.ZodUnion<[z.ZodNumber, z.ZodString]>;
|
|
116
|
+
prompt: z.ZodString;
|
|
117
|
+
expected_output: z.ZodOptional<z.ZodString>;
|
|
118
|
+
files: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
119
|
+
expectations: z.ZodArray<z.ZodString, "many">;
|
|
120
|
+
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
121
|
+
id: z.ZodUnion<[z.ZodNumber, z.ZodString]>;
|
|
122
|
+
prompt: z.ZodString;
|
|
123
|
+
expected_output: z.ZodOptional<z.ZodString>;
|
|
124
|
+
files: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
125
|
+
expectations: z.ZodArray<z.ZodString, "many">;
|
|
126
|
+
}, z.ZodTypeAny, "passthrough">>, z.objectOutputType<{
|
|
127
|
+
id: z.ZodUnion<[z.ZodNumber, z.ZodString]>;
|
|
128
|
+
prompt: z.ZodString;
|
|
129
|
+
expected_output: z.ZodOptional<z.ZodString>;
|
|
130
|
+
files: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
131
|
+
expectations: z.ZodArray<z.ZodString, "many">;
|
|
132
|
+
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
133
|
+
id: z.ZodUnion<[z.ZodNumber, z.ZodString]>;
|
|
134
|
+
prompt: z.ZodString;
|
|
135
|
+
expected_output: z.ZodOptional<z.ZodString>;
|
|
136
|
+
files: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
137
|
+
expectations: z.ZodArray<z.ZodString, "many">;
|
|
138
|
+
}, z.ZodTypeAny, "passthrough">>, "many">;
|
|
139
|
+
}, z.ZodTypeAny, "passthrough">>;
|
|
140
|
+
export type EvalEntry = z.infer<typeof EvalEntrySchema>;
|
|
141
|
+
export type EvalSuite = z.infer<typeof EvalSuiteSchema>;
|
|
142
|
+
/** Parse + validate a skill-test eval suite. Throws {@link EvalInputError} on any problem. */
|
|
143
|
+
export declare function parseEvalSuite(jsonText: string): EvalSuite;
|
|
144
|
+
export interface StageEvalWorkspacesInput {
|
|
145
|
+
/** Parsed suite (Task 1). */
|
|
146
|
+
suite: EvalSuite;
|
|
147
|
+
/** Directory containing evals.json — the base for each eval's relative `files`. */
|
|
148
|
+
evalsDir: string;
|
|
149
|
+
/** `<harnessRoot>/workspaces` — per-eval dirs are created beneath it. */
|
|
150
|
+
workspacesRoot: string;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Materialize each eval's declared input `files` into `<workspacesRoot>/<id>/<relpath>`,
|
|
154
|
+
* preserving relative structure. Evals without `files` are skipped. Throws
|
|
155
|
+
* {@link EvalInputError} if a listed file does not exist (the eval cannot run without it).
|
|
156
|
+
* Returns `workspacesRoot`.
|
|
157
|
+
*/
|
|
158
|
+
export declare function stageEvalWorkspaces(input: StageEvalWorkspacesInput): string;
|
|
159
|
+
//# sourceMappingURL=eval-inputs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eval-inputs.d.ts","sourceRoot":"","sources":["../../src/skill-test/eval-inputs.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,wGAAwG;AACxG,qBAAa,cAAe,SAAQ,KAAK;gBAC3B,OAAO,EAAE,MAAM;CAI5B;AA4CD,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gCAmCxB,CAAC;AAEL,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gCAMZ,CAAC;AAEjB,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AACxD,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAExD,8FAA8F;AAC9F,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAmB1D;AAED,MAAM,WAAW,wBAAwB;IACvC,6BAA6B;IAC7B,KAAK,EAAE,SAAS,CAAC;IACjB,mFAAmF;IACnF,QAAQ,EAAE,MAAM,CAAC;IACjB,yEAAyE;IACzE,cAAc,EAAE,MAAM,CAAC;CACxB;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,wBAAwB,GAAG,MAAM,CAkC3E"}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { cpSync, existsSync } from 'node:fs';
|
|
2
|
+
import { mkdirSyncReal, safePath } from '@vibe-agent-toolkit/utils';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
/** Raised for any eval-input problem (bad JSON, schema failure, missing input file). Maps to exit 2. */
|
|
5
|
+
export class EvalInputError extends Error {
|
|
6
|
+
constructor(message) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.name = 'EvalInputError';
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* String eval ids name a per-eval working directory ({@link stageEvalWorkspaces}),
|
|
13
|
+
* so they must be safe path segments on every platform. Letters, digits, hyphen,
|
|
14
|
+
* and underscore only — this rejects `/`, `\`, `:`, spaces, `..`, and other
|
|
15
|
+
* filesystem-illegal characters that would otherwise fail (or behave
|
|
16
|
+
* inconsistently) on Windows. Descriptive adopter ids like `dollar-quote-recovery`
|
|
17
|
+
* pass unchanged; `year:extraction` is rejected at parse with a clear message
|
|
18
|
+
* instead of failing later as an opaque copy/escape error.
|
|
19
|
+
*/
|
|
20
|
+
const EVAL_ID_PATTERN = /^[A-Za-z0-9_-]+$/;
|
|
21
|
+
/** Fields VAT recognizes per eval. Unknown fields are allowed (passthrough); a
|
|
22
|
+
* near-miss of one of these is flagged as a likely typo (see superRefine). */
|
|
23
|
+
const RECOGNIZED_EVAL_FIELDS = ['id', 'prompt', 'expected_output', 'files', 'expectations'];
|
|
24
|
+
/**
|
|
25
|
+
* True when `key` is exactly one edit (insert/delete/substitute one char) from
|
|
26
|
+
* `target`. Used only to catch typos of recognized fields — deliberately a tiny
|
|
27
|
+
* single-edit check, not a general edit-distance routine, so it stays cheap and
|
|
28
|
+
* never fires on legitimately distinct adopter keys (`name`, `category`, `notes`).
|
|
29
|
+
*/
|
|
30
|
+
function isSingleEditAway(key, target) {
|
|
31
|
+
if (key === target)
|
|
32
|
+
return false;
|
|
33
|
+
const lk = key.length;
|
|
34
|
+
const lt = target.length;
|
|
35
|
+
if (Math.abs(lk - lt) > 1)
|
|
36
|
+
return false;
|
|
37
|
+
let i = 0;
|
|
38
|
+
while (i < lk && i < lt && key[i] === target[i])
|
|
39
|
+
i++;
|
|
40
|
+
if (lk === lt)
|
|
41
|
+
return key.slice(i + 1) === target.slice(i + 1); // substitution
|
|
42
|
+
if (lk > lt)
|
|
43
|
+
return key.slice(i + 1) === target.slice(i); // deletion from key
|
|
44
|
+
return key.slice(i) === target.slice(i + 1); // insertion into key
|
|
45
|
+
}
|
|
46
|
+
// evals.json is adopter-authored input that VAT *reads* — so per the project's
|
|
47
|
+
// Postel's Law (read the outside world liberally), we validate only the fields
|
|
48
|
+
// VAT actually consumes and pass everything else through untouched. `id` accepts
|
|
49
|
+
// a string OR an int: skill-creator's methodology encourages *descriptive* eval
|
|
50
|
+
// identifiers, and real adopter suites (e.g. dxa) use descriptive string ids plus
|
|
51
|
+
// adopter-owned metadata like `category` / top-level `_category_note`. The
|
|
52
|
+
// load-bearing fields stay required, so a typo in a REQUIRED field is caught by
|
|
53
|
+
// its absence; a near-miss typo of the OPTIONAL `files` field (which would
|
|
54
|
+
// otherwise be silently swallowed by passthrough) is caught by the superRefine.
|
|
55
|
+
export const EvalEntrySchema = z
|
|
56
|
+
.object({
|
|
57
|
+
id: z.union([
|
|
58
|
+
z.number().int(),
|
|
59
|
+
z
|
|
60
|
+
.string()
|
|
61
|
+
.min(1)
|
|
62
|
+
.regex(EVAL_ID_PATTERN, 'string eval id must contain only letters, digits, hyphen, or underscore (it names a working directory)'),
|
|
63
|
+
]),
|
|
64
|
+
prompt: z.string().min(1),
|
|
65
|
+
// Optional: a human-readable success description. The pass/fail verdict is
|
|
66
|
+
// always decided per `expectations` entry, so this is not load-bearing and
|
|
67
|
+
// (per Postel's Law) is not required — real adopter suites (e.g. dxa-consumption)
|
|
68
|
+
// grade with `expectations` alone. When present, the experimenter prompt feeds it
|
|
69
|
+
// to the grader as prose CONTEXT informing judgment (see experimenter-prompt.ts).
|
|
70
|
+
expected_output: z.string().min(1).optional(),
|
|
71
|
+
files: z.array(z.string().min(1)).optional(),
|
|
72
|
+
expectations: z.array(z.string().min(1)).min(1),
|
|
73
|
+
})
|
|
74
|
+
.passthrough()
|
|
75
|
+
.superRefine((entry, ctx) => {
|
|
76
|
+
for (const key of Object.keys(entry)) {
|
|
77
|
+
if (RECOGNIZED_EVAL_FIELDS.includes(key))
|
|
78
|
+
continue;
|
|
79
|
+
const near = RECOGNIZED_EVAL_FIELDS.find((field) => isSingleEditAway(key.toLowerCase(), field));
|
|
80
|
+
if (near !== undefined) {
|
|
81
|
+
ctx.addIssue({
|
|
82
|
+
code: z.ZodIssueCode.custom,
|
|
83
|
+
message: `unknown eval field "${key}" — did you mean "${near}"? (other custom fields are allowed and ignored)`,
|
|
84
|
+
path: [key],
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
export const EvalSuiteSchema = z
|
|
90
|
+
.object({
|
|
91
|
+
_comment: z.array(z.string()).optional(),
|
|
92
|
+
skill_name: z.string().min(1),
|
|
93
|
+
evals: z.array(EvalEntrySchema).min(1),
|
|
94
|
+
})
|
|
95
|
+
.passthrough();
|
|
96
|
+
/** Parse + validate a skill-test eval suite. Throws {@link EvalInputError} on any problem. */
|
|
97
|
+
export function parseEvalSuite(jsonText) {
|
|
98
|
+
let raw;
|
|
99
|
+
try {
|
|
100
|
+
raw = JSON.parse(jsonText);
|
|
101
|
+
}
|
|
102
|
+
catch (e) {
|
|
103
|
+
throw new EvalInputError(`evals.json is not valid JSON: ${e.message}`);
|
|
104
|
+
}
|
|
105
|
+
const result = EvalSuiteSchema.safeParse(raw);
|
|
106
|
+
if (!result.success) {
|
|
107
|
+
throw new EvalInputError(`evals.json failed schema validation: ${result.error.message}`);
|
|
108
|
+
}
|
|
109
|
+
// Compare ids as strings: each id names a working directory via String(id),
|
|
110
|
+
// so a numeric `1` and a string `"1"` would collide on disk even though they
|
|
111
|
+
// are distinct JS values. Dedup on the stringified form to catch that.
|
|
112
|
+
const ids = result.data.evals.map((e) => String(e.id));
|
|
113
|
+
if (new Set(ids).size !== ids.length) {
|
|
114
|
+
throw new EvalInputError('eval ids must be unique within a suite (ids are compared as strings, so 1 and "1" collide)');
|
|
115
|
+
}
|
|
116
|
+
return result.data;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Materialize each eval's declared input `files` into `<workspacesRoot>/<id>/<relpath>`,
|
|
120
|
+
* preserving relative structure. Evals without `files` are skipped. Throws
|
|
121
|
+
* {@link EvalInputError} if a listed file does not exist (the eval cannot run without it).
|
|
122
|
+
* Returns `workspacesRoot`.
|
|
123
|
+
*/
|
|
124
|
+
export function stageEvalWorkspaces(input) {
|
|
125
|
+
for (const entry of input.suite.evals) {
|
|
126
|
+
if (entry.files === undefined || entry.files.length === 0)
|
|
127
|
+
continue;
|
|
128
|
+
const evalWorkspace = safePath.joinUnderRoot(input.workspacesRoot, String(entry.id));
|
|
129
|
+
for (const rel of entry.files) {
|
|
130
|
+
// Containment first: a `rel` that escapes evalsDir or the workspace is a
|
|
131
|
+
// genuine "escapes the eval directory" problem and is reported as such.
|
|
132
|
+
let src;
|
|
133
|
+
let dest;
|
|
134
|
+
try {
|
|
135
|
+
src = safePath.joinUnderRoot(input.evalsDir, rel);
|
|
136
|
+
dest = safePath.joinUnderRoot(evalWorkspace, rel);
|
|
137
|
+
}
|
|
138
|
+
catch (err) {
|
|
139
|
+
throw new EvalInputError(`eval ${entry.id} declares input file "${rel}" that escapes the eval directory: ${err.message}`);
|
|
140
|
+
}
|
|
141
|
+
// eslint-disable-next-line security/detect-non-literal-fs-filename -- src is contained under evalsDir via joinUnderRoot; suite is developer-authored
|
|
142
|
+
if (!existsSync(src)) {
|
|
143
|
+
throw new EvalInputError(`eval ${entry.id} declares input file "${rel}" but it is absent at ${src}`);
|
|
144
|
+
}
|
|
145
|
+
// Copy failures (permissions, illegal filename on the host, disk) are
|
|
146
|
+
// reported accurately rather than mislabeled as a containment escape.
|
|
147
|
+
try {
|
|
148
|
+
mkdirSyncReal(safePath.join(dest, '..'), { recursive: true });
|
|
149
|
+
cpSync(src, dest, { recursive: true });
|
|
150
|
+
}
|
|
151
|
+
catch (err) {
|
|
152
|
+
throw new EvalInputError(`eval ${entry.id} failed to stage input file "${rel}" into the workspace: ${err.message}`);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return input.workspacesRoot;
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=eval-inputs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eval-inputs.js","sourceRoot":"","sources":["../../src/skill-test/eval-inputs.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"evals-template.d.ts","sourceRoot":"","sources":["../../src/skill-test/evals-template.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAMH,2EAA2E;AAC3E,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"evals-template.d.ts","sourceRoot":"","sources":["../../src/skill-test/evals-template.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAMH,2EAA2E;AAC3E,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAsC5D;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAW/E"}
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* Both are stripped by the user as they fill in real evals; the harness does not
|
|
13
13
|
* read `_comment`.
|
|
14
14
|
*/
|
|
15
|
-
import { writeFileSync } from 'node:fs';
|
|
15
|
+
import { existsSync, writeFileSync } from 'node:fs';
|
|
16
16
|
import { mkdirSyncReal, safePath } from '@vibe-agent-toolkit/utils';
|
|
17
17
|
/** Build the annotated evals.json template text for a given skill name. */
|
|
18
18
|
export function buildEvalsTemplate(skillName) {
|
|
@@ -21,21 +21,33 @@ export function buildEvalsTemplate(skillName) {
|
|
|
21
21
|
'This is a starter evals.json scaffolded by `vat skill test`.',
|
|
22
22
|
'Replace the placeholder eval below with one entry per behavior you want to verify.',
|
|
23
23
|
'Fields per eval:',
|
|
24
|
-
' id — unique integer
|
|
25
|
-
'
|
|
26
|
-
'
|
|
27
|
-
'
|
|
28
|
-
'
|
|
29
|
-
'
|
|
24
|
+
' id — unique identifier: an integer (1) or a short descriptive',
|
|
25
|
+
' string ("year-extraction"). Descriptive ids read better in results.',
|
|
26
|
+
' A string id names a working directory, so use only letters,',
|
|
27
|
+
' digits, hyphen, or underscore (no spaces, slashes, or colons).',
|
|
28
|
+
' prompt — the task, written the way a REAL user would phrase it. The executor',
|
|
29
|
+
' is NOT told it is being tested, so do not mention testing/evals here.',
|
|
30
|
+
' expected_output — OPTIONAL human-readable description of what a correct result looks like',
|
|
31
|
+
' files — OPTIONAL input files (paths relative to THIS evals.json dir),',
|
|
32
|
+
' staged into a per-eval working directory the executor operates on',
|
|
33
|
+
' expectations — verifiable statements the grader checks. Make them DISCRIMINATING:',
|
|
34
|
+
' a wrong or hallucinated output should FAIL them (presence != correctness).',
|
|
35
|
+
' Include negative assertions too, e.g. "does NOT claim every row reconciles".',
|
|
36
|
+
' category — OPTIONAL label you choose to group evals (e.g. "recognition",',
|
|
37
|
+
' "guidance", "recovery"). VAT ignores it; it is for your own organization.',
|
|
38
|
+
'Aim for at least 3 evals covering real scenarios. Delete this _comment field once filled in, then re-run.',
|
|
30
39
|
],
|
|
31
40
|
skill_name: skillName,
|
|
32
41
|
evals: [
|
|
33
42
|
{
|
|
34
43
|
id: 1,
|
|
35
|
-
|
|
44
|
+
category: 'TODO: optional grouping label, or remove this field',
|
|
45
|
+
prompt: 'TODO: a realistic task a user would actually ask this skill to perform.',
|
|
36
46
|
expected_output: 'TODO: describe what a correct result looks like.',
|
|
47
|
+
files: [],
|
|
37
48
|
expectations: [
|
|
38
|
-
'TODO: a verifiable statement
|
|
49
|
+
'TODO: a verifiable statement a correct output satisfies, e.g. "The output reports a total of 29500".',
|
|
50
|
+
'TODO: a negative assertion a wrong output would trip, e.g. "The output does NOT claim the file is empty".',
|
|
39
51
|
],
|
|
40
52
|
},
|
|
41
53
|
],
|
|
@@ -49,8 +61,13 @@ export function buildEvalsTemplate(skillName) {
|
|
|
49
61
|
export function writeEvalsTemplate(evalsPath, skillName) {
|
|
50
62
|
const parent = safePath.join(evalsPath, '..');
|
|
51
63
|
mkdirSyncReal(parent, { recursive: true });
|
|
64
|
+
// Defensive: never clobber an authored eval suite. Callers only reach here when
|
|
65
|
+
// the suite is absent, but guard so a stray call can never destroy real evals.
|
|
52
66
|
// eslint-disable-next-line security/detect-non-literal-fs-filename -- our own resolved scaffold path
|
|
53
|
-
|
|
67
|
+
if (!existsSync(evalsPath)) {
|
|
68
|
+
// eslint-disable-next-line security/detect-non-literal-fs-filename -- our own resolved scaffold path
|
|
69
|
+
writeFileSync(evalsPath, buildEvalsTemplate(skillName), 'utf8');
|
|
70
|
+
}
|
|
54
71
|
return evalsPath;
|
|
55
72
|
}
|
|
56
73
|
//# sourceMappingURL=evals-template.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"evals-template.js","sourceRoot":"","sources":["../../src/skill-test/evals-template.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"evals-template.js","sourceRoot":"","sources":["../../src/skill-test/evals-template.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAEpD,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAEpE,2EAA2E;AAC3E,MAAM,UAAU,kBAAkB,CAAC,SAAiB;IAClD,MAAM,QAAQ,GAAG;QACf,QAAQ,EAAE;YACR,8DAA8D;YAC9D,oFAAoF;YACpF,kBAAkB;YAClB,8EAA8E;YAC9E,yFAAyF;YACzF,iFAAiF;YACjF,oFAAoF;YACpF,yFAAyF;YACzF,2FAA2F;YAC3F,6FAA6F;YAC7F,mFAAmF;YACnF,uFAAuF;YACvF,wFAAwF;YACxF,gGAAgG;YAChG,kGAAkG;YAClG,mFAAmF;YACnF,+FAA+F;YAC/F,2GAA2G;SAC5G;QACD,UAAU,EAAE,SAAS;QACrB,KAAK,EAAE;YACL;gBACE,EAAE,EAAE,CAAC;gBACL,QAAQ,EAAE,qDAAqD;gBAC/D,MAAM,EAAE,yEAAyE;gBACjF,eAAe,EAAE,kDAAkD;gBACnE,KAAK,EAAE,EAAE;gBACT,YAAY,EAAE;oBACZ,sGAAsG;oBACtG,2GAA2G;iBAC5G;aACF;SACF;KACF,CAAC;IACF,OAAO,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC;AAClD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,SAAiB,EAAE,SAAiB;IACrE,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IAC9C,aAAa,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3C,gFAAgF;IAChF,+EAA+E;IAC/E,qGAAqG;IACrG,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC3B,qGAAqG;QACrG,aAAa,CAAC,SAAS,EAAE,kBAAkB,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC,CAAC;IAClE,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
|
@@ -4,17 +4,48 @@ export declare const SkillTestExitCode: {
|
|
|
4
4
|
readonly Internal: 1;
|
|
5
5
|
readonly Preflight: 2;
|
|
6
6
|
readonly Bootstrap: 3;
|
|
7
|
+
/**
|
|
8
|
+
* At least one eval FAILED and the caller opted into eval-gating via
|
|
9
|
+
* `--fail-on-eval-failure`. Distinct from the harness-broke codes (1/2):
|
|
10
|
+
* the harness ran to completion and produced a valid grading.json — the
|
|
11
|
+
* skill's expectations simply did not all pass. Returned DIRECTLY by the
|
|
12
|
+
* harness verdict (see verdictExitCode in run-harness.ts), not via
|
|
13
|
+
* mapErrorToExitCode, because it is an outcome, not a thrown error.
|
|
14
|
+
*/
|
|
15
|
+
readonly EvalFailure: 4;
|
|
7
16
|
};
|
|
8
17
|
export type SkillTestExitCodeValue = (typeof SkillTestExitCode)[keyof typeof SkillTestExitCode];
|
|
9
18
|
/**
|
|
10
19
|
* A required input is absent in a way vat can scaffold (missing evals.json).
|
|
11
|
-
* Exit 3, NOT a failure. `expectedPath` is the
|
|
12
|
-
*
|
|
20
|
+
* Exit 3, NOT a failure. `expectedPath` is the persistent location of the
|
|
21
|
+
* annotated starter template.
|
|
22
|
+
*
|
|
23
|
+
* In a real run the harness has already written that template, and the message
|
|
24
|
+
* says so. Under `--dry-run` nothing is written — a dry run must never touch the
|
|
25
|
+
* filesystem — so the message instead describes what a real run *would* scaffold
|
|
26
|
+
* and where, while surfacing the same exit-3 "bootstrap needed" signal.
|
|
13
27
|
*/
|
|
14
28
|
export declare class BootstrapNeededError extends Error {
|
|
15
29
|
readonly expectedPath: string;
|
|
16
30
|
readonly exitCode: 3;
|
|
17
|
-
constructor(expectedPath: string
|
|
31
|
+
constructor(expectedPath: string, opts?: {
|
|
32
|
+
dryRun?: boolean;
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
/** Thrown when building a declared skill (pool packageSkill or plugin build) fails. Exit 2 (preflight class). */
|
|
36
|
+
export declare class SkillBuildError extends Error {
|
|
37
|
+
readonly exitCode: 2;
|
|
38
|
+
constructor(message: string);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* The §12 security acknowledgment is required but absent, thrown BEFORE any
|
|
42
|
+
* build/pre-stage command (which executes untrusted repo code) runs for a
|
|
43
|
+
* buildable subject. Exit 2 (preflight class). Mirrors the harness Step-6 ack
|
|
44
|
+
* message wording so the two enforcement points read identically.
|
|
45
|
+
*/
|
|
46
|
+
export declare class SecurityAckError extends Error {
|
|
47
|
+
readonly exitCode: 2;
|
|
48
|
+
constructor();
|
|
18
49
|
}
|
|
19
50
|
/** Internal harness failure (incl. experimenter exiting without valid grading.json). Exit 1. */
|
|
20
51
|
export declare class InternalHarnessError extends Error {
|
|
@@ -25,8 +56,16 @@ export declare class InternalHarnessError extends Error {
|
|
|
25
56
|
* Map any thrown error to the process exit code. Errors that carry their own
|
|
26
57
|
* `exitCode` (Bootstrap/Auth/HarnessLocation/Internal) are authoritative;
|
|
27
58
|
* a PromptInvariantError is a user-correctable preflight problem (a supplied
|
|
28
|
-
* prompt override is missing a required safety instruction) → 2;
|
|
29
|
-
* is a
|
|
59
|
+
* prompt override is missing a required safety instruction) → 2; a BuildHookError
|
|
60
|
+
* is a pre-stage build failure → 2; a SkillBuildError is a declared-skill build
|
|
61
|
+
* failure → 2; a SecurityAckError is a missing security ack before a build → 2;
|
|
62
|
+
* an UnknownEnvTokenError is a bad ${token} in a
|
|
63
|
+
* declared env value → 2; GradingSkewError (parse failure) and GradingNonceError
|
|
64
|
+
* (forged/mismatched grading nonce) are both → 1; everything unknown → 1.
|
|
65
|
+
*
|
|
66
|
+
* Note: SkillTestExitCode.EvalFailure (4) is NOT produced here — it is an
|
|
67
|
+
* outcome of a completed run (an eval failed under `--fail-on-eval-failure`),
|
|
68
|
+
* not a thrown error, so the harness returns it directly (see verdictExitCode).
|
|
30
69
|
*/
|
|
31
70
|
export declare function mapErrorToExitCode(err: unknown): number;
|
|
32
71
|
//# sourceMappingURL=exit-codes.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"exit-codes.d.ts","sourceRoot":"","sources":["../../src/skill-test/exit-codes.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"exit-codes.d.ts","sourceRoot":"","sources":["../../src/skill-test/exit-codes.ts"],"names":[],"mappings":"AAQA,kDAAkD;AAClD,eAAO,MAAM,iBAAiB;;;;;IAK5B;;;;;;;OAOG;;CAEK,CAAC;AAEX,MAAM,MAAM,sBAAsB,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,OAAO,iBAAiB,CAAC,CAAC;AAEhG;;;;;;;;;GASG;AACH,qBAAa,oBAAqB,SAAQ,KAAK;aAEjB,YAAY,EAAE,MAAM;IADhD,QAAQ,CAAC,QAAQ,EAAG,CAAC,CAAU;gBACH,YAAY,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE;CAQ9E;AAED,iHAAiH;AACjH,qBAAa,eAAgB,SAAQ,KAAK;IACxC,QAAQ,CAAC,QAAQ,EAAG,CAAC,CAAU;gBACnB,OAAO,EAAE,MAAM;CAI5B;AAED;;;;;GAKG;AACH,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,QAAQ,CAAC,QAAQ,EAAG,CAAC,CAAU;;CAKhC;AAED,gGAAgG;AAChG,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,QAAQ,CAAC,QAAQ,EAAG,CAAC,CAAU;gBACnB,OAAO,EAAE,MAAM;CAI5B;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAqBvD"}
|