@velum-labs/routekit-eval-setup 1.3.2 → 1.5.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 (342) hide show
  1. package/dist/adapters/authoring-responses-request.d.ts +5 -0
  2. package/dist/adapters/authoring-responses-request.js +38 -0
  3. package/dist/adapters/evaluation-evidence-freshness.d.ts +7 -0
  4. package/dist/adapters/evaluation-evidence-freshness.js +76 -0
  5. package/dist/adapters/git-task-history.d.ts +67 -0
  6. package/dist/adapters/git-task-history.js +171 -0
  7. package/dist/adapters/integrated-repository-history.d.ts +21 -0
  8. package/dist/adapters/integrated-repository-history.js +175 -0
  9. package/dist/adapters/repository-command-diagnostic.d.ts +8 -0
  10. package/dist/adapters/repository-command-diagnostic.js +46 -0
  11. package/dist/adapters/repository-command-evidence.d.ts +13 -0
  12. package/dist/adapters/repository-command-evidence.js +102 -0
  13. package/dist/adapters/repository-command-runner.d.ts +238 -0
  14. package/dist/adapters/repository-command-runner.js +1483 -0
  15. package/dist/adapters/repository-import-context.d.ts +47 -0
  16. package/dist/adapters/repository-import-context.js +469 -0
  17. package/dist/adapters/repository-node-test-reporter.d.ts +3 -0
  18. package/dist/adapters/repository-node-test-reporter.js +27 -0
  19. package/dist/adapters/repository-review-evidence.d.ts +39 -0
  20. package/dist/adapters/repository-review-evidence.js +632 -0
  21. package/dist/adapters/repository-seed-selection.d.ts +7 -0
  22. package/dist/adapters/repository-seed-selection.js +79 -0
  23. package/dist/adapters/repository-solution-edits.d.ts +49 -0
  24. package/dist/adapters/repository-solution-edits.js +136 -0
  25. package/dist/adapters/repository-vitest-phase-adapter.d.ts +8 -0
  26. package/dist/adapters/repository-vitest-phase-adapter.js +310 -0
  27. package/dist/adapters/repository-vitest-reporter.d.ts +24 -0
  28. package/dist/adapters/repository-vitest-reporter.js +314 -0
  29. package/dist/adapters/strict-authoring-schema.d.ts +5 -0
  30. package/dist/adapters/strict-authoring-schema.js +158 -0
  31. package/dist/adapters/test-discovery.d.ts +30 -0
  32. package/dist/adapters/test-discovery.js +124 -0
  33. package/dist/adapters/typescript-repository-index.d.ts +51 -0
  34. package/dist/adapters/typescript-repository-index.js +226 -0
  35. package/dist/agentic-capabilities-protocol.d.ts +1373 -0
  36. package/dist/agentic-capabilities-protocol.js +786 -0
  37. package/dist/case-checkpoint-store.d.ts +29 -0
  38. package/dist/case-checkpoint-store.js +133 -0
  39. package/dist/case-pipeline-protocol-v2.d.ts +184 -0
  40. package/dist/case-pipeline-protocol-v2.js +193 -0
  41. package/dist/case-pipeline-protocol.d.ts +2626 -0
  42. package/dist/case-pipeline-protocol.js +371 -0
  43. package/dist/effect-api.d.ts +74 -10
  44. package/dist/effect-api.js +56 -6
  45. package/dist/errors.d.ts +31 -0
  46. package/dist/errors.js +10 -0
  47. package/dist/eval-capability-execution-envelope.d.ts +64 -0
  48. package/dist/eval-capability-execution-envelope.js +98 -0
  49. package/dist/eval-capability-policy.d.ts +90 -0
  50. package/dist/eval-capability-policy.js +107 -0
  51. package/dist/eval-event-log.d.ts +140 -0
  52. package/dist/eval-event-log.js +220 -0
  53. package/dist/evaluation-authoring-policy.d.ts +18 -0
  54. package/dist/evaluation-authoring-policy.js +19 -0
  55. package/dist/evaluation-authoring-validation.d.ts +22 -0
  56. package/dist/evaluation-authoring-validation.js +72 -0
  57. package/dist/evaluation-evidence.d.ts +20 -0
  58. package/dist/evaluation-evidence.js +319 -0
  59. package/dist/evaluation-grader-calibration-protocol.d.ts +108 -0
  60. package/dist/evaluation-grader-calibration-protocol.js +80 -0
  61. package/dist/evaluation-grader-calibration.d.ts +18 -0
  62. package/dist/evaluation-grader-calibration.js +334 -0
  63. package/dist/evaluation-grading-policy.d.ts +24 -0
  64. package/dist/evaluation-grading-policy.js +54 -0
  65. package/dist/evaluation-proposal-policy.d.ts +4 -0
  66. package/dist/evaluation-proposal-policy.js +91 -0
  67. package/dist/evaluation-source-retrieval.d.ts +68 -0
  68. package/dist/evaluation-source-retrieval.js +513 -0
  69. package/dist/evaluation-structure-policy.d.ts +29 -0
  70. package/dist/evaluation-structure-policy.js +138 -0
  71. package/dist/index.d.ts +124 -17
  72. package/dist/index.js +69 -11
  73. package/dist/inspection.js +2 -3
  74. package/dist/project-artifacts.d.ts +7 -2
  75. package/dist/project-artifacts.js +49 -136
  76. package/dist/project-authoring.d.ts +66 -5
  77. package/dist/project-authoring.js +783 -109
  78. package/dist/project-contracts.d.ts +419 -84
  79. package/dist/project-contracts.js +160 -52
  80. package/dist/project-store.js +2 -1
  81. package/dist/project-workflow.d.ts +5 -4
  82. package/dist/project-workflow.js +154 -35
  83. package/dist/repository-adversary-protocol.d.ts +64 -0
  84. package/dist/repository-adversary-protocol.js +105 -0
  85. package/dist/repository-behavior-protocol.d.ts +188 -0
  86. package/dist/repository-behavior-protocol.js +202 -0
  87. package/dist/repository-benchmark-protocol.d.ts +487 -0
  88. package/dist/repository-benchmark-protocol.js +96 -0
  89. package/dist/repository-execution-protocol.d.ts +150 -0
  90. package/dist/repository-execution-protocol.js +38 -0
  91. package/dist/repository-fixture-instructions.d.ts +3 -0
  92. package/dist/repository-fixture-instructions.js +91 -0
  93. package/dist/repository-fixture-protocol.d.ts +79 -0
  94. package/dist/repository-fixture-protocol.js +79 -0
  95. package/dist/repository-foundry-plan-protocol.d.ts +118 -0
  96. package/dist/repository-foundry-plan-protocol.js +296 -0
  97. package/dist/repository-foundry-progress-protocol.d.ts +52 -0
  98. package/dist/repository-foundry-progress-protocol.js +52 -0
  99. package/dist/repository-improvement-protocol.d.ts +100 -0
  100. package/dist/repository-improvement-protocol.js +106 -0
  101. package/dist/repository-language-model-protocol.d.ts +43 -0
  102. package/dist/repository-language-model-protocol.js +146 -0
  103. package/dist/repository-oracle-coverage-protocol.d.ts +18 -0
  104. package/dist/repository-oracle-coverage-protocol.js +39 -0
  105. package/dist/repository-oracle-execution-binding.d.ts +27 -0
  106. package/dist/repository-oracle-execution-binding.js +59 -0
  107. package/dist/repository-oracle-protocol.d.ts +230 -0
  108. package/dist/repository-oracle-protocol.js +156 -0
  109. package/dist/repository-oracle-scope-policy.d.ts +22 -0
  110. package/dist/repository-oracle-scope-policy.js +92 -0
  111. package/dist/repository-quality-policy.d.ts +15 -0
  112. package/dist/repository-quality-policy.js +357 -0
  113. package/dist/repository-routing-benchmark-protocol.d.ts +176 -0
  114. package/dist/repository-routing-benchmark-protocol.js +103 -0
  115. package/dist/repository-routing-model-protocol.d.ts +36 -0
  116. package/dist/repository-routing-model-protocol.js +89 -0
  117. package/dist/repository-routing-plan-protocol.d.ts +112 -0
  118. package/dist/repository-routing-plan-protocol.js +58 -0
  119. package/dist/repository-routing-quality-policy.d.ts +9 -0
  120. package/dist/repository-routing-quality-policy.js +191 -0
  121. package/dist/repository-seed-qualification-progress-protocol.d.ts +205 -0
  122. package/dist/repository-seed-qualification-progress-protocol.js +28 -0
  123. package/dist/repository-semantic-calibration-protocol.d.ts +768 -0
  124. package/dist/repository-semantic-calibration-protocol.js +276 -0
  125. package/dist/repository-semantic-calibration.d.ts +163 -0
  126. package/dist/repository-semantic-calibration.js +581 -0
  127. package/dist/repository-specification-contract-facts-protocol.d.ts +224 -0
  128. package/dist/repository-specification-contract-facts-protocol.js +276 -0
  129. package/dist/repository-specification-critique-protocol.d.ts +189 -0
  130. package/dist/repository-specification-critique-protocol.js +103 -0
  131. package/dist/repository-task-family-protocol.d.ts +24 -0
  132. package/dist/repository-task-family-protocol.js +37 -0
  133. package/dist/repository-task-seed-protocol.d.ts +384 -0
  134. package/dist/repository-task-seed-protocol.js +236 -0
  135. package/dist/repository-trajectory-protocol.d.ts +20 -0
  136. package/dist/repository-trajectory-protocol.js +42 -0
  137. package/dist/service.js +1 -1
  138. package/dist/services/adversary/service.d.ts +64 -0
  139. package/dist/services/adversary/service.js +330 -0
  140. package/dist/services/benchmark-compiler/service.d.ts +450 -0
  141. package/dist/services/benchmark-compiler/service.js +9 -0
  142. package/dist/services/budgeted-model/service.d.ts +118 -0
  143. package/dist/services/budgeted-model/service.js +460 -0
  144. package/dist/services/case-authoring/service.d.ts +163 -0
  145. package/dist/services/case-authoring/service.js +1456 -0
  146. package/dist/services/case-finalization/service.d.ts +283 -0
  147. package/dist/services/case-finalization/service.js +370 -0
  148. package/dist/services/case-generation/service.d.ts +619 -0
  149. package/dist/services/case-generation/service.js +2628 -0
  150. package/dist/services/case-pipeline/service.d.ts +31 -0
  151. package/dist/services/case-pipeline/service.js +485 -0
  152. package/dist/services/case-pipeline-v2/service.d.ts +70 -0
  153. package/dist/services/case-pipeline-v2/service.js +477 -0
  154. package/dist/services/command-observability/service.d.ts +13 -0
  155. package/dist/services/command-observability/service.js +3 -0
  156. package/dist/services/dimension-labeling/service.d.ts +77 -0
  157. package/dist/services/dimension-labeling/service.js +188 -0
  158. package/dist/services/eval-candidate/service.d.ts +208 -0
  159. package/dist/services/eval-candidate/service.js +64 -0
  160. package/dist/services/eval-capabilities/service.d.ts +183 -0
  161. package/dist/services/eval-capabilities/service.js +1433 -0
  162. package/dist/services/eval-environment/service.d.ts +173 -0
  163. package/dist/services/eval-environment/service.js +127 -0
  164. package/dist/services/evidence-reconstruction/service.d.ts +36 -0
  165. package/dist/services/evidence-reconstruction/service.js +145 -0
  166. package/dist/services/fixture-builder/service.d.ts +62 -0
  167. package/dist/services/fixture-builder/service.js +36 -0
  168. package/dist/services/fixture-validation/service.d.ts +75 -0
  169. package/dist/services/fixture-validation/service.js +295 -0
  170. package/dist/services/foundry/service.d.ts +831 -0
  171. package/dist/services/foundry/service.js +442 -0
  172. package/dist/services/foundry-progress/service.d.ts +62 -0
  173. package/dist/services/foundry-progress/service.js +149 -0
  174. package/dist/services/foundry-v2/service.d.ts +54 -0
  175. package/dist/services/foundry-v2/service.js +28 -0
  176. package/dist/services/grounded-authoring/service.d.ts +126 -0
  177. package/dist/services/grounded-authoring/service.js +822 -0
  178. package/dist/services/historical-case/service.d.ts +722 -0
  179. package/dist/services/historical-case/service.js +177 -0
  180. package/dist/services/improvement-loop/service.d.ts +59 -0
  181. package/dist/services/improvement-loop/service.js +176 -0
  182. package/dist/services/language-model/service.d.ts +52 -0
  183. package/dist/services/language-model/service.js +194 -0
  184. package/dist/services/oracle-builder/service.d.ts +146 -0
  185. package/dist/services/oracle-builder/service.js +513 -0
  186. package/dist/services/oracle-coverage/service.d.ts +28 -0
  187. package/dist/services/oracle-coverage/service.js +50 -0
  188. package/dist/services/oracle-coverage-witness/service.d.ts +130 -0
  189. package/dist/services/oracle-coverage-witness/service.js +538 -0
  190. package/dist/services/pipeline-challenge/service.d.ts +551 -0
  191. package/dist/services/pipeline-challenge/service.js +427 -0
  192. package/dist/services/pipeline-controls/service.d.ts +130 -0
  193. package/dist/services/pipeline-controls/service.js +483 -0
  194. package/dist/services/pipeline-oracle/service.d.ts +8 -0
  195. package/dist/services/pipeline-oracle/service.js +256 -0
  196. package/dist/services/pipeline-seed/service.d.ts +298 -0
  197. package/dist/services/pipeline-seed/service.js +428 -0
  198. package/dist/services/pipeline-spec/service.d.ts +103 -0
  199. package/dist/services/pipeline-spec/service.js +619 -0
  200. package/dist/services/pipeline-tournament/service.d.ts +258 -0
  201. package/dist/services/pipeline-tournament/service.js +476 -0
  202. package/dist/services/quality-gate/service.d.ts +233 -0
  203. package/dist/services/quality-gate/service.js +136 -0
  204. package/dist/services/repository-bundle/service.d.ts +33 -0
  205. package/dist/services/repository-bundle/service.js +114 -0
  206. package/dist/services/repository-model/service.d.ts +105 -0
  207. package/dist/services/repository-model/service.js +250 -0
  208. package/dist/services/repository-public-artifact/service.d.ts +133 -0
  209. package/dist/services/repository-public-artifact/service.js +330 -0
  210. package/dist/services/routing-benchmark/service.d.ts +362 -0
  211. package/dist/services/routing-benchmark/service.js +96 -0
  212. package/dist/services/specification-critic/service.d.ts +92 -0
  213. package/dist/services/specification-critic/service.js +172 -0
  214. package/dist/services/task-family/service.d.ts +40 -0
  215. package/dist/services/task-family/service.js +55 -0
  216. package/dist/services/task-seed/service.d.ts +906 -0
  217. package/dist/services/task-seed/service.js +1406 -0
  218. package/dist/services/task-specification/service.d.ts +27 -0
  219. package/dist/services/task-specification/service.js +40 -0
  220. package/dist/services/trajectory-policy/service.d.ts +110 -0
  221. package/dist/services/trajectory-policy/service.js +216 -0
  222. package/dist/test/agentic-capabilities-protocol.test.d.ts +1 -0
  223. package/dist/test/agentic-capabilities-protocol.test.js +570 -0
  224. package/dist/test/agentic-capabilities.test.d.ts +1 -0
  225. package/dist/test/agentic-capabilities.test.js +1461 -0
  226. package/dist/test/agentic-environment.test.d.ts +1 -0
  227. package/dist/test/agentic-environment.test.js +213 -0
  228. package/dist/test/case-pipeline-foundation.test.d.ts +1 -0
  229. package/dist/test/case-pipeline-foundation.test.js +535 -0
  230. package/dist/test/case-pipeline-protocol-v2.test.d.ts +1 -0
  231. package/dist/test/case-pipeline-protocol-v2.test.js +124 -0
  232. package/dist/test/case-pipeline-v2.test.d.ts +1 -0
  233. package/dist/test/case-pipeline-v2.test.js +286 -0
  234. package/dist/test/case-pipeline.test.d.ts +1 -0
  235. package/dist/test/case-pipeline.test.js +851 -0
  236. package/dist/test/eval-capability-policy.test.d.ts +1 -0
  237. package/dist/test/eval-capability-policy.test.js +50 -0
  238. package/dist/test/eval-event-log.test.d.ts +1 -0
  239. package/dist/test/eval-event-log.test.js +125 -0
  240. package/dist/test/evaluation-evidence-freshness.test.d.ts +1 -0
  241. package/dist/test/evaluation-evidence-freshness.test.js +44 -0
  242. package/dist/test/evaluation-evidence.test.d.ts +1 -0
  243. package/dist/test/evaluation-evidence.test.js +230 -0
  244. package/dist/test/evaluation-grader-calibration.test.d.ts +1 -0
  245. package/dist/test/evaluation-grader-calibration.test.js +373 -0
  246. package/dist/test/evaluation-proposal-digest.test.d.ts +1 -0
  247. package/dist/test/evaluation-proposal-digest.test.js +187 -0
  248. package/dist/test/evaluation-source-retrieval.test.d.ts +1 -0
  249. package/dist/test/evaluation-source-retrieval.test.js +237 -0
  250. package/dist/test/evaluation-structure-policy.test.d.ts +1 -0
  251. package/dist/test/evaluation-structure-policy.test.js +196 -0
  252. package/dist/test/fixtures/repository-resource-panel.d.ts +39 -0
  253. package/dist/test/fixtures/repository-resource-panel.js +111 -0
  254. package/dist/test/fixtures/vitest-boundary-panel.d.ts +84 -0
  255. package/dist/test/fixtures/vitest-boundary-panel.js +120 -0
  256. package/dist/test/fixtures/vitest-phase-panel.d.ts +135 -0
  257. package/dist/test/fixtures/vitest-phase-panel.js +213 -0
  258. package/dist/test/fixtures/vitest-reporter-results.d.ts +76 -0
  259. package/dist/test/fixtures/vitest-reporter-results.js +94 -0
  260. package/dist/test/grounded-authoring.test.d.ts +1 -0
  261. package/dist/test/grounded-authoring.test.js +565 -0
  262. package/dist/test/integrated-repository-history.test.d.ts +1 -0
  263. package/dist/test/integrated-repository-history.test.js +227 -0
  264. package/dist/test/project-authoring.test.js +593 -43
  265. package/dist/test/project-workflow.test.js +419 -40
  266. package/dist/test/repository-authoring-artifacts.test.d.ts +1 -0
  267. package/dist/test/repository-authoring-artifacts.test.js +185 -0
  268. package/dist/test/repository-bundle.test.d.ts +1 -0
  269. package/dist/test/repository-bundle.test.js +52 -0
  270. package/dist/test/repository-case-generation.test.d.ts +1 -0
  271. package/dist/test/repository-case-generation.test.js +3465 -0
  272. package/dist/test/repository-command-diagnostic.test.d.ts +1 -0
  273. package/dist/test/repository-command-diagnostic.test.js +55 -0
  274. package/dist/test/repository-command-signals.test.d.ts +1 -0
  275. package/dist/test/repository-command-signals.test.js +124 -0
  276. package/dist/test/repository-fixture-scope-coverage.test.d.ts +1 -0
  277. package/dist/test/repository-fixture-scope-coverage.test.js +127 -0
  278. package/dist/test/repository-fixture-validation.test.d.ts +1 -0
  279. package/dist/test/repository-fixture-validation.test.js +362 -0
  280. package/dist/test/repository-foundry-progress.test.d.ts +1 -0
  281. package/dist/test/repository-foundry-progress.test.js +110 -0
  282. package/dist/test/repository-foundry-quality.test.d.ts +1 -0
  283. package/dist/test/repository-foundry-quality.test.js +1138 -0
  284. package/dist/test/repository-import-context.test.d.ts +1 -0
  285. package/dist/test/repository-import-context.test.js +354 -0
  286. package/dist/test/repository-model-authoring.test.d.ts +1 -0
  287. package/dist/test/repository-model-authoring.test.js +544 -0
  288. package/dist/test/repository-model.test.d.ts +1 -0
  289. package/dist/test/repository-model.test.js +2195 -0
  290. package/dist/test/repository-node-test-reporter.test.d.ts +1 -0
  291. package/dist/test/repository-node-test-reporter.test.js +104 -0
  292. package/dist/test/repository-oracle-concurrency.test.d.ts +1 -0
  293. package/dist/test/repository-oracle-concurrency.test.js +542 -0
  294. package/dist/test/repository-oracle-coverage-witness.test.d.ts +1 -0
  295. package/dist/test/repository-oracle-coverage-witness.test.js +511 -0
  296. package/dist/test/repository-oracle-coverage.test.d.ts +1 -0
  297. package/dist/test/repository-oracle-coverage.test.js +168 -0
  298. package/dist/test/repository-oracle-evidence.test.d.ts +1 -0
  299. package/dist/test/repository-oracle-evidence.test.js +185 -0
  300. package/dist/test/repository-oracle-plan.test.d.ts +1 -0
  301. package/dist/test/repository-oracle-plan.test.js +176 -0
  302. package/dist/test/repository-overlay-isolation.test.d.ts +1 -0
  303. package/dist/test/repository-overlay-isolation.test.js +85 -0
  304. package/dist/test/repository-preparation-cache.test.d.ts +1 -0
  305. package/dist/test/repository-preparation-cache.test.js +414 -0
  306. package/dist/test/repository-public-artifact.test.d.ts +1 -0
  307. package/dist/test/repository-public-artifact.test.js +273 -0
  308. package/dist/test/repository-qualification-diagnostics.test.d.ts +1 -0
  309. package/dist/test/repository-qualification-diagnostics.test.js +524 -0
  310. package/dist/test/repository-reference-authoring.test.d.ts +1 -0
  311. package/dist/test/repository-reference-authoring.test.js +1633 -0
  312. package/dist/test/repository-review-evidence-v2.test.d.ts +1 -0
  313. package/dist/test/repository-review-evidence-v2.test.js +183 -0
  314. package/dist/test/repository-review-evidence.test.d.ts +1 -0
  315. package/dist/test/repository-review-evidence.test.js +124 -0
  316. package/dist/test/repository-seed-exclusions.test.d.ts +1 -0
  317. package/dist/test/repository-seed-exclusions.test.js +96 -0
  318. package/dist/test/repository-seed-selection.test.d.ts +1 -0
  319. package/dist/test/repository-seed-selection.test.js +504 -0
  320. package/dist/test/repository-semantic-calibration.test.d.ts +1 -0
  321. package/dist/test/repository-semantic-calibration.test.js +688 -0
  322. package/dist/test/repository-solution-edits.test.d.ts +1 -0
  323. package/dist/test/repository-solution-edits.test.js +377 -0
  324. package/dist/test/repository-specification-budget.test.d.ts +1 -0
  325. package/dist/test/repository-specification-budget.test.js +171 -0
  326. package/dist/test/repository-specification-contract-checkpoint.test.d.ts +1 -0
  327. package/dist/test/repository-specification-contract-checkpoint.test.js +228 -0
  328. package/dist/test/repository-specification-contract-facts.test.d.ts +1 -0
  329. package/dist/test/repository-specification-contract-facts.test.js +177 -0
  330. package/dist/test/repository-trajectory-authoring.test.d.ts +1 -0
  331. package/dist/test/repository-trajectory-authoring.test.js +176 -0
  332. package/dist/test/repository-valid-control-plan.test.d.ts +1 -0
  333. package/dist/test/repository-valid-control-plan.test.js +45 -0
  334. package/dist/test/repository-vitest-phase.test.d.ts +1 -0
  335. package/dist/test/repository-vitest-phase.test.js +848 -0
  336. package/dist/test/repository-vitest-reporter.test.d.ts +1 -0
  337. package/dist/test/repository-vitest-reporter.test.js +158 -0
  338. package/dist/test/repository-workspace-build.test.d.ts +1 -0
  339. package/dist/test/repository-workspace-build.test.js +160 -0
  340. package/dist/test/strict-authoring-schema.test.d.ts +1 -0
  341. package/dist/test/strict-authoring-schema.test.js +169 -0
  342. package/package.json +48 -6
@@ -1,13 +1,17 @@
1
1
  import { assertDecompositionResult, assertPublishedRoutingActivation, assertRoutingObjectivePolicy, isForbiddenEvalModel } from "@velum-labs/routekit-eval-contracts";
2
2
  import { RoutingActivationConstraints, RoutingObjectivePolicy } from "@velum-labs/routekit-eval-contracts";
3
+ import { CostService } from "@velum-labs/routekit-registry";
3
4
  import { Clock, Context, Effect, Layer, Path, Schema } from "effect";
5
+ import { assertCurrentEvaluationEvidence } from "./adapters/evaluation-evidence-freshness.js";
4
6
  import { EvalDimensionContrastError, EvalProjectTransitionError } from "./errors.js";
7
+ import { EVAL_STRUCTURE_POLICY_VERSION, assertEvaluationStructure, evaluationStructureReportDigest } from "./evaluation-structure-policy.js";
5
8
  import { EvalRepositoryInspector } from "./inspection.js";
6
9
  import { candidateReasoningEffortFromAnswer } from "./model-selection.js";
7
10
  import { EvalProjectArtifacts, evaluationProposalDigest, routingBasisDigest } from "./project-artifacts.js";
8
- import { EVAL_PROJECT_VERSION, scopedExpectedCalls, summarizeEvalRunLedger } from "./project-contracts.js";
11
+ import { EVAL_PROJECT_VERSION, estimateEvalPlanCost, scopedExpectedCalls, summarizeEvalRunLedger } from "./project-contracts.js";
9
12
  import { EvalProjectStore } from "./project-store.js";
10
13
  import { EvalModelCatalog } from "./services/model-catalog/service.js";
14
+ import { assertEvalRunCanFail } from "./eval-event-log.js";
11
15
  const isoNow = Effect.map(Clock.currentTimeMillis, (millis) => new Date(millis).toISOString());
12
16
  const questionForProgress = (progress) => {
13
17
  switch (progress._tag) {
@@ -92,7 +96,7 @@ const nextAction = (state, artifacts) => {
92
96
  ? "propose-evaluations"
93
97
  : "approve-evaluations";
94
98
  case "ready":
95
- return "run";
99
+ return artifacts.evaluationsApproved ? "run" : "approve-evaluations";
96
100
  case "running":
97
101
  return "none";
98
102
  case "qualified":
@@ -157,15 +161,18 @@ const sameLedger = (left, right) => left.expectedCalls === right.expectedCalls &
157
161
  left.knownOutputTokens === right.knownOutputTokens &&
158
162
  left.unknownTokenMeasurements === right.unknownTokenMeasurements &&
159
163
  left.knownPricedSubtotalUsd === right.knownPricedSubtotalUsd &&
160
- left.unpricedCalls === right.unpricedCalls;
161
- const validateQualifiedReport = (state, plan, proposal, report) => {
162
- assertPublishedRoutingActivation(report.activation, {
163
- dimensionIds: plan.selectedCaseIds.map((entry) => entry.dimensionId)
164
- });
165
- if (report.activation.basisDigest !== state.basisDigest ||
166
- report.activation.classifierModel !== state.configuration.classifierModel ||
167
- !sameStrings(report.activation.candidateModels, plan.candidateModels)) {
168
- throw new Error("published activation does not match the immutable execution plan");
164
+ left.unpricedCalls === right.unpricedCalls &&
165
+ left.subscriptionUnitCalls === right.subscriptionUnitCalls;
166
+ const validateQualifiedReport = (state, plan, proposal, report, costService) => Effect.gen(function* () {
167
+ if (report.status === "passed") {
168
+ assertPublishedRoutingActivation(report.activation, {
169
+ dimensionIds: plan.selectedCaseIds.map((entry) => entry.dimensionId)
170
+ });
171
+ if (report.activation.basisDigest !== state.basisDigest ||
172
+ report.activation.classifierModel !== state.configuration.classifierModel ||
173
+ !sameStrings(report.activation.candidateModels, plan.candidateModels)) {
174
+ throw new Error("published activation does not match the immutable execution plan");
175
+ }
169
176
  }
170
177
  const expectedDimensions = new Map(plan.selectedCaseIds.map((entry) => [entry.dimensionId, new Set(entry.caseIds)]));
171
178
  const comparisons = new Map();
@@ -285,30 +292,60 @@ const validateQualifiedReport = (state, plan, proposal, report) => {
285
292
  observedCompositionCases.size !== 0 ||
286
293
  qualification.composition.comparableCases !== 0 ||
287
294
  qualification.composition.agreeingCases !== 0 ||
295
+ qualification.composition.winnerAgreement !== undefined ||
296
+ qualification.composition.conclusion !== "inconclusive" ||
297
+ qualification.composition.publishable ||
288
298
  qualification.composition.cases.length !== 0) {
289
299
  throw new Error("composition qualification summary does not meet the reviewed threshold");
290
300
  }
291
301
  }
292
302
  else if (qualification.composition.expectedCases !== expectedCompositionCases.size ||
293
303
  observedCompositionCases.size !== expectedCompositionCases.size ||
294
- qualification.composition.comparableCases < 1 ||
295
304
  qualification.composition.agreeingCases !==
296
305
  qualification.composition.cases.filter((result) => result.passed).length ||
297
- Math.abs(qualification.composition.winnerAgreement -
298
- qualification.composition.agreeingCases / qualification.composition.comparableCases) > 1e-6 ||
299
- qualification.composition.winnerAgreement <
300
- proposal.compositionSuite.minimumWinnerAgreement) {
306
+ qualification.composition.comparableCases !==
307
+ qualification.composition.cases.filter((result) => result.comparable).length ||
308
+ qualification.composition.cases.some((result) => result.comparable !==
309
+ (result.predictedWinner !== null &&
310
+ result.observedWinner !== null &&
311
+ result.predictedScoreGap >= proposal.compositionSuite.minimumWinnerScoreGap &&
312
+ result.observedScoreGap >= proposal.compositionSuite.minimumWinnerScoreGap) ||
313
+ result.passed !==
314
+ (result.comparable && result.predictedWinner === result.observedWinner))) {
301
315
  throw new Error("composition qualification summary does not meet the reviewed threshold");
302
316
  }
317
+ if (expectedCompositionCases.size > 0) {
318
+ const comparableCases = qualification.composition.comparableCases;
319
+ const expectedAgreement = comparableCases === 0
320
+ ? undefined
321
+ : qualification.composition.agreeingCases / comparableCases;
322
+ const meetsThreshold = expectedAgreement !== undefined &&
323
+ expectedAgreement >= proposal.compositionSuite.minimumWinnerAgreement;
324
+ if ((expectedAgreement === undefined
325
+ ? qualification.composition.winnerAgreement !== undefined
326
+ : qualification.composition.winnerAgreement === undefined ||
327
+ Math.abs(qualification.composition.winnerAgreement - expectedAgreement) > 1e-6) ||
328
+ qualification.composition.conclusion !==
329
+ (expectedAgreement === undefined
330
+ ? "inconclusive"
331
+ : meetsThreshold
332
+ ? "passed"
333
+ : "failed") ||
334
+ qualification.composition.publishable !==
335
+ (plan.scope === "full" && meetsThreshold) ||
336
+ (plan.scope === "full" && !meetsThreshold)) {
337
+ throw new Error("composition qualification summary does not meet the reviewed threshold");
338
+ }
339
+ }
303
340
  }
304
341
  const expected = scopedExpectedCalls(plan);
305
- const ledger = summarizeEvalRunLedger(report.comparisons, expected.expectedCallCount, qualification?.decomposition.observations ?? []);
342
+ const ledger = yield* summarizeEvalRunLedger(report.comparisons, expected.expectedCallCount, costService, qualification?.decomposition.observations ?? [], plan.classifierModel);
306
343
  if (ledger.observedCalls !== expected.expectedCallCount ||
307
344
  ledger.observedCandidateRows !== expected.expectedCandidateCalls ||
308
345
  !sameLedger(ledger, report.ledger)) {
309
346
  throw new Error("qualification ledger does not match the completed evidence");
310
347
  }
311
- };
348
+ });
312
349
  const parseObjective = (state, answer) => Effect.gen(function* () {
313
350
  const text = yield* nonEmptyAnswer(state, answer);
314
351
  const json = yield* Effect.try({
@@ -512,8 +549,26 @@ export const makeEvalProjectWorkflow = Effect.gen(function* () {
512
549
  const artifacts = yield* EvalProjectArtifacts;
513
550
  const inspector = yield* EvalRepositoryInspector;
514
551
  const modelCatalog = yield* EvalModelCatalog;
552
+ const costService = yield* CostService;
515
553
  const paths = yield* Path.Path;
554
+ const platform = yield* Effect.context();
516
555
  const resolveRoot = (repositoryRoot) => paths.resolve(repositoryRoot);
556
+ const evaluationStructureFor = (root, state, proposal) => Effect.gen(function* () {
557
+ const report = yield* Effect.try({
558
+ try: () => assertEvaluationStructure({
559
+ proposal,
560
+ sourceInventory: state.sourceInventory
561
+ }),
562
+ catch: (cause) => transitionError(state.stage, cause instanceof Error
563
+ ? cause.message
564
+ : "evaluation proposal failed structure validation")
565
+ });
566
+ yield* assertCurrentEvaluationEvidence({
567
+ repositoryRoot: root,
568
+ evidenceSources: proposal.evidenceSources ?? []
569
+ }).pipe(Effect.provide(platform), Effect.mapError((cause) => transitionError(state.stage, cause.message)));
570
+ return report;
571
+ });
517
572
  const statusOf = (root, state) => Effect.gen(function* () {
518
573
  const [basis, basisApproval, evaluations, evaluationsApproval, plans] = yield* Effect.all([
519
574
  artifacts.loadBasisProposal(root),
@@ -522,6 +577,15 @@ export const makeEvalProjectWorkflow = Effect.gen(function* () {
522
577
  artifacts.loadEvaluationsApproval(root),
523
578
  artifacts.listPlans(root)
524
579
  ]);
580
+ const structureReport = evaluations === undefined
581
+ ? undefined
582
+ : yield* evaluationStructureFor(root, state, evaluations).pipe(Effect.match({
583
+ onFailure: () => undefined,
584
+ onSuccess: (report) => report
585
+ }));
586
+ const structureReportDigest = structureReport === undefined
587
+ ? undefined
588
+ : evaluationStructureReportDigest(structureReport);
525
589
  const artifactStatus = {
526
590
  ...(basis === undefined ? {} : { basisProposalDigest: basis.basisDigest }),
527
591
  basisApproved: basis !== undefined &&
@@ -532,7 +596,10 @@ export const makeEvalProjectWorkflow = Effect.gen(function* () {
532
596
  : { evaluationProposalDigest: evaluations.evaluationDigest }),
533
597
  evaluationsApproved: evaluations !== undefined &&
534
598
  evaluationsApproval?.kind === "evaluations" &&
535
- evaluationsApproval.digest === evaluations.evaluationDigest,
599
+ evaluationsApproval.digest === evaluations.evaluationDigest &&
600
+ evaluationsApproval.structurePolicyVersion ===
601
+ EVAL_STRUCTURE_POLICY_VERSION &&
602
+ evaluationsApproval.structureReportDigest === structureReportDigest,
536
603
  plans
537
604
  };
538
605
  return {
@@ -697,7 +764,9 @@ export const makeEvalProjectWorkflow = Effect.gen(function* () {
697
764
  const proposeEvaluations = (repositoryRoot, input) => Effect.gen(function* () {
698
765
  const root = resolveRoot(repositoryRoot);
699
766
  const state = yield* loadRequired(root);
700
- if (state.stage !== "evaluations-review") {
767
+ if (state.stage !== "evaluations-review" &&
768
+ state.stage !== "ready" &&
769
+ state.stage !== "qualified") {
701
770
  return yield* transitionError(state.stage, "dimension evaluations can only be proposed after routing-basis approval");
702
771
  }
703
772
  const basis = yield* artifacts.loadBasisProposal(root);
@@ -743,6 +812,9 @@ export const makeEvalProjectWorkflow = Effect.gen(function* () {
743
812
  candidateReasoningEfforts: state.configuration.candidateReasoningEfforts
744
813
  }),
745
814
  judgeModel: state.configuration.judgeModel,
815
+ ...(input.evidenceSources === undefined
816
+ ? {}
817
+ : { evidenceSources: input.evidenceSources }),
746
818
  suites: input.suites,
747
819
  decompositionBenchmark: input.decompositionBenchmark,
748
820
  compositionSuite: input.compositionSuite
@@ -757,7 +829,9 @@ export const makeEvalProjectWorkflow = Effect.gen(function* () {
757
829
  const approveEvaluations = (repositoryRoot, expectedDigest) => Effect.gen(function* () {
758
830
  const root = resolveRoot(repositoryRoot);
759
831
  const state = yield* loadRequired(root);
760
- if (state.stage !== "evaluations-review") {
832
+ if (state.stage !== "evaluations-review" &&
833
+ state.stage !== "ready" &&
834
+ state.stage !== "qualified") {
761
835
  return yield* transitionError(state.stage, "dimension evaluations are not awaiting approval");
762
836
  }
763
837
  const proposal = yield* artifacts.loadEvaluationProposal(root);
@@ -768,13 +842,19 @@ export const makeEvalProjectWorkflow = Effect.gen(function* () {
768
842
  proposal.basisDigest !== state.basisDigest) {
769
843
  return yield* transitionError(state.stage, "evaluation proposal changed after review; approve its current digest");
770
844
  }
845
+ const structureReport = yield* evaluationStructureFor(root, state, proposal);
771
846
  const now = yield* isoNow;
772
847
  yield* artifacts.saveEvaluationsApproval(root, {
773
848
  version: EVAL_PROJECT_VERSION,
774
849
  kind: "evaluations",
775
850
  digest: proposal.evaluationDigest,
776
- approvedAt: now
851
+ approvedAt: now,
852
+ structurePolicyVersion: EVAL_STRUCTURE_POLICY_VERSION,
853
+ structureReportDigest: evaluationStructureReportDigest(structureReport)
777
854
  });
855
+ if (state.stage !== "evaluations-review") {
856
+ return yield* statusOf(root, state);
857
+ }
778
858
  const next = {
779
859
  version: state.version,
780
860
  projectId: state.projectId,
@@ -790,7 +870,7 @@ export const makeEvalProjectWorkflow = Effect.gen(function* () {
790
870
  yield* store.save(root, next);
791
871
  return yield* statusOf(root, next);
792
872
  });
793
- const createPlan = (repositoryRoot, scope) => Effect.gen(function* () {
873
+ const createPlan = (repositoryRoot, scope, repetitions = 1) => Effect.gen(function* () {
794
874
  const root = resolveRoot(repositoryRoot);
795
875
  const state = yield* loadRequired(root);
796
876
  if (state.stage !== "ready" && state.stage !== "qualified") {
@@ -798,13 +878,24 @@ export const makeEvalProjectWorkflow = Effect.gen(function* () {
798
878
  }
799
879
  const proposal = yield* artifacts.loadEvaluationProposal(root);
800
880
  const approval = yield* artifacts.loadEvaluationsApproval(root);
881
+ const structureReport = proposal === undefined
882
+ ? undefined
883
+ : yield* evaluationStructureFor(root, state, proposal);
801
884
  if (proposal === undefined ||
802
885
  approval?.kind !== "evaluations" ||
803
886
  approval.digest !== proposal.evaluationDigest ||
887
+ approval.structurePolicyVersion !== EVAL_STRUCTURE_POLICY_VERSION ||
888
+ approval.structureReportDigest !==
889
+ (structureReport === undefined
890
+ ? undefined
891
+ : evaluationStructureReportDigest(structureReport)) ||
804
892
  proposal.evaluationDigest !== state.evaluationDigest ||
805
893
  proposal.basisDigest !== state.basisDigest) {
806
894
  return yield* transitionError(state.stage, "approved evaluation artifacts are stale");
807
895
  }
896
+ if (!Number.isSafeInteger(repetitions) || repetitions < 1) {
897
+ return yield* transitionError(state.stage, "eval repetitions N must be at least 1");
898
+ }
808
899
  if (scope === "full") {
809
900
  const shortSuite = proposal.suites.find((suite) => suite.cases.length < 20);
810
901
  if (shortSuite !== undefined ||
@@ -817,16 +908,22 @@ export const makeEvalProjectWorkflow = Effect.gen(function* () {
817
908
  }
818
909
  const selectedCaseIds = proposal.suites.map((suite) => ({
819
910
  dimensionId: suite.dimensionId,
820
- caseIds: suite.cases
911
+ caseIds: Array.from({ length: repetitions }, (_, repetition) => suite.cases
821
912
  .slice(0, scope === "pilot" ? 5 : undefined)
822
- .map((testCase) => testCase.id)
913
+ .map((testCase) => repetitions === 1
914
+ ? testCase.id
915
+ : `${testCase.id}#${String(repetition + 1)}`)).flat()
823
916
  }));
824
- const selectedDecompositionCaseIds = proposal.decompositionBenchmark.cases
917
+ const selectedDecompositionCaseIds = Array.from({ length: repetitions }, (_, repetition) => proposal.decompositionBenchmark.cases
825
918
  .slice(0, scope === "pilot" ? 5 : undefined)
826
- .map((testCase) => testCase.id);
827
- const selectedCompositionCaseIds = proposal.compositionSuite.cases
919
+ .map((testCase) => repetitions === 1
920
+ ? testCase.id
921
+ : `${testCase.id}#${String(repetition + 1)}`)).flat();
922
+ const selectedCompositionCaseIds = Array.from({ length: repetitions }, (_, repetition) => proposal.compositionSuite.cases
828
923
  .slice(0, scope === "pilot" ? 5 : undefined)
829
- .map((testCase) => testCase.id);
924
+ .map((testCase) => repetitions === 1
925
+ ? testCase.id
926
+ : `${testCase.id}#${String(repetition + 1)}`)).flat();
830
927
  const expected = scopedExpectedCalls({
831
928
  candidateModels: proposal.candidateModels,
832
929
  selectedCaseIds,
@@ -840,6 +937,7 @@ export const makeEvalProjectWorkflow = Effect.gen(function* () {
840
937
  projectRevision: state.revision,
841
938
  createdAt: yield* isoNow,
842
939
  scope,
940
+ repetitions,
843
941
  basisDigest: state.basisDigest,
844
942
  evaluationDigest: state.evaluationDigest,
845
943
  candidateModels: state.configuration.candidateModels,
@@ -855,7 +953,15 @@ export const makeEvalProjectWorkflow = Effect.gen(function* () {
855
953
  selectedDecompositionCaseIds,
856
954
  selectedCompositionCaseIds,
857
955
  maximumOutputTokens: Math.max(proposal.compositionSuite.maximumOutputTokens, ...proposal.suites.map((suite) => suite.maximumOutputTokens)),
858
- ...expected
956
+ ...expected,
957
+ costEstimate: yield* estimateEvalPlanCost({
958
+ candidateModels: state.configuration.candidateModels,
959
+ candidateReasoningEfforts: state.configuration.candidateReasoningEfforts,
960
+ classifierModel: state.configuration.classifierModel,
961
+ judgeModel: state.configuration.judgeModel,
962
+ maximumOutputTokens: Math.max(proposal.compositionSuite.maximumOutputTokens, ...proposal.suites.map((suite) => suite.maximumOutputTokens)),
963
+ ...expected
964
+ }, costService)
859
965
  };
860
966
  yield* artifacts.materializePlanSuites(root, plan, proposal);
861
967
  yield* artifacts.savePlan(root, plan);
@@ -877,6 +983,9 @@ export const makeEvalProjectWorkflow = Effect.gen(function* () {
877
983
  plan.evaluationDigest !== state.evaluationDigest ||
878
984
  !sameStrings(plan.candidateModels, state.configuration.candidateModels) ||
879
985
  !sameReasoningEfforts(plan.candidateReasoningEfforts, state.configuration.candidateReasoningEfforts) ||
986
+ (plan.costEstimate !== undefined &&
987
+ JSON.stringify(plan.costEstimate) !==
988
+ JSON.stringify(yield* estimateEvalPlanCost(plan, costService))) ||
880
989
  plan.classifierModel !== state.configuration.classifierModel ||
881
990
  plan.authorModel !== state.configuration.authorModel ||
882
991
  plan.judgeModel !== state.configuration.judgeModel) {
@@ -888,6 +997,15 @@ export const makeEvalProjectWorkflow = Effect.gen(function* () {
888
997
  proposal.basisDigest !== plan.basisDigest) {
889
998
  return yield* transitionError(state.stage, "the approved evaluation proposal for the execution plan is missing or stale");
890
999
  }
1000
+ const approval = yield* artifacts.loadEvaluationsApproval(root);
1001
+ const structureReport = yield* evaluationStructureFor(root, state, proposal);
1002
+ if (approval?.kind !== "evaluations" ||
1003
+ approval.digest !== proposal.evaluationDigest ||
1004
+ approval.structurePolicyVersion !== EVAL_STRUCTURE_POLICY_VERSION ||
1005
+ approval.structureReportDigest !==
1006
+ evaluationStructureReportDigest(structureReport)) {
1007
+ return yield* transitionError(state.stage, "the evaluation approval is stale under the current structure policy");
1008
+ }
891
1009
  yield* artifacts.materializePlanSuites(root, plan, proposal, "rematerialize");
892
1010
  const now = yield* isoNow;
893
1011
  const runId = crypto.randomUUID();
@@ -923,7 +1041,7 @@ export const makeEvalProjectWorkflow = Effect.gen(function* () {
923
1041
  if ((report.target.kind === "configured"
924
1042
  ? !report.cleanup.sessionOpened || !report.cleanup.sessionClosed
925
1043
  : report.cleanup.sessionOpened || report.cleanup.sessionClosed) ||
926
- report.activation.basisDigest !== state.basisDigest) {
1044
+ (report.status === "passed" && report.activation.basisDigest !== state.basisDigest)) {
927
1045
  return yield* transitionError(state.stage, "a run cannot qualify before session cleanup and activation validation complete");
928
1046
  }
929
1047
  const plan = yield* artifacts.loadPlan(root, state.planId);
@@ -940,10 +1058,7 @@ export const makeEvalProjectWorkflow = Effect.gen(function* () {
940
1058
  (plan.scope === "pilot" && report.status !== "completed")) {
941
1059
  return yield* transitionError(state.stage, "only full plans may qualify routing activation; pilot plans are completed diagnostics");
942
1060
  }
943
- yield* Effect.try({
944
- try: () => validateQualifiedReport(state, plan, proposal, report),
945
- catch: (cause) => transitionError(state.stage, cause instanceof Error ? cause.message : "qualification report is invalid")
946
- });
1061
+ yield* validateQualifiedReport(state, plan, proposal, report, costService).pipe(Effect.catchDefect((cause) => Effect.fail(transitionError(state.stage, cause instanceof Error ? cause.message : "qualification report is invalid"))));
947
1062
  const reportPath = yield* artifacts.saveRunReport(root, report);
948
1063
  const common = {
949
1064
  version: state.version,
@@ -982,6 +1097,10 @@ export const makeEvalProjectWorkflow = Effect.gen(function* () {
982
1097
  report.evaluationDigest !== state.evaluationDigest) {
983
1098
  return yield* transitionError(state.stage, "failure report does not match the active run");
984
1099
  }
1100
+ yield* Effect.try({
1101
+ try: () => assertEvalRunCanFail(report.events ?? []),
1102
+ catch: (cause) => transitionError(state.stage, cause instanceof Error ? cause.message : "failure report has no terminal event")
1103
+ });
985
1104
  yield* artifacts.saveRunReport(root, report);
986
1105
  const next = {
987
1106
  version: state.version,
@@ -0,0 +1,64 @@
1
+ import { Schema } from "effect";
2
+ export declare const RepositoryAdversaryMutationOperatorV1: Schema.Literals<readonly ["condition-negation", "boundary-operator", "partial-output-drop", "cross-file-omission"]>;
3
+ export type RepositoryAdversaryMutationOperatorV1 = typeof RepositoryAdversaryMutationOperatorV1.Type;
4
+ export declare const RepositoryAdversaryValidationObservationV1: Schema.Struct<{
5
+ readonly repetition: Schema.Finite;
6
+ readonly outcome: Schema.Literals<readonly ["pass", "fail"]>;
7
+ readonly detail: Schema.String;
8
+ }>;
9
+ export type RepositoryAdversaryValidationObservationV1 = typeof RepositoryAdversaryValidationObservationV1.Type;
10
+ export declare const RepositoryAdversaryCandidateV1: Schema.Struct<{
11
+ readonly version: Schema.Literal<1>;
12
+ readonly id: Schema.String;
13
+ readonly solutionId: Schema.String;
14
+ readonly family: Schema.String;
15
+ readonly operator: Schema.Literals<readonly ["condition-negation", "boundary-operator", "partial-output-drop", "cross-file-omission"]>;
16
+ readonly sourcePath: Schema.String;
17
+ readonly relatedPaths: Schema.$Array<Schema.String>;
18
+ readonly sourceCommit: Schema.String;
19
+ readonly originalSnippet: Schema.String;
20
+ readonly mutatedSnippet: Schema.String;
21
+ readonly validationRecipeId: Schema.String;
22
+ readonly compilationStatus: Schema.Literals<readonly ["passed", "failed"]>;
23
+ readonly validationObservations: Schema.$Array<Schema.Struct<{
24
+ readonly repetition: Schema.Finite;
25
+ readonly outcome: Schema.Literals<readonly ["pass", "fail"]>;
26
+ readonly detail: Schema.String;
27
+ }>>;
28
+ readonly rejectionReasons: Schema.$Array<Schema.String>;
29
+ }>;
30
+ export type RepositoryAdversaryCandidateV1 = typeof RepositoryAdversaryCandidateV1.Type;
31
+ export declare const RepositoryAdversaryGenerationReportV1: Schema.Struct<{
32
+ readonly version: Schema.Literal<1>;
33
+ readonly seedId: Schema.String;
34
+ readonly generationCoverage: Schema.Struct<{
35
+ readonly implementationPathCount: Schema.Finite;
36
+ readonly changedPathCount: Schema.Finite;
37
+ readonly generatedCrossFileCandidateCount: Schema.Finite;
38
+ readonly omittedCrossFileCandidateCount: Schema.Finite;
39
+ }>;
40
+ readonly candidates: Schema.$Array<Schema.Struct<{
41
+ readonly version: Schema.Literal<1>;
42
+ readonly id: Schema.String;
43
+ readonly solutionId: Schema.String;
44
+ readonly family: Schema.String;
45
+ readonly operator: Schema.Literals<readonly ["condition-negation", "boundary-operator", "partial-output-drop", "cross-file-omission"]>;
46
+ readonly sourcePath: Schema.String;
47
+ readonly relatedPaths: Schema.$Array<Schema.String>;
48
+ readonly sourceCommit: Schema.String;
49
+ readonly originalSnippet: Schema.String;
50
+ readonly mutatedSnippet: Schema.String;
51
+ readonly validationRecipeId: Schema.String;
52
+ readonly compilationStatus: Schema.Literals<readonly ["passed", "failed"]>;
53
+ readonly validationObservations: Schema.$Array<Schema.Struct<{
54
+ readonly repetition: Schema.Finite;
55
+ readonly outcome: Schema.Literals<readonly ["pass", "fail"]>;
56
+ readonly detail: Schema.String;
57
+ }>>;
58
+ readonly rejectionReasons: Schema.$Array<Schema.String>;
59
+ }>>;
60
+ readonly admittedCandidateIds: Schema.$Array<Schema.String>;
61
+ readonly rejectedCandidateIds: Schema.$Array<Schema.String>;
62
+ }>;
63
+ export type RepositoryAdversaryGenerationReportV1 = typeof RepositoryAdversaryGenerationReportV1.Type;
64
+ export declare function assertRepositoryAdversaryGenerationReportV1(value: unknown): asserts value is RepositoryAdversaryGenerationReportV1;
@@ -0,0 +1,105 @@
1
+ import { Schema } from "effect";
2
+ export const RepositoryAdversaryMutationOperatorV1 = Schema.Literals([
3
+ "condition-negation",
4
+ "boundary-operator",
5
+ "partial-output-drop",
6
+ "cross-file-omission"
7
+ ]);
8
+ export const RepositoryAdversaryValidationObservationV1 = Schema.Struct({
9
+ repetition: Schema.Finite,
10
+ outcome: Schema.Literals(["pass", "fail"]),
11
+ detail: Schema.String
12
+ });
13
+ export const RepositoryAdversaryCandidateV1 = Schema.Struct({
14
+ version: Schema.Literal(1),
15
+ id: Schema.String,
16
+ solutionId: Schema.String,
17
+ family: Schema.String,
18
+ operator: RepositoryAdversaryMutationOperatorV1,
19
+ sourcePath: Schema.String,
20
+ relatedPaths: Schema.Array(Schema.String),
21
+ sourceCommit: Schema.String,
22
+ originalSnippet: Schema.String,
23
+ mutatedSnippet: Schema.String,
24
+ validationRecipeId: Schema.String,
25
+ compilationStatus: Schema.Literals(["passed", "failed"]),
26
+ validationObservations: Schema.Array(RepositoryAdversaryValidationObservationV1),
27
+ rejectionReasons: Schema.Array(Schema.String)
28
+ });
29
+ export const RepositoryAdversaryGenerationReportV1 = Schema.Struct({
30
+ version: Schema.Literal(1),
31
+ seedId: Schema.String,
32
+ generationCoverage: Schema.Struct({
33
+ implementationPathCount: Schema.Finite,
34
+ changedPathCount: Schema.Finite,
35
+ generatedCrossFileCandidateCount: Schema.Finite,
36
+ omittedCrossFileCandidateCount: Schema.Finite
37
+ }),
38
+ candidates: Schema.Array(RepositoryAdversaryCandidateV1),
39
+ admittedCandidateIds: Schema.Array(Schema.String),
40
+ rejectedCandidateIds: Schema.Array(Schema.String)
41
+ });
42
+ export function assertRepositoryAdversaryGenerationReportV1(value) {
43
+ const report = Schema.decodeUnknownSync(RepositoryAdversaryGenerationReportV1)(value);
44
+ const candidateIds = new Set(report.candidates.map((candidate) => candidate.id));
45
+ const solutionIds = new Set(report.candidates.map((candidate) => candidate.solutionId));
46
+ const crossFileCandidateCount = report.candidates.filter((candidate) => candidate.operator === "cross-file-omission").length;
47
+ if (candidateIds.size !== report.candidates.length ||
48
+ solutionIds.size !== report.candidates.length) {
49
+ throw new Error("repository adversary candidate ids must be unique");
50
+ }
51
+ if (!Number.isInteger(report.generationCoverage.implementationPathCount) ||
52
+ !Number.isInteger(report.generationCoverage.changedPathCount) ||
53
+ !Number.isInteger(report.generationCoverage.generatedCrossFileCandidateCount) ||
54
+ !Number.isInteger(report.generationCoverage.omittedCrossFileCandidateCount) ||
55
+ report.generationCoverage.implementationPathCount < 0 ||
56
+ report.generationCoverage.changedPathCount < 0 ||
57
+ report.generationCoverage.generatedCrossFileCandidateCount < 0 ||
58
+ report.generationCoverage.omittedCrossFileCandidateCount < 0 ||
59
+ report.generationCoverage.changedPathCount >
60
+ report.generationCoverage.implementationPathCount ||
61
+ report.generationCoverage.generatedCrossFileCandidateCount !==
62
+ crossFileCandidateCount ||
63
+ (report.generationCoverage.changedPathCount >= 2
64
+ ? report.generationCoverage.generatedCrossFileCandidateCount +
65
+ report.generationCoverage.omittedCrossFileCandidateCount !==
66
+ report.generationCoverage.changedPathCount
67
+ : report.generationCoverage.generatedCrossFileCandidateCount !== 0 ||
68
+ report.generationCoverage.omittedCrossFileCandidateCount !== 0)) {
69
+ throw new Error("repository adversary generation coverage must account for every eligible cross-file path");
70
+ }
71
+ const classified = new Set([
72
+ ...report.admittedCandidateIds,
73
+ ...report.rejectedCandidateIds
74
+ ]);
75
+ if (classified.size !== report.candidates.length ||
76
+ [...classified].some((id) => !candidateIds.has(id))) {
77
+ throw new Error("every repository adversary candidate must be classified exactly once");
78
+ }
79
+ for (const candidate of report.candidates) {
80
+ if (new Set(candidate.relatedPaths).size !== candidate.relatedPaths.length ||
81
+ candidate.relatedPaths.includes(candidate.sourcePath) ||
82
+ (candidate.operator === "cross-file-omission"
83
+ ? candidate.relatedPaths.length === 0
84
+ : candidate.relatedPaths.length !== 0)) {
85
+ throw new Error("repository adversary related paths must identify only the coupled files for cross-file mutations");
86
+ }
87
+ if (candidate.validationObservations.length < 2 ||
88
+ candidate.validationObservations.some((observation) => !Number.isInteger(observation.repetition) ||
89
+ observation.repetition < 1)) {
90
+ throw new Error("repository adversary candidates require repeated validation observations");
91
+ }
92
+ const passed = candidate.validationObservations.every((observation) => observation.outcome === "pass");
93
+ if ((candidate.compilationStatus === "passed") !== passed ||
94
+ (candidate.compilationStatus === "passed") !==
95
+ report.admittedCandidateIds.includes(candidate.id) ||
96
+ (candidate.compilationStatus === "failed") !==
97
+ report.rejectedCandidateIds.includes(candidate.id)) {
98
+ throw new Error("repository adversary classification must match compilation observations");
99
+ }
100
+ if (candidate.compilationStatus === "passed" &&
101
+ candidate.rejectionReasons.length > 0) {
102
+ throw new Error("admitted repository adversaries cannot have rejection reasons");
103
+ }
104
+ }
105
+ }