@vibe-agent-toolkit/agent-skills 0.1.42 → 0.2.0-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 +5 -5
- package/dist/builder.d.ts.map +1 -1
- package/dist/builder.js +7 -17
- package/dist/builder.js.map +1 -1
- package/dist/content-type-routing.d.ts +32 -0
- package/dist/content-type-routing.d.ts.map +1 -1
- package/dist/content-type-routing.js +23 -0
- package/dist/content-type-routing.js.map +1 -1
- package/dist/files-config.d.ts +34 -1
- package/dist/files-config.d.ts.map +1 -1
- package/dist/files-config.js +277 -39
- package/dist/files-config.js.map +1 -1
- package/dist/fs-attribution.d.ts +45 -0
- package/dist/fs-attribution.d.ts.map +1 -0
- package/dist/fs-attribution.js +57 -0
- package/dist/fs-attribution.js.map +1 -0
- package/dist/import.d.ts.map +1 -1
- package/dist/import.js +0 -4
- package/dist/import.js.map +1 -1
- package/dist/index.d.ts +13 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +25 -7
- package/dist/index.js.map +1 -1
- package/dist/inventory/detectors/declared-but-missing.d.ts +1 -1
- package/dist/inventory/detectors/declared-but-missing.d.ts.map +1 -1
- package/dist/inventory/detectors/marketplace-source-missing.d.ts +1 -1
- package/dist/inventory/detectors/marketplace-source-missing.d.ts.map +1 -1
- package/dist/inventory/detectors/present-but-undeclared.d.ts +1 -1
- package/dist/inventory/detectors/present-but-undeclared.d.ts.map +1 -1
- package/dist/inventory/detectors/reference-target-missing.d.ts +1 -1
- package/dist/inventory/detectors/reference-target-missing.d.ts.map +1 -1
- package/dist/inventory/index.d.ts +1 -1
- package/dist/inventory/index.d.ts.map +1 -1
- package/dist/inventory/index.js +1 -1
- package/dist/inventory/index.js.map +1 -1
- package/dist/inventory/serialize.d.ts +4 -4
- package/dist/inventory/serialize.d.ts.map +1 -1
- package/dist/inventory/serialize.js +6 -6
- package/dist/inventory/serialize.js.map +1 -1
- package/dist/inventory/types.d.ts +8 -0
- package/dist/inventory/types.d.ts.map +1 -1
- package/dist/inventory/types.js.map +1 -1
- package/dist/link-graph-members.d.ts +18 -0
- package/dist/link-graph-members.d.ts.map +1 -0
- package/dist/link-graph-members.js +18 -0
- package/dist/link-graph-members.js.map +1 -0
- package/dist/parsers/frontmatter-parser.d.ts.map +1 -1
- package/dist/parsers/frontmatter-parser.js +30 -6
- package/dist/parsers/frontmatter-parser.js.map +1 -1
- package/dist/plugin-distribution-layout.d.ts +70 -6
- package/dist/plugin-distribution-layout.d.ts.map +1 -1
- package/dist/plugin-distribution-layout.js +84 -11
- package/dist/plugin-distribution-layout.js.map +1 -1
- package/dist/post-build-checks.d.ts +38 -1
- package/dist/post-build-checks.d.ts.map +1 -1
- package/dist/post-build-checks.js +68 -17
- package/dist/post-build-checks.js.map +1 -1
- package/dist/projection/skill-extent.d.ts +247 -0
- package/dist/projection/skill-extent.d.ts.map +1 -0
- package/dist/projection/skill-extent.js +560 -0
- package/dist/projection/skill-extent.js.map +1 -0
- package/dist/schemas/agent-skill-frontmatter.js +1 -1
- package/dist/schemas/agent-skill-frontmatter.js.map +1 -1
- package/dist/schemas/allowed-tools.d.ts +31 -0
- package/dist/schemas/allowed-tools.d.ts.map +1 -0
- package/dist/schemas/allowed-tools.js +88 -0
- package/dist/schemas/allowed-tools.js.map +1 -0
- package/dist/schemas/index.d.ts +1 -0
- package/dist/schemas/index.d.ts.map +1 -1
- package/dist/schemas/index.js +1 -0
- package/dist/schemas/index.js.map +1 -1
- package/dist/schemas/installed-plugins-registry.d.ts.map +1 -1
- package/dist/schemas/installed-plugins-registry.js +7 -1
- package/dist/schemas/installed-plugins-registry.js.map +1 -1
- package/dist/schemas/marketplace-manifest.d.ts.map +1 -1
- package/dist/schemas/marketplace-manifest.js +17 -6
- package/dist/schemas/marketplace-manifest.js.map +1 -1
- package/dist/skill-identity.d.ts +18 -3
- package/dist/skill-identity.d.ts.map +1 -1
- package/dist/skill-identity.js +25 -6
- package/dist/skill-identity.js.map +1 -1
- package/dist/skill-packager.d.ts +144 -20
- package/dist/skill-packager.d.ts.map +1 -1
- package/dist/skill-packager.js +447 -105
- package/dist/skill-packager.js.map +1 -1
- package/dist/skill-source/content-hash.d.ts.map +1 -1
- package/dist/skill-source/content-hash.js +21 -10
- package/dist/skill-source/content-hash.js.map +1 -1
- package/dist/skill-source/fetch-cache.d.ts.map +1 -1
- package/dist/skill-source/fetch-cache.js +0 -5
- package/dist/skill-source/fetch-cache.js.map +1 -1
- package/dist/skill-source/git-clone.d.ts +1 -1
- package/dist/skill-source/git-clone.d.ts.map +1 -1
- package/dist/skill-source/git-clone.js +10 -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 +2 -2
- package/dist/skill-source/sources/url-source.js.map +1 -1
- package/dist/skill-source/stage.d.ts.map +1 -1
- package/dist/skill-source/stage.js +0 -6
- package/dist/skill-source/stage.js.map +1 -1
- package/dist/skill-test/baseline-delta.d.ts +1575 -0
- package/dist/skill-test/baseline-delta.d.ts.map +1 -0
- package/dist/skill-test/baseline-delta.js +272 -0
- package/dist/skill-test/baseline-delta.js.map +1 -0
- package/dist/skill-test/baseline-integrity.d.ts +944 -0
- package/dist/skill-test/baseline-integrity.d.ts.map +1 -0
- package/dist/skill-test/baseline-integrity.js +3090 -0
- package/dist/skill-test/baseline-integrity.js.map +1 -0
- package/dist/skill-test/build-hook.d.ts +3 -2
- package/dist/skill-test/build-hook.d.ts.map +1 -1
- package/dist/skill-test/build-hook.js +4 -5
- package/dist/skill-test/build-hook.js.map +1 -1
- package/dist/skill-test/configure-writer.js +1 -1
- package/dist/skill-test/configure-writer.js.map +1 -1
- package/dist/skill-test/declared-env.d.ts +5 -4
- package/dist/skill-test/declared-env.d.ts.map +1 -1
- package/dist/skill-test/declared-env.js +8 -9
- package/dist/skill-test/declared-env.js.map +1 -1
- package/dist/skill-test/eval-executor.d.ts +21 -5
- package/dist/skill-test/eval-executor.d.ts.map +1 -1
- package/dist/skill-test/eval-executor.js +6 -6
- package/dist/skill-test/eval-executor.js.map +1 -1
- package/dist/skill-test/eval-fragment.d.ts +106 -28
- package/dist/skill-test/eval-fragment.d.ts.map +1 -1
- package/dist/skill-test/eval-fragment.js +78 -16
- package/dist/skill-test/eval-fragment.js.map +1 -1
- package/dist/skill-test/eval-grader.d.ts +65 -7
- package/dist/skill-test/eval-grader.d.ts.map +1 -1
- package/dist/skill-test/eval-grader.js +263 -64
- package/dist/skill-test/eval-grader.js.map +1 -1
- package/dist/skill-test/eval-inputs.d.ts +110 -8
- package/dist/skill-test/eval-inputs.d.ts.map +1 -1
- package/dist/skill-test/eval-inputs.js +177 -22
- package/dist/skill-test/eval-inputs.js.map +1 -1
- package/dist/skill-test/eval-lint.d.ts +17 -4
- package/dist/skill-test/eval-lint.d.ts.map +1 -1
- package/dist/skill-test/eval-lint.js +22 -9
- package/dist/skill-test/eval-lint.js.map +1 -1
- package/dist/skill-test/eval-suite-isolation.d.ts.map +1 -1
- package/dist/skill-test/eval-suite-isolation.js +8 -5
- package/dist/skill-test/eval-suite-isolation.js.map +1 -1
- package/dist/skill-test/evals-template.d.ts +1 -1
- package/dist/skill-test/evals-template.d.ts.map +1 -1
- package/dist/skill-test/evals-template.js +1 -3
- package/dist/skill-test/evals-template.js.map +1 -1
- package/dist/skill-test/executor-prompt.d.ts +15 -7
- package/dist/skill-test/executor-prompt.d.ts.map +1 -1
- package/dist/skill-test/executor-prompt.js +10 -7
- package/dist/skill-test/executor-prompt.js.map +1 -1
- package/dist/skill-test/failure-reason.d.ts +113 -0
- package/dist/skill-test/failure-reason.d.ts.map +1 -0
- package/dist/skill-test/failure-reason.js +124 -0
- package/dist/skill-test/failure-reason.js.map +1 -0
- package/dist/skill-test/fragment-merge.d.ts +3 -20
- package/dist/skill-test/fragment-merge.d.ts.map +1 -1
- package/dist/skill-test/fragment-merge.js +67 -8
- package/dist/skill-test/fragment-merge.js.map +1 -1
- package/dist/skill-test/grader-prompt.d.ts +29 -9
- package/dist/skill-test/grader-prompt.d.ts.map +1 -1
- package/dist/skill-test/grader-prompt.js +264 -68
- package/dist/skill-test/grader-prompt.js.map +1 -1
- package/dist/skill-test/grader-text.d.ts +145 -0
- package/dist/skill-test/grader-text.d.ts.map +1 -0
- package/dist/skill-test/grader-text.js +410 -0
- package/dist/skill-test/grader-text.js.map +1 -0
- package/dist/skill-test/grading-adapter.d.ts +38 -2
- package/dist/skill-test/grading-adapter.d.ts.map +1 -1
- package/dist/skill-test/grading-adapter.js +57 -9
- package/dist/skill-test/grading-adapter.js.map +1 -1
- package/dist/skill-test/grading-schema.d.ts +160 -5
- package/dist/skill-test/grading-schema.d.ts.map +1 -1
- package/dist/skill-test/grading-schema.js +66 -7
- package/dist/skill-test/grading-schema.js.map +1 -1
- package/dist/skill-test/harness-location.d.ts +3 -2
- package/dist/skill-test/harness-location.d.ts.map +1 -1
- package/dist/skill-test/harness-location.js +5 -16
- package/dist/skill-test/harness-location.js.map +1 -1
- package/dist/skill-test/index.d.ts +2 -2
- package/dist/skill-test/index.d.ts.map +1 -1
- package/dist/skill-test/index.js +2 -2
- package/dist/skill-test/index.js.map +1 -1
- package/dist/skill-test/lock.d.ts +58 -1
- package/dist/skill-test/lock.d.ts.map +1 -1
- package/dist/skill-test/lock.js +78 -6
- package/dist/skill-test/lock.js.map +1 -1
- package/dist/skill-test/pipeline.d.ts +19 -1
- package/dist/skill-test/pipeline.d.ts.map +1 -1
- package/dist/skill-test/pipeline.js +21 -10
- package/dist/skill-test/pipeline.js.map +1 -1
- package/dist/skill-test/preflight.d.ts +1 -1
- package/dist/skill-test/preflight.d.ts.map +1 -1
- package/dist/skill-test/preflight.js +59 -16
- package/dist/skill-test/preflight.js.map +1 -1
- package/dist/skill-test/prompt-invariants.d.ts +4 -2
- package/dist/skill-test/prompt-invariants.d.ts.map +1 -1
- package/dist/skill-test/prompt-invariants.js +5 -4
- package/dist/skill-test/prompt-invariants.js.map +1 -1
- package/dist/skill-test/run-harness.d.ts +665 -85
- package/dist/skill-test/run-harness.d.ts.map +1 -1
- package/dist/skill-test/run-harness.js +1522 -237
- package/dist/skill-test/run-harness.js.map +1 -1
- package/dist/skill-test/staging.d.ts +20 -8
- package/dist/skill-test/staging.d.ts.map +1 -1
- package/dist/skill-test/staging.js +25 -18
- package/dist/skill-test/staging.js.map +1 -1
- package/dist/skill-test/tier-plan.d.ts +1 -1
- package/dist/skill-test/tier-plan.js +1 -1
- package/dist/skill-test/tool-eval-schema.d.ts +6 -6
- package/dist/skill-test/tool-eval-schema.js +2 -2
- package/dist/skill-test/vendor-manifest.d.ts +2 -1
- package/dist/skill-test/vendor-manifest.d.ts.map +1 -1
- package/dist/skill-test/vendor-manifest.js +10 -10
- package/dist/skill-test/vendor-manifest.js.map +1 -1
- package/dist/test-input.d.ts +59 -8
- package/dist/test-input.d.ts.map +1 -1
- package/dist/test-input.js +64 -19
- package/dist/test-input.js.map +1 -1
- package/dist/validators/agent-instruction-presence.d.ts +1 -1
- package/dist/validators/agent-instruction-presence.d.ts.map +1 -1
- package/dist/validators/agent-instruction-presence.js +45 -2
- package/dist/validators/agent-instruction-presence.js.map +1 -1
- package/dist/validators/bundled-resource-link-detection.d.ts +6 -4
- package/dist/validators/bundled-resource-link-detection.d.ts.map +1 -1
- package/dist/validators/bundled-resource-link-detection.js +39 -39
- package/dist/validators/bundled-resource-link-detection.js.map +1 -1
- package/dist/validators/compat-detectors.d.ts +18 -1
- package/dist/validators/compat-detectors.d.ts.map +1 -1
- package/dist/validators/compat-detectors.js +47 -20
- package/dist/validators/compat-detectors.js.map +1 -1
- package/dist/validators/cross-skill-dependency-detection.d.ts +1 -1
- package/dist/validators/cross-skill-dependency-detection.d.ts.map +1 -1
- package/dist/validators/cross-skill-dependency-detection.js +1 -1
- package/dist/validators/cross-skill-dependency-detection.js.map +1 -1
- package/dist/validators/description-style-detection.d.ts +1 -1
- package/dist/validators/description-style-detection.d.ts.map +1 -1
- package/dist/validators/description-style-detection.js +1 -1
- package/dist/validators/description-style-detection.js.map +1 -1
- package/dist/validators/format-detection.d.ts +3 -0
- package/dist/validators/format-detection.d.ts.map +1 -1
- package/dist/validators/format-detection.js +41 -26
- package/dist/validators/format-detection.js.map +1 -1
- package/dist/validators/frontmatter-validation.d.ts +1 -1
- package/dist/validators/frontmatter-validation.d.ts.map +1 -1
- package/dist/validators/frontmatter-validation.js +2 -2
- package/dist/validators/frontmatter-validation.js.map +1 -1
- package/dist/validators/imperative-body-detection.d.ts +1 -1
- package/dist/validators/imperative-body-detection.d.ts.map +1 -1
- package/dist/validators/imperative-body-detection.js +1 -1
- package/dist/validators/imperative-body-detection.js.map +1 -1
- package/dist/validators/index.d.ts +1 -1
- package/dist/validators/index.d.ts.map +1 -1
- package/dist/validators/kebab-case-detection.d.ts +1 -1
- package/dist/validators/kebab-case-detection.d.ts.map +1 -1
- package/dist/validators/kebab-case-detection.js +1 -1
- package/dist/validators/kebab-case-detection.js.map +1 -1
- package/dist/validators/marketplace-validator.d.ts.map +1 -1
- package/dist/validators/marketplace-validator.js +7 -2
- package/dist/validators/marketplace-validator.js.map +1 -1
- package/dist/validators/mcp-tool-qualification.d.ts +158 -0
- package/dist/validators/mcp-tool-qualification.d.ts.map +1 -0
- package/dist/validators/mcp-tool-qualification.js +467 -0
- package/dist/validators/mcp-tool-qualification.js.map +1 -0
- package/dist/validators/packaged-size-limit.d.ts +296 -0
- package/dist/validators/packaged-size-limit.d.ts.map +1 -0
- package/dist/validators/packaged-size-limit.js +492 -0
- package/dist/validators/packaged-size-limit.js.map +1 -0
- package/dist/validators/packaging-validator.d.ts +149 -10
- package/dist/validators/packaging-validator.d.ts.map +1 -1
- package/dist/validators/packaging-validator.js +371 -55
- package/dist/validators/packaging-validator.js.map +1 -1
- package/dist/validators/plugin-hosted-shape.d.ts +4 -2
- package/dist/validators/plugin-hosted-shape.d.ts.map +1 -1
- package/dist/validators/plugin-hosted-shape.js +6 -7
- package/dist/validators/plugin-hosted-shape.js.map +1 -1
- package/dist/validators/plugin-recommended-fields.d.ts +1 -1
- package/dist/validators/plugin-recommended-fields.d.ts.map +1 -1
- package/dist/validators/plugin-recommended-fields.js +1 -1
- package/dist/validators/plugin-recommended-fields.js.map +1 -1
- package/dist/validators/referenced-path-missing.d.ts +211 -0
- package/dist/validators/referenced-path-missing.d.ts.map +1 -0
- package/dist/validators/referenced-path-missing.js +378 -0
- package/dist/validators/referenced-path-missing.js.map +1 -0
- package/dist/validators/registry-validator.d.ts.map +1 -1
- package/dist/validators/registry-validator.js +1 -2
- package/dist/validators/registry-validator.js.map +1 -1
- package/dist/validators/rule-engine/index.d.ts +1 -1
- package/dist/validators/rule-engine/rule-context.d.ts +20 -3
- package/dist/validators/rule-engine/rule-context.d.ts.map +1 -1
- package/dist/validators/rule-engine/rule-context.js +3 -1
- package/dist/validators/rule-engine/rule-context.js.map +1 -1
- package/dist/validators/rule-engine/rule-engine.d.ts +2 -2
- package/dist/validators/rule-engine/rule-engine.d.ts.map +1 -1
- package/dist/validators/rule-engine/rule-engine.js +52 -13
- package/dist/validators/rule-engine/rule-engine.js.map +1 -1
- package/dist/validators/skill-validator.d.ts.map +1 -1
- package/dist/validators/skill-validator.js +91 -54
- package/dist/validators/skill-validator.js.map +1 -1
- package/dist/validators/source-only-codes.js +1 -1
- package/dist/validators/source-only-codes.js.map +1 -1
- package/dist/validators/types.d.ts +21 -1
- package/dist/validators/types.d.ts.map +1 -1
- package/dist/validators/unified-validator.d.ts.map +1 -1
- package/dist/validators/unified-validator.js +4 -5
- package/dist/validators/unified-validator.js.map +1 -1
- package/dist/validators/validation-rules.d.ts +4 -4
- package/dist/validators/validation-rules.d.ts.map +1 -1
- package/dist/validators/validation-rules.js +9 -38
- package/dist/validators/validation-rules.js.map +1 -1
- package/dist/validators/walker-to-issues.d.ts +9 -3
- package/dist/validators/walker-to-issues.d.ts.map +1 -1
- package/dist/validators/walker-to-issues.js +64 -19
- package/dist/validators/walker-to-issues.js.map +1 -1
- package/dist/walk-link-graph.d.ts +64 -5
- package/dist/walk-link-graph.d.ts.map +1 -1
- package/dist/walk-link-graph.js +376 -92
- package/dist/walk-link-graph.js.map +1 -1
- package/package.json +14 -22
- package/dist/skill-test/exit-codes.d.ts +0 -97
- package/dist/skill-test/exit-codes.d.ts.map +0 -1
- package/dist/skill-test/exit-codes.js +0 -141
- package/dist/skill-test/exit-codes.js.map +0 -1
|
@@ -1,16 +1,53 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { randomBytes } from 'node:crypto';
|
|
2
|
+
import { existsSync, readFileSync, rmSync } from 'node:fs';
|
|
3
|
+
import { mkdirSyncReal, safePath, VatError } from '@vibe-agent-toolkit/utils';
|
|
4
|
+
import { parseStreamJsonTranscript, spawnHeadlessClaude, } from '@vibe-agent-toolkit/utils/skill-test';
|
|
5
|
+
import { parseEvalFragment } from './eval-fragment.js';
|
|
6
|
+
import { InternalHarnessError } from './failure-reason.js';
|
|
5
7
|
import { assertGraderPromptInvariants, buildGraderPrompt } from './grader-prompt.js';
|
|
8
|
+
import { sanitizeGraderText } from './grader-text.js';
|
|
6
9
|
import { GradingNonceError } from './grading-adapter.js';
|
|
7
10
|
import { computeToolPassed } from './tool-eval-schema.js';
|
|
11
|
+
/** The reason named in {@link GraderFragmentUnparseableError}'s message and in every `evidence` of the failing fragment vat synthesizes from it. */
|
|
12
|
+
export const GRADER_FRAGMENT_UNPARSEABLE = 'grader-fragment-unparseable';
|
|
13
|
+
/**
|
|
14
|
+
* Thrown when the grader's fragment was not valid JSON on BOTH attempts (see
|
|
15
|
+
* {@link runGraderForEval}). A per-eval GRADING failure, deliberately neither
|
|
16
|
+
* {@link InternalHarnessError} nor `EvalFragmentError`: the harness did its
|
|
17
|
+
* job twice and the model could not write strict JSON, which is a verdict about
|
|
18
|
+
* this eval's grading, not about the suite — so it ends on the verdict path
|
|
19
|
+
* (`FINDINGS`), never on `ERROR` with `Reason: internal`. `runEvalWorker` (run-harness.ts)
|
|
20
|
+
* turns it into that eval's failing fragment (reason
|
|
21
|
+
* {@link GRADER_FRAGMENT_UNPARSEABLE}) on the treatment arm, and into a recorded
|
|
22
|
+
* control-arm failure on the other — where a fabricated `fail` would read as
|
|
23
|
+
* skill lift. `detail` is already sanitized. Carries no `reason` on purpose:
|
|
24
|
+
* `skillTestFailureReason` would read it only if this escaped, and escaping IS
|
|
25
|
+
* the bug — the worker catches it on both arms.
|
|
26
|
+
*/
|
|
27
|
+
export class GraderFragmentUnparseableError extends VatError {
|
|
28
|
+
evalId;
|
|
29
|
+
detail;
|
|
30
|
+
constructor(evalId, detail) {
|
|
31
|
+
super('SKILL_TEST_GRADER_FRAGMENT_UNPARSEABLE', `${GRADER_FRAGMENT_UNPARSEABLE}: the grader for eval "${evalId}" wrote a fragment that was not valid JSON ` +
|
|
32
|
+
`on either attempt (${detail}).`);
|
|
33
|
+
this.evalId = evalId;
|
|
34
|
+
this.detail = detail;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Adapt the grader's stdout `onProgress` sink into the `onWarn` callback
|
|
39
|
+
* {@link parseEvalFragment} requires (called only when it drops malformed
|
|
40
|
+
* friction items).
|
|
41
|
+
*/
|
|
42
|
+
function fragmentWarnRouter(onProgress) {
|
|
43
|
+
return (message) => onProgress(`[skill-test] ${message}\n`);
|
|
44
|
+
}
|
|
8
45
|
/**
|
|
9
46
|
* Run ONE eval's grader: a blind `claude -p` spawn (grader model, NO
|
|
10
47
|
* skill/plugin loaded) that reads the executor's captured transcript via its
|
|
11
|
-
* prompt and writes a nonce'd fragment JSON to `graderOutDir
|
|
12
|
-
*
|
|
13
|
-
* executor ran in
|
|
48
|
+
* prompt and writes a nonce'd fragment JSON to `graderOutDir`.
|
|
49
|
+
* `graderOutDir` is vat-only and separate from the skill sandbox the
|
|
50
|
+
* executor ran in — the grader's `sandboxDir` --add-dir is
|
|
14
51
|
* `graderOutDir` itself, and `pluginDirs: []` means no skill code ever runs
|
|
15
52
|
* inside the grader's process, so skill code cannot forge or tamper with the
|
|
16
53
|
* fragment this run trusts.
|
|
@@ -19,49 +56,100 @@ import { computeToolPassed } from './tool-eval-schema.js';
|
|
|
19
56
|
* executor (see eval-executor.ts), there is NO clean-failure path here. A
|
|
20
57
|
* spawn rejection, watchdog kill (`timedOut`/`stalled`), non-zero exit, or a
|
|
21
58
|
* missing fragment file all mean the grader failed to do its ONE job and are
|
|
22
|
-
* thrown as {@link InternalHarnessError} (
|
|
59
|
+
* thrown as {@link InternalHarnessError} (`ERROR`, `Reason: internal`) — never laundered into a
|
|
23
60
|
* passing (or even a valid failing) verdict.
|
|
24
61
|
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
62
|
+
* A fragment that exists but is not valid JSON is the one exception, because
|
|
63
|
+
* the grader MODEL writes it: one bad escape in a free-text `evidence` took a
|
|
64
|
+
* six-eval suite down as harness-broke after five evals had graded fine. That
|
|
65
|
+
* attempt is re-run ONCE — same transcript, a FRESH nonce (so the stale file, or
|
|
66
|
+
* anything left behind, cannot satisfy the retry), the bad file consumed first,
|
|
67
|
+
* and the prompt told what went wrong. Only a second unparseable fragment
|
|
68
|
+
* surfaces, as {@link GraderFragmentUnparseableError}. Once a fragment parses,
|
|
69
|
+
* shape problems throw `EvalFragmentError` (via {@link parseEvalFragment})
|
|
70
|
+
* and a nonce that doesn't match the nonce THAT attempt was prompted with throws
|
|
71
|
+
* {@link GradingNonceError} — both fail-closed with no retry, because the grader
|
|
72
|
+
* DID produce JSON, just not JSON we can trust.
|
|
36
73
|
*/
|
|
37
|
-
function fragmentWarnRouter(onProgress) {
|
|
38
|
-
if (onProgress === undefined)
|
|
39
|
-
return undefined;
|
|
40
|
-
return (message) => onProgress(`[skill-test] ${message}\n`);
|
|
41
|
-
}
|
|
42
74
|
export async function runGraderForEval(input) {
|
|
43
|
-
|
|
75
|
+
// 0700, like every other vat-only directory this codebase creates (the grader
|
|
76
|
+
// root in `resolveGraderOutDir`, the workspaces root and every eval workspace in
|
|
77
|
+
// `stageEvalWorkspaces`). This is the per-ARM subdirectory of an already-0700
|
|
78
|
+
// parent, so nothing is exposed today — traversal into it is blocked one level
|
|
79
|
+
// up. It is made explicit because the rule is only worth anything while it is
|
|
80
|
+
// uniform: an unmoded `mkdir` here is the one place a reader would have to prove
|
|
81
|
+
// the parent's mode to know the fragment (which echoes the run's integrity nonce)
|
|
82
|
+
// is unreadable, and the day this dir is created somewhere else that proof is
|
|
83
|
+
// gone. Fragments are consumed-on-read anyway; this is the resting-state half.
|
|
84
|
+
mkdirSyncReal(input.graderOutDir, { recursive: true, mode: 0o700 });
|
|
44
85
|
// evalId is validated `[A-Za-z0-9_-]+` upstream (eval-inputs.ts) so a plain
|
|
45
86
|
// join is safe, but `joinUnderRoot` is used defensively — it costs nothing
|
|
46
87
|
// and closes off any future path where an unvalidated id reaches here.
|
|
47
88
|
const fragmentOut = safePath.joinUnderRoot(input.graderOutDir, `${input.evalId}.json`);
|
|
48
|
-
|
|
89
|
+
let attempt = await runGraderAttempt(input, fragmentOut, input.nonce, undefined);
|
|
90
|
+
if (attempt.unparseable !== undefined) {
|
|
91
|
+
input.onProgress(`[skill-test] grader fragment for eval "${input.evalId}" was not valid JSON (${attempt.unparseable}); re-grading once.\n`);
|
|
92
|
+
// Minted here, not derived from the run nonce: the retry must accept nothing
|
|
93
|
+
// written under the first prompt.
|
|
94
|
+
attempt = await runGraderAttempt(input, fragmentOut, randomBytes(16).toString('hex'), attempt.unparseable);
|
|
95
|
+
if (attempt.unparseable !== undefined) {
|
|
96
|
+
throw new GraderFragmentUnparseableError(input.evalId, attempt.unparseable);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
const fragment = parseEvalFragment(attempt.parsed, fragmentWarnRouter(input.onProgress));
|
|
100
|
+
// Integrity gate: a missing/wrong nonce means this fragment was not produced
|
|
101
|
+
// by the grader we prompted for THIS attempt — most likely forged or left
|
|
102
|
+
// behind by untrusted skill code — so the verdict cannot be trusted, hard error.
|
|
103
|
+
if (fragment.runNonce !== attempt.nonce) {
|
|
104
|
+
throw new GradingNonceError(`eval "${input.evalId}" fragment \`runNonce\` does not match this run`);
|
|
105
|
+
}
|
|
106
|
+
assertExpectationCountDeclared(input.evalId, input.expectations, fragment.expectations);
|
|
107
|
+
assertToolVerdictConsistent(input.evalId, input.toolExpectations, fragment.tool);
|
|
108
|
+
// The grader's only input is the executor transcript, which untrusted skill code
|
|
109
|
+
// controls, and `evalId` is schema-typed as any non-empty string. It is echoed
|
|
110
|
+
// verbatim into the run summary and into `baseline.json` — including the
|
|
111
|
+
// CONTAMINATED banner — so a grader talked into emitting an id containing
|
|
112
|
+
// newlines and ANSI escapes can paint a reassuring "known false positive, the
|
|
113
|
+
// delta is valid" line directly beneath vat's own warning. VAT knows which eval
|
|
114
|
+
// it asked about; take the id from the request, never from the answer.
|
|
115
|
+
//
|
|
116
|
+
// `runNonce` is re-stamped for the same reason: the merge re-verifies every
|
|
117
|
+
// fragment against the ONE nonce the run minted, and a re-graded fragment has
|
|
118
|
+
// already passed the gate above against the nonce its own prompt carried.
|
|
119
|
+
return { ...fragment, evalId: input.evalId, runNonce: input.nonce };
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* ONE grader spawn under `nonce`: build and assert the prompt, spawn, apply the
|
|
123
|
+
* harness-breakage gates, report cost, consume the fragment file. `previousFailure`
|
|
124
|
+
* is the re-grade's only difference — a trailing line telling the grader what its
|
|
125
|
+
* first fragment got wrong (sanitized where it was caught, at the bottom of this
|
|
126
|
+
* function). Required, not defaulted, so both call sites say which attempt they are.
|
|
127
|
+
*/
|
|
128
|
+
async function runGraderAttempt(input, fragmentOut, nonce, previousFailure) {
|
|
129
|
+
const built = buildGraderPrompt({
|
|
49
130
|
evalId: input.evalId,
|
|
50
131
|
transcript: input.transcript,
|
|
51
132
|
expectations: input.expectations,
|
|
52
133
|
...(input.expectedOutput === undefined ? {} : { expectedOutput: input.expectedOutput }),
|
|
53
134
|
rubricPath: input.rubricPath,
|
|
54
135
|
fragmentOut,
|
|
55
|
-
nonce
|
|
136
|
+
nonce,
|
|
56
137
|
...(input.toolExpectations === undefined ? {} : { toolExpectations: input.toolExpectations }),
|
|
57
138
|
...(input.declaredExecutables === undefined ? {} : { declaredExecutables: input.declaredExecutables }),
|
|
58
139
|
});
|
|
140
|
+
const prompt = previousFailure === undefined
|
|
141
|
+
? built
|
|
142
|
+
: `${built}\n\nYour previous fragment was not valid JSON: ${previousFailure}. Write strict JSON.`;
|
|
59
143
|
// Defense-in-depth (parity with eval-executor.ts's build→assert→use pattern):
|
|
60
144
|
// re-verify the built grader prompt still carries its required invariants
|
|
61
|
-
// (STOP, fragment path, browser/iteration forbids, nonce directive
|
|
62
|
-
// spawning, so a regressed buildGraderPrompt is
|
|
63
|
-
// that silently misbehaves.
|
|
64
|
-
|
|
145
|
+
// (STOP, fragment path, browser/iteration forbids, nonce directive, and the
|
|
146
|
+
// untrusted-data fences) before spawning, so a regressed buildGraderPrompt is
|
|
147
|
+
// caught here, not by a grader that silently misbehaves. The nonce is handed
|
|
148
|
+
// over so the assertion can cut out every fenced region — transcript, subject
|
|
149
|
+
// manifest, and the suite's own expectations/expected_output — and none of
|
|
150
|
+
// that attacker-controlled text can satisfy an invariant on the builder's
|
|
151
|
+
// behalf.
|
|
152
|
+
assertGraderPromptInvariants(prompt, nonce);
|
|
65
153
|
const spawn = input.spawn ?? spawnHeadlessClaude;
|
|
66
154
|
// Accumulate the grader's stream-json stdout so we can read its terminal
|
|
67
155
|
// `total_cost_usd` for run-wide spend aggregation (adopter follow-up). Held in
|
|
@@ -69,7 +157,7 @@ export async function runGraderForEval(input) {
|
|
|
69
157
|
let graderTranscript = '';
|
|
70
158
|
const onStdout = (chunk) => {
|
|
71
159
|
graderTranscript += chunk;
|
|
72
|
-
input.onProgress
|
|
160
|
+
input.onProgress(chunk);
|
|
73
161
|
};
|
|
74
162
|
let spawnResult;
|
|
75
163
|
try {
|
|
@@ -109,53 +197,110 @@ export async function runGraderForEval(input) {
|
|
|
109
197
|
// the in-memory transcript (not the fragment) so it reflects real API spend even
|
|
110
198
|
// under subscription auth; `undefined` when the transcript carried no result.
|
|
111
199
|
input.costSink?.(parseStreamJsonTranscript(graderTranscript).result?.totalCostUsd);
|
|
112
|
-
const
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
200
|
+
const warn = fragmentWarnRouter(input.onProgress);
|
|
201
|
+
const text = readAndConsumeFragmentFile(fragmentOut, input.evalId, spawnResult.status, warn);
|
|
202
|
+
try {
|
|
203
|
+
return { nonce, parsed: JSON.parse(text) };
|
|
204
|
+
}
|
|
205
|
+
catch (err) {
|
|
206
|
+
if (!(err instanceof SyntaxError))
|
|
207
|
+
throw err;
|
|
208
|
+
// V8 embeds a VERBATIM slice of the offending bytes in its SyntaxError
|
|
209
|
+
// message, unescaped — and this is one of the few grader-controlled strings
|
|
210
|
+
// that reaches an operator WITHOUT passing `parseEvalFragment`, the
|
|
211
|
+
// documented text boundary, because the parse it would have gone through is
|
|
212
|
+
// the one that just failed. It lands in a thrown message (which the CLI writes
|
|
213
|
+
// as `Error: ${err.message}`, so an unsanitized `ESC[2K CR ESC[32m…` wipes the
|
|
214
|
+
// line vat just printed and continues in vat's own colour) AND in the re-grade
|
|
215
|
+
// prompt.
|
|
216
|
+
return { nonce, unparseable: sanitizeGraderText(err.message) };
|
|
119
217
|
}
|
|
120
|
-
assertToolVerdictConsistent(input.evalId, input.toolExpectations, fragment.tool);
|
|
121
|
-
return fragment;
|
|
122
218
|
}
|
|
123
219
|
/**
|
|
124
|
-
* Read the grader's fragment
|
|
125
|
-
* consume-on-read
|
|
126
|
-
*
|
|
127
|
-
* wrote no fragment, {@link EvalFragmentError} if it is not valid JSON.
|
|
220
|
+
* Read the grader's fragment file into memory and remove it immediately —
|
|
221
|
+
* consume-on-read, whether or not it will parse. Throws {@link InternalHarnessError}
|
|
222
|
+
* if the grader wrote no fragment.
|
|
128
223
|
*
|
|
129
|
-
* The
|
|
224
|
+
* The removal is the security-relevant half: the grader dir is same-uid (see
|
|
130
225
|
* `resolveGraderOutDir`), so a fragment left on disk lets skill code that
|
|
131
226
|
* survived the process-group kill read the echoed nonce at leisure and forge
|
|
132
227
|
* LATER fragments. Consuming it on read leaves no persisted copy — exposure
|
|
133
|
-
* shrinks to each fragment's own read window (no cross-eval harvest).
|
|
134
|
-
*
|
|
135
|
-
*
|
|
136
|
-
*
|
|
228
|
+
* shrinks to each fragment's own read window (no cross-eval harvest). It is also
|
|
229
|
+
* what makes the re-grade honest: a retry that writes nothing finds no file, not
|
|
230
|
+
* the unparseable one. The read here is the ONLY read of the file; all downstream
|
|
231
|
+
* logic runs off the returned text. A failed removal is not a run failure
|
|
232
|
+
* (end-of-run cleanup removes the whole dir) but it IS the one degradation this
|
|
233
|
+
* design exists to prevent, so it is reported through `onWarn` rather than
|
|
234
|
+
* swallowed: the operator learns the fragment lingered, with the errno. True
|
|
235
|
+
* isolation from same-uid code is a separate, unbuilt mechanism (a different uid
|
|
236
|
+
* or a sandbox), not this removal.
|
|
137
237
|
*/
|
|
138
|
-
function readAndConsumeFragmentFile(fragmentOut, evalId, status) {
|
|
139
|
-
// eslint-disable-next-line security/detect-non-literal-fs-filename -- fragmentOut is our own derived path (joinUnderRoot-guarded)
|
|
238
|
+
function readAndConsumeFragmentFile(fragmentOut, evalId, status, onWarn) {
|
|
140
239
|
if (!existsSync(fragmentOut)) {
|
|
141
240
|
throw new InternalHarnessError(`Grader exited (status ${status}) without writing a fragment at ${fragmentOut} for eval "${evalId}".`);
|
|
142
241
|
}
|
|
143
|
-
|
|
242
|
+
const text = readFileSync(fragmentOut, 'utf-8');
|
|
144
243
|
try {
|
|
145
|
-
//
|
|
146
|
-
|
|
244
|
+
// `force` covers the one benign case — the file is already gone — so what the
|
|
245
|
+
// catch sees is a refusal (EACCES/EPERM/EBUSY), never an absence.
|
|
246
|
+
rmSync(fragmentOut, { force: true });
|
|
147
247
|
}
|
|
148
248
|
catch (err) {
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
try {
|
|
152
|
-
// eslint-disable-next-line security/detect-non-literal-fs-filename -- fragmentOut is our own derived path (joinUnderRoot-guarded)
|
|
153
|
-
unlinkSync(fragmentOut);
|
|
154
|
-
}
|
|
155
|
-
catch {
|
|
156
|
-
// Swallow: cleanup removes the grader dir regardless.
|
|
249
|
+
onWarn(`grader fragment for eval "${evalId}" at ${fragmentOut} could not be removed after it was read ` +
|
|
250
|
+
`(${err instanceof Error ? err.message : String(err)}); it stays on disk until end-of-run cleanup.`);
|
|
157
251
|
}
|
|
158
|
-
return
|
|
252
|
+
return text;
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* The OUTPUT channel's declared-vs-reported check — the exact thing
|
|
256
|
+
* {@link assertToolCheckNamesDeclared} does for the TOOL channel, applied to the
|
|
257
|
+
* channel every reported number is computed from.
|
|
258
|
+
*
|
|
259
|
+
* Each arm's `summary`, the pass/fail verdict `reconcileGrading` produces, and
|
|
260
|
+
* the `--baseline` delta between the arms are all computed over
|
|
261
|
+
* `fragment.expectations` — i.e. over however many entries the grader chose to
|
|
262
|
+
* write. The prompt ASKS for "one per expectation above" and, until this check,
|
|
263
|
+
* nothing verified it:
|
|
264
|
+
*
|
|
265
|
+
* - **Omission laundered a pass, on EVERY run.** A grader that skips a FAILING
|
|
266
|
+
* expectation leaves a fragment where the survivors all passed, so
|
|
267
|
+
* `reconcileGrading` reports `allPassed: true` and the run exits 0.
|
|
268
|
+
* - **Invention inflated the delta.** A suite declaring 1 expectation whose two
|
|
269
|
+
* graders each emit 3 of their own yields `Baseline delta: +3` where the
|
|
270
|
+
* maximum legal lift is +1.
|
|
271
|
+
*
|
|
272
|
+
* The existing `armExpectationSkew` cannot see either: it compares the two ARMS
|
|
273
|
+
* to each other, and both graders receive the same declared list from the same
|
|
274
|
+
* template, so they drift together and parity holds while a confident wrong
|
|
275
|
+
* number prints.
|
|
276
|
+
*
|
|
277
|
+
* COUNT, not text. The grader is asked to echo each expectation's `text`, but it
|
|
278
|
+
* routinely reworks the wording, and a reworded text is not a wrong verdict —
|
|
279
|
+
* whereas a missing or extra ENTRY always is, because the entry is the unit
|
|
280
|
+
* every score counts.
|
|
281
|
+
*
|
|
282
|
+
* Fail-closed like its siblings below: this is vat's own grading infrastructure
|
|
283
|
+
* failing its one job, not adopter data being audited.
|
|
284
|
+
*
|
|
285
|
+
* FAIL-CLOSED IS NOT FAIL-THE-RUN, and the distinction is the caller's to make, not
|
|
286
|
+
* this function's. Throwing here is unconditional and stays that way: a fragment
|
|
287
|
+
* whose entry count does not match the declaration is not a verdict, and returning
|
|
288
|
+
* it "leniently" for the control arm would put an unchecked number straight into the
|
|
289
|
+
* delta — which is the hole this check was added to close. What changed is where the
|
|
290
|
+
* throw lands. `runEvalWorker` (run-harness.ts) catches a CONTROL-arm throw, records
|
|
291
|
+
* it as a control-arm failure, and lets the run finish; a TREATMENT-arm throw still
|
|
292
|
+
* propagates and fails the run. So a control-arm grader miscount now withholds the
|
|
293
|
+
* delta as `null` with the reason attached, instead of destroying fully-billed
|
|
294
|
+
* treatment work that was never in doubt. Do not soften this assert to get that
|
|
295
|
+
* behaviour — it is already there, one level up, where the arm is known.
|
|
296
|
+
*/
|
|
297
|
+
function assertExpectationCountDeclared(evalId, declared, reported) {
|
|
298
|
+
if (reported.length === declared.length)
|
|
299
|
+
return;
|
|
300
|
+
throw new InternalHarnessError(`Grader for eval "${evalId}" returned ${reported.length} expectation entr${reported.length === 1 ? 'y' : 'ies'} ` +
|
|
301
|
+
`for an eval that declares ${declared.length}. Every score vat reports — each arm's summary and the ` +
|
|
302
|
+
`--baseline delta between them — is computed over the entries the grader emitted, so an invented or ` +
|
|
303
|
+
`omitted entry silently changes it.`);
|
|
159
304
|
}
|
|
160
305
|
/**
|
|
161
306
|
* Fail-open guards on the grader's tool verdict, split out of
|
|
@@ -171,6 +316,8 @@ function readAndConsumeFragmentFile(fragmentOut, evalId, status) {
|
|
|
171
316
|
* that disagrees with its own sub-checks is grader malfunction (a false green
|
|
172
317
|
* or a false red), surfaced loudly rather than merged. Mirrors
|
|
173
318
|
* `reconcileGrading`'s summary/expectations reconciliation (grading-adapter.ts).
|
|
319
|
+
* - Fix #4: the check NAMES must be exactly the eval's declared ones. See
|
|
320
|
+
* {@link assertToolCheckNamesDeclared}.
|
|
174
321
|
*/
|
|
175
322
|
function assertToolVerdictConsistent(evalId, toolExpectations, tool) {
|
|
176
323
|
if (toolExpectations !== undefined && tool === undefined) {
|
|
@@ -180,5 +327,57 @@ function assertToolVerdictConsistent(evalId, toolExpectations, tool) {
|
|
|
180
327
|
throw new InternalHarnessError(`Grader for eval "${evalId}" emitted a tool verdict whose \`passed\` (${tool.passed}) ` +
|
|
181
328
|
`disagrees with its own sub-checks (recomputed ${computeToolPassed(tool)}).`);
|
|
182
329
|
}
|
|
330
|
+
assertToolCheckNamesDeclared(evalId, toolExpectations, tool);
|
|
331
|
+
}
|
|
332
|
+
/** Render grader-supplied names for an error message, already sanitized by the fragment parse. */
|
|
333
|
+
function quoteNames(names) {
|
|
334
|
+
return names.map((name) => `"${name}"`).join(', ');
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* One channel's check names must be EXACTLY the declared ones — no invention,
|
|
338
|
+
* no omission.
|
|
339
|
+
*
|
|
340
|
+
* `computeToolPassed` iterates the checks the GRADER emitted, not the ones the
|
|
341
|
+
* eval declared, so both directions are load-bearing and neither is cosmetic:
|
|
342
|
+
*
|
|
343
|
+
* - **Omission laundered a pass.** Drop the `mustRun` entry for an executable
|
|
344
|
+
* that never ran and the channel is vacuously true — the verdict reads
|
|
345
|
+
* `passed: true` for an expectation nobody checked.
|
|
346
|
+
* - **Invention gates on a name vat never asked about.** A grader talked into
|
|
347
|
+
* emitting `{name: "totally-fine", ran: true}` adds a check the eval does not
|
|
348
|
+
* declare, and it counts toward the verdict exactly like a real one.
|
|
349
|
+
*
|
|
350
|
+
* Names are compared AFTER {@link sanitizeGraderText} on both sides. The
|
|
351
|
+
* reported side is already sanitized (parseEvalFragment); normalizing the
|
|
352
|
+
* declared side too means the comparison happens in one space, so an adopter
|
|
353
|
+
* who declared a name containing a tab does not get an unexplainable mismatch.
|
|
354
|
+
*
|
|
355
|
+
* Fail-closed like its siblings above: this is vat's own grading infrastructure
|
|
356
|
+
* failing to do its one job, not adopter data being audited.
|
|
357
|
+
*/
|
|
358
|
+
function assertToolCheckNamesDeclared(evalId, toolExpectations, tool) {
|
|
359
|
+
if (tool === undefined)
|
|
360
|
+
return;
|
|
361
|
+
const declared = toolExpectations ?? {};
|
|
362
|
+
assertChannelNames(evalId, 'mustRun', declared.mustRun, (tool.mustRun ?? []).map((c) => c.name));
|
|
363
|
+
assertChannelNames(evalId, 'mustNotRun', declared.mustNotRun, (tool.mustNotRun ?? []).map((c) => c.name));
|
|
364
|
+
assertChannelNames(evalId, 'mustSucceed', declared.mustSucceed, (tool.mustSucceed ?? []).map((c) => c.name));
|
|
365
|
+
assertChannelNames(evalId, 'sequence', declared.sequence, (tool.sequence ?? []).flatMap((c) => c.steps));
|
|
366
|
+
}
|
|
367
|
+
function assertChannelNames(evalId, channel, declared, reported) {
|
|
368
|
+
const declaredSet = new Set((declared ?? []).map(sanitizeGraderText));
|
|
369
|
+
const reportedSet = new Set(reported);
|
|
370
|
+
const invented = [...reportedSet].filter((name) => !declaredSet.has(name));
|
|
371
|
+
const missing = [...declaredSet].filter((name) => !reportedSet.has(name));
|
|
372
|
+
if (invented.length === 0 && missing.length === 0)
|
|
373
|
+
return;
|
|
374
|
+
const problems = [];
|
|
375
|
+
if (invented.length > 0)
|
|
376
|
+
problems.push(`invented ${quoteNames(invented)}`);
|
|
377
|
+
if (missing.length > 0)
|
|
378
|
+
problems.push(`omitted ${quoteNames(missing)}`);
|
|
379
|
+
throw new InternalHarnessError(`Grader for eval "${evalId}" emitted \`tool.${channel}\` checks that do not match the eval's ` +
|
|
380
|
+
`declared toolExpectations: ${problems.join('; ')}. The verdict is computed from the checks the ` +
|
|
381
|
+
`grader emitted, so an invented or omitted name silently changes it.`);
|
|
183
382
|
}
|
|
184
383
|
//# sourceMappingURL=eval-grader.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eval-grader.js","sourceRoot":"","sources":["../../src/skill-test/eval-grader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,
|
|
1
|
+
{"version":3,"file":"eval-grader.js","sourceRoot":"","sources":["../../src/skill-test/eval-grader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAE3D,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAC9E,OAAO,EACL,yBAAyB,EACzB,mBAAmB,GACpB,MAAM,sCAAsC,CAAC;AAE9C,OAAO,EAAE,iBAAiB,EAAqB,MAAM,oBAAoB,CAAC;AAE1E,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,4BAA4B,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACrF,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAuD1D,oJAAoJ;AACpJ,MAAM,CAAC,MAAM,2BAA2B,GAAG,6BAA6B,CAAC;AAEzE;;;;;;;;;;;;;GAaG;AACH,MAAM,OAAO,8BAA+B,SAAQ,QAAQ;IAExC;IACA;IAFlB,YACkB,MAAc,EACd,MAAc;QAE9B,KAAK,CACH,wCAAwC,EACxC,GAAG,2BAA2B,0BAA0B,MAAM,6CAA6C;YACzG,sBAAsB,MAAM,IAAI,CACnC,CAAC;QAPc,WAAM,GAAN,MAAM,CAAQ;QACd,WAAM,GAAN,MAAM,CAAQ;IAOhC,CAAC;CACF;AAED;;;;GAIG;AACH,SAAS,kBAAkB,CAAC,UAAwC;IAClE,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,gBAAgB,OAAO,IAAI,CAAC,CAAC;AAC9D,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,KAAqB;IAC1D,8EAA8E;IAC9E,iFAAiF;IACjF,8EAA8E;IAC9E,+EAA+E;IAC/E,8EAA8E;IAC9E,iFAAiF;IACjF,kFAAkF;IAClF,8EAA8E;IAC9E,+EAA+E;IAC/E,aAAa,CAAC,KAAK,CAAC,YAAY,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAEpE,4EAA4E;IAC5E,2EAA2E;IAC3E,uEAAuE;IACvE,MAAM,WAAW,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,YAAY,EAAE,GAAG,KAAK,CAAC,MAAM,OAAO,CAAC,CAAC;IAEvF,IAAI,OAAO,GAAG,MAAM,gBAAgB,CAAC,KAAK,EAAE,WAAW,EAAE,KAAK,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;IACjF,IAAI,OAAO,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;QACtC,KAAK,CAAC,UAAU,CACd,0CAA0C,KAAK,CAAC,MAAM,yBAAyB,OAAO,CAAC,WAAW,uBAAuB,CAC1H,CAAC;QACF,6EAA6E;QAC7E,kCAAkC;QAClC,OAAO,GAAG,MAAM,gBAAgB,CAAC,KAAK,EAAE,WAAW,EAAE,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;QAC3G,IAAI,OAAO,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;YACtC,MAAM,IAAI,8BAA8B,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;QAC9E,CAAC;IACH,CAAC;IAED,MAAM,QAAQ,GAAG,iBAAiB,CAAC,OAAO,CAAC,MAAM,EAAE,kBAAkB,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC;IAEzF,6EAA6E;IAC7E,0EAA0E;IAC1E,iFAAiF;IACjF,IAAI,QAAQ,CAAC,QAAQ,KAAK,OAAO,CAAC,KAAK,EAAE,CAAC;QACxC,MAAM,IAAI,iBAAiB,CACzB,SAAS,KAAK,CAAC,MAAM,iDAAiD,CACvE,CAAC;IACJ,CAAC;IAED,8BAA8B,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,YAAY,EAAE,QAAQ,CAAC,YAAY,CAAC,CAAC;IACxF,2BAA2B,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,gBAAgB,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;IAEjF,iFAAiF;IACjF,+EAA+E;IAC/E,yEAAyE;IACzE,0EAA0E;IAC1E,8EAA8E;IAC9E,gFAAgF;IAChF,uEAAuE;IACvE,EAAE;IACF,4EAA4E;IAC5E,8EAA8E;IAC9E,0EAA0E;IAC1E,OAAO,EAAE,GAAG,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC;AACtE,CAAC;AAUD;;;;;;GAMG;AACH,KAAK,UAAU,gBAAgB,CAC7B,KAAqB,EACrB,WAAmB,EACnB,KAAa,EACb,eAAmC;IAEnC,MAAM,KAAK,GAAG,iBAAiB,CAAC;QAC9B,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,YAAY,EAAE,KAAK,CAAC,YAAY;QAChC,GAAG,CAAC,KAAK,CAAC,cAAc,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,KAAK,CAAC,cAAc,EAAE,CAAC;QACvF,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,WAAW;QACX,KAAK;QACL,GAAG,CAAC,KAAK,CAAC,gBAAgB,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,KAAK,CAAC,gBAAgB,EAAE,CAAC;QAC7F,GAAG,CAAC,KAAK,CAAC,mBAAmB,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,mBAAmB,EAAE,KAAK,CAAC,mBAAmB,EAAE,CAAC;KACvG,CAAC,CAAC;IACH,MAAM,MAAM,GACV,eAAe,KAAK,SAAS;QAC3B,CAAC,CAAC,KAAK;QACP,CAAC,CAAC,GAAG,KAAK,kDAAkD,eAAe,sBAAsB,CAAC;IACtG,8EAA8E;IAC9E,0EAA0E;IAC1E,4EAA4E;IAC5E,8EAA8E;IAC9E,6EAA6E;IAC7E,8EAA8E;IAC9E,2EAA2E;IAC3E,0EAA0E;IAC1E,UAAU;IACV,4BAA4B,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAE5C,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,IAAI,mBAAmB,CAAC;IAEjD,yEAAyE;IACzE,+EAA+E;IAC/E,uEAAuE;IACvE,IAAI,gBAAgB,GAAG,EAAE,CAAC;IAC1B,MAAM,QAAQ,GAAG,CAAC,KAAa,EAAQ,EAAE;QACvC,gBAAgB,IAAI,KAAK,CAAC;QAC1B,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;IAC1B,CAAC,CAAC;IAEF,IAAI,WAAW,CAAC;IAChB,IAAI,CAAC;QACH,WAAW,GAAG,MAAM,KAAK,CAAC;YACxB,MAAM;YACN,uEAAuE;YACvE,gEAAgE;YAChE,0CAA0C;YAC1C,UAAU,EAAE,EAAE;YACd,UAAU,EAAE,KAAK,CAAC,YAAY;YAC9B,GAAG,EAAE,KAAK,CAAC,YAAY;YACvB,GAAG,EAAE,KAAK,CAAC,GAAG;YACd,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,QAAQ;YACR,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,YAAY,EAAE,KAAK,CAAC,YAAY;YAChC,KAAK,EAAE,KAAK,CAAC,WAAW;YACxB,GAAG,CAAC,KAAK,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;SACnE,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,oBAAoB,CAC5B,iCAAiC,KAAK,CAAC,MAAM,MAAM,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CACtG,CAAC;IACJ,CAAC;IAED,0EAA0E;IAC1E,2EAA2E;IAC3E,wDAAwD;IACxD,IAAI,WAAW,CAAC,OAAO,EAAE,CAAC;QACxB,MAAM,IAAI,oBAAoB,CAC5B,4BAA4B,KAAK,CAAC,MAAM,oBAAoB,KAAK,CAAC,OAAO,IAAI,CAAC,MAAM,CACrF,CAAC;IACJ,CAAC;IACD,IAAI,WAAW,CAAC,QAAQ,EAAE,CAAC;QACzB,MAAM,IAAI,oBAAoB,CAC5B,8BAA8B,KAAK,CAAC,MAAM,YAAY,KAAK,CAAC,SAAS,MAAM,CAC5E,CAAC;IACJ,CAAC;IACD,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,oBAAoB,CAC5B,kCAAkC,WAAW,CAAC,MAAM,eAAe,KAAK,CAAC,MAAM,IAAI,CACpF,CAAC;IACJ,CAAC;IAED,+EAA+E;IAC/E,iFAAiF;IACjF,8EAA8E;IAC9E,KAAK,CAAC,QAAQ,EAAE,CAAC,yBAAyB,CAAC,gBAAgB,CAAC,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAEnF,MAAM,IAAI,GAAG,kBAAkB,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IAClD,MAAM,IAAI,GAAG,0BAA0B,CAAC,WAAW,EAAE,KAAK,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAC7F,IAAI,CAAC;QACH,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;IAC7C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,CAAC,GAAG,YAAY,WAAW,CAAC;YAAE,MAAM,GAAG,CAAC;QAC7C,uEAAuE;QACvE,4EAA4E;QAC5E,oEAAoE;QACpE,4EAA4E;QAC5E,+EAA+E;QAC/E,+EAA+E;QAC/E,+EAA+E;QAC/E,UAAU;QACV,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,kBAAkB,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;IACjE,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,SAAS,0BAA0B,CACjC,WAAmB,EACnB,MAAc,EACd,MAAc,EACd,MAAiC;IAEjC,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,oBAAoB,CAC5B,yBAAyB,MAAM,mCAAmC,WAAW,cAAc,MAAM,IAAI,CACtG,CAAC;IACJ,CAAC;IACD,MAAM,IAAI,GAAG,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAChD,IAAI,CAAC;QACH,8EAA8E;QAC9E,kEAAkE;QAClE,MAAM,CAAC,WAAW,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACvC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,CACJ,6BAA6B,MAAM,QAAQ,WAAW,0CAA0C;YAC9F,IAAI,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,+CAA+C,CACtG,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,SAAS,8BAA8B,CACrC,MAAc,EACd,QAA2B,EAC3B,QAAsC;IAEtC,IAAI,QAAQ,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM;QAAE,OAAO;IAChD,MAAM,IAAI,oBAAoB,CAC5B,oBAAoB,MAAM,cAAc,QAAQ,CAAC,MAAM,oBAAoB,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG;QAC/G,6BAA6B,QAAQ,CAAC,MAAM,yDAAyD;QACrG,qGAAqG;QACrG,oCAAoC,CACvC,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,SAAS,2BAA2B,CAClC,MAAc,EACd,gBAAoD,EACpD,IAA0B;IAE1B,IAAI,gBAAgB,KAAK,SAAS,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACzD,MAAM,IAAI,oBAAoB,CAC5B,oBAAoB,MAAM,mGAAmG,CAC9H,CAAC;IACJ,CAAC;IACD,IAAI,IAAI,KAAK,SAAS,IAAI,iBAAiB,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;QAClE,MAAM,IAAI,oBAAoB,CAC5B,oBAAoB,MAAM,8CAA8C,IAAI,CAAC,MAAM,IAAI;YACrF,iDAAiD,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAC/E,CAAC;IACJ,CAAC;IACD,4BAA4B,CAAC,MAAM,EAAE,gBAAgB,EAAE,IAAI,CAAC,CAAC;AAC/D,CAAC;AAED,kGAAkG;AAClG,SAAS,UAAU,CAAC,KAAwB;IAC1C,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACrD,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,SAAS,4BAA4B,CACnC,MAAc,EACd,gBAAoD,EACpD,IAA0B;IAE1B,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO;IAC/B,MAAM,QAAQ,GAAG,gBAAgB,IAAI,EAAE,CAAC;IACxC,kBAAkB,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IACjG,kBAAkB,CAAC,MAAM,EAAE,YAAY,EAAE,QAAQ,CAAC,UAAU,EAAE,CAAC,IAAI,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAC1G,kBAAkB,CAAC,MAAM,EAAE,aAAa,EAAE,QAAQ,CAAC,WAAW,EAAE,CAAC,IAAI,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAC7G,kBAAkB,CAAC,MAAM,EAAE,UAAU,EAAE,QAAQ,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;AAC3G,CAAC;AAED,SAAS,kBAAkB,CACzB,MAAc,EACd,OAAe,EACf,QAAuC,EACvC,QAA2B;IAE3B,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC,CAAC;IACtE,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC;IACtC,MAAM,QAAQ,GAAG,CAAC,GAAG,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;IAC3E,MAAM,OAAO,GAAG,CAAC,GAAG,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;IAC1E,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAC1D,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;QAAE,QAAQ,CAAC,IAAI,CAAC,YAAY,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IAC3E,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;QAAE,QAAQ,CAAC,IAAI,CAAC,WAAW,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACxE,MAAM,IAAI,oBAAoB,CAC5B,oBAAoB,MAAM,oBAAoB,OAAO,yCAAyC;QAC5F,8BAA8B,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,gDAAgD;QACjG,qEAAqE,CACxE,CAAC;AACJ,CAAC"}
|
|
@@ -1,8 +1,49 @@
|
|
|
1
|
+
import { VatError } from '@vibe-agent-toolkit/utils';
|
|
1
2
|
import { z } from 'zod';
|
|
2
|
-
/**
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Raised for any eval-input problem (bad JSON, schema failure, missing input file).
|
|
5
|
+
* Reason `preflight`.
|
|
6
|
+
*
|
|
7
|
+
* The FIELD is what makes that sentence true, and until it was added only one of this
|
|
8
|
+
* class's two routes delivered it. `attemptStageWorkspaces` catches the staging
|
|
9
|
+
* instance and maps it explicitly; the instance thrown from {@link armDirSegment}
|
|
10
|
+
* fires deep in the eval loop, outside that handler, and reached
|
|
11
|
+
* `skillTestFailureReason`'s `internal` default — reporting a harness bug for a
|
|
12
|
+
* preflight-class problem while the docblock above claimed otherwise. `preflight`
|
|
13
|
+
* for the internal-invariant case too is consistent with every sibling in this feature.
|
|
14
|
+
*/
|
|
15
|
+
export declare class EvalInputError extends VatError {
|
|
16
|
+
readonly reason: "preflight";
|
|
4
17
|
constructor(message: string);
|
|
5
18
|
}
|
|
19
|
+
/**
|
|
20
|
+
* Neutralize a SUITE-AUTHORED string before it is quoted into an
|
|
21
|
+
* {@link EvalInputError}, whose message reaches `process.stdout` on the
|
|
22
|
+
* `Summary:` line — the one channel deliberately kept machine-readable — and
|
|
23
|
+
* renders twice on the way there.
|
|
24
|
+
*
|
|
25
|
+
* The suite is nominally adopter-authored, but `resolveEvalSuitePath` will
|
|
26
|
+
* harvest one out of a FETCHED npm/url artifact, i.e. out of the skill under
|
|
27
|
+
* test, so treat it as untrusted. `files[]` is the sharp edge: it is
|
|
28
|
+
* `z.array(z.string().min(1))` with NO charset constraint, in deliberate
|
|
29
|
+
* contrast to `id`, which is regex-pinned precisely because it names a
|
|
30
|
+
* directory. A derived path or an OS error text built from such an entry
|
|
31
|
+
* carries the same bytes, so those are sanitized here too, not just the entry.
|
|
32
|
+
*
|
|
33
|
+
* Reuses {@link sanitizeGraderText} rather than growing a second neutralizer:
|
|
34
|
+
* the threat and the remedy (drop escape sequences whole, fold every remaining
|
|
35
|
+
* control code to a space, collapse, cap) are identical — only the source of
|
|
36
|
+
* the untrusted text differs.
|
|
37
|
+
*
|
|
38
|
+
* EXPORTED because the suite reaches an operator surface from more than this
|
|
39
|
+
* module: `eval-lint.ts` quotes `toolExpectations.*` entries — the same
|
|
40
|
+
* unconstrained `z.array(z.string().min(1))` shape as `files[]` — into an advisory
|
|
41
|
+
* that `run-harness.ts` writes to stderr verbatim, and does it at Step 5.5, ahead
|
|
42
|
+
* of both the security-ack gate and the `--dry-run` short-circuit. Every new
|
|
43
|
+
* suite-authored string bound for a terminal goes through HERE, so the trust model
|
|
44
|
+
* above stays stated in one place.
|
|
45
|
+
*/
|
|
46
|
+
export declare function quoteSuiteText(value: string): string;
|
|
6
47
|
/**
|
|
7
48
|
* True when `key` is exactly one edit (insert/delete/substitute one char) from
|
|
8
49
|
* `target`. Used to catch typos of recognized fields (here) and of declared
|
|
@@ -488,7 +529,7 @@ export declare const EvalSuiteSchema: z.ZodObject<{
|
|
|
488
529
|
export type EvalEntry = z.infer<typeof EvalEntrySchema>;
|
|
489
530
|
export type EvalSuite = z.infer<typeof EvalSuiteSchema>;
|
|
490
531
|
/**
|
|
491
|
-
* The declared tool expectations of ONE eval
|
|
532
|
+
* The declared tool expectations of ONE eval. Derived from
|
|
492
533
|
* {@link EvalEntry} so the grader input + prompt builder share the EXACT shape the
|
|
493
534
|
* parser produces — no drift, and no duplicated inline `{ mustRun?; mustNotRun?;
|
|
494
535
|
* sequence? }` literal across those consumers.
|
|
@@ -496,19 +537,80 @@ export type EvalSuite = z.infer<typeof EvalSuiteSchema>;
|
|
|
496
537
|
export type ToolExpectations = NonNullable<EvalEntry['toolExpectations']>;
|
|
497
538
|
/** Parse + validate a skill-test eval suite. Throws {@link EvalInputError} on any problem. */
|
|
498
539
|
export declare function parseEvalSuite(jsonText: string): EvalSuite;
|
|
540
|
+
/**
|
|
541
|
+
* One side of a `--baseline` A/B: `'with'` runs the skill staged and declared,
|
|
542
|
+
* `'without'` is the control. Declared here rather than in the run orchestrator
|
|
543
|
+
* because the staging layer needs it to give each arm its own workspace tree.
|
|
544
|
+
*/
|
|
545
|
+
export type EvalArm = 'with' | 'without';
|
|
546
|
+
/**
|
|
547
|
+
* The opaque directory segment each arm's workspaces live under, minted fresh per
|
|
548
|
+
* run. `with` is required and `without` present only under `--baseline`, so the
|
|
549
|
+
* set of arms is the keys — a shape that cannot express "stage nothing", unlike
|
|
550
|
+
* the `readonly EvalArm[]` this replaced (an empty array was a legal input that
|
|
551
|
+
* silently left every executor with a non-existent cwd).
|
|
552
|
+
*
|
|
553
|
+
* ⚠️ The VALUES must not be the literal arm names, and must not be derivable from
|
|
554
|
+
* each other. See {@link stageEvalWorkspaces}.
|
|
555
|
+
*/
|
|
556
|
+
export interface ArmWorkspaceDirs {
|
|
557
|
+
with: string;
|
|
558
|
+
without?: string;
|
|
559
|
+
}
|
|
560
|
+
/** The arms an {@link ArmWorkspaceDirs} covers, in dispatch order. */
|
|
561
|
+
export declare function armsOf(dirs: ArmWorkspaceDirs): readonly EvalArm[];
|
|
562
|
+
/**
|
|
563
|
+
* The directory segment for one arm. Throws rather than falling back to the arm
|
|
564
|
+
* NAME: a silent fallback would reinstate the unblinding this indirection exists
|
|
565
|
+
* to remove, and would do it invisibly.
|
|
566
|
+
*/
|
|
567
|
+
export declare function armDirSegment(dirs: ArmWorkspaceDirs, arm: EvalArm): string;
|
|
499
568
|
export interface StageEvalWorkspacesInput {
|
|
500
569
|
/** Parsed suite (Task 1). */
|
|
501
570
|
suite: EvalSuite;
|
|
502
571
|
/** Directory containing evals.json — the base for each eval's relative `files`. */
|
|
503
572
|
evalsDir: string;
|
|
504
|
-
/**
|
|
573
|
+
/** Per-run workspaces root — per-arm, per-eval dirs are created beneath it. */
|
|
505
574
|
workspacesRoot: string;
|
|
575
|
+
/**
|
|
576
|
+
* Opaque per-arm directory segments. Each arm gets its OWN copy of every
|
|
577
|
+
* workspace; see the note on the layout below for why that is not an
|
|
578
|
+
* optimization to undo.
|
|
579
|
+
*/
|
|
580
|
+
armDirs: ArmWorkspaceDirs;
|
|
506
581
|
}
|
|
507
582
|
/**
|
|
508
|
-
* Materialize each eval's declared input `files` into
|
|
509
|
-
* preserving relative structure.
|
|
510
|
-
* {@link EvalInputError} if a listed file does not exist (the eval cannot run
|
|
511
|
-
* Returns `workspacesRoot`.
|
|
583
|
+
* Materialize each eval's declared input `files` into
|
|
584
|
+
* `<workspacesRoot>/<armDir>/<id>/<relpath>`, preserving relative structure. Throws
|
|
585
|
+
* {@link EvalInputError} if a listed file does not exist (the eval cannot run
|
|
586
|
+
* without it). Returns `workspacesRoot`.
|
|
587
|
+
*
|
|
588
|
+
* EVERY eval gets a directory, including one that declares no `files` — it is
|
|
589
|
+
* simply left empty. An eval without a workspace used to leave the executor with
|
|
590
|
+
* no cwd of its own, so it ran inside the staged subject dir instead; for the
|
|
591
|
+
* skill-absent arm of a `--baseline` run that placed the control's cwd inside the
|
|
592
|
+
* very skill the arm exists to withhold. An empty dir costs nothing and keeps cwd
|
|
593
|
+
* shaped identically across both arms, which is what makes the A/B a comparison.
|
|
594
|
+
*
|
|
595
|
+
* WHY THE `<arm>` SEGMENT. The two arms of one eval are dispatched ADJACENTLY into
|
|
596
|
+
* a bounded-parallel pool, so they run at the same time. When they shared one
|
|
597
|
+
* directory, the control arm could simply `ls` and read whatever the treatment arm
|
|
598
|
+
* had just written — recovering the treatment's answer without ever touching the
|
|
599
|
+
* skill, and without producing a single detectable harness path. That is a channel
|
|
600
|
+
* BETWEEN the arms rather than into one of them, which is why auditing the four
|
|
601
|
+
* channels into a process (prompt, argv, cwd, env) did not surface it: each arm's
|
|
602
|
+
* own cwd was correct in isolation, and wrong as a pair. The arms must be
|
|
603
|
+
* byte-identical at start and unable to observe each other after it.
|
|
604
|
+
*
|
|
605
|
+
* WHY THE SEGMENT IS AN OPAQUE TOKEN and not the arm's name. It used to be the
|
|
606
|
+
* literal `with`/`without`, which made the executor's own working directory the
|
|
607
|
+
* loudest possible unblinding: the prompt tells each arm `Your working directory
|
|
608
|
+
* is …/vat-skill-test-ws-<token>/without/e1`, so the skill-absent arm was told, in
|
|
609
|
+
* the one string it cannot avoid reading, which side of the experiment it was on —
|
|
610
|
+
* while `buildExecutorPrompt`'s docblock promises it "must NEVER be told (directly
|
|
611
|
+
* or by implication) that it is being tested, evaluated, or graded". It also named
|
|
612
|
+
* the sibling: `../with/<id>/` was a guessable path to the treatment arm's live
|
|
613
|
+
* output. Independent random tokens fix both, and cost nothing.
|
|
512
614
|
*/
|
|
513
615
|
export declare function stageEvalWorkspaces(input: StageEvalWorkspacesInput): string;
|
|
514
616
|
//# sourceMappingURL=eval-inputs.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eval-inputs.d.ts","sourceRoot":"","sources":["../../src/skill-test/eval-inputs.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"eval-inputs.d.ts","sourceRoot":"","sources":["../../src/skill-test/eval-inputs.ts"],"names":[],"mappings":"AAEA,OAAO,EAA2B,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAC9E,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB;;;;;;;;;;;GAWG;AACH,qBAAa,cAAe,SAAQ,QAAQ;IAC1C,QAAQ,CAAC,MAAM,EAAG,WAAW,CAAU;gBAC3B,OAAO,EAAE,MAAM;CAG5B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEpD;AA2CD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAUrE;AAiDD,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gCAyDxB,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;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,GAAG,WAAW,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC,CAAC;AAE1E,8FAA8F;AAC9F,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAsB1D;AAED;;;;GAIG;AACH,MAAM,MAAM,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;AAEzC;;;;;;;;;GASG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,sEAAsE;AACtE,wBAAgB,MAAM,CAAC,IAAI,EAAE,gBAAgB,GAAG,SAAS,OAAO,EAAE,CAEjE;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,gBAAgB,EAAE,GAAG,EAAE,OAAO,GAAG,MAAM,CAU1E;AAED,MAAM,WAAW,wBAAwB;IACvC,6BAA6B;IAC7B,KAAK,EAAE,SAAS,CAAC;IACjB,mFAAmF;IACnF,QAAQ,EAAE,MAAM,CAAC;IACjB,+EAA+E;IAC/E,cAAc,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,OAAO,EAAE,gBAAgB,CAAC;CAC3B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,wBAAwB,GAAG,MAAM,CAK3E"}
|