stageflow 0.40.0 → 0.42.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 (326) hide show
  1. package/README.md +3 -1
  2. package/dist/agents/authorChat.d.ts +4 -0
  3. package/dist/agents/authorChat.js +113 -12
  4. package/dist/agents/authorSessionStore.d.ts +35 -0
  5. package/dist/agents/authorSessionStore.js +152 -0
  6. package/dist/agents/chatTurn.d.ts +2 -0
  7. package/dist/agents/chatTurn.js +17 -1
  8. package/dist/agents/errors.d.ts +1 -1
  9. package/dist/agents/errors.js +1 -0
  10. package/dist/agents/evalGate.d.ts +61 -0
  11. package/dist/agents/evalGate.js +103 -0
  12. package/dist/agents/evalSession.d.ts +26 -0
  13. package/dist/agents/evalSession.js +29 -0
  14. package/dist/agents/hostContext.d.ts +3 -0
  15. package/dist/agents/hostContext.js +4 -1
  16. package/dist/agents/runtime/piRuntime.d.ts +1 -1
  17. package/dist/agents/runtime/piRuntime.js +4 -4
  18. package/dist/agents/runtime/types.d.ts +3 -1
  19. package/dist/agents/service.d.ts +27 -2
  20. package/dist/agents/service.js +88 -13
  21. package/dist/agents/sessions.d.ts +8 -0
  22. package/dist/agents/sessions.js +50 -10
  23. package/dist/agents/store.d.ts +14 -3
  24. package/dist/agents/store.js +45 -7
  25. package/dist/agents/toolRisk.d.ts +21 -0
  26. package/dist/agents/toolRisk.js +50 -0
  27. package/dist/cli/doctorCommand.js +26 -0
  28. package/dist/cli/evalCommand.d.ts +20 -0
  29. package/dist/cli/evalCommand.js +720 -0
  30. package/dist/cli/exportAllCommand.js +1 -1
  31. package/dist/cli/hostClient.d.ts +60 -0
  32. package/dist/cli/hostClient.js +71 -0
  33. package/dist/cli/validateOutput.d.ts +2 -2
  34. package/dist/cli/validateOutput.js +2 -2
  35. package/dist/cli.js +10 -0
  36. package/dist/config/atomicWrite.d.ts +15 -0
  37. package/dist/config/atomicWrite.js +43 -0
  38. package/dist/config/browseCatalog.d.ts +2 -0
  39. package/dist/config/browseCatalog.js +4 -2
  40. package/dist/config/csv.d.ts +9 -0
  41. package/dist/config/csv.js +81 -0
  42. package/dist/config/datasetAgentCheck.d.ts +18 -0
  43. package/dist/config/datasetAgentCheck.js +109 -0
  44. package/dist/config/datasetCandidates.d.ts +22 -0
  45. package/dist/config/datasetCandidates.js +86 -0
  46. package/dist/config/datasetFromSessions.d.ts +34 -0
  47. package/dist/config/datasetFromSessions.js +105 -0
  48. package/dist/config/datasetHash.d.ts +1 -0
  49. package/dist/config/datasetHash.js +4 -0
  50. package/dist/config/datasetImport.d.ts +21 -0
  51. package/dist/config/datasetImport.js +120 -0
  52. package/dist/config/datasetStageCheck.d.ts +9 -0
  53. package/dist/config/datasetStageCheck.js +17 -0
  54. package/dist/config/datasetTypes.d.ts +27 -0
  55. package/dist/config/datasetTypes.js +1 -0
  56. package/dist/config/ensureCatalogScanRoot.d.ts +2 -1
  57. package/dist/config/ensureCatalogScanRoot.js +2 -6
  58. package/dist/config/evalCatalog.d.ts +22 -0
  59. package/dist/config/evalCatalog.js +67 -0
  60. package/dist/config/evalWriteRoots.d.ts +17 -0
  61. package/dist/config/evalWriteRoots.js +109 -0
  62. package/dist/config/hostConfig.js +1 -0
  63. package/dist/config/installEvalSample.d.ts +34 -0
  64. package/dist/config/installEvalSample.js +182 -0
  65. package/dist/config/loadDataset.d.ts +16 -0
  66. package/dist/config/loadDataset.js +318 -0
  67. package/dist/config/loadEval.d.ts +32 -0
  68. package/dist/config/loadEval.js +1085 -0
  69. package/dist/config/loadOutcome.d.ts +5 -0
  70. package/dist/config/loadStageflowManifest.js +64 -0
  71. package/dist/config/resolveAgentTarget.d.ts +32 -0
  72. package/dist/config/resolveAgentTarget.js +118 -0
  73. package/dist/config/resolveEvalTarget.d.ts +21 -0
  74. package/dist/config/resolveEvalTarget.js +89 -0
  75. package/dist/config/scanCatalogPaths.d.ts +1 -1
  76. package/dist/config/scanCatalogPaths.js +17 -5
  77. package/dist/config/validateCatalog.d.ts +1 -1
  78. package/dist/config/validateCatalog.js +9 -1
  79. package/dist/config/validateEval.d.ts +36 -0
  80. package/dist/config/validateEval.js +405 -0
  81. package/dist/config/writeDataset.d.ts +54 -0
  82. package/dist/config/writeDataset.js +186 -0
  83. package/dist/config/writeEval.d.ts +25 -0
  84. package/dist/config/writeEval.js +398 -0
  85. package/dist/diagnostics/checks.js +1 -1
  86. package/dist/evals/agentDiff.d.ts +13 -0
  87. package/dist/evals/agentDiff.js +11 -0
  88. package/dist/evals/canonical.d.ts +3 -0
  89. package/dist/evals/canonical.js +24 -0
  90. package/dist/evals/caseTask.d.ts +3 -0
  91. package/dist/evals/caseTask.js +9 -0
  92. package/dist/evals/compare.d.ts +94 -0
  93. package/dist/evals/compare.js +201 -0
  94. package/dist/evals/constants.d.ts +60 -0
  95. package/dist/evals/constants.js +95 -0
  96. package/dist/evals/engine/FakeEngine.d.ts +33 -0
  97. package/dist/evals/engine/FakeEngine.js +176 -0
  98. package/dist/evals/engine/index.d.ts +9 -0
  99. package/dist/evals/engine/index.js +19 -0
  100. package/dist/evals/engine/promptfoo/PromptfooEngine.d.ts +52 -0
  101. package/dist/evals/engine/promptfoo/PromptfooEngine.js +311 -0
  102. package/dist/evals/engine/promptfoo/errors.d.ts +5 -0
  103. package/dist/evals/engine/promptfoo/errors.js +8 -0
  104. package/dist/evals/engine/promptfoo/generate.d.ts +30 -0
  105. package/dist/evals/engine/promptfoo/generate.js +342 -0
  106. package/dist/evals/engine/promptfoo/guard.d.ts +10 -0
  107. package/dist/evals/engine/promptfoo/guard.js +116 -0
  108. package/dist/evals/engine/promptfoo/install.d.ts +17 -0
  109. package/dist/evals/engine/promptfoo/install.js +73 -0
  110. package/dist/evals/engine/promptfoo/judgeProviders.d.ts +2 -0
  111. package/dist/evals/engine/promptfoo/judgeProviders.js +9 -0
  112. package/dist/evals/engine/promptfoo/judgeServices.d.ts +6 -0
  113. package/dist/evals/engine/promptfoo/judgeServices.js +41 -0
  114. package/dist/evals/engine/promptfoo/locate.d.ts +21 -0
  115. package/dist/evals/engine/promptfoo/locate.js +68 -0
  116. package/dist/evals/engine/promptfoo/nodeVersion.d.ts +7 -0
  117. package/dist/evals/engine/promptfoo/nodeVersion.js +14 -0
  118. package/dist/evals/engine/promptfoo/normalize.d.ts +66 -0
  119. package/dist/evals/engine/promptfoo/normalize.js +261 -0
  120. package/dist/evals/engine/promptfoo/pinned.d.ts +5 -0
  121. package/dist/evals/engine/promptfoo/pinned.js +5 -0
  122. package/dist/evals/engine/promptfoo/rubricPrompt.d.ts +14 -0
  123. package/dist/evals/engine/promptfoo/rubricPrompt.js +103 -0
  124. package/dist/evals/engine/promptfoo/runTokens.d.ts +18 -0
  125. package/dist/evals/engine/promptfoo/runTokens.js +31 -0
  126. package/dist/evals/engine/promptfoo/status.d.ts +13 -0
  127. package/dist/evals/engine/promptfoo/status.js +16 -0
  128. package/dist/evals/estimate.d.ts +56 -0
  129. package/dist/evals/estimate.js +66 -0
  130. package/dist/evals/graders/codeGrader.d.ts +6 -0
  131. package/dist/evals/graders/codeGrader.js +85 -0
  132. package/dist/evals/graders/conversationCheckGrader.d.ts +6 -0
  133. package/dist/evals/graders/conversationCheckGrader.js +62 -0
  134. package/dist/evals/graders/fieldGrader.d.ts +11 -0
  135. package/dist/evals/graders/fieldGrader.js +117 -0
  136. package/dist/evals/graders/goal.d.ts +3 -0
  137. package/dist/evals/graders/goal.js +14 -0
  138. package/dist/evals/graders/index.d.ts +18 -0
  139. package/dist/evals/graders/index.js +34 -0
  140. package/dist/evals/graders/notApplicable.d.ts +5 -0
  141. package/dist/evals/graders/notApplicable.js +9 -0
  142. package/dist/evals/graders/path.d.ts +26 -0
  143. package/dist/evals/graders/path.js +75 -0
  144. package/dist/evals/graders/referenceGrader.d.ts +5 -0
  145. package/dist/evals/graders/referenceGrader.js +59 -0
  146. package/dist/evals/graders/schemaGrader.d.ts +5 -0
  147. package/dist/evals/graders/schemaGrader.js +29 -0
  148. package/dist/evals/graders/subject.d.ts +6 -0
  149. package/dist/evals/graders/subject.js +33 -0
  150. package/dist/evals/graders/toolCallsGrader.d.ts +6 -0
  151. package/dist/evals/graders/toolCallsGrader.js +100 -0
  152. package/dist/evals/graders/transcript.d.ts +12 -0
  153. package/dist/evals/graders/transcript.js +57 -0
  154. package/dist/evals/graders/types.d.ts +20 -0
  155. package/dist/evals/graders/types.js +1 -0
  156. package/dist/evals/judgeProviders.d.ts +16 -0
  157. package/dist/evals/judgeProviders.js +27 -0
  158. package/dist/evals/lineDiff.d.ts +5 -0
  159. package/dist/evals/lineDiff.js +34 -0
  160. package/dist/evals/listStatus.d.ts +31 -0
  161. package/dist/evals/listStatus.js +48 -0
  162. package/dist/evals/manager.d.ts +174 -0
  163. package/dist/evals/manager.js +787 -0
  164. package/dist/evals/plan.d.ts +58 -0
  165. package/dist/evals/plan.js +602 -0
  166. package/dist/evals/providerKeys.d.ts +1 -0
  167. package/dist/evals/providerKeys.js +21 -0
  168. package/dist/evals/read/agentTargets.d.ts +37 -0
  169. package/dist/evals/read/agentTargets.js +101 -0
  170. package/dist/evals/read/api.d.ts +196 -0
  171. package/dist/evals/read/api.js +358 -0
  172. package/dist/evals/read/compare.d.ts +4 -0
  173. package/dist/evals/read/compare.js +39 -0
  174. package/dist/evals/read/datasets.d.ts +105 -0
  175. package/dist/evals/read/datasets.js +318 -0
  176. package/dist/evals/read/list.d.ts +66 -0
  177. package/dist/evals/read/list.js +173 -0
  178. package/dist/evals/read/results.d.ts +46 -0
  179. package/dist/evals/read/results.js +107 -0
  180. package/dist/evals/read/runs.d.ts +149 -0
  181. package/dist/evals/read/runs.js +289 -0
  182. package/dist/evals/read/suggestions.d.ts +43 -0
  183. package/dist/evals/read/suggestions.js +73 -0
  184. package/dist/evals/runner/FakeAgentBackend.d.ts +40 -0
  185. package/dist/evals/runner/FakeAgentBackend.js +82 -0
  186. package/dist/evals/runner/agentCaseRunner.d.ts +24 -0
  187. package/dist/evals/runner/agentCaseRunner.js +388 -0
  188. package/dist/evals/runner/caseRunner.d.ts +7 -0
  189. package/dist/evals/runner/caseRunner.js +17 -0
  190. package/dist/evals/runner/conversationSubject.d.ts +18 -0
  191. package/dist/evals/runner/conversationSubject.js +123 -0
  192. package/dist/evals/runner/simulatorModel.d.ts +51 -0
  193. package/dist/evals/runner/simulatorModel.js +58 -0
  194. package/dist/evals/runner/simulatorPrompt.d.ts +29 -0
  195. package/dist/evals/runner/simulatorPrompt.js +59 -0
  196. package/dist/evals/runner/stageCaseRunner.d.ts +30 -0
  197. package/dist/evals/runner/stageCaseRunner.js +279 -0
  198. package/dist/evals/runner/userDriver.d.ts +71 -0
  199. package/dist/evals/runner/userDriver.js +104 -0
  200. package/dist/evals/scoring.d.ts +34 -0
  201. package/dist/evals/scoring.js +67 -0
  202. package/dist/evals/snapshot.d.ts +183 -0
  203. package/dist/evals/snapshot.js +65 -0
  204. package/dist/evals/stageDiff.d.ts +8 -0
  205. package/dist/evals/stageDiff.js +48 -0
  206. package/dist/evals/stats.d.ts +95 -0
  207. package/dist/evals/stats.js +220 -0
  208. package/dist/evals/statsAdapter.d.ts +4 -0
  209. package/dist/evals/statsAdapter.js +30 -0
  210. package/dist/evals/statsTypes.d.ts +51 -0
  211. package/dist/evals/statsTypes.js +18 -0
  212. package/dist/evals/storeError.d.ts +5 -0
  213. package/dist/evals/storeError.js +8 -0
  214. package/dist/evals/storeTypes.d.ts +207 -0
  215. package/dist/evals/storeTypes.js +1 -0
  216. package/dist/evals/tTable.d.ts +3 -0
  217. package/dist/evals/tTable.js +15 -0
  218. package/dist/evals/triage/constants.d.ts +26 -0
  219. package/dist/evals/triage/constants.js +33 -0
  220. package/dist/evals/triage/credentials.d.ts +13 -0
  221. package/dist/evals/triage/credentials.js +20 -0
  222. package/dist/evals/triage/jevClassifier.d.ts +14 -0
  223. package/dist/evals/triage/jevClassifier.js +124 -0
  224. package/dist/evals/triage/judgeClassifier.d.ts +10 -0
  225. package/dist/evals/triage/judgeClassifier.js +76 -0
  226. package/dist/evals/triage/prompts.d.ts +16 -0
  227. package/dist/evals/triage/prompts.js +64 -0
  228. package/dist/evals/triage/service.d.ts +79 -0
  229. package/dist/evals/triage/service.js +217 -0
  230. package/dist/evals/triage/stateBuilder.d.ts +19 -0
  231. package/dist/evals/triage/stateBuilder.js +125 -0
  232. package/dist/evals/triage/types.d.ts +60 -0
  233. package/dist/evals/triage/types.js +8 -0
  234. package/dist/evals/types.d.ts +347 -0
  235. package/dist/evals/types.js +1 -0
  236. package/dist/mcp/deps.d.ts +7 -0
  237. package/dist/mcp/evalTools.d.ts +3 -0
  238. package/dist/mcp/evalTools.js +280 -0
  239. package/dist/mcp/server.js +1 -0
  240. package/dist/mcp/tools.js +2 -0
  241. package/dist/models/response.d.ts +7 -2
  242. package/dist/models/response.js +6 -1
  243. package/dist/operatorAgent/agentAuthorContext.d.ts +1 -1
  244. package/dist/operatorAgent/agentAuthorContext.js +1 -1
  245. package/dist/operatorAgent/piModel.js +17 -4
  246. package/dist/operatorAgent/profiles/agentAuthor.d.ts +3 -1
  247. package/dist/operatorAgent/profiles/agentAuthor.js +145 -20
  248. package/dist/operatorAgent/profiles/agentAuthorPlaybook.d.ts +1 -1
  249. package/dist/operatorAgent/profiles/agentAuthorPlaybook.js +48 -15
  250. package/dist/operatorAgent/profiles/authorReadable.d.ts +2 -0
  251. package/dist/operatorAgent/profiles/authorReadable.js +26 -0
  252. package/dist/package-meta.d.ts +1 -1
  253. package/dist/package-meta.js +1 -1
  254. package/dist/runstore/port.d.ts +43 -0
  255. package/dist/runstore/sqlite/SqliteRunStore.d.ts +28 -0
  256. package/dist/runstore/sqlite/SqliteRunStore.js +99 -5
  257. package/dist/runstore/sqlite/evalStore.d.ts +20 -0
  258. package/dist/runstore/sqlite/evalStore.js +541 -0
  259. package/dist/runstore/sqlite/migrations/015-evals.d.ts +12 -0
  260. package/dist/runstore/sqlite/migrations/015-evals.js +157 -0
  261. package/dist/runstore/sqlite/migrations/016-eval-subject-ref.d.ts +12 -0
  262. package/dist/runstore/sqlite/migrations/016-eval-subject-ref.js +20 -0
  263. package/dist/runstore/sqlite/migrations/017-eval-result-suggestions.d.ts +11 -0
  264. package/dist/runstore/sqlite/migrations/017-eval-result-suggestions.js +36 -0
  265. package/dist/runstore/sqlite/migrations/index.js +6 -0
  266. package/dist/runstore/sqlite/suggestionStore.d.ts +14 -0
  267. package/dist/runstore/sqlite/suggestionStore.js +132 -0
  268. package/dist/runtime/pipelineRunner.d.ts +2 -1
  269. package/dist/runtime/pipelineRunner.js +2 -0
  270. package/dist/runtime/runManager.d.ts +2 -1
  271. package/dist/runtime/runManager.js +8 -6
  272. package/dist/runtime/runRetentionSweep.js +2 -2
  273. package/dist/server/agentAuthorRoutes.js +50 -1
  274. package/dist/server/bootstrap.d.ts +8 -0
  275. package/dist/server/bootstrap.js +56 -0
  276. package/dist/server/controlToken.js +3 -0
  277. package/dist/server/evalInternalRoutes.d.ts +14 -0
  278. package/dist/server/evalInternalRoutes.js +87 -0
  279. package/dist/server/evalRouteContext.d.ts +46 -0
  280. package/dist/server/evalRouteContext.js +43 -0
  281. package/dist/server/evalRoutes.d.ts +5 -0
  282. package/dist/server/evalRoutes.js +1427 -0
  283. package/dist/server/evalTriageRoutes.d.ts +2 -0
  284. package/dist/server/evalTriageRoutes.js +95 -0
  285. package/dist/server/http.d.ts +5 -0
  286. package/dist/server/http.js +32 -2
  287. package/dist/server/mcpHost.js +3 -0
  288. package/dist/toolkit/meta.d.ts +1 -1
  289. package/dist/toolkit/meta.js +15 -0
  290. package/dist/toolkit/profiles.js +1 -1
  291. package/dist/types/stageflowManifest.d.ts +6 -0
  292. package/dist/ui/assets/AssistantRuntimeProvider-qIX1xNoH.js +9 -0
  293. package/dist/ui/assets/{MarkdownText-D7tYaIFO.js → MarkdownText-BTrOqu5J.js} +1 -1
  294. package/dist/ui/assets/chat-Df_wCpak.js +5 -0
  295. package/dist/ui/assets/chat-P7KQznHm.css +2 -0
  296. package/dist/ui/assets/{main-BFo79krC.css → main-CHlmTNJe.css} +1 -1
  297. package/dist/ui/assets/main-CvVfxmMd.js +271 -0
  298. package/dist/ui/chat.html +3 -3
  299. package/dist/ui/index.html +3 -3
  300. package/examples/README.md +2 -0
  301. package/examples/document-policy-review/README.md +35 -0
  302. package/examples/document-policy-review/agents/compliance.agent.yaml +42 -0
  303. package/examples/document-policy-review/documents/acme-vendor-sow.md +15 -0
  304. package/examples/document-policy-review/documents/support-runbook.md +13 -0
  305. package/examples/document-policy-review/policies/acceptable-use.md +13 -0
  306. package/examples/document-policy-review/policies/data-handling.md +17 -0
  307. package/examples/document-policy-review/policies/vendor-security.md +17 -0
  308. package/examples/evals/README.md +123 -0
  309. package/examples/evals/critique-sample.dataset.jsonl +8 -0
  310. package/examples/evals/critique-sample.eval.yaml +34 -0
  311. package/examples/evals/critique-sample.task.yaml +4 -0
  312. package/examples/evals/eval-sample.pipeline.yaml +35 -0
  313. package/examples/evals/support-sample.agent.yaml +20 -0
  314. package/examples/evals/support-sample.dataset.jsonl +6 -0
  315. package/examples/evals/support-sample.eval.yaml +38 -0
  316. package/examples/stageflow.yaml +6 -0
  317. package/package.json +1 -1
  318. package/skills/stageflow/SKILL.md +5 -2
  319. package/skills/stageflow/references/control-surface.md +4 -2
  320. package/skills/stageflow/references/evals.md +68 -0
  321. package/skills/stageflow-author/SKILL.md +4 -0
  322. package/skills/stageflow-run/SKILL.md +4 -0
  323. package/dist/ui/assets/AssistantRuntimeProvider-CsiPFhCT.js +0 -9
  324. package/dist/ui/assets/chat-BbLukq9W.js +0 -5
  325. package/dist/ui/assets/chat-zIZU_bP1.css +0 -2
  326. package/dist/ui/assets/main-CijYMeM0.js +0 -259
@@ -26,6 +26,11 @@ export type LoadIssue = ({
26
26
  message: string;
27
27
  category: "trigger";
28
28
  triggerId?: string;
29
+ } & LoadIssueLocation) | ({
30
+ code: string;
31
+ message: string;
32
+ category: "eval";
33
+ severity?: "error" | "warning";
29
34
  } & LoadIssueLocation) | ({
30
35
  code: ValidationFindingCode | string;
31
36
  message: string;
@@ -8,6 +8,8 @@ import { parseModelField } from "./modelField.js";
8
8
  const DEFAULT_PIPELINE_PATTERN = "*.pipeline.yaml";
9
9
  const DEFAULT_TASK_PATTERN = "*.task.yaml";
10
10
  const DEFAULT_TRIGGER_PATTERN = "*.trigger.yaml";
11
+ const DEFAULT_EVAL_PATTERN = "*.eval.yaml";
12
+ const DEFAULT_DATASET_PATTERNS = ["*.dataset.jsonl", "*.dataset.json", "*.dataset.csv"];
11
13
  export function manifestPathForProject(projectRoot) {
12
14
  return path.join(projectRoot, "stageflow.yaml");
13
15
  }
@@ -37,11 +39,27 @@ function parseStringArray(raw, field, issues) {
37
39
  }
38
40
  return entries;
39
41
  }
42
+ function parseDatasetPattern(raw) {
43
+ const entries = typeof raw === "string" ? [raw] : Array.isArray(raw) ? raw : null;
44
+ if (entries === null || entries.length === 0) {
45
+ return null;
46
+ }
47
+ const parsed = [];
48
+ for (const entry of entries) {
49
+ if (typeof entry !== "string" || entry.trim().length === 0) {
50
+ return null;
51
+ }
52
+ parsed.push(entry.trim());
53
+ }
54
+ return parsed;
55
+ }
40
56
  function parsePatterns(raw, issues) {
41
57
  const defaults = {
42
58
  pipeline: DEFAULT_PIPELINE_PATTERN,
43
59
  task: DEFAULT_TASK_PATTERN,
44
60
  trigger: DEFAULT_TRIGGER_PATTERN,
61
+ eval: DEFAULT_EVAL_PATTERN,
62
+ dataset: DEFAULT_DATASET_PATTERNS,
45
63
  };
46
64
  if (raw === undefined || raw === null) {
47
65
  return defaults;
@@ -66,6 +84,12 @@ function parsePatterns(raw, issues) {
66
84
  : typeof record.trigger === "string" && record.trigger.trim().length > 0
67
85
  ? record.trigger.trim()
68
86
  : null;
87
+ const evalPattern = record.eval === undefined
88
+ ? defaults.eval
89
+ : typeof record.eval === "string" && record.eval.trim().length > 0
90
+ ? record.eval.trim()
91
+ : null;
92
+ const dataset = record.dataset === undefined ? defaults.dataset : parseDatasetPattern(record.dataset);
69
93
  if (pipeline === null) {
70
94
  issues.push(catalogIssue("catalog.manifest_invalid", "catalog.patterns.pipeline must be a string"));
71
95
  }
@@ -75,10 +99,18 @@ function parsePatterns(raw, issues) {
75
99
  if (trigger === null) {
76
100
  issues.push(catalogIssue("catalog.manifest_invalid", "catalog.patterns.trigger must be a string"));
77
101
  }
102
+ if (evalPattern === null) {
103
+ issues.push(catalogIssue("catalog.manifest_invalid", "catalog.patterns.eval must be a string"));
104
+ }
105
+ if (dataset === null) {
106
+ issues.push(catalogIssue("catalog.manifest_invalid", "catalog.patterns.dataset must be a non-empty string or an array of non-empty strings"));
107
+ }
78
108
  return {
79
109
  pipeline: pipeline ?? defaults.pipeline,
80
110
  task: task ?? defaults.task,
81
111
  trigger: trigger ?? defaults.trigger,
112
+ eval: evalPattern ?? defaults.eval,
113
+ dataset: dataset ?? defaults.dataset,
82
114
  };
83
115
  }
84
116
  export function parseStageflowManifestOutcome(yamlText, manifestPath, projectRoot) {
@@ -131,6 +163,22 @@ export function parseStageflowManifestOutcome(yamlText, manifestPath, projectRoo
131
163
  triggers = parsed;
132
164
  }
133
165
  }
166
+ const evalsRaw = catalogRecord.evals;
167
+ let evals;
168
+ if (evalsRaw !== undefined) {
169
+ const parsed = parseStringArray(evalsRaw, "evals", issues);
170
+ if (parsed !== null) {
171
+ evals = parsed;
172
+ }
173
+ }
174
+ const datasetsRaw = catalogRecord.datasets;
175
+ let datasets;
176
+ if (datasetsRaw !== undefined) {
177
+ const parsed = parseStringArray(datasetsRaw, "datasets", issues);
178
+ if (parsed !== null) {
179
+ datasets = parsed;
180
+ }
181
+ }
134
182
  const patterns = parsePatterns(catalogRecord.patterns, issues);
135
183
  let agent;
136
184
  const agentField = parseAgentField(record.agent);
@@ -161,6 +209,12 @@ export function parseStageflowManifestOutcome(yamlText, manifestPath, projectRoo
161
209
  if (triggers !== undefined) {
162
210
  catalog.triggers = triggers;
163
211
  }
212
+ if (evals !== undefined) {
213
+ catalog.evals = evals;
214
+ }
215
+ if (datasets !== undefined) {
216
+ catalog.datasets = datasets;
217
+ }
164
218
  if (catalogRecord.patterns !== undefined) {
165
219
  catalog.patterns = {};
166
220
  if (typeof catalogRecord.patterns.pipeline === "string") {
@@ -172,6 +226,16 @@ export function parseStageflowManifestOutcome(yamlText, manifestPath, projectRoo
172
226
  if (typeof catalogRecord.patterns.trigger === "string") {
173
227
  catalog.patterns.trigger = patterns.trigger;
174
228
  }
229
+ if (typeof catalogRecord.patterns.eval === "string") {
230
+ catalog.patterns.eval = patterns.eval;
231
+ }
232
+ const datasetRaw = catalogRecord.patterns.dataset;
233
+ if (typeof datasetRaw === "string") {
234
+ catalog.patterns.dataset = patterns.dataset[0];
235
+ }
236
+ else if (Array.isArray(datasetRaw)) {
237
+ catalog.patterns.dataset = patterns.dataset;
238
+ }
175
239
  }
176
240
  const manifest = {
177
241
  version: 1,
@@ -0,0 +1,32 @@
1
+ import type { AgentDetail, AgentSummary } from "../agents/service.js";
2
+ import type { EvalFile } from "../evals/types.js";
3
+ import { type AgentDefinition } from "./loadAgent.js";
4
+ import { type LoadIssue, type LoadOutcome } from "./loadOutcome.js";
5
+ export type AgentToolRisk = "read" | "write" | "shell" | "destructive" | "external" | "mcp_unknown" | "sub_agent" | "browser";
6
+ export type AgentToolGrant = {
7
+ id: string;
8
+ risk: AgentToolRisk;
9
+ };
10
+ export type ResolvedAgentTarget = {
11
+ agentId: string;
12
+ /** The revision read now; null when resolved offline from the file alone. */
13
+ revision: number | null;
14
+ definitionHash: string;
15
+ /** The definition after the eval's `defaults.model` override. */
16
+ definition: AgentDefinition;
17
+ modelResolved: string | undefined;
18
+ tools: AgentToolGrant[];
19
+ askFirst: string[];
20
+ issues: LoadIssue[];
21
+ };
22
+ /** The slice of `AgentService` that eval resolution reads. */
23
+ export type AgentCatalogPort = {
24
+ get(projectRoot: string, agentId: string): Promise<AgentDetail>;
25
+ list(projectRoot: string): Promise<AgentSummary[]>;
26
+ };
27
+ export declare function agentToolGrants(definition: AgentDefinition): AgentToolGrant[];
28
+ /** sha256 of the canonical JSON of the definition after the eval's `defaults.model` override. */
29
+ export declare function agentDefinitionHash(definition: AgentDefinition): string;
30
+ export declare function resolveAgentTarget(file: EvalFile, projectRoot: string, agents: AgentCatalogPort): Promise<LoadOutcome<ResolvedAgentTarget>>;
31
+ /** Offline resolution (`sf eval validate` without an agent service): parses `agents/<id>.agent.yaml` only. */
32
+ export declare function resolveAgentTargetFromFile(file: EvalFile, projectRoot: string): Promise<LoadOutcome<ResolvedAgentTarget>>;
@@ -0,0 +1,118 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { isAgentError } from "../agents/errors.js";
4
+ import { effectiveAskFirst } from "../agents/policy.js";
5
+ import { canonicalJson, sha256Hex } from "../evals/canonical.js";
6
+ import { grantedToolIds, parseAgentYaml } from "./loadAgent.js";
7
+ import { loadFailure, loadSuccess } from "./loadOutcome.js";
8
+ import { TOOL_META, STAGEFLOW_GRANT_PREFIX } from "../toolkit/meta.js";
9
+ const BUILTIN_RISK = {
10
+ read: "read",
11
+ grep: "read",
12
+ find: "read",
13
+ ls: "read",
14
+ write: "write",
15
+ edit: "write",
16
+ bash: "shell",
17
+ };
18
+ function agentIssue(code, message, severity = "error") {
19
+ return { code, message, category: "eval", severity };
20
+ }
21
+ function grantRisk(id) {
22
+ if (id in BUILTIN_RISK)
23
+ return BUILTIN_RISK[id];
24
+ if (id.startsWith("agent:"))
25
+ return "sub_agent";
26
+ if (id.startsWith(STAGEFLOW_GRANT_PREFIX)) {
27
+ return TOOL_META[id.slice(STAGEFLOW_GRANT_PREFIX.length)]?.risk ?? "mcp_unknown";
28
+ }
29
+ return "mcp_unknown";
30
+ }
31
+ export function agentToolGrants(definition) {
32
+ const grants = [...grantedToolIds(definition)].sort().map((id) => ({ id, risk: grantRisk(id) }));
33
+ if (definition.tools.browser)
34
+ grants.push({ id: "browser", risk: "browser" });
35
+ return grants;
36
+ }
37
+ /** sha256 of the canonical JSON of the definition after the eval's `defaults.model` override. */
38
+ export function agentDefinitionHash(definition) {
39
+ return sha256Hex(canonicalJson(definition));
40
+ }
41
+ function withModelOverride(definition, model) {
42
+ return model === undefined ? definition : { ...definition, model: { ...definition.model, id: model } };
43
+ }
44
+ function firstIssue(issues) {
45
+ const issue = issues[0];
46
+ if (!issue)
47
+ return "the definition does not load";
48
+ return issue.path ? `${issue.path}: ${issue.message}` : issue.message;
49
+ }
50
+ function resolved(agentId, revision, base, file, warnings) {
51
+ const definition = withModelOverride(base, file.defaults?.model);
52
+ const issues = [...warnings];
53
+ if (!definition.enabled) {
54
+ issues.push(agentIssue("eval.agent_disabled", `Agent "${agentId}" is disabled; eval sessions run anyway`, "warning"));
55
+ }
56
+ return loadSuccess({
57
+ agentId,
58
+ revision,
59
+ definitionHash: agentDefinitionHash(definition),
60
+ definition,
61
+ modelResolved: definition.model.id,
62
+ tools: agentToolGrants(definition),
63
+ askFirst: effectiveAskFirst(definition),
64
+ issues,
65
+ }, issues);
66
+ }
67
+ export async function resolveAgentTarget(file, projectRoot, agents) {
68
+ if (file.target.kind !== "agent") {
69
+ return loadFailure([agentIssue("eval.target_unresolved", "Not an agent target")]);
70
+ }
71
+ const agentId = file.target.agent;
72
+ let detail;
73
+ try {
74
+ detail = await agents.get(projectRoot, agentId);
75
+ }
76
+ catch (err) {
77
+ if (isAgentError(err) && err.code === "agent.not_found") {
78
+ return loadFailure([agentIssue("eval.agent_not_found", `Agent "${agentId}" was not found`)]);
79
+ }
80
+ throw err;
81
+ }
82
+ const listed = await agents.list(projectRoot);
83
+ if (!listed.some((agent) => agent.id === agentId)) {
84
+ return loadFailure([agentIssue("eval.agent_archived", `Agent "${agentId}" is archived`)]);
85
+ }
86
+ if (detail.agent.issues.length > 0 || detail.definition === null) {
87
+ return loadFailure([
88
+ agentIssue("eval.agent_invalid", `Agent "${agentId}" has problems in its definition: ${firstIssue(detail.agent.issues)}`),
89
+ ]);
90
+ }
91
+ return resolved(agentId, detail.agent.revision, detail.definition, file, []);
92
+ }
93
+ /** Offline resolution (`sf eval validate` without an agent service): parses `agents/<id>.agent.yaml` only. */
94
+ export async function resolveAgentTargetFromFile(file, projectRoot) {
95
+ if (file.target.kind !== "agent") {
96
+ return loadFailure([agentIssue("eval.target_unresolved", "Not an agent target")]);
97
+ }
98
+ const agentId = file.target.agent;
99
+ let text;
100
+ try {
101
+ text = await readFile(path.join(projectRoot, "agents", `${agentId}.agent.yaml`), "utf8");
102
+ }
103
+ catch {
104
+ return loadFailure([agentIssue("eval.agent_not_found", `Agent "${agentId}" was not found`)]);
105
+ }
106
+ const parsed = parseAgentYaml(text);
107
+ if (!parsed.ok) {
108
+ return loadFailure([
109
+ agentIssue("eval.agent_invalid", `Agent "${agentId}" has problems in its definition: ${firstIssue(parsed.issues)}`),
110
+ ]);
111
+ }
112
+ if (parsed.value.id !== agentId) {
113
+ return loadFailure([
114
+ agentIssue("eval.agent_invalid", `Agent "${agentId}" has problems in its definition: id must match the file name`),
115
+ ]);
116
+ }
117
+ return resolved(agentId, null, parsed.value, file, []);
118
+ }
@@ -0,0 +1,21 @@
1
+ import type { EvalFile } from "../evals/types.js";
2
+ import type { CompletionContract } from "../types/completion.js";
3
+ import type { LoadedStageConfig } from "../types/stage.js";
4
+ import { type LoadOutcome } from "./loadOutcome.js";
5
+ export type ResolvedEvalTarget = {
6
+ stageConfig: LoadedStageConfig;
7
+ pipelinePath?: string;
8
+ stageId?: string;
9
+ file?: string;
10
+ stageVersionHash: string;
11
+ completion?: CompletionContract;
12
+ inputSchema?: unknown;
13
+ outputSchema?: unknown;
14
+ modelResolved: string;
15
+ modelTier: "stage" | "pipeline" | "global";
16
+ };
17
+ /** The exact object the stage version hash is computed from. */
18
+ export declare function stageDefinition(stage: LoadedStageConfig, completion: CompletionContract | undefined): Record<string, unknown>;
19
+ /** sha256 of the canonical JSON of the materialized stage config plus its after-phase verify contract. */
20
+ export declare function stageVersionHash(stage: LoadedStageConfig, completion: CompletionContract | undefined): string;
21
+ export declare function resolveEvalTarget(file: EvalFile, evalAbsPath: string, projectRoot: string): Promise<LoadOutcome<ResolvedEvalTarget>>;
@@ -0,0 +1,89 @@
1
+ import path from "node:path";
2
+ import { canonicalJson, sha256Hex } from "../evals/canonical.js";
3
+ import { resolveEvalPaths } from "./loadEval.js";
4
+ import { loadFailure, loadSuccess } from "./loadOutcome.js";
5
+ import { loadPipelineOutcome } from "./loadPipeline.js";
6
+ import { afterCompletionForStage, loadStageOutcome } from "./loadStage.js";
7
+ import { materializeStageModels } from "./materializeStageModels.js";
8
+ function unresolved(message) {
9
+ return { code: "eval.target_unresolved", message, category: "eval" };
10
+ }
11
+ function describeIssues(issues) {
12
+ return issues.map((issue) => issue.message).join("; ");
13
+ }
14
+ /** The exact object the stage version hash is computed from. */
15
+ export function stageDefinition(stage, completion) {
16
+ const { model_tier: _tier, ...config } = stage;
17
+ return { ...config, ...(completion !== undefined ? { completion } : {}) };
18
+ }
19
+ /** sha256 of the canonical JSON of the materialized stage config plus its after-phase verify contract. */
20
+ export function stageVersionHash(stage, completion) {
21
+ return sha256Hex(canonicalJson(stageDefinition(stage, completion)));
22
+ }
23
+ export async function resolveEvalTarget(file, evalAbsPath, projectRoot) {
24
+ if (file.target.kind !== "stage") {
25
+ return loadFailure([unresolved("Agent targets are resolved by resolveAgentTarget")]);
26
+ }
27
+ const paths = resolveEvalPaths(file, evalAbsPath);
28
+ const rel = (abs) => path.relative(projectRoot, abs).split(path.sep).join("/");
29
+ if (paths.pipelinePath !== undefined) {
30
+ const pipelineRel = rel(paths.pipelinePath);
31
+ const outcome = await loadPipelineOutcome(paths.pipelinePath, { cwd: projectRoot, projectRoot, requireIo: false });
32
+ if (!outcome.ok) {
33
+ return loadFailure([
34
+ unresolved(`Target pipeline ${pipelineRel} does not load: ${describeIssues(outcome.issues)}`),
35
+ ]);
36
+ }
37
+ const { value } = outcome;
38
+ const stageId = file.target.stage;
39
+ const stage = value.stages.find((s) => s.id === stageId);
40
+ if (!stage) {
41
+ const known = value.stages.map((s) => s.id).join(", ");
42
+ return loadFailure([
43
+ unresolved(`Target stage "${stageId}" not found in pipeline ${pipelineRel} (stages: ${known})`),
44
+ ]);
45
+ }
46
+ const completion = value.dag.nodes.find((node) => node.id === stageId)?.completion;
47
+ return loadSuccess({
48
+ stageConfig: stage,
49
+ pipelinePath: paths.pipelinePath,
50
+ stageId,
51
+ stageVersionHash: stageVersionHash(stage, completion),
52
+ ...(completion !== undefined ? { completion } : {}),
53
+ inputSchema: stage.clone_input_schema,
54
+ outputSchema: stage.payload_schema,
55
+ modelResolved: stage.model,
56
+ modelTier: stage.model_tier ?? "global",
57
+ });
58
+ }
59
+ const stageFile = paths.stageFile;
60
+ const fileRel = rel(stageFile);
61
+ const loaded = await loadStageOutcome(stageFile, { requireIo: false });
62
+ if (!loaded.ok) {
63
+ return loadFailure([
64
+ unresolved(`Target stage file ${fileRel} does not load: ${describeIssues(loaded.issues)}`),
65
+ ]);
66
+ }
67
+ const materialized = await materializeStageModels([loaded.value], {
68
+ pipelineId: `standalone-${loaded.value.id}`,
69
+ projectRoot,
70
+ });
71
+ if (!materialized.ok) {
72
+ return loadFailure([
73
+ unresolved(`Target stage file ${fileRel} has no resolvable model: ${describeIssues(materialized.issues)}`),
74
+ ]);
75
+ }
76
+ const stage = materialized.value[0];
77
+ const fileCompletion = afterCompletionForStage(loaded.value);
78
+ return loadSuccess({
79
+ stageConfig: stage,
80
+ file: stageFile,
81
+ stageId: stage.id,
82
+ stageVersionHash: stageVersionHash(stage, fileCompletion),
83
+ ...(fileCompletion !== undefined ? { completion: fileCompletion } : {}),
84
+ inputSchema: stage.clone_input_schema,
85
+ outputSchema: stage.payload_schema,
86
+ modelResolved: stage.model,
87
+ modelTier: stage.model_tier ?? "global",
88
+ });
89
+ }
@@ -1,4 +1,4 @@
1
1
  import type { LoadedManifest } from "../types/stageflowManifest.js";
2
- export type CatalogPathKind = "pipeline" | "task" | "trigger";
2
+ export type CatalogPathKind = "pipeline" | "task" | "trigger" | "eval" | "dataset";
3
3
  export declare function isExcluded(repoRelPath: string, exclude: string[] | undefined): boolean;
4
4
  export declare function scanCatalogPaths(manifest: LoadedManifest, kind: CatalogPathKind): Promise<string[]>;
@@ -40,7 +40,7 @@ async function walkDirectory(absDir) {
40
40
  }
41
41
  return files;
42
42
  }
43
- async function expandCatalogEntry(projectRoot, entry, kind, pattern) {
43
+ async function expandCatalogEntry(projectRoot, entry, patterns) {
44
44
  const absPath = path.join(projectRoot, entry);
45
45
  let entryStat;
46
46
  try {
@@ -56,7 +56,7 @@ async function expandCatalogEntry(projectRoot, entry, kind, pattern) {
56
56
  return [];
57
57
  }
58
58
  const files = await walkDirectory(absPath);
59
- return files.filter((filePath) => matchesPattern(path.basename(filePath), pattern));
59
+ return files.filter((filePath) => patterns.some((pattern) => matchesPattern(path.basename(filePath), pattern)));
60
60
  }
61
61
  export async function scanCatalogPaths(manifest, kind) {
62
62
  const { projectRoot, manifest: doc, patterns } = manifest;
@@ -64,13 +64,25 @@ export async function scanCatalogPaths(manifest, kind) {
64
64
  ? doc.catalog.pipelines
65
65
  : kind === "task"
66
66
  ? doc.catalog.tasks
67
- : (doc.catalog.triggers ?? []);
68
- const pattern = kind === "pipeline" ? patterns.pipeline : kind === "task" ? patterns.task : patterns.trigger;
67
+ : kind === "trigger"
68
+ ? (doc.catalog.triggers ?? [])
69
+ : kind === "eval"
70
+ ? (doc.catalog.evals ?? ["evals"])
71
+ : (doc.catalog.datasets ?? ["datasets"]);
72
+ const matchPatterns = kind === "pipeline"
73
+ ? [patterns.pipeline]
74
+ : kind === "task"
75
+ ? [patterns.task]
76
+ : kind === "trigger"
77
+ ? [patterns.trigger]
78
+ : kind === "eval"
79
+ ? [patterns.eval]
80
+ : patterns.dataset;
69
81
  const exclude = doc.catalog.exclude;
70
82
  const seen = new Set();
71
83
  const resolved = [];
72
84
  for (const entry of entries) {
73
- const absPaths = await expandCatalogEntry(projectRoot, entry, kind, pattern);
85
+ const absPaths = await expandCatalogEntry(projectRoot, entry, matchPatterns);
74
86
  for (const absPath of absPaths) {
75
87
  const normalized = path.resolve(absPath);
76
88
  if (seen.has(normalized))
@@ -3,7 +3,7 @@ import type { TriggerFile } from "../types/trigger.js";
3
3
  import type { LoadIssue } from "./loadOutcome.js";
4
4
  import type { AnyChannelProvider } from "../channels/types.js";
5
5
  export type ValidationSeverity = "error" | "warning";
6
- export type ValidationCategory = "pipeline" | "stage" | "catalog" | "task" | "trigger";
6
+ export type ValidationCategory = "pipeline" | "stage" | "catalog" | "task" | "trigger" | "eval" | "dataset";
7
7
  export type ValidationFindingCode = "pipeline.invalid_shape" | "pipeline.dag_error" | "pipeline.missing_stage" | "pipeline.load_error" | "pipeline.string_stage_ref" | "pipeline.stage_uses_inline_conflict" | "pipeline.stage_missing_body" | "pipeline.stage_id_mismatch" | "pipeline.stage_wrapper_skill_rejected" | "pipeline.invalid_completion" | "catalog.path_case_mismatch" | "pipeline.invalid_recovery" | "pipeline.include_cycle" | "pipeline.include_invalid" | "pipeline.include_duplicate_stage" | "pipeline.invalid_agent" | "pipeline.invalid_model" | "pipeline.invalid_verify" | "pipeline.io_incompatible" | "pipeline.model_applies" | "pipeline.route_if_invalid" | "pipeline.route_all_gated" | "pipeline.invalid_requires" | "pipeline.requires_conflict" | "pipeline.invalid_channels" | "pipeline.invalid_memories" | "pipeline.memory_unavailable" | "stage.invalid_shape" | "stage.invalid_model" | "stage.missing_model" | "stage.invalid_payload_schema" | "stage.invalid_clone_input_schema" | "stage.unresolved_schema_ref" | "stage.invalid_clone_actions" | "stage.invalid_gate_kinds" | "stage.invalid_pre_emit_checks" | "stage.invalid_timeout_ms" | "stage.invalid_skill" | "stage.invalid_mcp" | "stage.invalid_channels" | "stage.channel_unavailable" | "stage.invalid_browser" | "stage.invalid_secrets" | "stage.unknown_secret" | "stage.denied_secret" | "stage.invalid_requires" | "stage.invalid_agent" | "stage.invalid_io" | "stage.load_error" | "stage.id_filename_mismatch" | "task.invalid_shape" | "task.load_error" | "task.entry_input_unmet" | "task.binding_conflict" | "task.repository_ref_required" | "task.ref_without_repository" | "task.repository_invalid" | "trigger.invalid_shape" | "trigger.load_error" | "trigger.unknown_pipeline" | "trigger.unknown_task" | "catalog.duplicate_pipeline_id" | "catalog.manifest_missing" | "catalog.manifest_invalid" | "catalog.empty_catalog" | "catalog.manifest_load_error" | "catalog.invalid_mcp" | "catalog.mcp_command_missing" | "catalog.mixed_yaml_dialect" | "catalog.legacy_yaml" | "catalog.stageflow_home_absolute_path";
8
8
  export type ValidationFinding = {
9
9
  severity: ValidationSeverity;
@@ -6,6 +6,8 @@ import { INLINE_PIPELINE_PATH, loadPipelineFromObjectOutcome, loadPipelineOutcom
6
6
  import { loadStageOutcome } from "./loadStage.js";
7
7
  import { loadTaskOutcome } from "./loadTask.js";
8
8
  import { loadTriggerOutcome } from "./loadTrigger.js";
9
+ import { loadEvalCatalog } from "./evalCatalog.js";
10
+ import { evalFindingsFromIssues } from "./validateEval.js";
9
11
  import { readYamlObject } from "./readYamlObject.js";
10
12
  import { resolveCatalogContext } from "./resolveCatalogContext.js";
11
13
  import { getCatalogScanPaths } from "./browseCatalog.js";
@@ -46,7 +48,7 @@ function sortFindings(findings) {
46
48
  export function effectiveSeverity(finding, strict) {
47
49
  if (strict &&
48
50
  finding.severity === "warning" &&
49
- STRICT_CATALOG_WARNINGS.has(finding.code)) {
51
+ (STRICT_CATALOG_WARNINGS.has(finding.code) || finding.category === "eval")) {
50
52
  return "error";
51
53
  }
52
54
  return finding.severity;
@@ -172,6 +174,9 @@ export function findingsFromLoadIssues(cwd, absPath, issues) {
172
174
  withIssueLocation(findingTriggerError(cwd, absPath, issue.message, issue.code), issue),
173
175
  ];
174
176
  }
177
+ if (issue.category === "eval") {
178
+ return evalFindingsFromIssues(relPath(cwd, absPath), [issue]);
179
+ }
175
180
  if (issue.category === "catalog") {
176
181
  const code = issue.code;
177
182
  const severity = code === "catalog.manifest_missing" ||
@@ -647,6 +652,9 @@ async function validateManifestAll(invocationCwd) {
647
652
  }));
648
653
  }
649
654
  }
655
+ for (const entry of await loadEvalCatalog(manifest)) {
656
+ findings.push(...entry.findings);
657
+ }
650
658
  return findings;
651
659
  }
652
660
  /** Confirms a trigger's `pipeline`/`task` refs resolve against known catalog ids. */
@@ -0,0 +1,36 @@
1
+ import { type LoadedEval } from "./loadEval.js";
2
+ import type { LoadIssue } from "./loadOutcome.js";
3
+ import { type AgentCatalogPort } from "./resolveAgentTarget.js";
4
+ import type { ValidationFinding, ValidationSeverity } from "./validateCatalog.js";
5
+ export declare const EVAL_LARGE_RUN = 500;
6
+ export declare const EVAL_TOO_LARGE_RUN = 5000;
7
+ /** The slice of the dataset loader's report that eval validation reads. */
8
+ export type DatasetReport = {
9
+ path: string;
10
+ relPath: string;
11
+ cases: Array<{
12
+ id: string;
13
+ input: Record<string, unknown>;
14
+ expected?: unknown;
15
+ tags?: string[];
16
+ }>;
17
+ findings: ValidationFinding[];
18
+ contentHash: string;
19
+ };
20
+ export type ValidateEvalContext = {
21
+ projectRoot: string;
22
+ evals?: ReadonlyArray<{
23
+ id: string;
24
+ absPath: string;
25
+ }>;
26
+ datasetReport?: DatasetReport;
27
+ datasetInline?: boolean;
28
+ isKnownModel?: (id: string) => Promise<boolean>;
29
+ agents?: AgentCatalogPort;
30
+ };
31
+ export declare function evalFinding(relPath: string, severity: ValidationSeverity, code: string, message: string, location?: {
32
+ line?: number;
33
+ column?: number;
34
+ }): ValidationFinding;
35
+ export declare function evalFindingsFromIssues(relPath: string, issues: LoadIssue[]): ValidationFinding[];
36
+ export declare function validateEval(loaded: LoadedEval, ctx: ValidateEvalContext): Promise<ValidationFinding[]>;