@sanity/ailf 0.4.1 → 1.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 (290) hide show
  1. package/config/features.ts +23 -0
  2. package/config/models.ts +83 -0
  3. package/config/prompts.ts +16 -0
  4. package/config/rubrics.ts +225 -0
  5. package/config/schedules.ts +47 -0
  6. package/config/sinks.ts +37 -0
  7. package/config/sources.ts +21 -0
  8. package/config/thresholds.ts +61 -0
  9. package/dist/_vendor/ailf-core/config-helpers.d.ts +174 -0
  10. package/dist/_vendor/ailf-core/config-helpers.js +150 -0
  11. package/dist/_vendor/ailf-core/env-helper.d.ts +35 -0
  12. package/dist/_vendor/ailf-core/env-helper.js +45 -0
  13. package/dist/_vendor/ailf-core/examples/index.d.ts +10 -10
  14. package/dist/_vendor/ailf-core/examples/index.js +10 -10
  15. package/dist/_vendor/ailf-core/index.d.ts +3 -0
  16. package/dist/_vendor/ailf-core/index.js +5 -0
  17. package/dist/_vendor/ailf-core/ports/context.d.ts +15 -2
  18. package/dist/_vendor/ailf-core/ports/doc-fetcher.d.ts +2 -2
  19. package/dist/_vendor/ailf-core/ports/index.d.ts +2 -1
  20. package/dist/_vendor/ailf-core/ports/mode-handler.d.ts +129 -0
  21. package/dist/_vendor/ailf-core/ports/mode-handler.js +19 -0
  22. package/dist/_vendor/ailf-core/ports/task-source.d.ts +16 -122
  23. package/dist/_vendor/ailf-core/ports/task-source.js +7 -7
  24. package/dist/_vendor/ailf-core/schemas/eval-config.d.ts +7 -2
  25. package/dist/_vendor/ailf-core/schemas/eval-config.js +7 -2
  26. package/dist/_vendor/ailf-core/schemas/pipeline-request.d.ts +8 -3
  27. package/dist/_vendor/ailf-core/schemas/pipeline-request.js +6 -1
  28. package/dist/_vendor/ailf-core/schemas/pipeline.d.ts +32 -31
  29. package/dist/_vendor/ailf-core/schemas/pipeline.js +52 -12
  30. package/dist/_vendor/ailf-core/schemas/schedules.d.ts +14 -4
  31. package/dist/_vendor/ailf-core/schemas/schedules.js +6 -2
  32. package/dist/_vendor/ailf-core/schemas/sinks.d.ts +1 -1
  33. package/dist/_vendor/ailf-core/services/comparison-formatters.js +57 -19
  34. package/dist/_vendor/ailf-core/services/index.d.ts +2 -1
  35. package/dist/_vendor/ailf-core/services/index.js +2 -1
  36. package/dist/_vendor/ailf-core/services/scoring-engine.d.ts +153 -0
  37. package/dist/_vendor/ailf-core/services/scoring-engine.js +237 -0
  38. package/dist/_vendor/ailf-core/services/scoring.d.ts +15 -2
  39. package/dist/_vendor/ailf-core/services/scoring.js +25 -15
  40. package/dist/_vendor/ailf-core/types/branded-ids.d.ts +137 -0
  41. package/dist/_vendor/ailf-core/types/branded-ids.js +136 -0
  42. package/dist/_vendor/ailf-core/types/eval-mode-config.d.ts +150 -0
  43. package/dist/_vendor/ailf-core/types/eval-mode-config.js +24 -0
  44. package/dist/_vendor/ailf-core/types/generalized-task.d.ts +319 -0
  45. package/dist/_vendor/ailf-core/types/generalized-task.js +13 -0
  46. package/dist/_vendor/ailf-core/types/index.d.ts +45 -81
  47. package/dist/_vendor/ailf-core/types/index.js +8 -1
  48. package/dist/_vendor/ailf-core/types/plugin-registry.d.ts +202 -0
  49. package/dist/_vendor/ailf-core/types/plugin-registry.js +132 -0
  50. package/dist/_vendor/ailf-core/types/storage-schema.d.ts +199 -0
  51. package/dist/_vendor/ailf-core/types/storage-schema.js +39 -0
  52. package/dist/_vendor/ailf-core/types/task-graph.d.ts +86 -0
  53. package/dist/_vendor/ailf-core/types/task-graph.js +20 -0
  54. package/dist/_vendor/ailf-core/types/trace.d.ts +118 -0
  55. package/dist/_vendor/ailf-core/types/trace.js +18 -0
  56. package/dist/_vendor/ailf-core/types/variable-envelope.d.ts +80 -0
  57. package/dist/_vendor/ailf-core/types/variable-envelope.js +16 -0
  58. package/dist/_vendor/ailf-shared/dimension-names.d.ts +5 -18
  59. package/dist/_vendor/ailf-shared/dimension-names.js +6 -24
  60. package/dist/_vendor/ailf-shared/eval-modes.d.ts +38 -6
  61. package/dist/_vendor/ailf-shared/eval-modes.js +26 -2
  62. package/dist/_vendor/ailf-shared/index.d.ts +0 -1
  63. package/dist/_vendor/ailf-shared/index.js +0 -1
  64. package/dist/adapters/api-client/build-request.js +14 -13
  65. package/dist/adapters/config-sources/file-config-adapter.d.ts +20 -11
  66. package/dist/adapters/config-sources/file-config-adapter.js +38 -12
  67. package/dist/adapters/config-sources/index.d.ts +2 -0
  68. package/dist/adapters/config-sources/index.js +1 -0
  69. package/dist/adapters/config-sources/ts-config-loader.d.ts +59 -0
  70. package/dist/adapters/config-sources/ts-config-loader.js +133 -0
  71. package/dist/adapters/doc-fetchers/sanity-doc-fetcher.d.ts +3 -2
  72. package/dist/adapters/doc-fetchers/sanity-doc-fetcher.js +7 -2
  73. package/dist/adapters/task-sources/composite-task-source.d.ts +3 -3
  74. package/dist/adapters/task-sources/composite-task-source.js +1 -1
  75. package/dist/adapters/task-sources/content-lake-task-source.d.ts +7 -6
  76. package/dist/adapters/task-sources/content-lake-task-source.js +22 -23
  77. package/dist/adapters/task-sources/index.d.ts +1 -0
  78. package/dist/adapters/task-sources/index.js +1 -0
  79. package/dist/adapters/task-sources/repo-task-source.d.ts +4 -4
  80. package/dist/adapters/task-sources/repo-task-source.js +69 -16
  81. package/dist/adapters/task-sources/task-file-loader.d.ts +64 -0
  82. package/dist/adapters/task-sources/task-file-loader.js +83 -0
  83. package/dist/adapters/task-sources/yaml-task-source.d.ts +6 -6
  84. package/dist/adapters/task-sources/yaml-task-source.js +19 -16
  85. package/dist/cli.js +0 -2
  86. package/dist/commands/baseline.js +4 -1
  87. package/dist/commands/calculate-scores.js +1 -1
  88. package/dist/commands/coverage-audit.js +7 -1
  89. package/dist/commands/explain-handler.js +25 -23
  90. package/dist/commands/fetch-docs.js +3 -2
  91. package/dist/commands/generate-configs.js +1 -1
  92. package/dist/commands/interactive.js +11 -7
  93. package/dist/commands/pipeline-action.d.ts +2 -0
  94. package/dist/commands/pipeline-action.js +16 -6
  95. package/dist/commands/pipeline.d.ts +1 -0
  96. package/dist/commands/pipeline.js +4 -2
  97. package/dist/commands/pr-comment.js +1 -1
  98. package/dist/commands/publish.js +2 -2
  99. package/dist/commands/readiness-report.js +13 -6
  100. package/dist/composition-root.d.ts +1 -1
  101. package/dist/composition-root.js +67 -4
  102. package/dist/orchestration/build-app-context.js +1 -0
  103. package/dist/orchestration/build-step-sequence.js +24 -6
  104. package/dist/orchestration/steps/calculate-scores-step.js +24 -11
  105. package/dist/orchestration/steps/fetch-docs-step.js +6 -4
  106. package/dist/orchestration/steps/gap-analysis-step.js +8 -7
  107. package/dist/orchestration/steps/generate-configs-step.d.ts +16 -3
  108. package/dist/orchestration/steps/generate-configs-step.js +245 -51
  109. package/dist/orchestration/steps/grader-consistency-step.js +7 -4
  110. package/dist/orchestration/steps/mirror-repo-tasks-step.js +1 -1
  111. package/dist/orchestration/steps/readiness-step.js +5 -6
  112. package/dist/orchestration/steps/run-eval-step.d.ts +1 -2
  113. package/dist/orchestration/steps/run-eval-step.js +8 -7
  114. package/dist/pipeline/cache.d.ts +1 -1
  115. package/dist/pipeline/cache.js +36 -8
  116. package/dist/pipeline/calculate-scores.d.ts +5 -7
  117. package/dist/pipeline/calculate-scores.js +74 -153
  118. package/dist/pipeline/checks.js +2 -2
  119. package/dist/pipeline/compare.js +8 -8
  120. package/dist/pipeline/compiler/__tests__/agent-harness-handler.test.d.ts +10 -0
  121. package/dist/pipeline/compiler/__tests__/agent-harness-handler.test.js +288 -0
  122. package/dist/pipeline/compiler/__tests__/assertion-mapper.test.d.ts +9 -0
  123. package/dist/pipeline/compiler/__tests__/assertion-mapper.test.js +145 -0
  124. package/dist/pipeline/compiler/__tests__/knowledge-probe-handler.test.d.ts +10 -0
  125. package/dist/pipeline/compiler/__tests__/knowledge-probe-handler.test.js +314 -0
  126. package/dist/pipeline/compiler/__tests__/literacy-handler.test.d.ts +10 -0
  127. package/dist/pipeline/compiler/__tests__/literacy-handler.test.js +486 -0
  128. package/dist/pipeline/compiler/__tests__/mcp-server-handler.test.d.ts +10 -0
  129. package/dist/pipeline/compiler/__tests__/mcp-server-handler.test.js +355 -0
  130. package/dist/pipeline/compiler/__tests__/promptfoo-compiler.test.d.ts +9 -0
  131. package/dist/pipeline/compiler/__tests__/promptfoo-compiler.test.js +333 -0
  132. package/dist/pipeline/compiler/__tests__/sandbox-and-fixtures.test.d.ts +12 -0
  133. package/dist/pipeline/compiler/__tests__/sandbox-and-fixtures.test.js +210 -0
  134. package/dist/pipeline/compiler/__tests__/scoring-and-presets.test.d.ts +7 -0
  135. package/dist/pipeline/compiler/__tests__/scoring-and-presets.test.js +471 -0
  136. package/dist/pipeline/compiler/__tests__/scoring-bridge.test.d.ts +10 -0
  137. package/dist/pipeline/compiler/__tests__/scoring-bridge.test.js +184 -0
  138. package/dist/pipeline/compiler/__tests__/task-graph-builder.test.d.ts +8 -0
  139. package/dist/pipeline/compiler/__tests__/task-graph-builder.test.js +301 -0
  140. package/dist/pipeline/compiler/__tests__/telemetry.test.d.ts +9 -0
  141. package/dist/pipeline/compiler/__tests__/telemetry.test.js +503 -0
  142. package/dist/pipeline/compiler/assertion-mapper.d.ts +58 -0
  143. package/dist/pipeline/compiler/assertion-mapper.js +175 -0
  144. package/dist/pipeline/compiler/compiler-to-yaml.d.ts +51 -0
  145. package/dist/pipeline/compiler/compiler-to-yaml.js +222 -0
  146. package/dist/pipeline/compiler/config-loader.d.ts +56 -0
  147. package/dist/pipeline/compiler/config-loader.js +111 -0
  148. package/dist/pipeline/compiler/fixture-resolver.d.ts +41 -0
  149. package/dist/pipeline/compiler/fixture-resolver.js +113 -0
  150. package/dist/pipeline/compiler/hash.d.ts +11 -0
  151. package/dist/pipeline/compiler/hash.js +18 -0
  152. package/dist/pipeline/compiler/ignore-fields.d.ts +53 -0
  153. package/dist/pipeline/compiler/ignore-fields.js +113 -0
  154. package/dist/pipeline/compiler/index.d.ts +29 -0
  155. package/dist/pipeline/compiler/index.js +45 -0
  156. package/dist/pipeline/compiler/literacy-bridge.d.ts +102 -0
  157. package/dist/pipeline/compiler/literacy-bridge.js +172 -0
  158. package/dist/pipeline/compiler/mode-handlers/__fixtures__/agent-harness-example-tasks.d.ts +14 -0
  159. package/dist/pipeline/compiler/mode-handlers/__fixtures__/agent-harness-example-tasks.js +152 -0
  160. package/dist/pipeline/compiler/mode-handlers/__fixtures__/knowledge-probe-example-tasks.d.ts +32 -0
  161. package/dist/pipeline/compiler/mode-handlers/__fixtures__/knowledge-probe-example-tasks.js +176 -0
  162. package/dist/pipeline/compiler/mode-handlers/__fixtures__/mcp-example-tasks.d.ts +49 -0
  163. package/dist/pipeline/compiler/mode-handlers/__fixtures__/mcp-example-tasks.js +259 -0
  164. package/dist/pipeline/compiler/mode-handlers/agent-harness-handler.d.ts +70 -0
  165. package/dist/pipeline/compiler/mode-handlers/agent-harness-handler.js +485 -0
  166. package/dist/pipeline/compiler/mode-handlers/index.d.ts +16 -0
  167. package/dist/pipeline/compiler/mode-handlers/index.js +21 -0
  168. package/dist/pipeline/compiler/mode-handlers/knowledge-probe-handler.d.ts +76 -0
  169. package/dist/pipeline/compiler/mode-handlers/knowledge-probe-handler.js +245 -0
  170. package/dist/pipeline/compiler/mode-handlers/literacy-handler.d.ts +89 -0
  171. package/dist/pipeline/compiler/mode-handlers/literacy-handler.js +379 -0
  172. package/dist/pipeline/compiler/mode-handlers/mcp-assertions.d.ts +50 -0
  173. package/dist/pipeline/compiler/mode-handlers/mcp-assertions.js +277 -0
  174. package/dist/pipeline/compiler/mode-handlers/mcp-server-handler.d.ts +67 -0
  175. package/dist/pipeline/compiler/mode-handlers/mcp-server-handler.js +309 -0
  176. package/dist/pipeline/compiler/presets/index.d.ts +9 -0
  177. package/dist/pipeline/compiler/presets/index.js +8 -0
  178. package/dist/pipeline/compiler/presets/sanity-literacy.d.ts +45 -0
  179. package/dist/pipeline/compiler/presets/sanity-literacy.js +354 -0
  180. package/dist/pipeline/compiler/promptfoo-compiler.d.ts +96 -0
  181. package/dist/pipeline/compiler/promptfoo-compiler.js +230 -0
  182. package/dist/pipeline/compiler/provider-assembler.d.ts +39 -0
  183. package/dist/pipeline/compiler/provider-assembler.js +137 -0
  184. package/dist/pipeline/compiler/sandbox/docker-sandbox.d.ts +21 -0
  185. package/dist/pipeline/compiler/sandbox/docker-sandbox.js +136 -0
  186. package/dist/pipeline/compiler/sandbox/fixture-provisioner.d.ts +69 -0
  187. package/dist/pipeline/compiler/sandbox/fixture-provisioner.js +189 -0
  188. package/dist/pipeline/compiler/sandbox/git-worktree-sandbox.d.ts +20 -0
  189. package/dist/pipeline/compiler/sandbox/git-worktree-sandbox.js +114 -0
  190. package/dist/pipeline/compiler/sandbox/index.d.ts +10 -0
  191. package/dist/pipeline/compiler/sandbox/index.js +11 -0
  192. package/dist/pipeline/compiler/sandbox/sandbox-selector.d.ts +35 -0
  193. package/dist/pipeline/compiler/sandbox/sandbox-selector.js +86 -0
  194. package/dist/pipeline/compiler/sandbox/sandbox-strategy.d.ts +81 -0
  195. package/dist/pipeline/compiler/sandbox/sandbox-strategy.js +15 -0
  196. package/dist/pipeline/compiler/sandbox/tempdir-sandbox.d.ts +20 -0
  197. package/dist/pipeline/compiler/sandbox/tempdir-sandbox.js +74 -0
  198. package/dist/pipeline/compiler/scoring-bridge.d.ts +49 -0
  199. package/dist/pipeline/compiler/scoring-bridge.js +114 -0
  200. package/dist/pipeline/compiler/task-graph-builder.d.ts +54 -0
  201. package/dist/pipeline/compiler/task-graph-builder.js +291 -0
  202. package/dist/pipeline/compiler/telemetry/cost-tracker.d.ts +90 -0
  203. package/dist/pipeline/compiler/telemetry/cost-tracker.js +146 -0
  204. package/dist/pipeline/compiler/telemetry/index.d.ts +14 -0
  205. package/dist/pipeline/compiler/telemetry/index.js +19 -0
  206. package/dist/pipeline/compiler/telemetry/redactor.d.ts +58 -0
  207. package/dist/pipeline/compiler/telemetry/redactor.js +222 -0
  208. package/dist/pipeline/compiler/telemetry/tool-classifier.d.ts +32 -0
  209. package/dist/pipeline/compiler/telemetry/tool-classifier.js +120 -0
  210. package/dist/pipeline/compiler/telemetry/trace-collector.d.ts +75 -0
  211. package/dist/pipeline/compiler/telemetry/trace-collector.js +297 -0
  212. package/dist/pipeline/compiler/telemetry/trace-store.d.ts +78 -0
  213. package/dist/pipeline/compiler/telemetry/trace-store.js +85 -0
  214. package/dist/pipeline/compiler/variable-resolver.d.ts +46 -0
  215. package/dist/pipeline/compiler/variable-resolver.js +115 -0
  216. package/dist/pipeline/coverage-audit.d.ts +15 -5
  217. package/dist/pipeline/coverage-audit.js +41 -22
  218. package/dist/pipeline/eval-constants.d.ts +16 -6
  219. package/dist/pipeline/eval-constants.js +25 -4
  220. package/dist/pipeline/eval-fingerprint.d.ts +2 -2
  221. package/dist/pipeline/eval-fingerprint.js +8 -9
  222. package/dist/pipeline/expand-tasks.d.ts +23 -14
  223. package/dist/pipeline/expand-tasks.js +37 -31
  224. package/dist/pipeline/gap-analysis.d.ts +1 -1
  225. package/dist/pipeline/gap-analysis.js +2 -2
  226. package/dist/pipeline/generate-configs.d.ts +22 -4
  227. package/dist/pipeline/generate-configs.js +53 -24
  228. package/dist/pipeline/grader-api.d.ts +3 -3
  229. package/dist/pipeline/grader-api.js +5 -12
  230. package/dist/pipeline/grader-compare-runner.js +20 -27
  231. package/dist/pipeline/grader-comparison.d.ts +4 -8
  232. package/dist/pipeline/grader-comparison.js +11 -17
  233. package/dist/pipeline/grader-consistency-runner.d.ts +2 -3
  234. package/dist/pipeline/grader-consistency-runner.js +18 -21
  235. package/dist/pipeline/grader-consistency.d.ts +6 -10
  236. package/dist/pipeline/grader-consistency.js +13 -32
  237. package/dist/pipeline/grader-sensitivity-runner.js +7 -5
  238. package/dist/pipeline/grader-sensitivity.d.ts +2 -6
  239. package/dist/pipeline/grader-sensitivity.js +10 -10
  240. package/dist/pipeline/grader-validate-runner.js +7 -5
  241. package/dist/pipeline/grader-validation.d.ts +2 -6
  242. package/dist/pipeline/grader-validation.js +14 -22
  243. package/dist/pipeline/map-request-to-config.js +6 -1
  244. package/dist/pipeline/mirror-repo-tasks.d.ts +6 -6
  245. package/dist/pipeline/mirror-repo-tasks.js +16 -15
  246. package/dist/pipeline/normalize-mode.d.ts +49 -0
  247. package/dist/pipeline/normalize-mode.js +64 -0
  248. package/dist/pipeline/plan.d.ts +5 -2
  249. package/dist/pipeline/plan.js +134 -78
  250. package/dist/pipeline/pr-comment.js +2 -0
  251. package/dist/pipeline/profile-resolution.d.ts +47 -0
  252. package/dist/pipeline/profile-resolution.js +91 -0
  253. package/dist/pipeline/provenance.d.ts +2 -2
  254. package/dist/pipeline/provenance.js +12 -17
  255. package/dist/pipeline/release-report.js +4 -4
  256. package/dist/pipeline/repo-threshold-evaluator.d.ts +1 -1
  257. package/dist/pipeline/repo-threshold-evaluator.js +1 -1
  258. package/dist/pipeline/rubric-loader.d.ts +20 -0
  259. package/dist/pipeline/rubric-loader.js +37 -0
  260. package/dist/pipeline/validate.d.ts +4 -4
  261. package/dist/pipeline/validate.js +64 -53
  262. package/dist/schedules/loader.js +18 -8
  263. package/dist/scripts/migrate-task-mode.d.ts +24 -0
  264. package/dist/scripts/migrate-task-mode.js +85 -0
  265. package/dist/scripts/migrate-tasks-to-content-lake.js +11 -10
  266. package/dist/scripts/validate-task-sources.d.ts +1 -1
  267. package/dist/scripts/validate-task-sources.js +15 -15
  268. package/dist/sinks/loader.js +5 -7
  269. package/dist/sources.d.ts +7 -7
  270. package/dist/sources.js +22 -24
  271. package/dist/webhook/dispatch.js +2 -1
  272. package/package.json +6 -3
  273. package/tasks/knowledge-probe/define-type-api.task.ts +55 -0
  274. package/tasks/knowledge-probe/groq-projections.task.ts +59 -0
  275. package/tasks/literacy/frameworks.task.ts +128 -0
  276. package/tasks/literacy/functions.task.ts +69 -0
  277. package/tasks/literacy/groq.task.ts +258 -0
  278. package/tasks/literacy/nextjs-live.task.ts +75 -0
  279. package/tasks/literacy/studio-setup.task.ts +131 -0
  280. package/tasks/literacy/visual-editing.task.ts +146 -0
  281. package/config/features.yaml +0 -116
  282. package/config/models.yaml +0 -116
  283. package/config/prompts.yaml +0 -75
  284. package/config/rubrics.yaml +0 -62
  285. package/config/schedules.yaml +0 -43
  286. package/config/sinks.yaml +0 -54
  287. package/config/sources.yaml +0 -51
  288. package/config/thresholds.yaml +0 -49
  289. package/dist/agent-observer/test-imports.d.ts +0 -7
  290. package/dist/agent-observer/test-imports.js +0 -185
@@ -5,11 +5,11 @@
5
5
  * typed options derived from AppContext. No env bridge needed.
6
6
  */
7
7
  import { join } from "path";
8
- import { FULL_MODE_SUBMODES } from "../../_vendor/ailf-shared/index.js";
8
+ import { LiteracyVariant } from "../../pipeline/normalize-mode.js";
9
9
  import { getStepInputPaths } from "../../pipeline/cache.js";
10
10
  import { calculateAndWriteScores } from "../../pipeline/calculate-scores.js";
11
11
  import { checkResultsExist, checkScoreSummaryValid, } from "../../pipeline/checks.js";
12
- import { RESULTS_FILES } from "../../pipeline/eval-constants.js";
12
+ import { resultsFileForMode } from "../../pipeline/eval-constants.js";
13
13
  import { loadSource } from "../../sources.js";
14
14
  import { configToSourceOverrides } from "../config-to-source-overrides.js";
15
15
  export class CalculateScoresStep {
@@ -23,10 +23,14 @@ export class CalculateScoresStep {
23
23
  // score-summary.json was already restored from the cached report.
24
24
  // Skip re-calculation — the raw eval-results files don't exist.
25
25
  if (state.remoteCacheHits?.size) {
26
- const requiredModes = ctx.config.mode === "full"
27
- ? [...FULL_MODE_SUBMODES]
28
- : [ctx.config.mode];
29
- const allCached = requiredModes.every((m) => state.remoteCacheHits.has(m));
26
+ // For literacy mode, determine required eval runs from variant
27
+ const variant = ctx.config.variant ?? LiteracyVariant.STANDARD;
28
+ const requiredRuns = ctx.config.mode === "literacy" && variant === LiteracyVariant.FULL
29
+ ? [LiteracyVariant.STANDARD, LiteracyVariant.AGENTIC]
30
+ : ctx.config.mode === "literacy"
31
+ ? [variant]
32
+ : [ctx.config.mode];
33
+ const allCached = requiredRuns.every((m) => state.remoteCacheHits.has(m));
30
34
  if (allCached) {
31
35
  // Verify the restored score-summary.json is valid
32
36
  const summaryIssues = checkScoreSummaryValid(ctx.config.rootDir);
@@ -40,10 +44,15 @@ export class CalculateScoresStep {
40
44
  // If the summary is invalid, fall through to normal calculation
41
45
  }
42
46
  }
43
- const primaryMode = ctx.config.mode === "full"
44
- ? "baseline"
47
+ // Primary results file to score.
48
+ // For literacy: "full" variant uses baseline as primary; others use variant directly.
49
+ // For other modes: use the mode name.
50
+ const primaryResultsRun = ctx.config.mode === "literacy"
51
+ ? ctx.config.variant === LiteracyVariant.FULL
52
+ ? LiteracyVariant.STANDARD
53
+ : (ctx.config.variant ?? LiteracyVariant.STANDARD)
45
54
  : ctx.config.mode;
46
- const resultsFile = RESULTS_FILES[primaryMode];
55
+ const resultsFile = resultsFileForMode(primaryResultsRun);
47
56
  // Precondition: results file exists
48
57
  const resultsIssues = checkResultsExist(ctx.config.rootDir, resultsFile);
49
58
  const resultsErrors = resultsIssues.filter((i) => i.severity === "error");
@@ -68,9 +77,13 @@ export class CalculateScoresStep {
68
77
  const result = calculateAndWriteScores({
69
78
  allowedOrigins: ctx.config.allowedOrigins,
70
79
  logger: ctx.logger,
71
- mode: ctx.config.mode,
80
+ // Pass the variant for literacy (scoring uses it to decide
81
+ // whether to read agentic results), or mode for other modes
82
+ mode: ctx.config.mode === "literacy"
83
+ ? (ctx.config.variant ?? LiteracyVariant.STANDARD)
84
+ : ctx.config.mode,
72
85
  resolvedSource,
73
- resultsPath: primaryMode !== "baseline"
86
+ resultsPath: primaryResultsRun !== LiteracyVariant.STANDARD
74
87
  ? join(ctx.config.rootDir, resultsFile)
75
88
  : undefined,
76
89
  rootDir: ctx.config.rootDir,
@@ -28,8 +28,10 @@ export class FetchDocsStep {
28
28
  }
29
29
  const start = Date.now();
30
30
  // Precondition: at least one task has canonical doc mappings
31
- const tasks = await ctx.taskSource.loadTasks(buildFilter(ctx));
32
- const tasksWithDocs = tasks.filter((t) => t.canonicalDocs.length > 0);
31
+ const allTasks = await ctx.taskSource.loadTasks(buildFilter(ctx));
32
+ // Bridge: narrow to literacy tasks for canonical doc access
33
+ const literacyTasks = allTasks.filter((t) => t.mode === "literacy");
34
+ const tasksWithDocs = literacyTasks.filter((t) => (t.context?.docs?.length ?? 0) > 0);
33
35
  if (tasksWithDocs.length === 0) {
34
36
  return {
35
37
  durationMs: Date.now() - start,
@@ -100,7 +102,7 @@ export class FetchDocsStep {
100
102
  if (resolvedSource.perspective &&
101
103
  releaseImpact &&
102
104
  !ctx.config.noAutoScope) {
103
- const autoScope = computeAutoScope(tasks, releaseImpact, resolvedSource.perspective);
105
+ const autoScope = computeAutoScope(literacyTasks, releaseImpact, resolvedSource.perspective);
104
106
  if (autoScope) {
105
107
  state.releaseAutoScope = autoScope;
106
108
  logAutoScope(autoScope);
@@ -171,7 +173,7 @@ function writeMetadataFiles(rootDir, metadata) {
171
173
  */
172
174
  function extractSlugsFromTask(task) {
173
175
  const slugs = [];
174
- for (const ref of task.canonicalDocs) {
176
+ for (const ref of task.context?.docs ?? []) {
175
177
  if (isSlugRef(ref)) {
176
178
  slugs.push(ref.slug);
177
179
  }
@@ -89,7 +89,7 @@ export class GapAnalysisStep {
89
89
  const areaToDocRefs = new Map();
90
90
  let tasks = [];
91
91
  try {
92
- tasks = await ctx.taskSource.loadTasks();
92
+ tasks = (await ctx.taskSource.loadTasks()).filter((t) => t.mode === "literacy");
93
93
  }
94
94
  catch {
95
95
  // TaskSource may not be available in all contexts (e.g., standalone
@@ -99,17 +99,18 @@ export class GapAnalysisStep {
99
99
  // Group tasks by feature area and build slug maps
100
100
  const byArea = new Map();
101
101
  for (const task of tasks) {
102
- const slugs = extractSlugsFromRefs(task.canonicalDocs);
102
+ const slugs = extractSlugsFromRefs(task.context?.docs ?? []);
103
103
  const refs = resolveRefs(slugs);
104
- // Map by description (what judgments use as taskId)
105
- descToDocRefs.set(task.description, refs);
104
+ // Map by title (what judgments use as taskId)
105
+ descToDocRefs.set(task.title, refs);
106
106
  // Also map by task ID for prefix-based matching
107
107
  descToDocRefs.set(task.id, refs);
108
108
  // Group slugs by feature area
109
- if (!byArea.has(task.featureArea))
110
- byArea.set(task.featureArea, new Set());
109
+ const area = task.area ?? "";
110
+ if (!byArea.has(area))
111
+ byArea.set(area, new Set());
111
112
  for (const s of slugs)
112
- byArea.get(task.featureArea).add(s);
113
+ byArea.get(area).add(s);
113
114
  }
114
115
  for (const [area, slugs] of byArea) {
115
116
  areaToDocRefs.set(area, resolveRefs([...slugs]));
@@ -1,14 +1,27 @@
1
1
  /**
2
2
  * Pipeline step: Generate Promptfoo configuration files.
3
3
  *
4
- * Calls generateConfigs() from pipeline/generate-configs.ts with typed options
5
- * derived from AppContext. No env bridge needed — source is resolved and
6
- * passed directly.
4
+ * ALL modes route through the Plugin Registry. The step looks up the mode
5
+ * handler via ctx.registry.getMode() and delegates compilation to it.
6
+ *
7
+ * Literacy mode has a variant strategy: baseline/agentic/observed/full.
8
+ * When the variant is "full", the handler is called twice (baseline + agentic)
9
+ * and three YAML files are written. Other modes produce one YAML file.
7
10
  */
8
11
  import type { AppContext, PipelineState, PipelineStep, StepResult, ValidationIssue } from "../../_vendor/ailf-core/index.d.ts";
9
12
  export declare class GenerateConfigsStep implements PipelineStep {
10
13
  readonly name = "generate-configs";
11
14
  check(ctx: AppContext): ValidationIssue[];
12
15
  execute(ctx: AppContext, state: PipelineState): Promise<StepResult>;
16
+ private compileLiteracyVariants;
17
+ private compileSingleMode;
18
+ private loadTasks;
19
+ private applyFilters;
20
+ /**
21
+ * Compile all tasks through a handler, merging results.
22
+ * For literacy mode, ctx can carry evalMode as an extension.
23
+ */
24
+ private compileAll;
25
+ private checkLiteracyPostconditions;
13
26
  cacheInputs(ctx: AppContext): string[];
14
27
  }
@@ -1,13 +1,16 @@
1
1
  /**
2
2
  * Pipeline step: Generate Promptfoo configuration files.
3
3
  *
4
- * Calls generateConfigs() from pipeline/generate-configs.ts with typed options
5
- * derived from AppContext. No env bridge needed — source is resolved and
6
- * passed directly.
4
+ * ALL modes route through the Plugin Registry. The step looks up the mode
5
+ * handler via ctx.registry.getMode() and delegates compilation to it.
6
+ *
7
+ * Literacy mode has a variant strategy: baseline/agentic/observed/full.
8
+ * When the variant is "full", the handler is called twice (baseline + agentic)
9
+ * and three YAML files are written. Other modes produce one YAML file.
7
10
  */
11
+ import { LiteracyVariant } from "../../pipeline/normalize-mode.js";
8
12
  import { getStepInputPaths } from "../../pipeline/cache.js";
9
13
  import { checkGeneratedConfigsExist } from "../../pipeline/checks.js";
10
- import { generateConfigs } from "../../pipeline/generate-configs.js";
11
14
  import { validateModelsYaml } from "../../pipeline/validate.js";
12
15
  import { loadSource } from "../../sources.js";
13
16
  import { configToSourceOverrides } from "../config-to-source-overrides.js";
@@ -19,68 +22,230 @@ export class GenerateConfigsStep {
19
22
  }
20
23
  async execute(ctx, state) {
21
24
  const start = Date.now();
22
- // Resolve source once with typed overrides
23
- const overrides = configToSourceOverrides(ctx.config);
24
- const resolvedSource = ctx.config.source
25
- ? loadSource(ctx.config.source, overrides)
26
- : undefined;
27
- // Load tasks via the TaskSource port — this picks up Content Lake,
28
- // repo-based, and YAML tasks depending on which adapter is wired.
29
- let tasks;
25
+ const mode = ctx.config.mode;
26
+ // Look up mode handler in the registry
27
+ const registration = ctx.registry.getMode(mode);
28
+ if (!registration) {
29
+ return {
30
+ durationMs: Date.now() - start,
31
+ error: `No handler registered for mode "${mode}". ` +
32
+ `Available modes: ${ctx.registry
33
+ .getModes()
34
+ .map((m) => m.id)
35
+ .join(", ")}`,
36
+ status: "failed",
37
+ };
38
+ }
30
39
  try {
31
- const filter = ctx.config.areas || ctx.config.tasks || ctx.config.tags
32
- ? {
33
- areas: ctx.config.areas,
34
- taskIds: ctx.config.tasks,
35
- tags: ctx.config.tags,
36
- }
40
+ // Dynamically import the handler module
41
+ const handlerModule = await import(`../../pipeline/compiler/${registration.handlerModule}`);
42
+ const handler = handlerModule.handler;
43
+ if (!handler?.compileTask) {
44
+ return {
45
+ durationMs: Date.now() - start,
46
+ error: `Handler module for "${mode}" does not export a valid ModeHandler`,
47
+ status: "failed",
48
+ };
49
+ }
50
+ // Load tasks
51
+ const tasks = await this.loadTasks(ctx, mode, state);
52
+ if (tasks.length === 0) {
53
+ return {
54
+ durationMs: Date.now() - start,
55
+ error: `No ${mode} tasks found. Create *.task.ts files in ` +
56
+ `packages/eval/tasks/${mode}/`,
57
+ status: "failed",
58
+ };
59
+ }
60
+ // Load models
61
+ const { loadModelsAndProviders } = await import("../../pipeline/compiler/provider-assembler.js");
62
+ const overrides = configToSourceOverrides(ctx.config);
63
+ const resolvedSource = ctx.config.source
64
+ ? loadSource(ctx.config.source, overrides)
37
65
  : undefined;
38
- tasks = await ctx.taskSource.loadTasks(filter);
66
+ const { models, providers } = loadModelsAndProviders(ctx.config.rootDir, resolvedSource, ctx.config.searchMode, ctx.config.allowedOrigins);
67
+ // Literacy mode: variant expansion (baseline + agentic → 3 YAML files)
68
+ if (mode === "literacy") {
69
+ return this.compileLiteracyVariants(ctx, handler, tasks, models, providers, start);
70
+ }
71
+ // All other modes: single compilation → single YAML file
72
+ return this.compileSingleMode(ctx, handler, tasks, mode, models, start);
39
73
  }
40
74
  catch (err) {
75
+ const msg = err instanceof Error ? err.message : String(err);
41
76
  return {
42
77
  durationMs: Date.now() - start,
43
- error: `TaskSource.loadTasks failed: ${err instanceof Error ? err.message : String(err)}`,
78
+ error: `${mode} compilation failed: ${msg}`,
44
79
  status: "failed",
45
80
  };
46
81
  }
47
- // Release auto-scope: narrow tasks to those affected by the release.
48
- // When explicit area/task filters are also active, this produces the
49
- // intersection (only tasks matching BOTH the explicit filter AND the
50
- // release impact are included).
82
+ }
83
+ // ---------------------------------------------------------------------------
84
+ // Literacy variant compilation (baseline + agentic 3 YAML files)
85
+ // ---------------------------------------------------------------------------
86
+ async compileLiteracyVariants(ctx, handler, tasks, models, providers, start) {
87
+ ctx.logger.info(`Compiling ${tasks.length} literacy task(s) via registry handler...`);
88
+ // Filter models per variant
89
+ const baselineModels = models.models
90
+ .filter((m) => !m.modes || m.modes.includes(LiteracyVariant.STANDARD))
91
+ .map((m) => ({
92
+ id: m.id,
93
+ label: m.label,
94
+ }));
95
+ const agenticModels = models.models
96
+ .filter((m) => !m.modes ||
97
+ m.modes.includes("agentic-naive") ||
98
+ m.modes.includes("agentic-optimized"))
99
+ .map((m) => ({
100
+ id: m.id,
101
+ label: m.label,
102
+ }));
103
+ // Load rubric config for template resolution
104
+ let rubricConfig;
105
+ try {
106
+ const { loadRubricTemplates } = await import("../../pipeline/rubric-loader.js");
107
+ rubricConfig = loadRubricTemplates(ctx.config.rootDir);
108
+ }
109
+ catch {
110
+ ctx.logger.warn(" ⚠ Could not load rubric config — templates will not resolve");
111
+ }
112
+ // Compile for each variant
113
+ const baselineResults = this.compileAll(handler, tasks, {
114
+ rootDir: ctx.config.rootDir,
115
+ graderProvider: models.grader.id,
116
+ models: baselineModels,
117
+ rubricConfig,
118
+ evalMode: LiteracyVariant.STANDARD,
119
+ });
120
+ const agenticResults = this.compileAll(handler, tasks, {
121
+ rootDir: ctx.config.rootDir,
122
+ graderProvider: models.grader.id,
123
+ models: agenticModels,
124
+ rubricConfig,
125
+ evalMode: LiteracyVariant.AGENTIC,
126
+ });
127
+ // Log warnings
128
+ for (const w of [...baselineResults.warnings, ...agenticResults.warnings]) {
129
+ ctx.logger.warn(` ⚠ ${w}`);
130
+ }
131
+ ctx.logger.info(` Compiled ${tasks.length} task(s) → ${baselineResults.tests.length} baseline + ${agenticResults.tests.length} agentic entries`);
132
+ // Write 3 YAML files via the literacy-specific writer
133
+ const { writeCompiledLiteracyConfigs } = await import("../../pipeline/compiler/compiler-to-yaml.js");
134
+ writeCompiledLiteracyConfigs(baselineResults, agenticResults, providers, {
135
+ rootDir: ctx.config.rootDir,
136
+ graderProvider: models.grader.id,
137
+ maxConcurrency: models.maxConcurrency,
138
+ logger: ctx.logger,
139
+ });
140
+ return this.checkLiteracyPostconditions(ctx, start);
141
+ }
142
+ // ---------------------------------------------------------------------------
143
+ // Single-mode compilation (all non-literacy modes)
144
+ // ---------------------------------------------------------------------------
145
+ async compileSingleMode(ctx, handler, tasks, mode, models, start) {
146
+ ctx.logger.info(`Compiling ${tasks.length} ${mode} task(s) via registry handler...`);
147
+ const merged = this.compileAll(handler, tasks, {
148
+ rootDir: ctx.config.rootDir,
149
+ graderProvider: models.grader.id,
150
+ models: models.models.map((m) => ({
151
+ id: m.id,
152
+ label: m.label,
153
+ })),
154
+ });
155
+ for (const w of merged.warnings) {
156
+ ctx.logger.warn(` ⚠ ${w}`);
157
+ }
158
+ ctx.logger.info(` Compiled ${tasks.length} task(s) → ${merged.tests.length} test entries`);
159
+ const { writeCompiledModeConfig } = await import("../../pipeline/compiler/compiler-to-yaml.js");
160
+ writeCompiledModeConfig(merged, mode, {
161
+ rootDir: ctx.config.rootDir,
162
+ graderProvider: models.grader.id,
163
+ maxConcurrency: models.maxConcurrency,
164
+ logger: ctx.logger,
165
+ });
166
+ return {
167
+ durationMs: Date.now() - start,
168
+ status: "success",
169
+ summary: `Generated promptfooconfig.${mode}.yaml`,
170
+ };
171
+ }
172
+ // ---------------------------------------------------------------------------
173
+ // Task loading — unified for all modes
174
+ // ---------------------------------------------------------------------------
175
+ async loadTasks(ctx, mode, state) {
176
+ const { resolve } = await import("path");
177
+ const { discoverTsTaskFiles, loadTsTaskFile } = await import("../../adapters/task-sources/task-file-loader.js");
178
+ const tasksDir = resolve(ctx.config.rootDir, "tasks", mode);
179
+ const files = discoverTsTaskFiles(tasksDir);
180
+ const tasks = [];
181
+ for (const file of files) {
182
+ const raw = await loadTsTaskFile(file);
183
+ for (const t of raw.tasks) {
184
+ const task = t;
185
+ // Filter to matching mode (skip tasks from other modes in same dir)
186
+ if (!("mode" in task) || task.mode === mode) {
187
+ tasks.push(task);
188
+ }
189
+ }
190
+ }
191
+ // Apply area/task/tag filters
192
+ const filtered = this.applyFilters(ctx, tasks);
193
+ // Release auto-scope
51
194
  if (state.releaseAutoScope && !ctx.config.noAutoScope) {
52
195
  const scopedIds = new Set(state.releaseAutoScope.affectedTaskIds);
53
- const beforeCount = tasks.length;
54
- tasks = tasks.filter((t) => scopedIds.has(t.id));
55
- console.log(` 🎯 Auto-scoped to ${tasks.length} of ${beforeCount} task(s) affected by release` +
56
- ` (${beforeCount - tasks.length} skipped, --no-auto-scope to override)`);
196
+ const beforeCount = filtered.length;
197
+ const scoped = filtered.filter((t) => "id" in t && scopedIds.has(t.id));
198
+ ctx.logger.info(` 🎯 Auto-scoped to ${scoped.length} of ${beforeCount} task(s) affected by release`);
199
+ return scoped;
57
200
  }
58
- try {
59
- generateConfigs({
60
- allowedOrigins: ctx.config.allowedOrigins,
61
- filter: ctx.config.areas || ctx.config.tasks || ctx.config.tags
62
- ? {
63
- areas: ctx.config.areas,
64
- taskIds: ctx.config.tasks,
65
- tags: ctx.config.tags,
66
- }
67
- : undefined,
68
- logger: ctx.logger,
69
- resolvedSource,
70
- rootDir: ctx.config.rootDir,
71
- searchMode: ctx.config.searchMode,
72
- source: ctx.config.source,
73
- tasks,
201
+ return filtered;
202
+ }
203
+ applyFilters(ctx, tasks) {
204
+ let result = tasks;
205
+ if (ctx.config.areas?.length) {
206
+ const allowed = new Set(ctx.config.areas.map((a) => a.toLowerCase()));
207
+ result = result.filter((t) => {
208
+ const area = t.area?.toLowerCase();
209
+ return area && allowed.has(area);
74
210
  });
75
211
  }
76
- catch (err) {
77
- return {
78
- durationMs: Date.now() - start,
79
- error: `generate-configs failed: ${err instanceof Error ? err.message : String(err)}`,
80
- status: "failed",
81
- };
212
+ if (ctx.config.tasks?.length) {
213
+ const allowed = new Set(ctx.config.tasks);
214
+ result = result.filter((t) => {
215
+ const id = t.id;
216
+ return id && allowed.has(id);
217
+ });
82
218
  }
83
- // Postcondition: config files exist
219
+ if (ctx.config.tags?.length) {
220
+ const allowed = new Set(ctx.config.tags);
221
+ result = result.filter((t) => {
222
+ const tags = t.tags;
223
+ return tags?.some((tag) => allowed.has(tag));
224
+ });
225
+ }
226
+ return result;
227
+ }
228
+ // ---------------------------------------------------------------------------
229
+ // Compilation helpers
230
+ // ---------------------------------------------------------------------------
231
+ /**
232
+ * Compile all tasks through a handler, merging results.
233
+ * For literacy mode, ctx can carry evalMode as an extension.
234
+ */
235
+ compileAll(handler, tasks, ctx) {
236
+ const results = [];
237
+ const warnings = [];
238
+ for (const task of tasks) {
239
+ const result = handler.compileTask(task, ctx);
240
+ results.push(result);
241
+ warnings.push(...result.warnings);
242
+ }
243
+ return mergeCompileResults(results);
244
+ }
245
+ // ---------------------------------------------------------------------------
246
+ // Postcondition checks
247
+ // ---------------------------------------------------------------------------
248
+ checkLiteracyPostconditions(ctx, start) {
84
249
  const configIssues = checkGeneratedConfigsExist(ctx.config.rootDir);
85
250
  const configErrors = configIssues.filter((i) => i.severity === "error");
86
251
  if (configErrors.length > 0) {
@@ -100,3 +265,32 @@ export class GenerateConfigsStep {
100
265
  return getStepInputPaths(ctx.config.rootDir, "generate-configs");
101
266
  }
102
267
  }
268
+ // ---------------------------------------------------------------------------
269
+ // Helpers
270
+ // ---------------------------------------------------------------------------
271
+ /**
272
+ * Merge multiple compile results into one.
273
+ *
274
+ * Note: `providers` and `prompts` are taken from the first result only.
275
+ * This is correct for single-mode compilation where all tasks share the
276
+ * same provider set. Cross-mode merging with per-task provider overrides
277
+ * would need deduplication here.
278
+ */
279
+ function mergeCompileResults(results) {
280
+ const tests = results.flatMap((r) => r.tests);
281
+ const warnings = results.flatMap((r) => r.warnings);
282
+ const providers = results[0]?.providers ?? [];
283
+ const prompts = results[0]?.prompts ?? [];
284
+ const extras = {};
285
+ for (const r of results) {
286
+ if (r.extras)
287
+ Object.assign(extras, r.extras);
288
+ }
289
+ return {
290
+ providers,
291
+ tests,
292
+ prompts,
293
+ warnings,
294
+ ...(Object.keys(extras).length > 0 ? { extras } : {}),
295
+ };
296
+ }
@@ -6,8 +6,9 @@
6
6
  */
7
7
  import { existsSync } from "fs";
8
8
  import { resolve } from "path";
9
+ import { LiteracyVariant } from "../../pipeline/normalize-mode.js";
9
10
  import { checkResultsExist } from "../../pipeline/checks.js";
10
- import { RESULTS_FILES } from "../../pipeline/eval-constants.js";
11
+ import { resultsFileForMode } from "../../pipeline/eval-constants.js";
11
12
  import { runGraderConsistency } from "../../pipeline/grader-consistency-runner.js";
12
13
  export class GraderConsistencyStep {
13
14
  name = "grader-consistency";
@@ -18,10 +19,12 @@ export class GraderConsistencyStep {
18
19
  async execute(ctx) {
19
20
  const start = Date.now();
20
21
  const replications = ctx.config.graderReplications ?? 5;
21
- const concreteMode = ctx.config.mode === "full"
22
- ? "baseline"
22
+ const primaryResultsRun = ctx.config.mode === "literacy"
23
+ ? ctx.config.variant === LiteracyVariant.FULL
24
+ ? LiteracyVariant.STANDARD
25
+ : (ctx.config.variant ?? LiteracyVariant.STANDARD)
23
26
  : ctx.config.mode;
24
- const resultsFile = RESULTS_FILES[concreteMode];
27
+ const resultsFile = resultsFileForMode(primaryResultsRun);
25
28
  // Precondition: results file exists
26
29
  const resultsIssues = checkResultsExist(ctx.config.rootDir, resultsFile);
27
30
  const resultsErrors = resultsIssues.filter((i) => i.severity === "error");
@@ -43,7 +43,7 @@ export class MirrorRepoTasksStep {
43
43
  // RepoTaskSource via a fresh instance.
44
44
  const { RepoTaskSource } = await import("../../adapters/task-sources/repo-task-source.js");
45
45
  const repoSource = new RepoTaskSource(ctx.config.repoTasksPath);
46
- const repoTasks = await repoSource.loadTasks();
46
+ const repoTasks = (await repoSource.loadTasks()).filter((t) => t.mode === "literacy");
47
47
  if (repoTasks.length === 0) {
48
48
  return {
49
49
  durationMs: Date.now() - start,
@@ -6,7 +6,7 @@
6
6
  */
7
7
  import { existsSync, readFileSync, writeFileSync } from "fs";
8
8
  import { resolve } from "path";
9
- import { load } from "js-yaml";
9
+ import { tryLoadConfigFile } from "../../pipeline/compiler/config-loader.js";
10
10
  import { formatReadinessMarkdown, generateReadinessReport, } from "../../pipeline/readiness-report.js";
11
11
  import { ThresholdConfigSchema } from "../../pipeline/schemas.js";
12
12
  export class ReadinessStep {
@@ -20,7 +20,6 @@ export class ReadinessStep {
20
20
  const start = Date.now();
21
21
  try {
22
22
  const scoreSummaryPath = resolve(root, "results", "latest", "score-summary.json");
23
- const thresholdsPath = resolve(root, "config", "thresholds.yaml");
24
23
  if (!existsSync(scoreSummaryPath)) {
25
24
  return {
26
25
  durationMs: Date.now() - start,
@@ -28,16 +27,16 @@ export class ReadinessStep {
28
27
  status: "failed",
29
28
  };
30
29
  }
31
- if (!existsSync(thresholdsPath)) {
30
+ const thresholdsLoaded = tryLoadConfigFile("thresholds", root);
31
+ if (!thresholdsLoaded) {
32
32
  return {
33
33
  durationMs: Date.now() - start,
34
- error: "config/thresholds.yaml not found",
34
+ error: "config/thresholds not found",
35
35
  status: "failed",
36
36
  };
37
37
  }
38
38
  const scoreSummary = JSON.parse(readFileSync(scoreSummaryPath, "utf-8"));
39
- const rawThresholds = load(readFileSync(thresholdsPath, "utf-8"));
40
- const thresholdConfig = ThresholdConfigSchema.parse(rawThresholds);
39
+ const thresholdConfig = ThresholdConfigSchema.parse(thresholdsLoaded.data);
41
40
  const gapPath = resolve(root, "results", "latest", "gap-analysis.json");
42
41
  const gapAnalysis = existsSync(gapPath)
43
42
  ? JSON.parse(readFileSync(gapPath, "utf-8"))
@@ -5,12 +5,11 @@
5
5
  * invocation. Builds a clean env object for the subprocess instead of
6
6
  * polluting global process.env.
7
7
  */
8
- import type { ConcreteEvalMode } from "../../_vendor/ailf-shared/index.d.ts";
9
8
  import type { AppContext, PipelineState, PipelineStep, StepResult, ValidationIssue } from "../../_vendor/ailf-core/index.d.ts";
10
9
  export declare class RunEvalStep implements PipelineStep {
11
10
  private readonly mode;
12
11
  readonly name: string;
13
- constructor(mode: ConcreteEvalMode);
12
+ constructor(mode: string);
14
13
  check(): ValidationIssue[];
15
14
  execute(ctx: AppContext, state: PipelineState): Promise<StepResult>;
16
15
  cacheInputs(ctx: AppContext): string[];
@@ -10,7 +10,7 @@ import { resolve } from "path";
10
10
  import { getStepInputPaths } from "../../pipeline/cache.js";
11
11
  import { checkCanonicalContextsExist, checkGeneratedConfigsExist, checkResultsExist, } from "../../pipeline/checks.js";
12
12
  import { computeEvalFingerprint } from "../../pipeline/eval-fingerprint.js";
13
- import { buildFilterFlags, CONFIG_FILES, RESULTS_FILES, scanResultsForErrors, } from "../../pipeline/eval-constants.js";
13
+ import { buildFilterFlags, configFileForMode, resultsFileForMode, scanResultsForErrors, } from "../../pipeline/eval-constants.js";
14
14
  export class RunEvalStep {
15
15
  mode;
16
16
  name;
@@ -59,7 +59,8 @@ export class RunEvalStep {
59
59
  // The generated Promptfoo config still includes their "without-docs"
60
60
  // variant (testing model knowledge alone), which doesn't need a
61
61
  // context file.
62
- const tasksWithDocs = tasks.filter((t) => t.canonicalDocs.length > 0);
62
+ // Bridge: narrow to literacy tasks with docs
63
+ const tasksWithDocs = tasks.filter((t) => t.mode === "literacy" && (t.context?.docs?.length ?? 0) > 0);
63
64
  const taskIds = tasksWithDocs.map((t) => t.id);
64
65
  const contextIssues = checkCanonicalContextsExist(rootDir, taskIds);
65
66
  const contextErrors = contextIssues.filter((i) => i.severity === "error");
@@ -123,7 +124,7 @@ export class RunEvalStep {
123
124
  };
124
125
  // Only set env vars that differ from defaults — the subprocess inherits
125
126
  // process.env via PromptfooEvalAdapter's { ...process.env, ...config.env }
126
- if (ctx.config.mode !== "baseline") {
127
+ if (ctx.config.mode !== "literacy") {
127
128
  subprocessEnv.EVAL_MODE = ctx.config.mode;
128
129
  }
129
130
  if (ctx.config.searchMode !== "open") {
@@ -135,7 +136,7 @@ export class RunEvalStep {
135
136
  // -----------------------------------------------------------------
136
137
  // Execute — use the EvalRunner port
137
138
  // -----------------------------------------------------------------
138
- const configFile = CONFIG_FILES[this.mode];
139
+ const configFile = configFileForMode(this.mode);
139
140
  const filterFlags = buildFilterFlags(debug);
140
141
  const result = await ctx.evalRunner.run({
141
142
  concurrency,
@@ -145,7 +146,7 @@ export class RunEvalStep {
145
146
  });
146
147
  // Check if results were written despite non-zero exit
147
148
  if (result.status === "failed") {
148
- const resultsExist = checkResultsExist(rootDir, RESULTS_FILES[this.mode]);
149
+ const resultsExist = checkResultsExist(rootDir, resultsFileForMode(this.mode));
149
150
  const hasResults = resultsExist.filter((i) => i.severity === "error").length === 0;
150
151
  if (!hasResults) {
151
152
  return {
@@ -156,7 +157,7 @@ export class RunEvalStep {
156
157
  }
157
158
  }
158
159
  // Postcondition: results file exists
159
- const resultsIssues = checkResultsExist(rootDir, RESULTS_FILES[this.mode]);
160
+ const resultsIssues = checkResultsExist(rootDir, resultsFileForMode(this.mode));
160
161
  const resultsErrors = resultsIssues.filter((i) => i.severity === "error");
161
162
  if (resultsErrors.length > 0) {
162
163
  return {
@@ -166,7 +167,7 @@ export class RunEvalStep {
166
167
  };
167
168
  }
168
169
  // Scan results for errors
169
- const errorSummary = scanResultsForErrors(resolve(rootDir, RESULTS_FILES[this.mode]));
170
+ const errorSummary = scanResultsForErrors(resolve(rootDir, resultsFileForMode(this.mode)));
170
171
  if (errorSummary) {
171
172
  console.log();
172
173
  console.log(errorSummary);