@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
@@ -0,0 +1,513 @@
1
+ export const EVAL_SOURCE_RETRIEVAL_INDEX_FILES = 512;
2
+ export const EVAL_SOURCE_RETRIEVAL_INDEX_BYTES = 8 * 1024 * 1024;
3
+ export const EVAL_SOURCE_RETRIEVAL_FILE_BYTES = 256 * 1024;
4
+ export const EVAL_SOURCE_RETRIEVAL_PACKET_BLOCKS = 20;
5
+ export const EVAL_SOURCE_RETRIEVAL_BLOCKS_PER_SOURCE = 2;
6
+ const STOP_WORDS = new Set([
7
+ "about",
8
+ "after",
9
+ "and",
10
+ "are",
11
+ "been",
12
+ "for",
13
+ "from",
14
+ "has",
15
+ "into",
16
+ "request",
17
+ "requests",
18
+ "that",
19
+ "the",
20
+ "this",
21
+ "with"
22
+ ]);
23
+ const canonicalCompare = (left, right) => left < right ? -1 : left > right ? 1 : 0;
24
+ const alphaNumeric = (character) => {
25
+ const code = character.codePointAt(0);
26
+ return (code !== undefined &&
27
+ ((code >= 48 && code <= 57) ||
28
+ (code >= 65 && code <= 90) ||
29
+ (code >= 97 && code <= 122)));
30
+ };
31
+ const upper = (character) => {
32
+ const code = character.codePointAt(0);
33
+ return code !== undefined && code >= 65 && code <= 90;
34
+ };
35
+ const lowerOrNumber = (character) => {
36
+ const code = character.codePointAt(0);
37
+ return (code !== undefined &&
38
+ ((code >= 48 && code <= 57) || (code >= 97 && code <= 122)));
39
+ };
40
+ const normalizeToken = (value) => {
41
+ const lower = value.toLowerCase();
42
+ if (lower.length >= 5 && lower.endsWith("ies")) {
43
+ return `${lower.slice(0, -3)}y`;
44
+ }
45
+ if (lower.length >= 5 &&
46
+ lower.endsWith("s") &&
47
+ !lower.endsWith("ss") &&
48
+ !lower.endsWith("us") &&
49
+ !lower.endsWith("is")) {
50
+ return lower.slice(0, -1);
51
+ }
52
+ return lower;
53
+ };
54
+ /**
55
+ * Tokenizes identifiers and prose without asking a model to infer source
56
+ * relevance. CamelCase boundaries are retained so `providerBackend` can match
57
+ * the reviewed positive scope `provider backend`.
58
+ */
59
+ export const evaluationSourceTokens = (value) => {
60
+ const tokens = [];
61
+ let token = "";
62
+ const flush = () => {
63
+ const normalized = normalizeToken(token);
64
+ token = "";
65
+ if (normalized.length >= 3 && !STOP_WORDS.has(normalized)) {
66
+ tokens.push(normalized);
67
+ }
68
+ };
69
+ const characters = [...value];
70
+ for (const [index, character] of characters.entries()) {
71
+ if (!alphaNumeric(character)) {
72
+ flush();
73
+ continue;
74
+ }
75
+ const previous = token.at(-1);
76
+ const next = characters[index + 1];
77
+ if (token.length > 0 &&
78
+ previous !== undefined &&
79
+ upper(character) &&
80
+ (lowerOrNumber(previous) ||
81
+ (upper(previous) && next !== undefined && lowerOrNumber(next)))) {
82
+ flush();
83
+ }
84
+ token += character;
85
+ }
86
+ flush();
87
+ return tokens;
88
+ };
89
+ const positiveQueryTerms = (input) => {
90
+ const dimensions = input.targetDimensions ?? [];
91
+ const values = dimensions.length === 0
92
+ ? [input.workloadDescription ?? ""]
93
+ : dimensions.flatMap((dimension) => [
94
+ dimension.id,
95
+ dimension.description,
96
+ ...dimension.includes
97
+ ]);
98
+ return [...new Set(values.flatMap(evaluationSourceTokens))].sort(canonicalCompare);
99
+ };
100
+ const positiveQueryFacets = (dimensions) => dimensions.flatMap((dimension) => {
101
+ const includes = dimension.includes
102
+ .map((value, index) => ({
103
+ label: `${dimension.id} include ${String(index + 1)}`,
104
+ terms: [...new Set(evaluationSourceTokens(value))].sort(canonicalCompare)
105
+ }))
106
+ .filter((facet) => facet.terms.length > 0);
107
+ return includes.length > 0
108
+ ? includes
109
+ : [
110
+ {
111
+ label: dimension.id,
112
+ terms: [
113
+ ...new Set(evaluationSourceTokens(`${dimension.id} ${dimension.description}`))
114
+ ].sort(canonicalCompare)
115
+ }
116
+ ];
117
+ });
118
+ const ownershipRoot = (path) => {
119
+ const segments = path.split("/");
120
+ const first = segments[0] ?? path;
121
+ if (["apps", "packages", "services", "tooling"].includes(first) &&
122
+ segments[1] !== undefined) {
123
+ return `${first}/${segments[1]}`;
124
+ }
125
+ return first;
126
+ };
127
+ const retrievalScope = (path) => {
128
+ const segments = path.split("/");
129
+ if (["apps", "packages", "services", "tooling"].includes(segments[0] ?? "") &&
130
+ segments[1] !== undefined &&
131
+ segments[2] === "src" &&
132
+ segments[3] !== undefined) {
133
+ return segments.slice(0, 4).join("/");
134
+ }
135
+ return undefined;
136
+ };
137
+ const frequencies = (tokens) => {
138
+ const values = new Map();
139
+ for (const token of tokens) {
140
+ values.set(token, (values.get(token) ?? 0) + 1);
141
+ }
142
+ return values;
143
+ };
144
+ const bm25 = (input) => {
145
+ if (input.termFrequency === 0)
146
+ return 0;
147
+ const k1 = 1.2;
148
+ const b = 0.75;
149
+ const normalizedLength = input.averageLength <= 0 ? 1 : input.length / input.averageLength;
150
+ return ((input.termFrequency * (k1 + 1)) /
151
+ (input.termFrequency + k1 * (1 - b + b * normalizedLength)));
152
+ };
153
+ const pathRanks = (candidates, queryTerms) => {
154
+ const tokenized = candidates.map((candidate) => ({
155
+ candidate,
156
+ tokens: evaluationSourceTokens(candidate.path)
157
+ }));
158
+ const averageLength = tokenized.reduce((total, item) => total + item.tokens.length, 0) /
159
+ Math.max(1, tokenized.length);
160
+ const documentFrequency = new Map(queryTerms.map((term) => [
161
+ term,
162
+ tokenized.filter((item) => item.tokens.includes(term)).length
163
+ ]));
164
+ return tokenized
165
+ .map(({ candidate, tokens }) => {
166
+ const counts = frequencies(tokens);
167
+ const matchedTerms = queryTerms.filter((term) => (counts.get(term) ?? 0) > 0);
168
+ const score = matchedTerms.reduce((total, term) => {
169
+ const frequency = documentFrequency.get(term) ?? 0;
170
+ const inverseDocumentFrequency = Math.log(1 +
171
+ (tokenized.length - frequency + 0.5) /
172
+ (frequency + 0.5));
173
+ return (total +
174
+ inverseDocumentFrequency *
175
+ bm25({
176
+ termFrequency: counts.get(term) ?? 0,
177
+ length: tokens.length,
178
+ averageLength
179
+ }));
180
+ }, 0);
181
+ return { candidate, score, matchedTerms };
182
+ })
183
+ .sort((left, right) => right.score - left.score ||
184
+ canonicalCompare(left.candidate.path, right.candidate.path));
185
+ };
186
+ /**
187
+ * Produces a bounded content-index plan. Positive path matches identify likely
188
+ * ownership roots, then generic filenames inside those roots may compete by
189
+ * content. This avoids reading an unbounded repository or relying on inventory
190
+ * order.
191
+ */
192
+ export function planEvaluationSourceRetrieval(input) {
193
+ const maximumFiles = input.maximumFiles ?? EVAL_SOURCE_RETRIEVAL_INDEX_FILES;
194
+ const maximumBytes = input.maximumBytes ?? EVAL_SOURCE_RETRIEVAL_INDEX_BYTES;
195
+ const queryTerms = positiveQueryTerms(input);
196
+ const ranked = pathRanks(input.candidates, queryTerms);
197
+ const eligible = ranked.filter((item) => item.candidate.sizeBytes <= EVAL_SOURCE_RETRIEVAL_FILE_BYTES);
198
+ const eligibleBytes = eligible.reduce((total, item) => total + item.candidate.sizeBytes, 0);
199
+ if (eligible.length <= maximumFiles &&
200
+ eligibleBytes <= maximumBytes) {
201
+ const scopeScores = new Map();
202
+ for (const item of eligible) {
203
+ const scope = retrievalScope(item.candidate.path);
204
+ if (scope !== undefined) {
205
+ scopeScores.set(scope, Math.max(scopeScores.get(scope) ?? 0, item.score));
206
+ }
207
+ }
208
+ return eligible
209
+ .map((item) => {
210
+ const scope = retrievalScope(item.candidate.path);
211
+ return {
212
+ ...item.candidate,
213
+ pathScore: item.score +
214
+ (scope === undefined ? 0 : scopeScores.get(scope) ?? 0)
215
+ };
216
+ })
217
+ .sort((left, right) => canonicalCompare(left.path, right.path));
218
+ }
219
+ const positivePathMatches = ranked.filter((item) => item.score > 0);
220
+ const scopeScores = new Map();
221
+ for (const item of positivePathMatches) {
222
+ const scope = retrievalScope(item.candidate.path);
223
+ if (scope !== undefined) {
224
+ scopeScores.set(scope, Math.max(scopeScores.get(scope) ?? 0, item.score));
225
+ }
226
+ }
227
+ const explicit = ranked.filter((item) => item.candidate.explicitReason !== undefined);
228
+ const implicatedRoots = new Set(positivePathMatches
229
+ .slice(0, 32)
230
+ .map((item) => ownershipRoot(item.candidate.path)));
231
+ const retrieved = positivePathMatches.length === 0
232
+ ? ranked
233
+ : ranked.filter((item) => item.score > 0 ||
234
+ implicatedRoots.has(ownershipRoot(item.candidate.path)));
235
+ const planned = [
236
+ ...explicit,
237
+ ...retrieved.filter((item) => item.candidate.explicitReason === undefined)
238
+ ];
239
+ const selected = [];
240
+ let bytes = 0;
241
+ for (const item of planned) {
242
+ if (selected.length >= maximumFiles)
243
+ break;
244
+ if (item.candidate.sizeBytes > EVAL_SOURCE_RETRIEVAL_FILE_BYTES) {
245
+ continue;
246
+ }
247
+ if (bytes + item.candidate.sizeBytes > maximumBytes)
248
+ continue;
249
+ const scope = retrievalScope(item.candidate.path);
250
+ selected.push({
251
+ ...item.candidate,
252
+ pathScore: item.score +
253
+ (scope === undefined ? 0 : scopeScores.get(scope) ?? 0)
254
+ });
255
+ bytes += item.candidate.sizeBytes;
256
+ }
257
+ return selected.sort((left, right) => canonicalCompare(left.path, right.path));
258
+ }
259
+ const scoreDocuments = (documents, queryTerms) => {
260
+ const prepared = documents.map((document) => ({
261
+ document,
262
+ pathTokens: evaluationSourceTokens(document.path),
263
+ contentTokens: evaluationSourceTokens(document.content)
264
+ }));
265
+ const averagePathLength = prepared.reduce((total, item) => total + item.pathTokens.length, 0) /
266
+ Math.max(1, prepared.length);
267
+ const averageContentLength = prepared.reduce((total, item) => total + item.contentTokens.length, 0) /
268
+ Math.max(1, prepared.length);
269
+ const documentFrequency = new Map(queryTerms.map((term) => [
270
+ term,
271
+ prepared.filter((item) => item.pathTokens.includes(term) ||
272
+ item.contentTokens.includes(term)).length
273
+ ]));
274
+ return prepared
275
+ .map(({ document, pathTokens, contentTokens }) => {
276
+ const pathCounts = frequencies(pathTokens);
277
+ const contentCounts = frequencies(contentTokens);
278
+ const pathMatches = queryTerms.filter((term) => (pathCounts.get(term) ?? 0) > 0);
279
+ const contentMatches = queryTerms.filter((term) => (contentCounts.get(term) ?? 0) > 0);
280
+ const score = queryTerms.reduce((total, term) => {
281
+ const frequency = documentFrequency.get(term) ?? 0;
282
+ const inverseDocumentFrequency = Math.log(1 +
283
+ (prepared.length - frequency + 0.5) /
284
+ (frequency + 0.5));
285
+ return (total +
286
+ inverseDocumentFrequency *
287
+ (3 *
288
+ bm25({
289
+ termFrequency: pathCounts.get(term) ?? 0,
290
+ length: pathTokens.length,
291
+ averageLength: averagePathLength
292
+ }) +
293
+ bm25({
294
+ termFrequency: contentCounts.get(term) ?? 0,
295
+ length: contentTokens.length,
296
+ averageLength: averageContentLength
297
+ })));
298
+ }, 0);
299
+ return {
300
+ document,
301
+ score: score +
302
+ (document.explicitReason === undefined ? 0 : 1_000_000),
303
+ pathMatches,
304
+ contentMatches
305
+ };
306
+ })
307
+ .sort((left, right) => right.score - left.score ||
308
+ canonicalCompare(left.document.path, right.document.path));
309
+ };
310
+ export function selectEvaluationSourcePacket(input) {
311
+ const queryTerms = positiveQueryTerms(input);
312
+ const ranked = scoreDocuments(input.documents, queryTerms);
313
+ const hasPositiveMatch = ranked.some((item) => item.pathMatches.length > 0 ||
314
+ item.contentMatches.length > 0);
315
+ const candidates = hasPositiveMatch
316
+ ? ranked.filter((item) => item.document.explicitReason !== undefined ||
317
+ item.pathMatches.length > 0 ||
318
+ item.contentMatches.length > 0)
319
+ : ranked;
320
+ const selected = [];
321
+ let bytes = 0;
322
+ for (const [rankIndex, item] of candidates.entries()) {
323
+ if (selected.length >= input.maximumFiles)
324
+ break;
325
+ if (bytes + item.document.sizeBytes > input.maximumBytes)
326
+ continue;
327
+ const terms = [
328
+ ...new Set([...item.pathMatches, ...item.contentMatches])
329
+ ].sort(canonicalCompare);
330
+ selected.push({
331
+ ...item.document,
332
+ inclusionReason: item.document.explicitReason === undefined
333
+ ? terms.length === 0
334
+ ? "bounded fallback source; no positive query term matched"
335
+ : [
336
+ `sparse retrieval rank ${String(rankIndex + 1)} in ${ownershipRoot(item.document.path)}`,
337
+ `matched positive terms: ${terms.join(", ")}`,
338
+ `fields: ${item.pathMatches.length > 0 &&
339
+ item.contentMatches.length > 0
340
+ ? "path+content"
341
+ : item.pathMatches.length > 0
342
+ ? "path"
343
+ : "content"}`
344
+ ].join("; ")
345
+ : `explicit inclusion: ${item.document.explicitReason}`
346
+ });
347
+ bytes += item.document.sizeBytes;
348
+ }
349
+ return selected.sort((left, right) => canonicalCompare(left.path, right.path));
350
+ }
351
+ const rankEvidenceBlocks = (documents, queryTerms) => {
352
+ const prepared = documents.flatMap((document) => {
353
+ const pathTokens = evaluationSourceTokens(document.path);
354
+ return document.evidenceSource.blocks.map((block) => ({
355
+ document,
356
+ block,
357
+ pathTokens,
358
+ contentTokens: evaluationSourceTokens(block.text)
359
+ }));
360
+ });
361
+ const averagePathLength = prepared.reduce((total, item) => total + item.pathTokens.length, 0) /
362
+ Math.max(1, prepared.length);
363
+ const averageContentLength = prepared.reduce((total, item) => total + item.contentTokens.length, 0) /
364
+ Math.max(1, prepared.length);
365
+ const documentFrequency = new Map(queryTerms.map((term) => [
366
+ term,
367
+ prepared.filter((item) => item.pathTokens.includes(term) ||
368
+ item.contentTokens.includes(term)).length
369
+ ]));
370
+ return prepared
371
+ .map(({ document, block, pathTokens, contentTokens }) => {
372
+ const pathCounts = frequencies(pathTokens);
373
+ const contentCounts = frequencies(contentTokens);
374
+ const pathMatches = queryTerms.filter((term) => (pathCounts.get(term) ?? 0) > 0);
375
+ const contentMatches = queryTerms.filter((term) => (contentCounts.get(term) ?? 0) > 0);
376
+ const score = queryTerms.reduce((total, term) => {
377
+ const frequency = documentFrequency.get(term) ?? 0;
378
+ const inverseDocumentFrequency = Math.log(1 +
379
+ (prepared.length - frequency + 0.5) /
380
+ (frequency + 0.5));
381
+ return (total +
382
+ inverseDocumentFrequency *
383
+ (3 *
384
+ bm25({
385
+ termFrequency: pathCounts.get(term) ?? 0,
386
+ length: pathTokens.length,
387
+ averageLength: averagePathLength
388
+ }) +
389
+ bm25({
390
+ termFrequency: contentCounts.get(term) ?? 0,
391
+ length: contentTokens.length,
392
+ averageLength: averageContentLength
393
+ })));
394
+ }, 0);
395
+ return {
396
+ document,
397
+ block,
398
+ score: score +
399
+ (document.pathScore ?? 0) +
400
+ (document.explicitReason === undefined ? 0 : 1_000_000),
401
+ matchedTermCount: new Set([
402
+ ...pathMatches,
403
+ ...contentMatches
404
+ ]).size,
405
+ pathMatches,
406
+ contentMatches
407
+ };
408
+ })
409
+ .sort((left, right) => Number(right.document.explicitReason !== undefined) -
410
+ Number(left.document.explicitReason !== undefined) ||
411
+ right.score - left.score ||
412
+ right.matchedTermCount - left.matchedTermCount ||
413
+ canonicalCompare(left.document.path, right.document.path) ||
414
+ left.block.ordinal - right.block.ordinal);
415
+ };
416
+ /**
417
+ * Selects compiler-owned evidence blocks rather than whole files. Packet
418
+ * assembly proceeds in per-source rounds so one large source cannot consume
419
+ * the complete authoring budget before complementary owners can compete.
420
+ */
421
+ export function selectEvaluationEvidencePacket(input) {
422
+ const maximumBlocks = input.maximumBlocks ?? EVAL_SOURCE_RETRIEVAL_PACKET_BLOCKS;
423
+ const maximumBlocksPerSource = input.maximumBlocksPerSource ??
424
+ EVAL_SOURCE_RETRIEVAL_BLOCKS_PER_SOURCE;
425
+ const facets = positiveQueryFacets(input.targetDimensions).map((facet) => {
426
+ const ranked = rankEvidenceBlocks(input.documents, facet.terms);
427
+ const positive = ranked.filter((item) => item.document.explicitReason !== undefined ||
428
+ item.pathMatches.length > 0 ||
429
+ item.contentMatches.length > 0);
430
+ return {
431
+ ...facet,
432
+ candidates: positive.length > 0 ? positive : ranked
433
+ };
434
+ });
435
+ const selected = [];
436
+ const selectedIds = new Set();
437
+ let selectedBytes = 0;
438
+ const admit = (facet, predicate) => {
439
+ const item = facet.candidates.find((candidate) => {
440
+ if (selectedIds.has(candidate.block.id) || !predicate(candidate)) {
441
+ return false;
442
+ }
443
+ const sourceCount = selected.filter((selectedItem) => selectedItem.document.path === candidate.document.path).length;
444
+ if (sourceCount >= maximumBlocksPerSource)
445
+ return false;
446
+ const blockBytes = Buffer.byteLength(candidate.block.text, "utf8");
447
+ return selectedBytes + blockBytes <= input.maximumBytes;
448
+ });
449
+ if (item === undefined)
450
+ return false;
451
+ selected.push({ ...item, facetLabel: facet.label });
452
+ selectedIds.add(item.block.id);
453
+ selectedBytes += Buffer.byteLength(item.block.text, "utf8");
454
+ return true;
455
+ };
456
+ for (const facet of facets) {
457
+ if (selected.length >= maximumBlocks)
458
+ break;
459
+ admit(facet, (candidate) => (candidate.document.sourceClass === "implementation" ||
460
+ candidate.document.sourceClass === "protocol") &&
461
+ !selected.some((selectedItem) => selectedItem.document.path === candidate.document.path));
462
+ }
463
+ while (selected.length < maximumBlocks) {
464
+ let admitted = false;
465
+ for (const facet of facets) {
466
+ if (selected.length >= maximumBlocks)
467
+ break;
468
+ admitted = admit(facet, () => true) || admitted;
469
+ }
470
+ if (!admitted)
471
+ break;
472
+ }
473
+ const grouped = new Map();
474
+ for (const item of selected) {
475
+ const values = grouped.get(item.document.path) ?? [];
476
+ values.push(item);
477
+ grouped.set(item.document.path, values);
478
+ }
479
+ return [...grouped.entries()]
480
+ .map(([path, items]) => {
481
+ const first = items[0];
482
+ const blocks = items
483
+ .map((item) => item.block)
484
+ .sort((left, right) => left.ordinal - right.ordinal);
485
+ const terms = [
486
+ ...new Set(items.flatMap((item) => [
487
+ ...item.pathMatches,
488
+ ...item.contentMatches
489
+ ]))
490
+ ].sort(canonicalCompare);
491
+ const facets = [
492
+ ...new Set(items.map((item) => item.facetLabel))
493
+ ].sort(canonicalCompare);
494
+ return {
495
+ source: {
496
+ path,
497
+ sizeBytes: first.document.sizeBytes,
498
+ sourceClass: first.document.sourceClass,
499
+ ...(first.document.explicitReason === undefined
500
+ ? {}
501
+ : { explicitReason: first.document.explicitReason })
502
+ },
503
+ blocks,
504
+ sizeBytes: blocks.reduce((total, block) => total + Buffer.byteLength(block.text, "utf8"), 0),
505
+ inclusionReason: first.document.explicitReason === undefined
506
+ ? terms.length === 0
507
+ ? `bounded block fallback in ${ownershipRoot(path)}`
508
+ : `compiler-block retrieval in ${ownershipRoot(path)}; facets: ${facets.join(", ")}; matched positive terms: ${terms.join(", ")}`
509
+ : `explicit inclusion: ${first.document.explicitReason}`
510
+ };
511
+ })
512
+ .sort((left, right) => canonicalCompare(left.source.path, right.source.path));
513
+ }
@@ -0,0 +1,29 @@
1
+ import type { EvalCriterion, EvalDimensionCase, EvalEvaluationProposal, EvalNegativeControl, EvalPositiveControl } from "./project-contracts.js";
2
+ export declare const EVAL_STRUCTURE_POLICY_VERSION: 1;
3
+ export type EvalCandidateCaseProjection = {
4
+ readonly id: string;
5
+ readonly prompt: string;
6
+ readonly context: string;
7
+ };
8
+ export type EvalHiddenOracleProjection = {
9
+ readonly id: string;
10
+ readonly rubric: string;
11
+ readonly criteria: readonly EvalCriterion[];
12
+ readonly positiveControls: readonly EvalPositiveControl[];
13
+ readonly negativeControls: readonly EvalNegativeControl[];
14
+ };
15
+ export type EvalStructureReport = {
16
+ readonly policyVersion: typeof EVAL_STRUCTURE_POLICY_VERSION;
17
+ readonly evidenceSourceCount: number;
18
+ readonly evidenceBlockCount: number;
19
+ readonly caseCount: number;
20
+ readonly duplicateEvidenceSelectionGroups: readonly (readonly string[])[];
21
+ };
22
+ export declare const renderEvaluationCriteria: (criteria: readonly EvalCriterion[]) => string;
23
+ export declare function candidateCaseProjection(testCase: EvalDimensionCase): EvalCandidateCaseProjection;
24
+ export declare function hiddenOracleProjection(testCase: EvalDimensionCase): EvalHiddenOracleProjection;
25
+ export declare function assertEvaluationStructure(input: {
26
+ readonly proposal: EvalEvaluationProposal;
27
+ readonly sourceInventory: readonly string[];
28
+ }): EvalStructureReport;
29
+ export declare function evaluationStructureReportDigest(report: EvalStructureReport): string;
@@ -0,0 +1,138 @@
1
+ import { createHash } from "node:crypto";
2
+ import { assertEvaluationEvidenceSources, renderEvaluationEvidenceContext, resolveEvaluationEvidence } from "./evaluation-evidence.js";
3
+ import { EVAL_AUTHORING_CASE_EVIDENCE_BYTES, EVAL_AUTHORING_EVIDENCE_BLOCK_BYTES } from "./evaluation-authoring-policy.js";
4
+ export const EVAL_STRUCTURE_POLICY_VERSION = 1;
5
+ const sha256 = (value) => createHash("sha256").update(value).digest("hex");
6
+ const uniqueIds = (values, label) => {
7
+ if (new Set(values.map((value) => value.id)).size !== values.length) {
8
+ throw new Error(`${label} ids must be unique`);
9
+ }
10
+ };
11
+ export const renderEvaluationCriteria = (criteria) => criteria
12
+ .map((criterion) => `${criterion.importance === "critical" ? "Critical" : "Supporting"} criterion ${criterion.id}: ${criterion.description}`)
13
+ .join("\n");
14
+ const compiledCaseFields = (testCase) => {
15
+ if (testCase.context === undefined ||
16
+ testCase.evidenceIds === undefined ||
17
+ testCase.criteria === undefined ||
18
+ testCase.positiveControls === undefined ||
19
+ testCase.negativeControls === undefined) {
20
+ throw new Error(`evaluation case ${JSON.stringify(testCase.id)} is not compiler-backed`);
21
+ }
22
+ return {
23
+ context: testCase.context,
24
+ evidenceIds: testCase.evidenceIds,
25
+ criteria: testCase.criteria,
26
+ positiveControls: testCase.positiveControls,
27
+ negativeControls: testCase.negativeControls
28
+ };
29
+ };
30
+ const assertControls = (caseId, criteria, positiveControls, negativeControls) => {
31
+ if (criteria.length === 0 || !criteria.some((criterion) => criterion.importance === "critical")) {
32
+ throw new Error(`evaluation case ${JSON.stringify(caseId)} requires a critical criterion`);
33
+ }
34
+ uniqueIds(criteria, `evaluation case ${JSON.stringify(caseId)} criterion`);
35
+ if (positiveControls.length === 0) {
36
+ throw new Error(`evaluation case ${JSON.stringify(caseId)} requires a positive control`);
37
+ }
38
+ uniqueIds(positiveControls, `evaluation case ${JSON.stringify(caseId)} positive control`);
39
+ uniqueIds(negativeControls, `evaluation case ${JSON.stringify(caseId)} negative control`);
40
+ const criterionIds = new Set(criteria.map((criterion) => criterion.id));
41
+ for (const negative of negativeControls) {
42
+ if (negative.targetedCriterionIds.length === 0 ||
43
+ new Set(negative.targetedCriterionIds).size !==
44
+ negative.targetedCriterionIds.length ||
45
+ negative.targetedCriterionIds.some((criterionId) => !criterionIds.has(criterionId))) {
46
+ throw new Error(`evaluation case ${JSON.stringify(caseId)} has an invalid negative-control target`);
47
+ }
48
+ }
49
+ for (const kind of [
50
+ "missing-criterion",
51
+ "forbidden-behavior",
52
+ "non-responsive"
53
+ ]) {
54
+ if (!negativeControls.some((control) => control.kind === kind)) {
55
+ throw new Error(`evaluation case ${JSON.stringify(caseId)} requires a ${kind} negative control`);
56
+ }
57
+ }
58
+ };
59
+ export function candidateCaseProjection(testCase) {
60
+ const fields = compiledCaseFields(testCase);
61
+ return {
62
+ id: testCase.id,
63
+ prompt: testCase.prompt,
64
+ context: fields.context
65
+ };
66
+ }
67
+ export function hiddenOracleProjection(testCase) {
68
+ const fields = compiledCaseFields(testCase);
69
+ return {
70
+ id: testCase.id,
71
+ rubric: testCase.rubric,
72
+ criteria: fields.criteria,
73
+ positiveControls: fields.positiveControls,
74
+ negativeControls: fields.negativeControls
75
+ };
76
+ }
77
+ export function assertEvaluationStructure(input) {
78
+ const { proposal } = input;
79
+ const evidenceSources = proposal.evidenceSources;
80
+ if (evidenceSources === undefined || evidenceSources.length === 0) {
81
+ throw new Error("evaluation proposal has no compiler-owned evidence sources");
82
+ }
83
+ assertEvaluationEvidenceSources(evidenceSources);
84
+ const inventory = new Set(input.sourceInventory);
85
+ for (const source of evidenceSources) {
86
+ if (!inventory.has(source.path)) {
87
+ throw new Error(`evaluation evidence source is outside the project inventory: ${JSON.stringify(source.path)}`);
88
+ }
89
+ for (const block of source.blocks) {
90
+ if (Buffer.byteLength(block.text, "utf8") > EVAL_AUTHORING_EVIDENCE_BLOCK_BYTES) {
91
+ throw new Error(`evaluation evidence block exceeds policy bytes: ${JSON.stringify(block.id)}`);
92
+ }
93
+ }
94
+ }
95
+ const cases = [
96
+ ...proposal.suites.flatMap((suite) => suite.cases.map((testCase) => ({
97
+ identity: `${suite.dimensionId}/${testCase.id}`,
98
+ testCase
99
+ }))),
100
+ ...proposal.compositionSuite.cases.map((testCase) => ({
101
+ identity: `composition/${testCase.id}`,
102
+ testCase
103
+ }))
104
+ ];
105
+ const selectionCases = new Map();
106
+ for (const { identity, testCase } of cases) {
107
+ const fields = compiledCaseFields(testCase);
108
+ const selected = resolveEvaluationEvidence({
109
+ sources: evidenceSources,
110
+ evidenceIds: fields.evidenceIds,
111
+ maximumContextBytes: EVAL_AUTHORING_CASE_EVIDENCE_BYTES
112
+ });
113
+ if (fields.context !== renderEvaluationEvidenceContext(selected)) {
114
+ throw new Error(`evaluation case ${JSON.stringify(testCase.id)} context is not compiler-rendered`);
115
+ }
116
+ assertControls(testCase.id, fields.criteria, fields.positiveControls, fields.negativeControls);
117
+ if (testCase.rubric !== renderEvaluationCriteria(fields.criteria)) {
118
+ throw new Error(`evaluation case ${JSON.stringify(testCase.id)} rubric is not compiler-rendered`);
119
+ }
120
+ const fingerprint = fields.evidenceIds.join("\u0000");
121
+ const matching = selectionCases.get(fingerprint) ?? [];
122
+ matching.push(identity);
123
+ selectionCases.set(fingerprint, matching);
124
+ }
125
+ return {
126
+ policyVersion: EVAL_STRUCTURE_POLICY_VERSION,
127
+ evidenceSourceCount: evidenceSources.length,
128
+ evidenceBlockCount: evidenceSources.reduce((count, source) => count + source.blocks.length, 0),
129
+ caseCount: cases.length,
130
+ duplicateEvidenceSelectionGroups: [...selectionCases.values()]
131
+ .filter((caseIds) => caseIds.length > 1)
132
+ .map((caseIds) => [...caseIds].sort((left, right) => left < right ? -1 : left > right ? 1 : 0))
133
+ .sort((left, right) => left[0] < right[0] ? -1 : left[0] > right[0] ? 1 : 0)
134
+ };
135
+ }
136
+ export function evaluationStructureReportDigest(report) {
137
+ return sha256(JSON.stringify(report));
138
+ }