@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,228 @@
1
+ import assert from "node:assert/strict";
2
+ import { test } from "node:test";
3
+ import { parseRepositorySpecificationContractFactsProposalV1, repositorySpecificationContractFactsPacketV1, repositorySpecificationContractFactsScopeV1 } from "../repository-specification-contract-facts-protocol.js";
4
+ import { assertRepositorySpecificationContractFactsEvidenceV1 } from "../services/case-generation/service.js";
5
+ // Pure saved-evidence boundary fixture. The packet compiler is real; the model
6
+ // calls and judgments are synthetic and confer no semantic or admission proof.
7
+ const acceptedEvidence = () => {
8
+ const evidence = [{ sourceId: "after-fixture", startLine: 1, endLine: 1 }];
9
+ const frozenScope = {
10
+ clauses: [{
11
+ id: "lower-bound",
12
+ kind: "changed",
13
+ behaviorIds: ["clamp-range"],
14
+ description: "Preserve the numeric range and repair its lower boundary.",
15
+ evidence
16
+ }],
17
+ unresolvedQuestions: []
18
+ };
19
+ const proposal = parseRepositorySpecificationContractFactsProposalV1({
20
+ version: 1,
21
+ facts: [{
22
+ id: "negative-input",
23
+ scopeId: "lower-bound",
24
+ kind: "behavior",
25
+ statement: "Numeric values below zero produce zero.",
26
+ evidence
27
+ }]
28
+ });
29
+ const scope = repositorySpecificationContractFactsScopeV1(frozenScope, proposal);
30
+ const packet = repositorySpecificationContractFactsPacketV1(scope, proposal);
31
+ const visible = {
32
+ lane: "repository-agent",
33
+ id: "synthetic-fact-case",
34
+ requestText: scope.clauses[0].description,
35
+ checkoutCommit: "before-fixture",
36
+ allowedTools: ["read", "edit", "test"],
37
+ constraints: ["Preserve unrelated behavior."]
38
+ };
39
+ const reviewerOperationIds = [
40
+ "synthetic-facts:specification-critic-a",
41
+ "synthetic-facts:specification-critic-b"
42
+ ];
43
+ const reviews = reviewerOperationIds.map((reviewerId, index) => ({
44
+ reviewerId,
45
+ reviewerKind: index === 0 ? "independent-solver" : "model-critic",
46
+ independentlyProduced: true,
47
+ verdict: "sufficient",
48
+ detail: "Synthetic complete review of the exact saved packet.",
49
+ findings: [],
50
+ contractFactReview: {
51
+ packetDigest: packet.digest,
52
+ scopeChecks: [{
53
+ scopeId: "lower-bound",
54
+ factIds: ["negative-input"],
55
+ outcome: "complete",
56
+ detail: "The supplied numeric boundary is explicit.",
57
+ evidence: index === 0 ? [] : evidence
58
+ }],
59
+ clarificationRequests: []
60
+ }
61
+ }));
62
+ return {
63
+ version: 1,
64
+ caseId: visible.id,
65
+ analysis: {
66
+ summary: "Synthetic lower-bound scope.",
67
+ userObservableBehaviors: ["Negative values produce zero."],
68
+ constraints: [],
69
+ risks: [],
70
+ relevantPaths: [],
71
+ referenceScope: frozenScope
72
+ },
73
+ contextSources: [],
74
+ visible,
75
+ reviews,
76
+ modelCalls: [
77
+ {
78
+ operationId: "synthetic-facts:repository-analyst",
79
+ role: "repository-analyst",
80
+ model: "offline/analyst",
81
+ reasoningEffort: "high"
82
+ },
83
+ {
84
+ operationId: "synthetic-facts:specification-writer",
85
+ role: "specification-writer",
86
+ model: "offline/writer",
87
+ reasoningEffort: "high"
88
+ },
89
+ ...reviewerOperationIds.map((operationId, index) => ({
90
+ operationId,
91
+ role: index === 0 ? "specification-critic-a" : "specification-critic-b",
92
+ model: `offline/critic-${index}`,
93
+ reasoningEffort: "high"
94
+ }))
95
+ ],
96
+ contractFacts: {
97
+ version: 1,
98
+ packet,
99
+ independentlyReviewed: true,
100
+ reviewerOperationIds,
101
+ history: [{
102
+ sequence: 0,
103
+ packetDigest: packet.digest,
104
+ analystOperationId: "synthetic-facts:repository-analyst",
105
+ clarificationRequestIds: []
106
+ }]
107
+ },
108
+ referenceGrounding: {
109
+ beforeCommit: "before-fixture",
110
+ referenceCommit: "after-fixture",
111
+ sources: [],
112
+ scope
113
+ },
114
+ groundedTargetBehavior: [{
115
+ id: "clamp-range",
116
+ description: scope.clauses[0].description,
117
+ critical: true,
118
+ evidence: []
119
+ }],
120
+ specificationRevisions: [{
121
+ sequence: 0,
122
+ visible,
123
+ reviews,
124
+ rejectionReasons: [],
125
+ contractFactsDigest: packet.digest
126
+ }]
127
+ };
128
+ };
129
+ const withFinalReviews = (authored, reviews) => ({
130
+ ...authored,
131
+ reviews,
132
+ specificationRevisions: [{
133
+ ...authored.specificationRevisions[0],
134
+ reviews
135
+ }]
136
+ });
137
+ test("saved contract facts bind the final rendered scope and both actual independent reviews", () => {
138
+ const authored = acceptedEvidence();
139
+ assertRepositorySpecificationContractFactsEvidenceV1(authored);
140
+ const detached = JSON.parse(JSON.stringify(authored));
141
+ assertRepositorySpecificationContractFactsEvidenceV1(detached);
142
+ assert.deepEqual(detached, authored, "validation does not rewrite archived evidence");
143
+ assert.notEqual(authored.analysis.referenceScope?.clauses[0]?.description, authored.referenceGrounding?.scope.clauses[0]?.description, "the packet is bound to the final rendered scope, not the analyst's original description");
144
+ });
145
+ test("a saved accepted flag cannot replace missing or stale final packet/reviewer evidence", () => {
146
+ const authored = acceptedEvidence();
147
+ const accepted = authored.contractFacts;
148
+ for (const invalid of [
149
+ { ...authored, contractFacts: undefined },
150
+ { ...authored, specificationRevisions: undefined },
151
+ {
152
+ ...authored,
153
+ specificationRevisions: [{
154
+ ...authored.specificationRevisions[0],
155
+ contractFactsDigest: "0".repeat(64)
156
+ }]
157
+ },
158
+ { ...authored, referenceGrounding: undefined },
159
+ { ...authored, modelCalls: authored.modelCalls.filter((call) => call.role !== "specification-critic-b") },
160
+ { ...authored, visible: { ...authored.visible, requestText: "A different final request." } },
161
+ {
162
+ ...authored,
163
+ contractFacts: {
164
+ ...accepted,
165
+ reviewerOperationIds: [accepted.reviewerOperationIds[0], accepted.reviewerOperationIds[0]]
166
+ }
167
+ },
168
+ {
169
+ ...authored,
170
+ contractFacts: {
171
+ ...accepted,
172
+ reviewerOperationIds: ["synthetic-replacement:specification-critic-a", accepted.reviewerOperationIds[1]]
173
+ }
174
+ },
175
+ {
176
+ ...authored,
177
+ contractFacts: { ...accepted, packet: { ...accepted.packet, digest: "0".repeat(64) } }
178
+ },
179
+ {
180
+ ...authored,
181
+ referenceGrounding: {
182
+ ...authored.referenceGrounding,
183
+ scope: authored.analysis.referenceScope
184
+ }
185
+ }
186
+ ]) {
187
+ assert.throws(() => assertRepositorySpecificationContractFactsEvidenceV1(invalid));
188
+ }
189
+ });
190
+ test("matching archived review copies must still approve this complete packet without pending questions", () => {
191
+ const authored = acceptedEvidence();
192
+ for (const first of [
193
+ { ...authored.reviews[0], independentlyProduced: false },
194
+ { ...authored.reviews[0], verdict: "insufficient" },
195
+ {
196
+ ...authored.reviews[0],
197
+ contractFactReview: { ...authored.reviews[0].contractFactReview, packetDigest: "0".repeat(64) }
198
+ },
199
+ {
200
+ ...authored.reviews[0],
201
+ contractFactReview: { ...authored.reviews[0].contractFactReview, scopeChecks: [] }
202
+ },
203
+ {
204
+ ...authored.reviews[0],
205
+ contractFactReview: {
206
+ ...authored.reviews[0].contractFactReview,
207
+ scopeChecks: [{
208
+ ...authored.reviews[0].contractFactReview.scopeChecks[0],
209
+ factIds: []
210
+ }]
211
+ }
212
+ },
213
+ {
214
+ ...authored.reviews[0],
215
+ contractFactReview: {
216
+ ...authored.reviews[0].contractFactReview,
217
+ clarificationRequests: [{
218
+ scopeId: "lower-bound",
219
+ factIds: ["negative-input"],
220
+ reason: "missing-boundary",
221
+ question: "Is the negative boundary complete?"
222
+ }]
223
+ }
224
+ }
225
+ ]) {
226
+ assert.throws(() => assertRepositorySpecificationContractFactsEvidenceV1(withFinalReviews(authored, [first, authored.reviews[1]])));
227
+ }
228
+ });
@@ -0,0 +1,177 @@
1
+ import assert from "node:assert/strict";
2
+ import { test } from "node:test";
3
+ import { Schema } from "effect";
4
+ import { parseRepositorySpecificationContractFactsPacketV1, parseRepositorySpecificationContractFactsProposalV1, renderRepositorySpecificationContractFactV1, RepositorySpecificationContractFactsProposalV1, repositorySpecificationContractFactsPacketV1, repositorySpecificationContractFactsScopeV1, repositorySpecificationPublicContractFactV1 } from "../repository-specification-contract-facts-protocol.js";
5
+ const references = [
6
+ { sourceId: "before-source", startLine: 1, endLine: 1 },
7
+ { sourceId: "after-source", startLine: 2, endLine: 3 }
8
+ ];
9
+ const scope = {
10
+ clauses: [
11
+ {
12
+ id: "response-policy",
13
+ kind: "changed",
14
+ behaviorIds: ["response-normalization"],
15
+ description: "Normalize eligible responses and preserve ineligible responses.",
16
+ evidence: references
17
+ }
18
+ ],
19
+ unresolvedQuestions: []
20
+ };
21
+ const raw = () => ({
22
+ version: 1,
23
+ facts: [
24
+ {
25
+ id: "response-types",
26
+ scopeId: "response-policy",
27
+ kind: "closed-set",
28
+ subject: "response types selected for normalization",
29
+ appliesWhen: "the request is non-streaming",
30
+ members: ["event-stream", "event-records"],
31
+ outsideBehavior: "Preserve the original response.",
32
+ evidence: references.map((entry) => ({ ...entry }))
33
+ }
34
+ ]
35
+ });
36
+ const prepared = () => {
37
+ const proposal = parseRepositorySpecificationContractFactsProposalV1(raw());
38
+ const finalScope = repositorySpecificationContractFactsScopeV1(scope, proposal);
39
+ const packet = repositorySpecificationContractFactsPacketV1(finalScope, proposal);
40
+ return { proposal, finalScope, packet };
41
+ };
42
+ test("marked fact schemas reject excess fields before a public projection can hide them", () => {
43
+ for (const value of [
44
+ { ...raw(), confidence: "approved" },
45
+ { ...raw(), facts: [{ ...raw().facts[0], privateSource: "not an allowed field" }] },
46
+ {
47
+ ...raw(),
48
+ facts: [
49
+ {
50
+ ...raw().facts[0],
51
+ evidence: [{ ...references[0], sourceText: "not an allowed field" }]
52
+ }
53
+ ]
54
+ }
55
+ ]) {
56
+ assert.throws(() => parseRepositorySpecificationContractFactsProposalV1(value));
57
+ // The schema itself is strict, including use by the language-model owner
58
+ // whose general decode call does not supply onExcessProperty explicitly.
59
+ assert.throws(() => Schema.decodeUnknownSync(RepositorySpecificationContractFactsProposalV1)(value));
60
+ }
61
+ });
62
+ test("public facts are positively projected and deterministically rendered without provenance", () => {
63
+ const { proposal, finalScope, packet } = prepared();
64
+ const privateFact = {
65
+ ...proposal.facts[0],
66
+ privateAnswer: "PRIVATE-DATA",
67
+ evidence: references
68
+ };
69
+ const projected = repositorySpecificationPublicContractFactV1(privateFact);
70
+ assert.deepEqual(projected, packet.facts[0]);
71
+ const publicText = JSON.stringify(packet);
72
+ for (const privateValue of ["PRIVATE-DATA", "before-source", "after-source", '"evidence"']) {
73
+ assert.equal(publicText.includes(privateValue), false);
74
+ }
75
+ const rendered = renderRepositorySpecificationContractFactV1(packet.facts[0]);
76
+ assert.ok(rendered.includes('"event-stream", "event-records"'));
77
+ assert.ok(rendered.includes("Outside this set: Preserve the original response."));
78
+ assert.ok(finalScope.clauses[0].description.includes(rendered));
79
+ assert.equal(scope.clauses[0].description.includes(rendered), false);
80
+ assert.deepEqual(finalScope.clauses[0].behaviorIds, scope.clauses[0].behaviorIds);
81
+ assert.deepEqual(finalScope.unresolvedQuestions, scope.unresolvedQuestions);
82
+ assert.ok(Object.isFrozen(packet));
83
+ assert.ok(Object.isFrozen(packet.facts));
84
+ assert.ok(Object.isFrozen(packet.facts[0]));
85
+ });
86
+ test("packet roundtrip binds final rendered scope, facts, and both digests", () => {
87
+ const { packet, finalScope } = prepared();
88
+ const loaded = parseRepositorySpecificationContractFactsPacketV1(JSON.parse(JSON.stringify(packet)), finalScope);
89
+ assert.deepEqual(loaded, packet);
90
+ assert.notEqual(loaded, packet);
91
+ assert.throws(() => parseRepositorySpecificationContractFactsPacketV1(packet, scope));
92
+ for (const changed of [
93
+ { ...packet, digest: "0".repeat(64) },
94
+ { ...packet, scopeDigest: "0".repeat(64) },
95
+ { ...packet, facts: [] },
96
+ { ...packet, privateEvidence: references },
97
+ {
98
+ ...packet,
99
+ facts: [{ ...packet.facts[0], outsideBehavior: "Discard all other responses." }]
100
+ }
101
+ ]) {
102
+ assert.throws(() => parseRepositorySpecificationContractFactsPacketV1(changed, finalScope));
103
+ }
104
+ assert.throws(() => parseRepositorySpecificationContractFactsPacketV1(packet, {
105
+ ...finalScope,
106
+ clauses: [{ ...finalScope.clauses[0], behaviorIds: ["another-behavior"] }]
107
+ }));
108
+ });
109
+ test("fact bounds refuse duplicates, partial closed sets, invalid evidence, and unknown scopes", () => {
110
+ const original = raw();
111
+ for (const facts of [
112
+ [],
113
+ [original.facts[0], original.facts[0]],
114
+ [{ ...original.facts[0], members: [] }],
115
+ [{ ...original.facts[0], members: ["same", "same"] }],
116
+ [{ ...original.facts[0], members: Array.from({ length: 129 }, (_, i) => `member-${String(i)}`) }],
117
+ [{ ...original.facts[0], outsideBehavior: "" }],
118
+ [{ ...original.facts[0], appliesWhen: "x".repeat(2_001) }],
119
+ [{ ...original.facts[0], evidence: [] }],
120
+ [{ ...original.facts[0], evidence: [{ ...references[0], startLine: 0 }] }],
121
+ [{ ...original.facts[0], evidence: [{ ...references[0], endLine: 0.5 }] }],
122
+ [{ ...original.facts[0], subject: "private-contract-fact-question-0-1" }]
123
+ ]) {
124
+ assert.throws(() => parseRepositorySpecificationContractFactsProposalV1({ version: 1, facts }));
125
+ }
126
+ const unknownScope = parseRepositorySpecificationContractFactsProposalV1({
127
+ version: 1,
128
+ facts: [{ ...original.facts[0], scopeId: "unrelated-scope" }]
129
+ });
130
+ assert.throws(() => repositorySpecificationContractFactsScopeV1(scope, unknownScope));
131
+ });
132
+ test("eligibility and behavior facts render both boundary outcomes without implementation syntax", () => {
133
+ const proposal = parseRepositorySpecificationContractFactsProposalV1({
134
+ version: 1,
135
+ facts: [
136
+ {
137
+ id: "eligibility",
138
+ scopeId: "response-policy",
139
+ kind: "eligibility",
140
+ condition: "the response is an event stream",
141
+ whenEligible: "Normalize its completed payload.",
142
+ whenIneligible: "Preserve the response body.",
143
+ evidence: references
144
+ },
145
+ {
146
+ id: "preservation",
147
+ scopeId: "response-policy",
148
+ kind: "behavior",
149
+ statement: "Preserve response status codes.",
150
+ evidence: references
151
+ }
152
+ ]
153
+ });
154
+ const rendered = proposal.facts
155
+ .map(repositorySpecificationPublicContractFactV1)
156
+ .map(renderRepositorySpecificationContractFactV1);
157
+ assert.ok(rendered[0].includes("When eligible: Normalize its completed payload."));
158
+ assert.ok(rendered[0].includes("When ineligible: Preserve the response body."));
159
+ assert.equal(rendered[1], "For this task: Preserve response status codes.");
160
+ });
161
+ test("oversize public contract packets fail without dropping or truncating facts", () => {
162
+ const proposal = parseRepositorySpecificationContractFactsProposalV1({
163
+ version: 1,
164
+ facts: Array.from({ length: 32 }, (_, index) => ({
165
+ id: `behavior-${String(index)}`,
166
+ scopeId: "response-policy",
167
+ kind: "behavior",
168
+ statement: "p".repeat(1_500),
169
+ evidence: references
170
+ }))
171
+ });
172
+ const finalScope = repositorySpecificationContractFactsScopeV1(scope, proposal);
173
+ assert.equal(proposal.facts.length, 32);
174
+ assert.throws(() => repositorySpecificationContractFactsPacketV1(finalScope, proposal), /32768 bytes/u);
175
+ assert.equal(proposal.facts.length, 32);
176
+ assert.equal(proposal.facts[31].kind, "behavior");
177
+ });
@@ -0,0 +1,176 @@
1
+ import assert from "node:assert/strict";
2
+ import { test } from "node:test";
3
+ import { Effect, Layer } from "effect";
4
+ import { EvalAuthoringTransport } from "../project-authoring.js";
5
+ import { gpt56RepositoryFoundryModelPlanV1 } from "../repository-language-model-protocol.js";
6
+ import { RepositoryFoundryLanguageModelLive } from "../services/language-model/service.js";
7
+ import { authorReviewedRepositoryTrajectoryPolicyV1 } from "../services/trajectory-policy/service.js";
8
+ const plan = () => gpt56RepositoryFoundryModelPlanV1({
9
+ primaryModel: "codex/gpt-5.6-sol",
10
+ criticAModel: "codex/gpt-5.6-terra",
11
+ criticBModel: "codex/gpt-5.6-luna",
12
+ reviewerModel: "codex/gpt-5.6-terra",
13
+ primaryReasoningEffort: "max",
14
+ reviewReasoningEffort: "max"
15
+ });
16
+ const proposal = (repaired) => ({
17
+ thresholds: {
18
+ maximumToolCalls: 28,
19
+ maximumFailedToolCalls: 6,
20
+ maximumRepeatedFailedActions: 2
21
+ },
22
+ rationale: repaired
23
+ ? "The numeric ceilings allow proportionate exploration and debugging; only compiler-owned requirements are normative."
24
+ : "The numeric ceilings allow debugging, but visible test changes must be legitimate and non-weakening."
25
+ });
26
+ const completion = (input, approveRepairSequence = 1) => {
27
+ const repairSequence = Number(input.operationId.match(/:repair-(\d+)$/u)?.[1] ?? "0");
28
+ if (input.foundryRole === "trajectory-designer") {
29
+ return proposal(repairSequence > 0);
30
+ }
31
+ if (input.foundryRole === "trajectory-critic") {
32
+ if (repairSequence < approveRepairSequence) {
33
+ return {
34
+ verdict: "reject",
35
+ detail: "The rationale introduces an unverifiable visible-test legitimacy rule.",
36
+ unverifiableRequirements: [
37
+ "Visible test changes must be legitimate and non-weakening."
38
+ ],
39
+ styleBiases: []
40
+ };
41
+ }
42
+ return {
43
+ verdict: "approve",
44
+ detail: "The replacement rationale only explains numeric headroom and every normative gate is mechanical.",
45
+ unverifiableRequirements: [],
46
+ styleBiases: []
47
+ };
48
+ }
49
+ throw new Error(`unexpected role ${String(input.foundryRole)}`);
50
+ };
51
+ const run = async (rejectRepair = false) => {
52
+ const calls = [];
53
+ const transport = Layer.succeed(EvalAuthoringTransport, EvalAuthoringTransport.of({
54
+ completeDetailed: (input) => {
55
+ calls.push(input);
56
+ return Effect.succeed({
57
+ text: JSON.stringify(completion(input, rejectRepair ? Number.POSITIVE_INFINITY : 1)),
58
+ callId: `call-${input.operationId}`
59
+ });
60
+ },
61
+ complete: (input) => Effect.succeed(JSON.stringify(completion(input, rejectRepair ? Number.POSITIVE_INFINITY : 1)))
62
+ }));
63
+ const effect = authorReviewedRepositoryTrajectoryPolicyV1({
64
+ operationId: "trajectory-case",
65
+ caseId: "case-gateway-stream",
66
+ visible: {
67
+ lane: "repository-agent",
68
+ id: "case-gateway-stream",
69
+ requestText: "Preserve terminal stream ordering without dropping usage.",
70
+ checkoutCommit: "a".repeat(40),
71
+ allowedTools: ["read", "search", "edit", "shell", "test"],
72
+ constraints: ["Preserve the external wire contract."]
73
+ },
74
+ targetBehavior: [
75
+ {
76
+ id: "terminal-order",
77
+ description: "Exactly one terminal event is emitted after all output and usage events.",
78
+ critical: true,
79
+ evidence: [{ kind: "test", id: "stream-test", path: "src/stream.test.ts" }]
80
+ }
81
+ ],
82
+ reviewedImplementationPathCount: 2,
83
+ validationRecipeIds: ["command-test-stream"],
84
+ protectedPaths: ["test/hidden-control.ts"],
85
+ reviewedCommands: [
86
+ {
87
+ id: "command-test-stream",
88
+ kind: "test",
89
+ timeoutMs: 30_000
90
+ }
91
+ ],
92
+ modelPlan: plan()
93
+ }).pipe(Effect.provide(RepositoryFoundryLanguageModelLive.pipe(Layer.provide(transport))));
94
+ return { calls, effect };
95
+ };
96
+ test("trajectory authoring repairs an unverifiable rationale and requires a fresh independent review", async () => {
97
+ const { calls, effect } = await run();
98
+ const result = await Effect.runPromise(effect);
99
+ assert.deepEqual(calls.map((call) => `${String(call.foundryRole)}:${call.operationId}`), [
100
+ "trajectory-designer:trajectory-case:trajectory-designer",
101
+ "trajectory-critic:trajectory-case:trajectory-critic",
102
+ "trajectory-designer:trajectory-case:trajectory-designer:repair-1",
103
+ "trajectory-critic:trajectory-case:trajectory-critic:repair-1"
104
+ ]);
105
+ assert.equal(result.review.verdict, "approve");
106
+ assert.equal(result.revisionAttempts.length, 1);
107
+ assert.equal(result.revisionAttempts[0]?.beforeReview.verdict, "reject");
108
+ assert.equal(result.revisionAttempts[0]?.candidateReview.verdict, "approve");
109
+ assert.equal(result.revisionAttempts[0]?.decision, "accepted");
110
+ assert.equal(result.modelCalls.length, 4);
111
+ assert.equal(result.policy.requirements.passingValidationAfterLastMutation, true);
112
+ assert.equal(result.policy.requirements.noProtectedPathMutations, true);
113
+ });
114
+ test("trajectory authoring fails closed when the repaired policy is still unverifiable", async () => {
115
+ const { calls, effect } = await run(true);
116
+ const exit = await Effect.runPromiseExit(effect);
117
+ assert.equal(exit._tag, "Failure");
118
+ assert.equal(calls.length, 6);
119
+ if (exit._tag === "Failure") {
120
+ assert.match(String(exit.cause), /trajectory policy failed validation/u);
121
+ assert.match(String(exit.cause), /unverifiable/u);
122
+ }
123
+ });
124
+ test("trajectory authoring uses a second independently reviewed repair when the first remains biased", async () => {
125
+ const calls = [];
126
+ const transport = Layer.succeed(EvalAuthoringTransport, EvalAuthoringTransport.of({
127
+ completeDetailed: (input) => {
128
+ calls.push(input);
129
+ return Effect.succeed({
130
+ text: JSON.stringify(completion(input, 2)),
131
+ callId: `call-${input.operationId}`
132
+ });
133
+ },
134
+ complete: (input) => {
135
+ calls.push(input);
136
+ return Effect.succeed(JSON.stringify(completion(input, 2)));
137
+ }
138
+ }));
139
+ const effect = authorReviewedRepositoryTrajectoryPolicyV1({
140
+ operationId: "trajectory-case",
141
+ caseId: "case-gateway-stream",
142
+ visible: {
143
+ lane: "repository-agent",
144
+ id: "case-gateway-stream",
145
+ requestText: "Preserve terminal stream ordering without dropping usage.",
146
+ checkoutCommit: "a".repeat(40),
147
+ allowedTools: ["read", "search", "edit", "shell", "test"],
148
+ constraints: ["Preserve the external wire contract."]
149
+ },
150
+ targetBehavior: [
151
+ {
152
+ id: "terminal-order",
153
+ description: "Exactly one terminal event is emitted after all output and usage events.",
154
+ critical: true,
155
+ evidence: [{ kind: "test", id: "stream-test", path: "src/stream.test.ts" }]
156
+ }
157
+ ],
158
+ reviewedImplementationPathCount: 2,
159
+ validationRecipeIds: ["command-test-stream"],
160
+ protectedPaths: ["test/hidden-control.ts"],
161
+ reviewedCommands: [
162
+ {
163
+ id: "command-test-stream",
164
+ kind: "test",
165
+ timeoutMs: 30_000
166
+ }
167
+ ],
168
+ modelPlan: plan()
169
+ }).pipe(Effect.provide(RepositoryFoundryLanguageModelLive.pipe(Layer.provide(transport))));
170
+ const result = await Effect.runPromise(effect);
171
+ assert.equal(result.review.verdict, "approve");
172
+ assert.equal(result.revisionAttempts.length, 2);
173
+ assert.equal(result.revisionAttempts[0]?.decision, "rejected");
174
+ assert.equal(result.revisionAttempts[1]?.decision, "accepted");
175
+ assert.equal(calls.length, 6);
176
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,45 @@
1
+ import assert from "node:assert/strict";
2
+ import { test } from "node:test";
3
+ import { assertRepositoryFoundryGenerationPlanV1, repositoryFoundryGenerationBudgetV1, repositoryFoundryGenerationPlanDigestV1 } from "../repository-foundry-plan-protocol.js";
4
+ import { repositoryFoundryModelPlanV1 } from "../repository-language-model-protocol.js";
5
+ test("valid-control review is pinned without changing legacy plans or the model-call budget", () => {
6
+ const unsignedPlan = (validControlReviewVersion) => ({
7
+ version: 1,
8
+ repository: { root: "/repo", requestedRef: "HEAD", commit: "commit", tree: "tree" },
9
+ caseId: "legacy-case",
10
+ ...(validControlReviewVersion === undefined ? {} : { validControlReviewVersion }),
11
+ seedId: "seed",
12
+ initialCommit: "initial",
13
+ referenceCommit: "reference",
14
+ modelPlan: repositoryFoundryModelPlanV1({ primaryModel: "codex/gpt-6-astra" }),
15
+ qualification: { batches: 2, repetitionsPerBatch: 2, oracleRepetitions: 2 },
16
+ budget: repositoryFoundryGenerationBudgetV1(2)
17
+ });
18
+ const unsigned = unsignedPlan();
19
+ const legacy = { ...unsigned, planDigest: repositoryFoundryGenerationPlanDigestV1(unsigned) };
20
+ assert.equal(legacy.planDigest, "357e58c2853e4379791e3d1c5b9475993a65c371684c8f6a6f4c69400f1d2994");
21
+ assertRepositoryFoundryGenerationPlanV1(legacy);
22
+ const reviewedUnsigned = unsignedPlan(1);
23
+ const reviewed = {
24
+ ...reviewedUnsigned,
25
+ planDigest: repositoryFoundryGenerationPlanDigestV1(reviewedUnsigned)
26
+ };
27
+ assertRepositoryFoundryGenerationPlanV1(reviewed);
28
+ assert.notEqual(reviewed.planDigest, legacy.planDigest);
29
+ assert.deepEqual(reviewed.budget, legacy.budget);
30
+ assert.throws(() => assertRepositoryFoundryGenerationPlanV1({ ...legacy, validControlReviewVersion: 1 }), /digest/u);
31
+ const { validControlReviewVersion: _version, ...stripped } = reviewed;
32
+ assert.throws(() => assertRepositoryFoundryGenerationPlanV1(stripped), /digest/u);
33
+ assert.throws(() => assertRepositoryFoundryGenerationPlanV1({ ...reviewed, validControlReviewVersion: 2 }));
34
+ const behavioralUnsigned = unsignedPlan(2);
35
+ const behavioral = {
36
+ ...behavioralUnsigned,
37
+ planDigest: repositoryFoundryGenerationPlanDigestV1(behavioralUnsigned)
38
+ };
39
+ assertRepositoryFoundryGenerationPlanV1(behavioral);
40
+ assert.notEqual(behavioral.planDigest, reviewed.planDigest);
41
+ assert.notEqual(behavioral.planDigest, legacy.planDigest);
42
+ assert.deepEqual(behavioral.budget, legacy.budget);
43
+ assert.throws(() => assertRepositoryFoundryGenerationPlanV1({ ...behavioral, validControlReviewVersion: 1 }));
44
+ assert.throws(() => assertRepositoryFoundryGenerationPlanV1({ ...behavioral, validControlReviewVersion: 3 }));
45
+ });
@@ -0,0 +1 @@
1
+ export {};