@sanity/ailf 0.5.0 → 2.0.0

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 (377) hide show
  1. package/README.md +0 -1
  2. package/config/features.ts +23 -0
  3. package/config/models.ts +95 -0
  4. package/config/prompts.ts +16 -0
  5. package/config/rubrics.ts +225 -0
  6. package/config/schedules.ts +47 -0
  7. package/config/sinks.ts +37 -0
  8. package/config/sources.ts +21 -0
  9. package/config/thresholds.ts +61 -0
  10. package/dist/_vendor/ailf-core/config-helpers.d.ts +171 -0
  11. package/dist/_vendor/ailf-core/config-helpers.js +170 -0
  12. package/dist/_vendor/ailf-core/env-helper.d.ts +35 -0
  13. package/dist/_vendor/ailf-core/env-helper.js +45 -0
  14. package/dist/_vendor/ailf-core/examples/index.d.ts +16 -0
  15. package/dist/_vendor/ailf-core/examples/index.js +25 -0
  16. package/dist/_vendor/ailf-core/index.d.ts +3 -0
  17. package/dist/_vendor/ailf-core/index.js +5 -0
  18. package/dist/_vendor/ailf-core/ports/context.d.ts +17 -2
  19. package/dist/_vendor/ailf-core/ports/doc-fetcher.d.ts +2 -2
  20. package/dist/_vendor/ailf-core/ports/index.d.ts +2 -1
  21. package/dist/_vendor/ailf-core/ports/mode-handler.d.ts +129 -0
  22. package/dist/_vendor/ailf-core/ports/mode-handler.js +19 -0
  23. package/dist/_vendor/ailf-core/ports/task-source.d.ts +16 -122
  24. package/dist/_vendor/ailf-core/ports/task-source.js +7 -7
  25. package/dist/_vendor/ailf-core/schemas/eval-config.d.ts +8 -2
  26. package/dist/_vendor/ailf-core/schemas/eval-config.js +17 -2
  27. package/dist/_vendor/ailf-core/schemas/pipeline-request.d.ts +9 -3
  28. package/dist/_vendor/ailf-core/schemas/pipeline-request.js +8 -1
  29. package/dist/_vendor/ailf-core/schemas/pipeline.d.ts +14 -31
  30. package/dist/_vendor/ailf-core/schemas/pipeline.js +17 -9
  31. package/dist/_vendor/ailf-core/schemas/schedules.d.ts +14 -4
  32. package/dist/_vendor/ailf-core/schemas/schedules.js +6 -2
  33. package/dist/_vendor/ailf-core/schemas/sinks.d.ts +1 -1
  34. package/dist/_vendor/ailf-core/services/comparison-formatters.js +57 -19
  35. package/dist/_vendor/ailf-core/services/index.d.ts +2 -1
  36. package/dist/_vendor/ailf-core/services/index.js +2 -1
  37. package/dist/_vendor/ailf-core/services/scoring-engine.d.ts +153 -0
  38. package/dist/_vendor/ailf-core/services/scoring-engine.js +237 -0
  39. package/dist/_vendor/ailf-core/services/scoring.d.ts +15 -2
  40. package/dist/_vendor/ailf-core/services/scoring.js +25 -15
  41. package/dist/_vendor/ailf-core/types/branded-ids.d.ts +137 -0
  42. package/dist/_vendor/ailf-core/types/branded-ids.js +136 -0
  43. package/dist/_vendor/ailf-core/types/eval-mode-config.d.ts +150 -0
  44. package/dist/_vendor/ailf-core/types/eval-mode-config.js +24 -0
  45. package/dist/_vendor/ailf-core/types/generalized-task.d.ts +332 -0
  46. package/dist/_vendor/ailf-core/types/generalized-task.js +13 -0
  47. package/dist/_vendor/ailf-core/types/index.d.ts +45 -83
  48. package/dist/_vendor/ailf-core/types/index.js +8 -1
  49. package/dist/_vendor/ailf-core/types/plugin-registry.d.ts +257 -0
  50. package/dist/_vendor/ailf-core/types/plugin-registry.js +185 -0
  51. package/dist/_vendor/ailf-core/types/storage-schema.d.ts +199 -0
  52. package/dist/_vendor/ailf-core/types/storage-schema.js +39 -0
  53. package/dist/_vendor/ailf-core/types/task-graph.d.ts +86 -0
  54. package/dist/_vendor/ailf-core/types/task-graph.js +20 -0
  55. package/dist/_vendor/ailf-core/types/trace.d.ts +118 -0
  56. package/dist/_vendor/ailf-core/types/trace.js +18 -0
  57. package/dist/_vendor/ailf-core/types/variable-envelope.d.ts +80 -0
  58. package/dist/_vendor/ailf-core/types/variable-envelope.js +16 -0
  59. package/dist/_vendor/ailf-shared/dimension-names.d.ts +5 -18
  60. package/dist/_vendor/ailf-shared/dimension-names.js +6 -24
  61. package/dist/_vendor/ailf-shared/eval-modes.d.ts +38 -6
  62. package/dist/_vendor/ailf-shared/eval-modes.js +26 -2
  63. package/dist/_vendor/ailf-shared/index.d.ts +0 -1
  64. package/dist/_vendor/ailf-shared/index.js +0 -1
  65. package/dist/adapters/api-client/build-request.js +14 -13
  66. package/dist/adapters/config-sources/file-config-adapter.d.ts +20 -11
  67. package/dist/adapters/config-sources/file-config-adapter.js +39 -12
  68. package/dist/adapters/config-sources/index.d.ts +2 -0
  69. package/dist/adapters/config-sources/index.js +1 -0
  70. package/dist/adapters/config-sources/ts-config-loader.d.ts +59 -0
  71. package/dist/adapters/config-sources/ts-config-loader.js +141 -0
  72. package/dist/adapters/doc-fetchers/sanity-doc-fetcher.d.ts +3 -2
  73. package/dist/adapters/doc-fetchers/sanity-doc-fetcher.js +7 -2
  74. package/dist/adapters/task-sources/composite-task-source.d.ts +3 -3
  75. package/dist/adapters/task-sources/composite-task-source.js +1 -1
  76. package/dist/adapters/task-sources/content-lake-task-source.d.ts +7 -6
  77. package/dist/adapters/task-sources/content-lake-task-source.js +35 -39
  78. package/dist/adapters/task-sources/index.d.ts +3 -2
  79. package/dist/adapters/task-sources/index.js +3 -2
  80. package/dist/adapters/task-sources/repo-schemas.d.ts +218 -16
  81. package/dist/adapters/task-sources/repo-schemas.js +227 -19
  82. package/dist/adapters/task-sources/repo-task-source.d.ts +16 -12
  83. package/dist/adapters/task-sources/repo-task-source.js +92 -80
  84. package/dist/adapters/task-sources/repo-validation.d.ts +36 -5
  85. package/dist/adapters/task-sources/repo-validation.js +126 -5
  86. package/dist/adapters/task-sources/task-file-loader.d.ts +64 -0
  87. package/dist/adapters/task-sources/task-file-loader.js +83 -0
  88. package/dist/adapters/task-sources/yaml-task-source.d.ts +6 -6
  89. package/dist/adapters/task-sources/yaml-task-source.js +19 -16
  90. package/dist/cli.js +0 -2
  91. package/dist/commands/baseline.js +4 -1
  92. package/dist/commands/calculate-scores.js +1 -1
  93. package/dist/commands/coverage-audit.js +9 -1
  94. package/dist/commands/explain-handler.js +25 -23
  95. package/dist/commands/fetch-docs.js +3 -2
  96. package/dist/commands/generate-configs.js +1 -1
  97. package/dist/commands/init.d.ts +6 -4
  98. package/dist/commands/init.js +302 -23
  99. package/dist/commands/interactive.js +11 -7
  100. package/dist/commands/pipeline-action.d.ts +2 -0
  101. package/dist/commands/pipeline-action.js +16 -6
  102. package/dist/commands/pipeline.d.ts +1 -0
  103. package/dist/commands/pipeline.js +4 -2
  104. package/dist/commands/pr-comment.js +1 -1
  105. package/dist/commands/publish.js +2 -2
  106. package/dist/commands/readiness-report.js +13 -6
  107. package/dist/commands/validate-tasks.d.ts +2 -2
  108. package/dist/commands/validate-tasks.js +26 -15
  109. package/dist/composition-root.d.ts +13 -1
  110. package/dist/composition-root.js +99 -4
  111. package/dist/index.d.ts +41 -0
  112. package/dist/index.js +48 -0
  113. package/dist/orchestration/build-app-context.js +1 -0
  114. package/dist/orchestration/build-step-sequence.js +28 -8
  115. package/dist/orchestration/steps/calculate-scores-step.js +24 -11
  116. package/dist/orchestration/steps/fetch-docs-step.js +8 -7
  117. package/dist/orchestration/steps/gap-analysis-step.js +8 -7
  118. package/dist/orchestration/steps/generate-configs-step.d.ts +16 -3
  119. package/dist/orchestration/steps/generate-configs-step.js +261 -51
  120. package/dist/orchestration/steps/grader-consistency-step.js +7 -4
  121. package/dist/orchestration/steps/mirror-repo-tasks-step.js +1 -1
  122. package/dist/orchestration/steps/readiness-step.js +5 -6
  123. package/dist/orchestration/steps/run-eval-step.d.ts +1 -2
  124. package/dist/orchestration/steps/run-eval-step.js +8 -7
  125. package/dist/pipeline/cache.d.ts +1 -1
  126. package/dist/pipeline/cache.js +36 -8
  127. package/dist/pipeline/calculate-scores.d.ts +2 -4
  128. package/dist/pipeline/calculate-scores.js +43 -113
  129. package/dist/pipeline/checks.js +2 -2
  130. package/dist/pipeline/compare.js +8 -8
  131. package/dist/pipeline/compiler/__tests__/agent-harness-handler.test.d.ts +10 -0
  132. package/dist/pipeline/compiler/__tests__/agent-harness-handler.test.js +288 -0
  133. package/dist/pipeline/compiler/__tests__/assertion-mapper.test.d.ts +9 -0
  134. package/dist/pipeline/compiler/__tests__/assertion-mapper.test.js +145 -0
  135. package/dist/pipeline/compiler/__tests__/knowledge-probe-handler.test.d.ts +10 -0
  136. package/dist/pipeline/compiler/__tests__/knowledge-probe-handler.test.js +314 -0
  137. package/dist/pipeline/compiler/__tests__/literacy-handler.test.d.ts +10 -0
  138. package/dist/pipeline/compiler/__tests__/literacy-handler.test.js +486 -0
  139. package/dist/pipeline/compiler/__tests__/mcp-server-handler.test.d.ts +10 -0
  140. package/dist/pipeline/compiler/__tests__/mcp-server-handler.test.js +392 -0
  141. package/dist/pipeline/compiler/__tests__/promptfoo-compiler.test.d.ts +9 -0
  142. package/dist/pipeline/compiler/__tests__/promptfoo-compiler.test.js +333 -0
  143. package/dist/pipeline/compiler/__tests__/sandbox-and-fixtures.test.d.ts +12 -0
  144. package/dist/pipeline/compiler/__tests__/sandbox-and-fixtures.test.js +210 -0
  145. package/dist/pipeline/compiler/__tests__/scoring-and-presets.test.d.ts +7 -0
  146. package/dist/pipeline/compiler/__tests__/scoring-and-presets.test.js +404 -0
  147. package/dist/pipeline/compiler/__tests__/scoring-bridge.test.d.ts +10 -0
  148. package/dist/pipeline/compiler/__tests__/scoring-bridge.test.js +184 -0
  149. package/dist/pipeline/compiler/__tests__/task-graph-builder.test.d.ts +8 -0
  150. package/dist/pipeline/compiler/__tests__/task-graph-builder.test.js +301 -0
  151. package/dist/pipeline/compiler/__tests__/telemetry.test.d.ts +9 -0
  152. package/dist/pipeline/compiler/__tests__/telemetry.test.js +503 -0
  153. package/dist/pipeline/compiler/assertion-mapper.d.ts +58 -0
  154. package/dist/pipeline/compiler/assertion-mapper.js +175 -0
  155. package/dist/pipeline/compiler/compiler-to-yaml.d.ts +51 -0
  156. package/dist/pipeline/compiler/compiler-to-yaml.js +222 -0
  157. package/dist/pipeline/compiler/config-loader.d.ts +56 -0
  158. package/dist/pipeline/compiler/config-loader.js +111 -0
  159. package/dist/pipeline/compiler/fixture-resolver.d.ts +41 -0
  160. package/dist/pipeline/compiler/fixture-resolver.js +113 -0
  161. package/dist/pipeline/compiler/hash.d.ts +11 -0
  162. package/dist/pipeline/compiler/hash.js +18 -0
  163. package/dist/pipeline/compiler/ignore-fields.d.ts +53 -0
  164. package/dist/pipeline/compiler/ignore-fields.js +113 -0
  165. package/dist/pipeline/compiler/index.d.ts +29 -0
  166. package/dist/pipeline/compiler/index.js +45 -0
  167. package/dist/pipeline/compiler/literacy-bridge.d.ts +102 -0
  168. package/dist/pipeline/compiler/literacy-bridge.js +172 -0
  169. package/dist/pipeline/compiler/mode-bases/agent-harness.d.ts +10 -0
  170. package/dist/pipeline/compiler/mode-bases/agent-harness.js +21 -0
  171. package/dist/pipeline/compiler/mode-bases/index.d.ts +4 -0
  172. package/dist/pipeline/compiler/mode-bases/index.js +4 -0
  173. package/dist/pipeline/compiler/mode-bases/knowledge-probe.d.ts +10 -0
  174. package/dist/pipeline/compiler/mode-bases/knowledge-probe.js +22 -0
  175. package/dist/pipeline/compiler/mode-bases/literacy.d.ts +12 -0
  176. package/dist/pipeline/compiler/mode-bases/literacy.js +78 -0
  177. package/dist/pipeline/compiler/mode-bases/mcp-server.d.ts +10 -0
  178. package/dist/pipeline/compiler/mode-bases/mcp-server.js +70 -0
  179. package/dist/pipeline/compiler/mode-handlers/__fixtures__/agent-harness-example-tasks.d.ts +14 -0
  180. package/dist/pipeline/compiler/mode-handlers/__fixtures__/agent-harness-example-tasks.js +152 -0
  181. package/dist/pipeline/compiler/mode-handlers/__fixtures__/knowledge-probe-example-tasks.d.ts +32 -0
  182. package/dist/pipeline/compiler/mode-handlers/__fixtures__/knowledge-probe-example-tasks.js +176 -0
  183. package/dist/pipeline/compiler/mode-handlers/__fixtures__/mcp-example-tasks.d.ts +49 -0
  184. package/dist/pipeline/compiler/mode-handlers/__fixtures__/mcp-example-tasks.js +259 -0
  185. package/dist/pipeline/compiler/mode-handlers/agent-harness/assertions.d.ts +43 -0
  186. package/dist/pipeline/compiler/mode-handlers/agent-harness/assertions.js +187 -0
  187. package/dist/pipeline/compiler/mode-handlers/agent-harness/compiler.d.ts +19 -0
  188. package/dist/pipeline/compiler/mode-handlers/agent-harness/compiler.js +138 -0
  189. package/dist/pipeline/compiler/mode-handlers/agent-harness/index.d.ts +16 -0
  190. package/dist/pipeline/compiler/mode-handlers/agent-harness/index.js +43 -0
  191. package/dist/pipeline/compiler/mode-handlers/agent-harness/prompts.d.ts +9 -0
  192. package/dist/pipeline/compiler/mode-handlers/agent-harness/prompts.js +29 -0
  193. package/dist/pipeline/compiler/mode-handlers/agent-harness/sandbox.d.ts +12 -0
  194. package/dist/pipeline/compiler/mode-handlers/agent-harness/sandbox.js +82 -0
  195. package/dist/pipeline/compiler/mode-handlers/agent-harness/tool-presets.d.ts +4 -0
  196. package/dist/pipeline/compiler/mode-handlers/agent-harness/tool-presets.js +19 -0
  197. package/dist/pipeline/compiler/mode-handlers/agent-harness/types.d.ts +49 -0
  198. package/dist/pipeline/compiler/mode-handlers/agent-harness/types.js +4 -0
  199. package/dist/pipeline/compiler/mode-handlers/agent-harness/validation.d.ts +9 -0
  200. package/dist/pipeline/compiler/mode-handlers/agent-harness/validation.js +16 -0
  201. package/dist/pipeline/compiler/mode-handlers/index.d.ts +15 -0
  202. package/dist/pipeline/compiler/mode-handlers/index.js +19 -0
  203. package/dist/pipeline/compiler/mode-handlers/knowledge-probe/assertions.d.ts +16 -0
  204. package/dist/pipeline/compiler/mode-handlers/knowledge-probe/assertions.js +61 -0
  205. package/dist/pipeline/compiler/mode-handlers/knowledge-probe/compiler.d.ts +18 -0
  206. package/dist/pipeline/compiler/mode-handlers/knowledge-probe/compiler.js +112 -0
  207. package/dist/pipeline/compiler/mode-handlers/knowledge-probe/index.d.ts +26 -0
  208. package/dist/pipeline/compiler/mode-handlers/knowledge-probe/index.js +49 -0
  209. package/dist/pipeline/compiler/mode-handlers/knowledge-probe/prompts.d.ts +9 -0
  210. package/dist/pipeline/compiler/mode-handlers/knowledge-probe/prompts.js +28 -0
  211. package/dist/pipeline/compiler/mode-handlers/knowledge-probe/types.d.ts +44 -0
  212. package/dist/pipeline/compiler/mode-handlers/knowledge-probe/types.js +4 -0
  213. package/dist/pipeline/compiler/mode-handlers/knowledge-probe/validation.d.ts +9 -0
  214. package/dist/pipeline/compiler/mode-handlers/knowledge-probe/validation.js +24 -0
  215. package/dist/pipeline/compiler/mode-handlers/literacy/assertions.d.ts +18 -0
  216. package/dist/pipeline/compiler/mode-handlers/literacy/assertions.js +118 -0
  217. package/dist/pipeline/compiler/mode-handlers/literacy/compiler.d.ts +14 -0
  218. package/dist/pipeline/compiler/mode-handlers/literacy/compiler.js +105 -0
  219. package/dist/pipeline/compiler/mode-handlers/literacy/index.d.ts +11 -0
  220. package/dist/pipeline/compiler/mode-handlers/literacy/index.js +38 -0
  221. package/dist/pipeline/compiler/mode-handlers/literacy/prompts.d.ts +9 -0
  222. package/dist/pipeline/compiler/mode-handlers/literacy/prompts.js +74 -0
  223. package/dist/pipeline/compiler/mode-handlers/literacy/types.d.ts +41 -0
  224. package/dist/pipeline/compiler/mode-handlers/literacy/types.js +4 -0
  225. package/dist/pipeline/compiler/mode-handlers/literacy/validation.d.ts +12 -0
  226. package/dist/pipeline/compiler/mode-handlers/literacy/validation.js +28 -0
  227. package/dist/pipeline/compiler/mode-handlers/mcp-server/assertions.d.ts +42 -0
  228. package/dist/pipeline/compiler/mode-handlers/mcp-server/assertions.js +334 -0
  229. package/dist/pipeline/compiler/mode-handlers/mcp-server/compiler.d.ts +19 -0
  230. package/dist/pipeline/compiler/mode-handlers/mcp-server/compiler.js +100 -0
  231. package/dist/pipeline/compiler/mode-handlers/mcp-server/index.d.ts +27 -0
  232. package/dist/pipeline/compiler/mode-handlers/mcp-server/index.js +54 -0
  233. package/dist/pipeline/compiler/mode-handlers/mcp-server/prompts.d.ts +8 -0
  234. package/dist/pipeline/compiler/mode-handlers/mcp-server/prompts.js +28 -0
  235. package/dist/pipeline/compiler/mode-handlers/mcp-server/provider-config.d.ts +28 -0
  236. package/dist/pipeline/compiler/mode-handlers/mcp-server/provider-config.js +104 -0
  237. package/dist/pipeline/compiler/mode-handlers/mcp-server/types.d.ts +37 -0
  238. package/dist/pipeline/compiler/mode-handlers/mcp-server/types.js +4 -0
  239. package/dist/pipeline/compiler/mode-handlers/mcp-server/validation.d.ts +9 -0
  240. package/dist/pipeline/compiler/mode-handlers/mcp-server/validation.js +43 -0
  241. package/dist/pipeline/compiler/mode-handlers/mcp-tool-provider/index.d.ts +33 -0
  242. package/dist/pipeline/compiler/mode-handlers/mcp-tool-provider/index.js +174 -0
  243. package/dist/pipeline/compiler/mode-handlers/mcp-tool-provider/mcp-connection.d.ts +19 -0
  244. package/dist/pipeline/compiler/mode-handlers/mcp-tool-provider/mcp-connection.js +95 -0
  245. package/dist/pipeline/compiler/mode-handlers/mcp-tool-provider/tool-loop-anthropic.d.ts +19 -0
  246. package/dist/pipeline/compiler/mode-handlers/mcp-tool-provider/tool-loop-anthropic.js +172 -0
  247. package/dist/pipeline/compiler/mode-handlers/mcp-tool-provider/tool-loop-openai.d.ts +14 -0
  248. package/dist/pipeline/compiler/mode-handlers/mcp-tool-provider/tool-loop-openai.js +16 -0
  249. package/dist/pipeline/compiler/mode-handlers/mcp-tool-provider/types.d.ts +93 -0
  250. package/dist/pipeline/compiler/mode-handlers/mcp-tool-provider/types.js +4 -0
  251. package/dist/pipeline/compiler/preset-loader.d.ts +22 -0
  252. package/dist/pipeline/compiler/preset-loader.js +99 -0
  253. package/dist/pipeline/compiler/presets/index.d.ts +9 -0
  254. package/dist/pipeline/compiler/presets/index.js +8 -0
  255. package/dist/pipeline/compiler/presets/sanity-literacy.d.ts +42 -0
  256. package/dist/pipeline/compiler/presets/sanity-literacy.js +208 -0
  257. package/dist/pipeline/compiler/promptfoo-compiler.d.ts +96 -0
  258. package/dist/pipeline/compiler/promptfoo-compiler.js +230 -0
  259. package/dist/pipeline/compiler/provider-assembler.d.ts +39 -0
  260. package/dist/pipeline/compiler/provider-assembler.js +137 -0
  261. package/dist/pipeline/compiler/sandbox/docker-sandbox.d.ts +21 -0
  262. package/dist/pipeline/compiler/sandbox/docker-sandbox.js +136 -0
  263. package/dist/pipeline/compiler/sandbox/fixture-provisioner.d.ts +69 -0
  264. package/dist/pipeline/compiler/sandbox/fixture-provisioner.js +189 -0
  265. package/dist/pipeline/compiler/sandbox/git-worktree-sandbox.d.ts +20 -0
  266. package/dist/pipeline/compiler/sandbox/git-worktree-sandbox.js +114 -0
  267. package/dist/pipeline/compiler/sandbox/index.d.ts +10 -0
  268. package/dist/pipeline/compiler/sandbox/index.js +11 -0
  269. package/dist/pipeline/compiler/sandbox/sandbox-selector.d.ts +35 -0
  270. package/dist/pipeline/compiler/sandbox/sandbox-selector.js +86 -0
  271. package/dist/pipeline/compiler/sandbox/sandbox-strategy.d.ts +81 -0
  272. package/dist/pipeline/compiler/sandbox/sandbox-strategy.js +15 -0
  273. package/dist/pipeline/compiler/sandbox/tempdir-sandbox.d.ts +20 -0
  274. package/dist/pipeline/compiler/sandbox/tempdir-sandbox.js +74 -0
  275. package/dist/pipeline/compiler/scoring-bridge.d.ts +49 -0
  276. package/dist/pipeline/compiler/scoring-bridge.js +114 -0
  277. package/dist/pipeline/compiler/task-graph-builder.d.ts +54 -0
  278. package/dist/pipeline/compiler/task-graph-builder.js +291 -0
  279. package/dist/pipeline/compiler/telemetry/cost-tracker.d.ts +90 -0
  280. package/dist/pipeline/compiler/telemetry/cost-tracker.js +146 -0
  281. package/dist/pipeline/compiler/telemetry/index.d.ts +14 -0
  282. package/dist/pipeline/compiler/telemetry/index.js +19 -0
  283. package/dist/pipeline/compiler/telemetry/redactor.d.ts +58 -0
  284. package/dist/pipeline/compiler/telemetry/redactor.js +222 -0
  285. package/dist/pipeline/compiler/telemetry/tool-classifier.d.ts +32 -0
  286. package/dist/pipeline/compiler/telemetry/tool-classifier.js +120 -0
  287. package/dist/pipeline/compiler/telemetry/trace-collector.d.ts +75 -0
  288. package/dist/pipeline/compiler/telemetry/trace-collector.js +297 -0
  289. package/dist/pipeline/compiler/telemetry/trace-store.d.ts +78 -0
  290. package/dist/pipeline/compiler/telemetry/trace-store.js +85 -0
  291. package/dist/pipeline/compiler/variable-resolver.d.ts +46 -0
  292. package/dist/pipeline/compiler/variable-resolver.js +115 -0
  293. package/dist/pipeline/coverage-audit.d.ts +15 -5
  294. package/dist/pipeline/coverage-audit.js +41 -22
  295. package/dist/pipeline/eval-constants.d.ts +16 -6
  296. package/dist/pipeline/eval-constants.js +25 -4
  297. package/dist/pipeline/eval-fingerprint.d.ts +2 -2
  298. package/dist/pipeline/eval-fingerprint.js +8 -9
  299. package/dist/pipeline/expand-tasks.d.ts +19 -10
  300. package/dist/pipeline/expand-tasks.js +34 -28
  301. package/dist/pipeline/gap-analysis.d.ts +1 -1
  302. package/dist/pipeline/gap-analysis.js +2 -2
  303. package/dist/pipeline/generate-configs.d.ts +22 -4
  304. package/dist/pipeline/generate-configs.js +53 -24
  305. package/dist/pipeline/grader-api.d.ts +3 -3
  306. package/dist/pipeline/grader-api.js +5 -12
  307. package/dist/pipeline/grader-compare-runner.js +20 -27
  308. package/dist/pipeline/grader-comparison.d.ts +4 -8
  309. package/dist/pipeline/grader-comparison.js +11 -17
  310. package/dist/pipeline/grader-consistency-runner.d.ts +2 -3
  311. package/dist/pipeline/grader-consistency-runner.js +16 -20
  312. package/dist/pipeline/grader-consistency.d.ts +6 -10
  313. package/dist/pipeline/grader-consistency.js +13 -32
  314. package/dist/pipeline/grader-sensitivity-runner.js +7 -5
  315. package/dist/pipeline/grader-sensitivity.d.ts +2 -6
  316. package/dist/pipeline/grader-sensitivity.js +10 -10
  317. package/dist/pipeline/grader-validate-runner.js +7 -5
  318. package/dist/pipeline/grader-validation.d.ts +2 -6
  319. package/dist/pipeline/grader-validation.js +14 -22
  320. package/dist/pipeline/map-request-to-config.js +7 -1
  321. package/dist/pipeline/mirror-repo-tasks.d.ts +13 -13
  322. package/dist/pipeline/mirror-repo-tasks.js +22 -21
  323. package/dist/pipeline/normalize-mode.d.ts +49 -0
  324. package/dist/pipeline/normalize-mode.js +64 -0
  325. package/dist/pipeline/plan.d.ts +5 -2
  326. package/dist/pipeline/plan.js +134 -78
  327. package/dist/pipeline/pr-comment.js +2 -0
  328. package/dist/pipeline/profile-resolution.d.ts +22 -14
  329. package/dist/pipeline/profile-resolution.js +41 -19
  330. package/dist/pipeline/provenance.d.ts +2 -2
  331. package/dist/pipeline/provenance.js +12 -17
  332. package/dist/pipeline/release-report.js +4 -4
  333. package/dist/pipeline/repo-threshold-evaluator.d.ts +1 -1
  334. package/dist/pipeline/repo-threshold-evaluator.js +1 -1
  335. package/dist/pipeline/rubric-loader.d.ts +20 -0
  336. package/dist/pipeline/rubric-loader.js +37 -0
  337. package/dist/pipeline/validate.d.ts +4 -4
  338. package/dist/pipeline/validate.js +64 -53
  339. package/dist/schedules/loader.js +18 -8
  340. package/dist/scripts/migrate-task-mode.d.ts +24 -0
  341. package/dist/scripts/migrate-task-mode.js +85 -0
  342. package/dist/scripts/migrate-tasks-to-content-lake.js +11 -10
  343. package/dist/scripts/validate-task-sources.d.ts +1 -1
  344. package/dist/scripts/validate-task-sources.js +15 -15
  345. package/dist/sinks/loader.js +5 -7
  346. package/dist/sources.d.ts +7 -7
  347. package/dist/sources.js +22 -24
  348. package/dist/webhook/dispatch.js +2 -1
  349. package/package.json +15 -4
  350. package/tasks/knowledge-probe/define-type-api.task.ts +55 -0
  351. package/tasks/knowledge-probe/groq-projections.task.ts +59 -0
  352. package/tasks/literacy/frameworks.task.ts +128 -0
  353. package/tasks/literacy/functions.task.ts +69 -0
  354. package/tasks/literacy/groq.task.ts +258 -0
  355. package/tasks/literacy/nextjs-live.task.ts +75 -0
  356. package/tasks/literacy/studio-setup.task.ts +131 -0
  357. package/tasks/literacy/visual-editing.task.ts +146 -0
  358. package/config/features.yaml +0 -116
  359. package/config/models.yaml +0 -116
  360. package/config/prompts.yaml +0 -75
  361. package/config/rubrics.yaml +0 -81
  362. package/config/schedules.yaml +0 -43
  363. package/config/sinks.yaml +0 -54
  364. package/config/sources.yaml +0 -51
  365. package/config/thresholds.yaml +0 -49
  366. package/dist/_vendor/ailf-tasks/cli.d.ts +0 -8
  367. package/dist/_vendor/ailf-tasks/cli.js +0 -61
  368. package/dist/_vendor/ailf-tasks/index.d.ts +0 -13
  369. package/dist/_vendor/ailf-tasks/index.js +0 -16
  370. package/dist/_vendor/ailf-tasks/parser.d.ts +0 -27
  371. package/dist/_vendor/ailf-tasks/parser.js +0 -73
  372. package/dist/_vendor/ailf-tasks/schemas.d.ts +0 -198
  373. package/dist/_vendor/ailf-tasks/schemas.js +0 -180
  374. package/dist/_vendor/ailf-tasks/validation.d.ts +0 -47
  375. package/dist/_vendor/ailf-tasks/validation.js +0 -162
  376. package/dist/agent-observer/test-imports.d.ts +0 -7
  377. package/dist/agent-observer/test-imports.js +0 -185
@@ -9,7 +9,7 @@
9
9
  * Doc Coverage (0–100) — Did docs provide the needed info?
10
10
  *
11
11
  * Dimensions are combined into a weighted composite (0–100) using named
12
- * scoring profiles from config/rubrics.yaml. Gold (with-docs) entries use
12
+ * scoring profiles from config/rubrics. Gold (with-docs) entries use
13
13
  * the "default" profile; baseline (without-docs) entries use "output-only"
14
14
  * which excludes doc-coverage (undefined without docs).
15
15
  * See docs/design-docs/named-scoring-profiles.md.
@@ -29,15 +29,17 @@
29
29
  */
30
30
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
31
31
  import { join } from "path";
32
+ import { classifyRubric, detectFeatureArea, extractUrlMetadata, mergeScores, parseRubricScore, } from "../_vendor/ailf-core/index.js";
32
33
  import { calculateCost } from "../agent-observer/pricing.js";
33
34
  import { ConsoleLogger } from "../adapters/loggers/index.js";
35
+ import { analyzeSourceIsolation, } from "../assertions/source-isolation.js";
34
36
  import { checkResultsExist } from "./checks.js";
35
- import { loadRubricTemplates } from "./expand-tasks.js";
37
+ import { loadRubricTemplates } from "./rubric-loader.js";
36
38
  import { resolveProfile } from "./profile-resolution.js";
37
39
  import { loadSource } from "../sources.js";
38
- import { analyzeSourceIsolation, } from "../assertions/source-isolation.js";
39
- import { classifyRubric, detectFeatureArea, extractUrlMetadata, mergeScores, parseRubricScore, } from "../_vendor/ailf-core/index.js";
40
- // Re-export pure functions from core for backward compatibility.
40
+ import { LiteracyVariant } from "./normalize-mode.js";
41
+ import { scoreTestGroup } from "./compiler/scoring-bridge.js";
42
+ // Re-export from core for backward compatibility.
41
43
  // Existing imports from this file continue to work unchanged.
42
44
  export { classifyRubric, detectFeatureArea, extractUrlMetadata, mergeScores, parseRubricScore, } from "../_vendor/ailf-core/index.js";
43
45
  /**
@@ -137,14 +139,8 @@ export function extractGraderJudgments(resultsPath) {
137
139
  // Not JSON — use raw reason string
138
140
  }
139
141
  }
140
- // Map internal dimension names to hyphenated form
141
- const dimensionMap = {
142
- codeCorrectness: "code-correctness",
143
- docCoverage: "doc-coverage",
144
- taskCompletion: "task-completion",
145
- };
146
142
  judgments.push({
147
- dimension: dimensionMap[kind] ?? kind,
143
+ dimension: kind,
148
144
  modelId,
149
145
  reason,
150
146
  score,
@@ -281,7 +277,7 @@ function aggregateUrlReferences(resultsPath) {
281
277
  * verification report.
282
278
  */
283
279
  function buildSourceVerification(root, source, verificationCtx) {
284
- const mode = verificationCtx?.mode ?? "baseline";
280
+ const mode = verificationCtx?.mode ?? LiteracyVariant.STANDARD;
285
281
  const sourceUrl = source?.baseUrl ?? "default";
286
282
  const searchMode = verificationCtx?.searchMode;
287
283
  const allowedOrigins = verificationCtx?.allowedOrigins;
@@ -493,62 +489,6 @@ function readAndNormalizeResults(resultsPath, log) {
493
489
  }
494
490
  return valid;
495
491
  }
496
- /**
497
- * Accumulate raw dimension scores across an array of test results.
498
- * Dimension-agnostic: any dimension returned by classifyRubric() is tracked.
499
- */
500
- function accumulateDimensions(tests) {
501
- const dimensions = {};
502
- let totalCost = 0;
503
- for (const test of tests) {
504
- totalCost += test.cost;
505
- for (const comp of test.gradingResult.componentResults) {
506
- if (comp.assertion?.type !== "llm-rubric")
507
- continue;
508
- const score = parseRubricScore(comp);
509
- const kind = classifyRubric(comp);
510
- if (kind) {
511
- dimensions[kind] = (dimensions[kind] ?? 0) + score;
512
- }
513
- }
514
- }
515
- return { dimensions, totalCost };
516
- }
517
- /**
518
- * Average accumulated dimension scores by a count.
519
- * Returns a dimension → average score map.
520
- */
521
- function averageDimensions(accumulated, count) {
522
- const avg = {};
523
- for (const [dim, total] of Object.entries(accumulated.dimensions)) {
524
- avg[dim] = total / count;
525
- }
526
- return avg;
527
- }
528
- /**
529
- * Compute a weighted composite score from dimension averages and a profile.
530
- * Only dimensions present in the profile contribute to the composite.
531
- * Dimensions not in the profile are ignored (e.g., doc-coverage on baseline).
532
- *
533
- * The profile maps camelCase dimension names (as returned by classifyRubric)
534
- * to kebab-case keys (as used in rubrics.yaml). This function handles the
535
- * mapping internally.
536
- */
537
- function weightedComposite(dimensionAverages, profile) {
538
- // Map profile keys (kebab-case: "task-completion") to classifyRubric
539
- // output (camelCase: "taskCompletion")
540
- const kebabToCamel = {
541
- "code-correctness": "codeCorrectness",
542
- "doc-coverage": "docCoverage",
543
- "task-completion": "taskCompletion",
544
- };
545
- let total = 0;
546
- for (const [profileKey, weight] of Object.entries(profile)) {
547
- const dimKey = kebabToCamel[profileKey] ?? profileKey;
548
- total += (dimensionAverages[dimKey] ?? 0) * weight;
549
- }
550
- return total;
551
- }
552
492
  /**
553
493
  * Core scoring logic: takes a pre-filtered array of TestResult and produces
554
494
  * FeatureScore[] grouped by feature area. This is the shared implementation
@@ -577,35 +517,28 @@ function scoreResults(results, goldProfile, baselineProfile, modelId) {
577
517
  }
578
518
  const scores = [];
579
519
  for (const [feature, data] of Object.entries(byFeature)) {
580
- // --- With docs (gold / ceiling) ---
581
- const goldDims = accumulateDimensions(data.withDocs);
582
- let featureCost = goldDims.totalCost;
583
- const countWithDocs = data.withDocs.length || 1;
584
- const avgGold = averageDimensions(goldDims, countWithDocs);
585
- const withDocsTotal = weightedComposite(avgGold, goldProfile);
520
+ // --- With docs (gold / ceiling) — scored via 4-tier engine ---
521
+ const gold = scoreTestGroup(data.withDocs, goldProfile, feature);
586
522
  // --- Without docs (baseline / floor) ---
587
523
  // Uses the baseline profile (e.g. "output-only") which may exclude
588
524
  // dimensions like doc-coverage that are undefined without docs.
589
525
  // See docs/design-docs/named-scoring-profiles.md.
590
- const baselineDims = accumulateDimensions(data.withoutDocs);
591
- featureCost += baselineDims.totalCost;
592
- const countWithoutDocs = data.withoutDocs.length || 1;
593
- const avgBaseline = averageDimensions(baselineDims, countWithoutDocs);
594
- const withoutDocsScore = weightedComposite(avgBaseline, baselineProfile);
595
- const ceilingScore = Math.round(withDocsTotal);
596
- const floorScore = Math.round(withoutDocsScore);
526
+ const baseline = scoreTestGroup(data.withoutDocs, baselineProfile, feature);
527
+ const featureCost = gold.totalCost + baseline.totalCost;
528
+ const ceilingScore = gold.composite;
529
+ const floorScore = baseline.composite;
597
530
  const docLift = ceilingScore - floorScore;
598
531
  const featureScore = {
599
532
  ceilingScore,
600
- codeCorrectness: Math.round(avgGold.codeCorrectness ?? 0),
601
- docCoverage: Math.round(avgGold.docCoverage ?? 0),
533
+ codeCorrectness: gold.dimensions.codeCorrectness ?? 0,
534
+ docCoverage: gold.dimensions.docCoverage ?? 0,
602
535
  docLift,
603
536
  docQualityGap: 100 - ceilingScore,
604
537
  feature,
605
538
  floorScore,
606
539
  ...(modelId && { modelId }),
607
540
  negativeDocLift: docLift < 0,
608
- taskCompletion: Math.round(avgGold.taskCompletion ?? 0),
541
+ taskCompletion: gold.dimensions.taskCompletion ?? 0,
609
542
  testCount: data.withDocs.length,
610
543
  totalCost: featureCost,
611
544
  totalScore: ceilingScore,
@@ -638,17 +571,14 @@ export function scoreAgenticResults(resultsPath, profile) {
638
571
  }
639
572
  const entries = {};
640
573
  for (const [feature, featureResults] of Object.entries(byFeature)) {
641
- const count = featureResults.length || 1;
642
- const accumulated = accumulateDimensions(featureResults);
643
- const avg = averageDimensions(accumulated, count);
644
- const actualScore = Math.round(weightedComposite(avg, profile));
574
+ const scored = scoreTestGroup(featureResults, profile, feature);
645
575
  entries[feature] = {
646
- actualScore,
647
- codeCorrectness: Math.round(avg.codeCorrectness ?? 0),
648
- docCoverage: Math.round(avg.docCoverage ?? 0),
649
- taskCompletion: Math.round(avg.taskCompletion ?? 0),
576
+ actualScore: scored.composite,
577
+ codeCorrectness: scored.dimensions.codeCorrectness ?? 0,
578
+ docCoverage: scored.dimensions.docCoverage ?? 0,
579
+ taskCompletion: scored.dimensions.taskCompletion ?? 0,
650
580
  testCount: featureResults.length,
651
- totalCost: accumulated.totalCost,
581
+ totalCost: scored.totalCost,
652
582
  };
653
583
  }
654
584
  return entries;
@@ -677,17 +607,14 @@ export function scoreAgenticResultsPerModel(resultsPath, profile) {
677
607
  for (const [modelId, features] of Object.entries(byModel)) {
678
608
  perModel[modelId] = {};
679
609
  for (const [feature, featureResults] of Object.entries(features)) {
680
- const count = featureResults.length || 1;
681
- const accumulated = accumulateDimensions(featureResults);
682
- const avg = averageDimensions(accumulated, count);
683
- const actualScore = Math.round(weightedComposite(avg, profile));
610
+ const scored = scoreTestGroup(featureResults, profile, feature);
684
611
  perModel[modelId][feature] = {
685
- actualScore,
686
- codeCorrectness: Math.round(avg.codeCorrectness ?? 0),
687
- docCoverage: Math.round(avg.docCoverage ?? 0),
688
- taskCompletion: Math.round(avg.taskCompletion ?? 0),
612
+ actualScore: scored.composite,
613
+ codeCorrectness: scored.dimensions.codeCorrectness ?? 0,
614
+ docCoverage: scored.dimensions.docCoverage ?? 0,
615
+ taskCompletion: scored.dimensions.taskCompletion ?? 0,
689
616
  testCount: featureResults.length,
690
- totalCost: accumulated.totalCost,
617
+ totalCost: scored.totalCost,
691
618
  };
692
619
  }
693
620
  }
@@ -725,7 +652,7 @@ export function calculateAndWriteScores(options) {
725
652
  }
726
653
  }
727
654
  // Determine mode — controls which result files are read
728
- const mode = options.mode ?? "baseline";
655
+ const mode = options.mode ?? LiteracyVariant.STANDARD;
729
656
  const baselineResultsPath = options.resultsPath ?? join(ROOT, "results", "latest", "eval-results.json");
730
657
  // Agentic results path (only used in full mode)
731
658
  const agenticResultsPath = join(ROOT, "results", "latest", "eval-results-agentic.json");
@@ -747,8 +674,8 @@ export function calculateAndWriteScores(options) {
747
674
  // Baseline (without-docs) entries use "output-only" (2 dimensions,
748
675
  // doc-coverage excluded). See docs/design-docs/named-scoring-profiles.md.
749
676
  const rubricConfig = loadRubricTemplates(ROOT);
750
- const goldProfile = resolveProfile("baseline", "gold", rubricConfig);
751
- const baselineProfileWeights = resolveProfile("baseline", "baseline", rubricConfig);
677
+ const goldProfile = resolveProfile("literacy", "gold", rubricConfig, LiteracyVariant.STANDARD);
678
+ const baselineProfileWeights = resolveProfile("literacy", LiteracyVariant.STANDARD, rubricConfig, LiteracyVariant.STANDARD);
752
679
  log.debug("Loaded scoring profiles", {
753
680
  gold: goldProfile,
754
681
  baseline: baselineProfileWeights,
@@ -776,9 +703,9 @@ export function calculateAndWriteScores(options) {
776
703
  let agentBehavior = null;
777
704
  let sourceIsolation = null;
778
705
  let evaluationMode;
779
- if (mode === "full" && existsSync(agenticResultsPath)) {
706
+ if (mode === LiteracyVariant.FULL && existsSync(agenticResultsPath)) {
780
707
  log.info(`\nReading agentic results from: ${agenticResultsPath}`);
781
- const agenticProfile = resolveProfile("agentic", "gold", rubricConfig);
708
+ const agenticProfile = resolveProfile("literacy", "gold", rubricConfig, LiteracyVariant.AGENTIC);
782
709
  const agenticScores = scoreAgenticResults(agenticResultsPath, agenticProfile);
783
710
  log.debug("Agentic scores calculated", {
784
711
  featureCount: Object.keys(agenticScores).length,
@@ -789,7 +716,7 @@ export function calculateAndWriteScores(options) {
789
716
  })),
790
717
  });
791
718
  scores = mergeScores(baselineScores, agenticScores);
792
- evaluationMode = "full";
719
+ evaluationMode = LiteracyVariant.FULL;
793
720
  // Merge agentic actual scores into the per-model breakdown
794
721
  if (perModel) {
795
722
  const agenticPerModel = scoreAgenticResultsPerModel(agenticResultsPath, agenticProfile);
@@ -812,17 +739,20 @@ export function calculateAndWriteScores(options) {
812
739
  graderCost.completionTokens += agenticGraderCost.completionTokens;
813
740
  }
814
741
  }
815
- else if (mode === "agentic") {
742
+ else if (mode === LiteracyVariant.AGENTIC) {
816
743
  scores = baselineScores;
817
744
  agentBehavior = aggregateAgentBehavior(baselineResultsPath);
818
745
  sourceIsolation = aggregateSourceIsolation(baselineResultsPath, options?.allowedOrigins);
819
- evaluationMode = "agentic";
746
+ evaluationMode = LiteracyVariant.AGENTIC;
820
747
  }
821
748
  else {
822
749
  scores = baselineScores;
823
750
  agentBehavior = aggregateAgentBehavior(baselineResultsPath);
824
751
  sourceIsolation = aggregateSourceIsolation(baselineResultsPath, options?.allowedOrigins);
825
- evaluationMode = mode === "observed" ? "observed" : "baseline";
752
+ evaluationMode =
753
+ mode === LiteracyVariant.OBSERVED
754
+ ? LiteracyVariant.OBSERVED
755
+ : LiteracyVariant.STANDARD;
826
756
  }
827
757
  const summary = printReport(scores, urlRefs, source, agentBehavior, graderCost, perModel, sourceIsolation, sourceVerification, evaluationMode, log);
828
758
  // Persist
@@ -833,7 +763,7 @@ export function calculateAndWriteScores(options) {
833
763
  // Extract and persist grader judgments (Phase 3a: failure mode extraction)
834
764
  const judgments = extractGraderJudgments(baselineResultsPath);
835
765
  // In full mode, also extract judgments from agentic results
836
- if (mode === "full" && existsSync(agenticResultsPath)) {
766
+ if (mode === LiteracyVariant.FULL && existsSync(agenticResultsPath)) {
837
767
  const agenticJudgments = extractGraderJudgments(agenticResultsPath);
838
768
  judgments.push(...agenticJudgments);
839
769
  }
@@ -117,7 +117,7 @@ export function checkGeneratedConfigsExist(rootDir) {
117
117
  const baselinePath = resolve(rootDir, "promptfooconfig.yaml");
118
118
  if (!existsSync(baselinePath)) {
119
119
  issues.push({
120
- message: "Baseline config 'promptfooconfig.yaml' not found. Run 'pnpm generate-configs'.",
120
+ message: "Baseline config 'promptfooconfig.yaml' not found. Run the pipeline to generate it.",
121
121
  path: baselinePath,
122
122
  severity: "error",
123
123
  source: "checkGeneratedConfigsExist",
@@ -131,7 +131,7 @@ export function checkGeneratedConfigsExist(rootDir) {
131
131
  const configPath = resolve(rootDir, name);
132
132
  if (!existsSync(configPath)) {
133
133
  issues.push({
134
- message: `Optional config \`${name}\` not found. Run \`pnpm generate-configs\` to create it.`,
134
+ message: `Optional config \`${name}\` not found. Run the pipeline to generate it.`,
135
135
  path: configPath,
136
136
  severity: "warning",
137
137
  source: "checkGeneratedConfigsExist",
@@ -79,14 +79,14 @@ export function compare(baseline, experiment, options) {
79
79
  // Per-dimension average deltas (only for areas present in both summaries)
80
80
  const commonAreas = areas.filter((a) => baselineAreas.has(a.area) && experimentAreas.has(a.area));
81
81
  const commonCount = commonAreas.length || 1;
82
- const perDimension = {
83
- codeCorrectness: commonAreas.reduce((s, a) => s + a.dimensions.codeCorrectness.delta, 0) /
84
- commonCount,
85
- docCoverage: commonAreas.reduce((s, a) => s + a.dimensions.docCoverage.delta, 0) /
86
- commonCount,
87
- taskCompletion: commonAreas.reduce((s, a) => s + a.dimensions.taskCompletion.delta, 0) /
88
- commonCount,
89
- };
82
+ // Collect all dimension keys from area deltas and average each
83
+ const allDimKeys = new Set(commonAreas.flatMap((a) => Object.keys(a.dimensions)));
84
+ const perDimension = {};
85
+ for (const dim of allDimKeys) {
86
+ perDimension[dim] =
87
+ commonAreas.reduce((s, a) => s + (a.dimensions[dim]?.delta ?? 0), 0) /
88
+ commonCount;
89
+ }
90
90
  // Doc Lift average delta (common areas only)
91
91
  const docLift = commonAreas.reduce((s, a) => s + a.docLiftDelta, 0) / commonCount;
92
92
  // Cost delta (if both summaries have cost data)
@@ -0,0 +1,10 @@
1
+ /**
2
+ * agent-harness-handler.test.ts — Tests for agent harness mode compilation.
3
+ *
4
+ * Tests validation, provider assembly, tool permission resolution,
5
+ * assertion mapping, sandbox config, lifecycle extensions, and
6
+ * end-to-end compilation of example tasks.
7
+ *
8
+ * Run: npx tsx --test src/pipeline/compiler/__tests__/agent-harness-handler.test.ts
9
+ */
10
+ export {};
@@ -0,0 +1,288 @@
1
+ /**
2
+ * agent-harness-handler.test.ts — Tests for agent harness mode compilation.
3
+ *
4
+ * Tests validation, provider assembly, tool permission resolution,
5
+ * assertion mapping, sandbox config, lifecycle extensions, and
6
+ * end-to-end compilation of example tasks.
7
+ *
8
+ * Run: npx tsx --test src/pipeline/compiler/__tests__/agent-harness-handler.test.ts
9
+ */
10
+ import assert from "node:assert/strict";
11
+ import { describe, it } from "node:test";
12
+ import { LiteracyVariant } from "../../normalize-mode.js";
13
+ import { compileAgentHarnessTask, AGENT_HARNESS_PROMPT_TEMPLATES, handler as agentHandler, validateAgentHarnessTask, } from "../mode-handlers/agent-harness/index.js";
14
+ import { allAgentHarnessExampleTasks, scaffoldProjectTask, modifyCodeTask, multiFileRefactorTask, } from "../mode-handlers/__fixtures__/agent-harness-example-tasks.js";
15
+ // ---------------------------------------------------------------------------
16
+ // Helpers
17
+ // ---------------------------------------------------------------------------
18
+ function makeTask(overrides) {
19
+ return {
20
+ mode: "agent-harness",
21
+ id: "test-agent-task",
22
+ title: "Test Agent Task",
23
+ description: "A test agent harness task",
24
+ area: "studio",
25
+ ...overrides,
26
+ };
27
+ }
28
+ // ---------------------------------------------------------------------------
29
+ // handler.getPrompts() — prompt template ownership
30
+ // ---------------------------------------------------------------------------
31
+ describe("AgentHarnessHandler.getPrompts", () => {
32
+ it("returns prompt templates", () => {
33
+ const prompts = agentHandler.getPrompts();
34
+ assert.ok(prompts, "getPrompts() should return a record");
35
+ assert.ok(Object.keys(prompts).length > 0, "should return at least one template");
36
+ });
37
+ it("returns templates keyed by agent-specific IDs (not literacy names)", () => {
38
+ const prompts = agentHandler.getPrompts();
39
+ const keys = Object.keys(prompts);
40
+ // Must not use literacy template names
41
+ assert.ok(!keys.includes("with-docs"), "should not use literacy key 'with-docs'");
42
+ assert.ok(!keys.includes("without-docs"), "should not use literacy key 'without-docs'");
43
+ assert.ok(!keys.includes(LiteracyVariant.AGENTIC), "should not use literacy key 'agentic'");
44
+ // Must have agent-appropriate key(s)
45
+ assert.ok(keys.includes("agent-harness"), "should include 'agent-harness' template");
46
+ });
47
+ it("agent-harness template describes task for agent execution", () => {
48
+ const prompts = agentHandler.getPrompts();
49
+ const template = prompts["agent-harness"];
50
+ assert.ok(template, "agent-harness template should exist");
51
+ assert.ok(template.template.includes("{{task}}"), "should include {{task}} placeholder");
52
+ // Should reference agent / sandbox / tool execution context
53
+ assert.ok(/sandbox|file|tool|implement|code/i.test(template.template), "template should reference agent execution concepts");
54
+ });
55
+ it("template has correct PromptTemplate shape", () => {
56
+ const prompts = agentHandler.getPrompts();
57
+ const template = prompts["agent-harness"];
58
+ assert.equal(template.id, "agent-harness");
59
+ assert.ok(template.label, "should have a human-readable label");
60
+ assert.ok(template.template, "should have a template string");
61
+ assert.ok(Array.isArray(template.variables), "should declare variables");
62
+ assert.ok(template.variables.includes("task"), "variables should include 'task'");
63
+ });
64
+ it("exported AGENT_HARNESS_PROMPT_TEMPLATES matches handler.getPrompts()", () => {
65
+ const fromHandler = agentHandler.getPrompts();
66
+ assert.deepEqual(fromHandler, AGENT_HARNESS_PROMPT_TEMPLATES);
67
+ });
68
+ });
69
+ // ---------------------------------------------------------------------------
70
+ // validateAgentHarnessTask
71
+ // ---------------------------------------------------------------------------
72
+ describe("validateAgentHarnessTask", () => {
73
+ it("passes for a valid minimal task", () => {
74
+ const errors = validateAgentHarnessTask(makeTask());
75
+ assert.equal(errors.length, 0);
76
+ });
77
+ it("errors on missing ID", () => {
78
+ const errors = validateAgentHarnessTask(makeTask({ id: "" }));
79
+ assert.ok(errors.some((e) => e.field === "id"));
80
+ });
81
+ it("errors on missing title", () => {
82
+ const errors = validateAgentHarnessTask(makeTask({ title: "" }));
83
+ assert.ok(errors.some((e) => e.field === "title"));
84
+ });
85
+ });
86
+ // ---------------------------------------------------------------------------
87
+ // compileAgentHarnessTask — provider assembly
88
+ // ---------------------------------------------------------------------------
89
+ describe("compileAgentHarnessTask — providers", () => {
90
+ it("produces a provider", () => {
91
+ const result = compileAgentHarnessTask(makeTask());
92
+ assert.ok(result.providers.length > 0);
93
+ assert.ok(result.providers[0].id.startsWith("agent:"));
94
+ });
95
+ it("resolves coding tool preset", () => {
96
+ const result = compileAgentHarnessTask(makeTask({ tools: ["coding"] }));
97
+ const config = result.providers[0].config;
98
+ const tools = config.allowedTools;
99
+ assert.ok(tools.includes("Bash"));
100
+ assert.ok(tools.includes("Read"));
101
+ assert.ok(tools.includes("Write"));
102
+ assert.ok(tools.includes("Edit"));
103
+ });
104
+ it("resolves read-only tool preset", () => {
105
+ const result = compileAgentHarnessTask(makeTask({ tools: ["read-only"] }));
106
+ const config = result.providers[0].config;
107
+ const tools = config.allowedTools;
108
+ assert.ok(tools.includes("Read"));
109
+ assert.ok(tools.includes("Grep"));
110
+ assert.ok(!tools.includes("Write"), "read-only should not include Write");
111
+ });
112
+ it("mixes preset and explicit tools", () => {
113
+ const result = compileAgentHarnessTask(makeTask({ tools: ["read-only", "WebFetch"] }));
114
+ const config = result.providers[0].config;
115
+ const tools = config.allowedTools;
116
+ assert.ok(tools.includes("Read"));
117
+ assert.ok(tools.includes("WebFetch"));
118
+ });
119
+ it("includes sandbox config in provider", () => {
120
+ const result = compileAgentHarnessTask(makeTask({
121
+ sandbox: { type: "docker", image: "node:22-slim" },
122
+ }));
123
+ const config = result.providers[0].config;
124
+ const sandbox = config.sandbox;
125
+ assert.equal(sandbox.type, "docker");
126
+ assert.equal(sandbox.image, "node:22-slim");
127
+ });
128
+ });
129
+ // ---------------------------------------------------------------------------
130
+ // compileAgentHarnessTask — test cases
131
+ // ---------------------------------------------------------------------------
132
+ describe("compileAgentHarnessTask — test cases", () => {
133
+ it("produces at least one test case", () => {
134
+ const result = compileAgentHarnessTask(makeTask());
135
+ assert.ok(result.tests.length > 0);
136
+ });
137
+ it("includes task description in vars", () => {
138
+ const result = compileAgentHarnessTask(makeTask({ description: "Do the thing" }));
139
+ assert.equal(result.tests[0].vars.task, "Do the thing");
140
+ });
141
+ it("prefers prompt.vars.task over description", () => {
142
+ const result = compileAgentHarnessTask(makeTask({
143
+ description: "Description",
144
+ prompt: { vars: { task: "Custom prompt" } },
145
+ }));
146
+ assert.equal(result.tests[0].vars.task, "Custom prompt");
147
+ });
148
+ it("creates multi-turn test case", () => {
149
+ const result = compileAgentHarnessTask(makeTask({
150
+ multiTurn: {
151
+ turns: [
152
+ { role: "user", content: "Hello" },
153
+ { role: "assistant", content: "Hi" },
154
+ ],
155
+ },
156
+ }));
157
+ assert.equal(result.tests.length, 2);
158
+ assert.ok(result.tests[1].description.includes("[multi-turn]"));
159
+ });
160
+ it("sets sandbox metadata in vars", () => {
161
+ const result = compileAgentHarnessTask(makeTask({ sandbox: { type: "docker" } }));
162
+ assert.equal(result.tests[0].vars.__sandboxType, "docker");
163
+ });
164
+ });
165
+ // ---------------------------------------------------------------------------
166
+ // compileAgentHarnessTask — assertions
167
+ // ---------------------------------------------------------------------------
168
+ describe("compileAgentHarnessTask — assertions", () => {
169
+ it("maps file-exists to javascript assertion", () => {
170
+ const result = compileAgentHarnessTask(makeTask({
171
+ assertions: [{ type: "file-exists", value: "sanity.config.ts" }],
172
+ }));
173
+ const assertion = result.tests[0].assert?.[0];
174
+ assert.ok(assertion);
175
+ assert.equal(assertion.type, "javascript");
176
+ assert.ok(assertion.value.includes("sanity.config.ts"));
177
+ });
178
+ it("maps file-contains to javascript assertion", () => {
179
+ const result = compileAgentHarnessTask(makeTask({
180
+ assertions: [
181
+ {
182
+ type: "file-contains",
183
+ value: { path: "config.ts", content: "projectId" },
184
+ },
185
+ ],
186
+ }));
187
+ const assertion = result.tests[0].assert?.[0];
188
+ assert.ok(assertion);
189
+ assert.equal(assertion.type, "javascript");
190
+ assert.ok(assertion.value.includes("projectId"));
191
+ });
192
+ it("maps command-succeeds to javascript assertion", () => {
193
+ const result = compileAgentHarnessTask(makeTask({
194
+ assertions: [{ type: "command-succeeds", value: "npx tsc --noEmit" }],
195
+ }));
196
+ const assertion = result.tests[0].assert?.[0];
197
+ assert.ok(assertion);
198
+ assert.equal(assertion.type, "javascript");
199
+ assert.ok(assertion.value.includes("tsc"));
200
+ });
201
+ it("maps diff-matches to javascript assertion", () => {
202
+ const result = compileAgentHarnessTask(makeTask({
203
+ assertions: [{ type: "diff-matches", value: "createClient" }],
204
+ }));
205
+ const assertion = result.tests[0].assert?.[0];
206
+ assert.ok(assertion);
207
+ assert.equal(assertion.type, "javascript");
208
+ assert.ok(assertion.value.includes("git diff"));
209
+ });
210
+ it("passes through standard assertions", () => {
211
+ const result = compileAgentHarnessTask(makeTask({
212
+ assertions: [{ type: "contains", value: "sanity" }],
213
+ }));
214
+ assert.equal(result.tests[0].assert?.[0]?.type, "contains");
215
+ });
216
+ it("sets grader provider on llm-rubric", () => {
217
+ const result = compileAgentHarnessTask(makeTask({
218
+ assertions: [{ type: "llm-rubric", value: "Check quality" }],
219
+ }), { graderProvider: "openai:chat:gpt-5" });
220
+ assert.equal(result.tests[0].assert?.[0]?.provider, "openai:chat:gpt-5");
221
+ });
222
+ });
223
+ // ---------------------------------------------------------------------------
224
+ // compileAgentHarnessTask — lifecycle extensions
225
+ // ---------------------------------------------------------------------------
226
+ describe("compileAgentHarnessTask — lifecycle", () => {
227
+ it("produces beforeEach and afterEach extensions", () => {
228
+ const result = compileAgentHarnessTask(makeTask());
229
+ assert.equal(result.extensions.length, 2);
230
+ assert.equal(result.extensions[0].type, "beforeEach");
231
+ assert.equal(result.extensions[1].type, "afterEach");
232
+ });
233
+ it("beforeEach hook creates working directory", () => {
234
+ const result = compileAgentHarnessTask(makeTask());
235
+ assert.ok(result.extensions[0].code.includes("mkdirSync"));
236
+ assert.ok(result.extensions[0].code.includes("__workingDir"));
237
+ });
238
+ it("afterEach hook cleans up", () => {
239
+ const result = compileAgentHarnessTask(makeTask());
240
+ assert.ok(result.extensions[1].code.includes("rmSync"));
241
+ });
242
+ it("sandbox config captures task settings", () => {
243
+ const result = compileAgentHarnessTask(makeTask({
244
+ sandbox: {
245
+ type: "docker",
246
+ image: "node:22",
247
+ limits: { cpus: 2, networkAccess: false },
248
+ },
249
+ fixtures: ["file://schema.ts"],
250
+ }));
251
+ assert.equal(result.sandboxConfig.type, "docker");
252
+ assert.equal(result.sandboxConfig.image, "node:22");
253
+ assert.deepEqual(result.sandboxConfig.fixtures, ["file://schema.ts"]);
254
+ assert.equal(result.sandboxConfig.limits?.cpus, 2);
255
+ assert.equal(result.sandboxConfig.limits?.networkAccess, false);
256
+ });
257
+ });
258
+ // ---------------------------------------------------------------------------
259
+ // Example task compilation (end-to-end)
260
+ // ---------------------------------------------------------------------------
261
+ describe("example agent harness tasks — end-to-end", () => {
262
+ it("compiles all example tasks without errors", () => {
263
+ for (const task of allAgentHarnessExampleTasks) {
264
+ const result = compileAgentHarnessTask(task);
265
+ assert.ok(result.providers.length > 0, `${task.id}: should produce providers`);
266
+ assert.ok(result.tests.length > 0, `${task.id}: should produce test cases`);
267
+ assert.ok(result.extensions.length > 0, `${task.id}: should produce lifecycle extensions`);
268
+ }
269
+ });
270
+ it("scaffold task has file-exists assertions", () => {
271
+ const result = compileAgentHarnessTask(scaffoldProjectTask);
272
+ assert.ok(result.tests[0].assert);
273
+ assert.ok(result.tests[0].assert.length >= 3);
274
+ // First two are file-exists (javascript), third is file-contains, fourth is command-succeeds
275
+ assert.equal(result.tests[0].assert[0].type, "javascript");
276
+ });
277
+ it("modify task has file-contains assertions", () => {
278
+ const result = compileAgentHarnessTask(modifyCodeTask);
279
+ assert.ok(result.tests[0].assert);
280
+ assert.ok(result.tests[0].assert.some((a) => a.type === "javascript" &&
281
+ a.value.includes("useDocumentOperation")));
282
+ });
283
+ it("refactor task has docker sandbox config", () => {
284
+ const result = compileAgentHarnessTask(multiFileRefactorTask);
285
+ assert.equal(result.sandboxConfig.type, "docker");
286
+ assert.equal(result.sandboxConfig.image, "node:22-slim");
287
+ });
288
+ });
@@ -0,0 +1,9 @@
1
+ /**
2
+ * assertion-mapper.test.ts — Unit tests for the assertion type mapper.
3
+ *
4
+ * Tests mapping of AILF assertion types to Promptfoo assertion types,
5
+ * mode compatibility checking, negation support, and templated assertions.
6
+ *
7
+ * Run: npx tsx --test src/pipeline/compiler/__tests__/assertion-mapper.test.ts
8
+ */
9
+ export {};