@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.
Files changed (322) hide show
  1. package/README.md +5 -5
  2. package/dist/builder.d.ts.map +1 -1
  3. package/dist/builder.js +7 -17
  4. package/dist/builder.js.map +1 -1
  5. package/dist/content-type-routing.d.ts +32 -0
  6. package/dist/content-type-routing.d.ts.map +1 -1
  7. package/dist/content-type-routing.js +23 -0
  8. package/dist/content-type-routing.js.map +1 -1
  9. package/dist/files-config.d.ts +34 -1
  10. package/dist/files-config.d.ts.map +1 -1
  11. package/dist/files-config.js +277 -39
  12. package/dist/files-config.js.map +1 -1
  13. package/dist/fs-attribution.d.ts +45 -0
  14. package/dist/fs-attribution.d.ts.map +1 -0
  15. package/dist/fs-attribution.js +57 -0
  16. package/dist/fs-attribution.js.map +1 -0
  17. package/dist/import.d.ts.map +1 -1
  18. package/dist/import.js +0 -4
  19. package/dist/import.js.map +1 -1
  20. package/dist/index.d.ts +13 -8
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +25 -7
  23. package/dist/index.js.map +1 -1
  24. package/dist/inventory/detectors/declared-but-missing.d.ts +1 -1
  25. package/dist/inventory/detectors/declared-but-missing.d.ts.map +1 -1
  26. package/dist/inventory/detectors/marketplace-source-missing.d.ts +1 -1
  27. package/dist/inventory/detectors/marketplace-source-missing.d.ts.map +1 -1
  28. package/dist/inventory/detectors/present-but-undeclared.d.ts +1 -1
  29. package/dist/inventory/detectors/present-but-undeclared.d.ts.map +1 -1
  30. package/dist/inventory/detectors/reference-target-missing.d.ts +1 -1
  31. package/dist/inventory/detectors/reference-target-missing.d.ts.map +1 -1
  32. package/dist/inventory/index.d.ts +1 -1
  33. package/dist/inventory/index.d.ts.map +1 -1
  34. package/dist/inventory/index.js +1 -1
  35. package/dist/inventory/index.js.map +1 -1
  36. package/dist/inventory/serialize.d.ts +4 -4
  37. package/dist/inventory/serialize.d.ts.map +1 -1
  38. package/dist/inventory/serialize.js +6 -6
  39. package/dist/inventory/serialize.js.map +1 -1
  40. package/dist/inventory/types.d.ts +8 -0
  41. package/dist/inventory/types.d.ts.map +1 -1
  42. package/dist/inventory/types.js.map +1 -1
  43. package/dist/link-graph-members.d.ts +18 -0
  44. package/dist/link-graph-members.d.ts.map +1 -0
  45. package/dist/link-graph-members.js +18 -0
  46. package/dist/link-graph-members.js.map +1 -0
  47. package/dist/parsers/frontmatter-parser.d.ts.map +1 -1
  48. package/dist/parsers/frontmatter-parser.js +30 -6
  49. package/dist/parsers/frontmatter-parser.js.map +1 -1
  50. package/dist/plugin-distribution-layout.d.ts +70 -6
  51. package/dist/plugin-distribution-layout.d.ts.map +1 -1
  52. package/dist/plugin-distribution-layout.js +84 -11
  53. package/dist/plugin-distribution-layout.js.map +1 -1
  54. package/dist/post-build-checks.d.ts +38 -1
  55. package/dist/post-build-checks.d.ts.map +1 -1
  56. package/dist/post-build-checks.js +68 -17
  57. package/dist/post-build-checks.js.map +1 -1
  58. package/dist/projection/skill-extent.d.ts +247 -0
  59. package/dist/projection/skill-extent.d.ts.map +1 -0
  60. package/dist/projection/skill-extent.js +560 -0
  61. package/dist/projection/skill-extent.js.map +1 -0
  62. package/dist/schemas/agent-skill-frontmatter.js +1 -1
  63. package/dist/schemas/agent-skill-frontmatter.js.map +1 -1
  64. package/dist/schemas/allowed-tools.d.ts +31 -0
  65. package/dist/schemas/allowed-tools.d.ts.map +1 -0
  66. package/dist/schemas/allowed-tools.js +88 -0
  67. package/dist/schemas/allowed-tools.js.map +1 -0
  68. package/dist/schemas/index.d.ts +1 -0
  69. package/dist/schemas/index.d.ts.map +1 -1
  70. package/dist/schemas/index.js +1 -0
  71. package/dist/schemas/index.js.map +1 -1
  72. package/dist/schemas/installed-plugins-registry.d.ts.map +1 -1
  73. package/dist/schemas/installed-plugins-registry.js +7 -1
  74. package/dist/schemas/installed-plugins-registry.js.map +1 -1
  75. package/dist/schemas/marketplace-manifest.d.ts.map +1 -1
  76. package/dist/schemas/marketplace-manifest.js +17 -6
  77. package/dist/schemas/marketplace-manifest.js.map +1 -1
  78. package/dist/skill-identity.d.ts +18 -3
  79. package/dist/skill-identity.d.ts.map +1 -1
  80. package/dist/skill-identity.js +25 -6
  81. package/dist/skill-identity.js.map +1 -1
  82. package/dist/skill-packager.d.ts +144 -20
  83. package/dist/skill-packager.d.ts.map +1 -1
  84. package/dist/skill-packager.js +447 -105
  85. package/dist/skill-packager.js.map +1 -1
  86. package/dist/skill-source/content-hash.d.ts.map +1 -1
  87. package/dist/skill-source/content-hash.js +21 -10
  88. package/dist/skill-source/content-hash.js.map +1 -1
  89. package/dist/skill-source/fetch-cache.d.ts.map +1 -1
  90. package/dist/skill-source/fetch-cache.js +0 -5
  91. package/dist/skill-source/fetch-cache.js.map +1 -1
  92. package/dist/skill-source/git-clone.d.ts +1 -1
  93. package/dist/skill-source/git-clone.d.ts.map +1 -1
  94. package/dist/skill-source/git-clone.js +10 -10
  95. package/dist/skill-source/git-clone.js.map +1 -1
  96. package/dist/skill-source/sources/url-source.d.ts.map +1 -1
  97. package/dist/skill-source/sources/url-source.js +2 -2
  98. package/dist/skill-source/sources/url-source.js.map +1 -1
  99. package/dist/skill-source/stage.d.ts.map +1 -1
  100. package/dist/skill-source/stage.js +0 -6
  101. package/dist/skill-source/stage.js.map +1 -1
  102. package/dist/skill-test/baseline-delta.d.ts +1575 -0
  103. package/dist/skill-test/baseline-delta.d.ts.map +1 -0
  104. package/dist/skill-test/baseline-delta.js +272 -0
  105. package/dist/skill-test/baseline-delta.js.map +1 -0
  106. package/dist/skill-test/baseline-integrity.d.ts +944 -0
  107. package/dist/skill-test/baseline-integrity.d.ts.map +1 -0
  108. package/dist/skill-test/baseline-integrity.js +3090 -0
  109. package/dist/skill-test/baseline-integrity.js.map +1 -0
  110. package/dist/skill-test/build-hook.d.ts +3 -2
  111. package/dist/skill-test/build-hook.d.ts.map +1 -1
  112. package/dist/skill-test/build-hook.js +4 -5
  113. package/dist/skill-test/build-hook.js.map +1 -1
  114. package/dist/skill-test/configure-writer.js +1 -1
  115. package/dist/skill-test/configure-writer.js.map +1 -1
  116. package/dist/skill-test/declared-env.d.ts +5 -4
  117. package/dist/skill-test/declared-env.d.ts.map +1 -1
  118. package/dist/skill-test/declared-env.js +8 -9
  119. package/dist/skill-test/declared-env.js.map +1 -1
  120. package/dist/skill-test/eval-executor.d.ts +21 -5
  121. package/dist/skill-test/eval-executor.d.ts.map +1 -1
  122. package/dist/skill-test/eval-executor.js +6 -6
  123. package/dist/skill-test/eval-executor.js.map +1 -1
  124. package/dist/skill-test/eval-fragment.d.ts +106 -28
  125. package/dist/skill-test/eval-fragment.d.ts.map +1 -1
  126. package/dist/skill-test/eval-fragment.js +78 -16
  127. package/dist/skill-test/eval-fragment.js.map +1 -1
  128. package/dist/skill-test/eval-grader.d.ts +65 -7
  129. package/dist/skill-test/eval-grader.d.ts.map +1 -1
  130. package/dist/skill-test/eval-grader.js +263 -64
  131. package/dist/skill-test/eval-grader.js.map +1 -1
  132. package/dist/skill-test/eval-inputs.d.ts +110 -8
  133. package/dist/skill-test/eval-inputs.d.ts.map +1 -1
  134. package/dist/skill-test/eval-inputs.js +177 -22
  135. package/dist/skill-test/eval-inputs.js.map +1 -1
  136. package/dist/skill-test/eval-lint.d.ts +17 -4
  137. package/dist/skill-test/eval-lint.d.ts.map +1 -1
  138. package/dist/skill-test/eval-lint.js +22 -9
  139. package/dist/skill-test/eval-lint.js.map +1 -1
  140. package/dist/skill-test/eval-suite-isolation.d.ts.map +1 -1
  141. package/dist/skill-test/eval-suite-isolation.js +8 -5
  142. package/dist/skill-test/eval-suite-isolation.js.map +1 -1
  143. package/dist/skill-test/evals-template.d.ts +1 -1
  144. package/dist/skill-test/evals-template.d.ts.map +1 -1
  145. package/dist/skill-test/evals-template.js +1 -3
  146. package/dist/skill-test/evals-template.js.map +1 -1
  147. package/dist/skill-test/executor-prompt.d.ts +15 -7
  148. package/dist/skill-test/executor-prompt.d.ts.map +1 -1
  149. package/dist/skill-test/executor-prompt.js +10 -7
  150. package/dist/skill-test/executor-prompt.js.map +1 -1
  151. package/dist/skill-test/failure-reason.d.ts +113 -0
  152. package/dist/skill-test/failure-reason.d.ts.map +1 -0
  153. package/dist/skill-test/failure-reason.js +124 -0
  154. package/dist/skill-test/failure-reason.js.map +1 -0
  155. package/dist/skill-test/fragment-merge.d.ts +3 -20
  156. package/dist/skill-test/fragment-merge.d.ts.map +1 -1
  157. package/dist/skill-test/fragment-merge.js +67 -8
  158. package/dist/skill-test/fragment-merge.js.map +1 -1
  159. package/dist/skill-test/grader-prompt.d.ts +29 -9
  160. package/dist/skill-test/grader-prompt.d.ts.map +1 -1
  161. package/dist/skill-test/grader-prompt.js +264 -68
  162. package/dist/skill-test/grader-prompt.js.map +1 -1
  163. package/dist/skill-test/grader-text.d.ts +145 -0
  164. package/dist/skill-test/grader-text.d.ts.map +1 -0
  165. package/dist/skill-test/grader-text.js +410 -0
  166. package/dist/skill-test/grader-text.js.map +1 -0
  167. package/dist/skill-test/grading-adapter.d.ts +38 -2
  168. package/dist/skill-test/grading-adapter.d.ts.map +1 -1
  169. package/dist/skill-test/grading-adapter.js +57 -9
  170. package/dist/skill-test/grading-adapter.js.map +1 -1
  171. package/dist/skill-test/grading-schema.d.ts +160 -5
  172. package/dist/skill-test/grading-schema.d.ts.map +1 -1
  173. package/dist/skill-test/grading-schema.js +66 -7
  174. package/dist/skill-test/grading-schema.js.map +1 -1
  175. package/dist/skill-test/harness-location.d.ts +3 -2
  176. package/dist/skill-test/harness-location.d.ts.map +1 -1
  177. package/dist/skill-test/harness-location.js +5 -16
  178. package/dist/skill-test/harness-location.js.map +1 -1
  179. package/dist/skill-test/index.d.ts +2 -2
  180. package/dist/skill-test/index.d.ts.map +1 -1
  181. package/dist/skill-test/index.js +2 -2
  182. package/dist/skill-test/index.js.map +1 -1
  183. package/dist/skill-test/lock.d.ts +58 -1
  184. package/dist/skill-test/lock.d.ts.map +1 -1
  185. package/dist/skill-test/lock.js +78 -6
  186. package/dist/skill-test/lock.js.map +1 -1
  187. package/dist/skill-test/pipeline.d.ts +19 -1
  188. package/dist/skill-test/pipeline.d.ts.map +1 -1
  189. package/dist/skill-test/pipeline.js +21 -10
  190. package/dist/skill-test/pipeline.js.map +1 -1
  191. package/dist/skill-test/preflight.d.ts +1 -1
  192. package/dist/skill-test/preflight.d.ts.map +1 -1
  193. package/dist/skill-test/preflight.js +59 -16
  194. package/dist/skill-test/preflight.js.map +1 -1
  195. package/dist/skill-test/prompt-invariants.d.ts +4 -2
  196. package/dist/skill-test/prompt-invariants.d.ts.map +1 -1
  197. package/dist/skill-test/prompt-invariants.js +5 -4
  198. package/dist/skill-test/prompt-invariants.js.map +1 -1
  199. package/dist/skill-test/run-harness.d.ts +665 -85
  200. package/dist/skill-test/run-harness.d.ts.map +1 -1
  201. package/dist/skill-test/run-harness.js +1522 -237
  202. package/dist/skill-test/run-harness.js.map +1 -1
  203. package/dist/skill-test/staging.d.ts +20 -8
  204. package/dist/skill-test/staging.d.ts.map +1 -1
  205. package/dist/skill-test/staging.js +25 -18
  206. package/dist/skill-test/staging.js.map +1 -1
  207. package/dist/skill-test/tier-plan.d.ts +1 -1
  208. package/dist/skill-test/tier-plan.js +1 -1
  209. package/dist/skill-test/tool-eval-schema.d.ts +6 -6
  210. package/dist/skill-test/tool-eval-schema.js +2 -2
  211. package/dist/skill-test/vendor-manifest.d.ts +2 -1
  212. package/dist/skill-test/vendor-manifest.d.ts.map +1 -1
  213. package/dist/skill-test/vendor-manifest.js +10 -10
  214. package/dist/skill-test/vendor-manifest.js.map +1 -1
  215. package/dist/test-input.d.ts +59 -8
  216. package/dist/test-input.d.ts.map +1 -1
  217. package/dist/test-input.js +64 -19
  218. package/dist/test-input.js.map +1 -1
  219. package/dist/validators/agent-instruction-presence.d.ts +1 -1
  220. package/dist/validators/agent-instruction-presence.d.ts.map +1 -1
  221. package/dist/validators/agent-instruction-presence.js +45 -2
  222. package/dist/validators/agent-instruction-presence.js.map +1 -1
  223. package/dist/validators/bundled-resource-link-detection.d.ts +6 -4
  224. package/dist/validators/bundled-resource-link-detection.d.ts.map +1 -1
  225. package/dist/validators/bundled-resource-link-detection.js +39 -39
  226. package/dist/validators/bundled-resource-link-detection.js.map +1 -1
  227. package/dist/validators/compat-detectors.d.ts +18 -1
  228. package/dist/validators/compat-detectors.d.ts.map +1 -1
  229. package/dist/validators/compat-detectors.js +47 -20
  230. package/dist/validators/compat-detectors.js.map +1 -1
  231. package/dist/validators/cross-skill-dependency-detection.d.ts +1 -1
  232. package/dist/validators/cross-skill-dependency-detection.d.ts.map +1 -1
  233. package/dist/validators/cross-skill-dependency-detection.js +1 -1
  234. package/dist/validators/cross-skill-dependency-detection.js.map +1 -1
  235. package/dist/validators/description-style-detection.d.ts +1 -1
  236. package/dist/validators/description-style-detection.d.ts.map +1 -1
  237. package/dist/validators/description-style-detection.js +1 -1
  238. package/dist/validators/description-style-detection.js.map +1 -1
  239. package/dist/validators/format-detection.d.ts +3 -0
  240. package/dist/validators/format-detection.d.ts.map +1 -1
  241. package/dist/validators/format-detection.js +41 -26
  242. package/dist/validators/format-detection.js.map +1 -1
  243. package/dist/validators/frontmatter-validation.d.ts +1 -1
  244. package/dist/validators/frontmatter-validation.d.ts.map +1 -1
  245. package/dist/validators/frontmatter-validation.js +2 -2
  246. package/dist/validators/frontmatter-validation.js.map +1 -1
  247. package/dist/validators/imperative-body-detection.d.ts +1 -1
  248. package/dist/validators/imperative-body-detection.d.ts.map +1 -1
  249. package/dist/validators/imperative-body-detection.js +1 -1
  250. package/dist/validators/imperative-body-detection.js.map +1 -1
  251. package/dist/validators/index.d.ts +1 -1
  252. package/dist/validators/index.d.ts.map +1 -1
  253. package/dist/validators/kebab-case-detection.d.ts +1 -1
  254. package/dist/validators/kebab-case-detection.d.ts.map +1 -1
  255. package/dist/validators/kebab-case-detection.js +1 -1
  256. package/dist/validators/kebab-case-detection.js.map +1 -1
  257. package/dist/validators/marketplace-validator.d.ts.map +1 -1
  258. package/dist/validators/marketplace-validator.js +7 -2
  259. package/dist/validators/marketplace-validator.js.map +1 -1
  260. package/dist/validators/mcp-tool-qualification.d.ts +158 -0
  261. package/dist/validators/mcp-tool-qualification.d.ts.map +1 -0
  262. package/dist/validators/mcp-tool-qualification.js +467 -0
  263. package/dist/validators/mcp-tool-qualification.js.map +1 -0
  264. package/dist/validators/packaged-size-limit.d.ts +296 -0
  265. package/dist/validators/packaged-size-limit.d.ts.map +1 -0
  266. package/dist/validators/packaged-size-limit.js +492 -0
  267. package/dist/validators/packaged-size-limit.js.map +1 -0
  268. package/dist/validators/packaging-validator.d.ts +149 -10
  269. package/dist/validators/packaging-validator.d.ts.map +1 -1
  270. package/dist/validators/packaging-validator.js +371 -55
  271. package/dist/validators/packaging-validator.js.map +1 -1
  272. package/dist/validators/plugin-hosted-shape.d.ts +4 -2
  273. package/dist/validators/plugin-hosted-shape.d.ts.map +1 -1
  274. package/dist/validators/plugin-hosted-shape.js +6 -7
  275. package/dist/validators/plugin-hosted-shape.js.map +1 -1
  276. package/dist/validators/plugin-recommended-fields.d.ts +1 -1
  277. package/dist/validators/plugin-recommended-fields.d.ts.map +1 -1
  278. package/dist/validators/plugin-recommended-fields.js +1 -1
  279. package/dist/validators/plugin-recommended-fields.js.map +1 -1
  280. package/dist/validators/referenced-path-missing.d.ts +211 -0
  281. package/dist/validators/referenced-path-missing.d.ts.map +1 -0
  282. package/dist/validators/referenced-path-missing.js +378 -0
  283. package/dist/validators/referenced-path-missing.js.map +1 -0
  284. package/dist/validators/registry-validator.d.ts.map +1 -1
  285. package/dist/validators/registry-validator.js +1 -2
  286. package/dist/validators/registry-validator.js.map +1 -1
  287. package/dist/validators/rule-engine/index.d.ts +1 -1
  288. package/dist/validators/rule-engine/rule-context.d.ts +20 -3
  289. package/dist/validators/rule-engine/rule-context.d.ts.map +1 -1
  290. package/dist/validators/rule-engine/rule-context.js +3 -1
  291. package/dist/validators/rule-engine/rule-context.js.map +1 -1
  292. package/dist/validators/rule-engine/rule-engine.d.ts +2 -2
  293. package/dist/validators/rule-engine/rule-engine.d.ts.map +1 -1
  294. package/dist/validators/rule-engine/rule-engine.js +52 -13
  295. package/dist/validators/rule-engine/rule-engine.js.map +1 -1
  296. package/dist/validators/skill-validator.d.ts.map +1 -1
  297. package/dist/validators/skill-validator.js +91 -54
  298. package/dist/validators/skill-validator.js.map +1 -1
  299. package/dist/validators/source-only-codes.js +1 -1
  300. package/dist/validators/source-only-codes.js.map +1 -1
  301. package/dist/validators/types.d.ts +21 -1
  302. package/dist/validators/types.d.ts.map +1 -1
  303. package/dist/validators/unified-validator.d.ts.map +1 -1
  304. package/dist/validators/unified-validator.js +4 -5
  305. package/dist/validators/unified-validator.js.map +1 -1
  306. package/dist/validators/validation-rules.d.ts +4 -4
  307. package/dist/validators/validation-rules.d.ts.map +1 -1
  308. package/dist/validators/validation-rules.js +9 -38
  309. package/dist/validators/validation-rules.js.map +1 -1
  310. package/dist/validators/walker-to-issues.d.ts +9 -3
  311. package/dist/validators/walker-to-issues.d.ts.map +1 -1
  312. package/dist/validators/walker-to-issues.js +64 -19
  313. package/dist/validators/walker-to-issues.js.map +1 -1
  314. package/dist/walk-link-graph.d.ts +64 -5
  315. package/dist/walk-link-graph.d.ts.map +1 -1
  316. package/dist/walk-link-graph.js +376 -92
  317. package/dist/walk-link-graph.js.map +1 -1
  318. package/package.json +14 -22
  319. package/dist/skill-test/exit-codes.d.ts +0 -97
  320. package/dist/skill-test/exit-codes.d.ts.map +0 -1
  321. package/dist/skill-test/exit-codes.js +0 -141
  322. package/dist/skill-test/exit-codes.js.map +0 -1
@@ -1,16 +1,53 @@
1
- import { existsSync, readFileSync, unlinkSync } from 'node:fs';
2
- import { mkdirSyncReal, parseStreamJsonTranscript, safePath, spawnHeadlessClaude } from '@vibe-agent-toolkit/utils';
3
- import { EvalFragmentError, parseEvalFragment } from './eval-fragment.js';
4
- import { InternalHarnessError } from './exit-codes.js';
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` (issue #145
12
- * Task 8). `graderOutDir` is vat-only and separate from the skill sandbox the
13
- * executor ran in (Task 7) — the grader's `sandboxDir` --add-dir is
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} (exit 1) — never laundered into a
59
+ * thrown as {@link InternalHarnessError} (`ERROR`, `Reason: internal`) — never laundered into a
23
60
  * passing (or even a valid failing) verdict.
24
61
  *
25
- * Once the fragment file exists, shape/JSON problems throw
26
- * {@link EvalFragmentError} (via {@link parseEvalFragment}) and a nonce that
27
- * doesn't match this run's expected nonce throws {@link GradingNonceError} —
28
- * both distinct from harness breakage because the grader DID run and produce
29
- * *something*, just not something we can trust.
30
- */
31
- /**
32
- * Adapt the grader's stdout `onProgress` sink into the `onWarn` callback
33
- * {@link parseEvalFragment} expects (used only when it drops malformed friction
34
- * items). Extracted so the ternary does not add a branch to `runGraderForEval`'s
35
- * cognitive complexity budget.
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
- mkdirSyncReal(input.graderOutDir, { recursive: true });
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
- const prompt = buildGraderPrompt({
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: input.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) before
62
- // spawning, so a regressed buildGraderPrompt is caught here, not by a grader
63
- // that silently misbehaves.
64
- assertGraderPromptInvariants(prompt, input.transcript);
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?.(chunk);
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 raw = readAndConsumeFragmentFile(fragmentOut, input.evalId, spawnResult.status);
113
- const fragment = parseEvalFragment(raw, fragmentWarnRouter(input.onProgress));
114
- // Integrity gate: a missing/wrong nonce means this fragment was not produced
115
- // by the grader we prompted for THIS run — most likely forged or left behind
116
- // by untrusted skill code — so the verdict cannot be trusted, hard error.
117
- if (fragment.runNonce !== input.nonce) {
118
- throw new GradingNonceError(`eval "${input.evalId}" fragment \`runNonce\` does not match this run`);
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 JSON into memory and unlink it immediately —
125
- * consume-on-read. Split out of {@link runGraderForEval} to keep its cognitive
126
- * complexity within budget. Throws {@link InternalHarnessError} if the grader
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 unlink is the security-relevant half: the grader dir is same-uid (see
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). The read
134
- * here is the ONLY read of the file; all downstream logic runs off the returned
135
- * value. Best-effort: a failed unlink is not a run failure (end-of-run cleanup
136
- * removes the whole dir), and true isolation from same-uid code is issue #149.
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
- let raw;
242
+ const text = readFileSync(fragmentOut, 'utf-8');
144
243
  try {
145
- // eslint-disable-next-line security/detect-non-literal-fs-filename -- fragmentOut is our own derived path (joinUnderRoot-guarded)
146
- raw = JSON.parse(readFileSync(fragmentOut, 'utf-8'));
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
- throw new EvalFragmentError(`grader fragment for eval "${evalId}" at ${fragmentOut} is not valid JSON: ${err instanceof Error ? err.message : String(err)}`);
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 raw;
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":"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"}
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
- /** Raised for any eval-input problem (bad JSON, schema failure, missing input file). Maps to exit 2. */
3
- export declare class EvalInputError extends Error {
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 (issue #145 Phase T). Derived from
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
- /** `<harnessRoot>/workspaces` — per-eval dirs are created beneath it. */
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 `<workspacesRoot>/<id>/<relpath>`,
509
- * preserving relative structure. Evals without `files` are skipped. Throws
510
- * {@link EvalInputError} if a listed file does not exist (the eval cannot run without it).
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":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,wGAAwG;AACxG,qBAAa,cAAe,SAAQ,KAAK;gBAC3B,OAAO,EAAE,MAAM;CAI5B;AAyBD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAUrE;AAWD,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gCAsDxB,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,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,CAoC3E"}
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"}