@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,619 @@
1
+ import { Clock, Effect, Option, Schema } from "effect";
2
+ import { captureGitTreeSnapshotV1, readGitTreeFileV1 } from "../../adapters/git-task-history.js";
3
+ import { checkpointDigestV1, PipelineStageError, pipelineStageToProgressStageV1 } from "../../case-pipeline-protocol.js";
4
+ import { RepositoryFoundryError } from "../../errors.js";
5
+ import { repositoryFoundryRoleOutputCeilingV1 } from "../../repository-foundry-plan-protocol.js";
6
+ import { repositoryFoundryModelAssignmentV1 } from "../../repository-language-model-protocol.js";
7
+ import { RepositorySpecificationBehaviorCoverageV1, RepositorySpecificationCritiqueAxisV1, RepositorySpecificationDimensionFitV1, RepositorySpecificationReferenceCompatibilityV1 } from "../../repository-specification-critique-protocol.js";
8
+ import { generateWithFeedbackV1 } from "../budgeted-model/service.js";
9
+ import { reportFoundryStageV1 } from "../foundry-progress/service.js";
10
+ import { groundedStructuredGenerationV1 } from "../grounded-authoring/service.js";
11
+ import { RepositoryFoundryLanguageModel } from "../language-model/service.js";
12
+ /**
13
+ * Reference-grounded specification stage for the additive case pipeline.
14
+ * The analyst and private critic inspect only pinned Git trees. The writer is
15
+ * deliberately blind to the reference tree and receives only public behavior
16
+ * prose plus complete pre-change sources. Reviews are advisory specification
17
+ * evidence; they never constitute benchmark admission evidence.
18
+ */
19
+ const STAGE = "spec";
20
+ const MAX_CONTEXT_FILES = 12;
21
+ const MAX_CONTEXT_FILE_BYTES = 96_000;
22
+ const MAX_CONTEXT_TOTAL_BYTES = 256_000;
23
+ const DIMENSION_MISMATCH_CONFIRMATIONS = 2;
24
+ const AnalystCitationV1 = Schema.Struct({
25
+ commit: Schema.Literals(["initial", "reference"]),
26
+ path: Schema.String,
27
+ startLine: Schema.Finite,
28
+ endLine: Schema.Finite
29
+ });
30
+ const AnalystScopeEntryV1 = Schema.Struct({
31
+ id: Schema.String,
32
+ kind: Schema.Literals(["changed", "preserved"]),
33
+ behaviorIds: Schema.Array(Schema.String),
34
+ description: Schema.String,
35
+ evidence: Schema.Array(AnalystCitationV1)
36
+ });
37
+ const PipelineSpecificationAnalysisV1 = Schema.Struct({
38
+ summary: Schema.String,
39
+ userObservableBehaviors: Schema.Array(Schema.String),
40
+ constraints: Schema.Array(Schema.String),
41
+ risks: Schema.Array(Schema.String),
42
+ relevantPaths: Schema.Array(Schema.String),
43
+ scope: Schema.Array(AnalystScopeEntryV1)
44
+ });
45
+ const PipelineVisibleTaskProposalV1 = Schema.Struct({
46
+ requestText: Schema.String,
47
+ constraints: Schema.Array(Schema.String)
48
+ });
49
+ const PipelineSpecificationReviewOutputV1 = Schema.Struct({
50
+ verdict: Schema.Literals(["sufficient", "insufficient"]),
51
+ detail: Schema.String,
52
+ criticalBehaviorCoverage: Schema.Array(RepositorySpecificationBehaviorCoverageV1),
53
+ dimensionFit: RepositorySpecificationDimensionFitV1,
54
+ referenceCompatibility: RepositorySpecificationReferenceCompatibilityV1,
55
+ findings: Schema.Array(Schema.Struct({
56
+ axis: RepositorySpecificationCritiqueAxisV1,
57
+ severity: Schema.Literals(["blocker", "warning"]),
58
+ detail: Schema.String
59
+ }))
60
+ });
61
+ const ANALYST_INSTRUCTIONS = `You are the private repository analyst for one coding benchmark case.
62
+ Inspect both pinned Git trees with the grounded tools before submitting. The complete dimension contract is
63
+ supplied as {id, description, includes, excludes}; apply every field and do not broaden the historical change
64
+ to force a fit. Establish the actual user-observable change and the behavior the reference preserves.
65
+ Return at least one changed and one preserved scope clause. Every clause must cite non-empty one-based inclusive
66
+ line ranges in both the initial and reference trees using {commit, path, startLine, endLine}. Cover every supplied
67
+ target behavior id with grounded scope. Select only complete pre-change files that a blind coding agent needs;
68
+ relevantPaths becomes the writer's entire repository context, so keep it focused. Public analysis and scope
69
+ prose must not include commits, private source identifiers, test contents, or implementation instructions.
70
+ Do not write the visible task, fixtures, or a solution. Return one submit action only after grounding the result.`;
71
+ const WRITER_INSTRUCTIONS = `You are the blind specification-writer for a repository coding benchmark.
72
+ You receive public issue scope, the complete dimension contract, and complete files from the pinned pre-change
73
+ checkout. You do not receive the reference tree, historical patch, private citations, tests added by the change,
74
+ or hidden fixtures. Write a realistic issue-style request that states all changed behavior and necessary
75
+ preservation boundaries while allowing any behaviorally correct implementation. Do not invent requirements to
76
+ match the dimension. Do not mention benchmark machinery or prescribe implementation details. On a revision,
77
+ resolve every supplied review finding while preserving the authentic scope. Return only requestText and constraints.`;
78
+ const CRITIC_INSTRUCTIONS = `You are the single private reference critic for a benchmark specification.
79
+ Inspect both pinned Git trees with the grounded tools. Review the visible task against the complete dimension
80
+ contract and every grounded changed and preserved scope clause. Model criticism is advisory: do not claim that
81
+ your review admits or rejects a benchmark. Return exactly one coverage record for every critical behavior id.
82
+ Return dimensionFit for the exact dimension id, supported by paths in the initial tree. Return
83
+ referenceCompatibility with exactly one scopeCoverage record per scope id; every support record must cite
84
+ non-empty one-based inclusive reference-tree lines using the supplied sourceId catalog. Mark the review
85
+ sufficient only when the task covers all critical behavior, fits the complete dimension contract, and is fully
86
+ compatible with the pinned reference. Findings and detail sent to the blind writer must remain public behavior
87
+ prose: do not quote private code, commits, source ids, tests, or prescribe a patch. If the authentic change is
88
+ off-dimension, say mismatch rather than widening it. Return one submit action after grounding the review.`;
89
+ const failure = (detail, cause) => new RepositoryFoundryError({
90
+ operation: "run-pipeline-stage",
91
+ detail,
92
+ ...(cause === undefined ? {} : { cause })
93
+ });
94
+ const assignmentOf = (input) => Effect.try({
95
+ try: () => repositoryFoundryModelAssignmentV1(input.plan, input.role),
96
+ catch: (cause) => failure(`could not resolve ${input.role} model assignment`, cause)
97
+ });
98
+ const nonEmpty = (value) => value.trim().length > 0;
99
+ const uniqueNonEmpty = (values) => values.length > 0 && new Set(values).size === values.length && values.every(nonEmpty);
100
+ const citationKey = (citation) => `${citation.commit}:${citation.path}:${String(citation.startLine)}:${String(citation.endLine)}`;
101
+ const readCitationContent = Effect.fnUntraced(function* (input) {
102
+ const snapshot = input.snapshots[input.citation.commit];
103
+ const key = `${input.citation.commit}:${input.citation.path}`;
104
+ const cached = input.cache.get(key);
105
+ if (cached !== undefined)
106
+ return cached;
107
+ if (!snapshot.files.includes(input.citation.path))
108
+ return undefined;
109
+ const content = yield* readGitTreeFileV1({ snapshot, path: input.citation.path });
110
+ input.cache.set(key, content);
111
+ return content;
112
+ });
113
+ const citationIsValid = Effect.fnUntraced(function* (input) {
114
+ if (!nonEmpty(input.citation.path) ||
115
+ !Number.isSafeInteger(input.citation.startLine) ||
116
+ !Number.isSafeInteger(input.citation.endLine) ||
117
+ input.citation.startLine < 1 ||
118
+ input.citation.endLine < input.citation.startLine) {
119
+ return false;
120
+ }
121
+ const content = yield* readCitationContent(input);
122
+ if (content === undefined)
123
+ return false;
124
+ const lines = content.split("\n");
125
+ return (input.citation.endLine <= lines.length &&
126
+ lines
127
+ .slice(input.citation.startLine - 1, input.citation.endLine)
128
+ .join("\n")
129
+ .trim().length > 0);
130
+ });
131
+ const validateAnalysis = Effect.fnUntraced(function* (input) {
132
+ const findings = [];
133
+ if (!nonEmpty(input.analysis.summary) ||
134
+ !uniqueNonEmpty(input.analysis.userObservableBehaviors) ||
135
+ input.analysis.constraints.some((entry) => !nonEmpty(entry)) ||
136
+ input.analysis.risks.some((entry) => !nonEmpty(entry))) {
137
+ findings.push({
138
+ kind: "contract",
139
+ message: "Analysis requires a summary, user-observable behaviors, and non-empty constraint and risk entries."
140
+ });
141
+ }
142
+ if (!uniqueNonEmpty(input.analysis.relevantPaths) ||
143
+ input.analysis.relevantPaths.length > MAX_CONTEXT_FILES ||
144
+ input.analysis.relevantPaths.some((path) => !input.snapshots.initial.files.includes(path))) {
145
+ findings.push({
146
+ kind: "contract",
147
+ message: `Select between one and ${String(MAX_CONTEXT_FILES)} unique files that exist in the pinned initial tree.`
148
+ });
149
+ }
150
+ const scopeIds = input.analysis.scope.map((entry) => entry.id);
151
+ if (input.analysis.scope.length < 2 ||
152
+ new Set(scopeIds).size !== scopeIds.length ||
153
+ input.analysis.scope.some((entry) => !nonEmpty(entry.id) ||
154
+ !nonEmpty(entry.description) ||
155
+ !uniqueNonEmpty(entry.behaviorIds) ||
156
+ entry.behaviorIds.some((id) => !input.behaviorIds.has(id)) ||
157
+ entry.evidence.length < 2 ||
158
+ new Set(entry.evidence.map(citationKey)).size !== entry.evidence.length ||
159
+ !entry.evidence.some((citation) => citation.commit === "initial") ||
160
+ !entry.evidence.some((citation) => citation.commit === "reference")) ||
161
+ !input.analysis.scope.some((entry) => entry.kind === "changed") ||
162
+ !input.analysis.scope.some((entry) => entry.kind === "preserved") ||
163
+ [...input.behaviorIds].some((behaviorId) => !input.analysis.scope.some((entry) => entry.behaviorIds.includes(behaviorId)))) {
164
+ findings.push({
165
+ kind: "contract",
166
+ message: "Scope needs unique changed and preserved clauses, must cover every target behavior id, and each clause needs initial and reference line citations."
167
+ });
168
+ }
169
+ const citations = input.analysis.scope.flatMap((entry) => entry.evidence);
170
+ const citationChecks = yield* Effect.forEach(citations, (citation) => citationIsValid({ citation, snapshots: input.snapshots, cache: input.cache }));
171
+ if (citationChecks.some((valid) => !valid)) {
172
+ findings.push({
173
+ kind: "contract",
174
+ message: "One or more scope citations do not identify non-empty, one-based inclusive lines in the named pinned tree."
175
+ });
176
+ }
177
+ const contextContents = yield* Effect.forEach(input.analysis.relevantPaths, (path) => readCitationContent({
178
+ citation: { commit: "initial", path, startLine: 1, endLine: 1 },
179
+ snapshots: input.snapshots,
180
+ cache: input.cache
181
+ }));
182
+ const contextBytes = contextContents.map((content) => content === undefined ? 0 : Buffer.byteLength(content));
183
+ if (contextBytes.some((bytes) => bytes > MAX_CONTEXT_FILE_BYTES) ||
184
+ contextBytes.reduce((total, bytes) => total + bytes, 0) > MAX_CONTEXT_TOTAL_BYTES) {
185
+ findings.push({
186
+ kind: "contract",
187
+ message: `Select complete context files within ${String(MAX_CONTEXT_FILE_BYTES)} bytes per file and ${String(MAX_CONTEXT_TOTAL_BYTES)} bytes total. Oversized files are not truncated.`
188
+ });
189
+ }
190
+ return findings;
191
+ });
192
+ const loadContextSources = Effect.fnUntraced(function* (input) {
193
+ const sources = [];
194
+ let totalBytes = 0;
195
+ for (const path of input.paths) {
196
+ if (!input.initial.files.includes(path)) {
197
+ return yield* failure(`analyst selected an unavailable initial-tree context path: ${path}`);
198
+ }
199
+ const content = yield* readGitTreeFileV1({ snapshot: input.initial, path });
200
+ const bytes = Buffer.byteLength(content);
201
+ if (bytes > MAX_CONTEXT_FILE_BYTES) {
202
+ return yield* failure(`analyst selected ${path}, whose complete ${String(bytes)} bytes exceed the ${String(MAX_CONTEXT_FILE_BYTES)}-byte context-file bound; no truncated file was presented as complete`);
203
+ }
204
+ totalBytes += bytes;
205
+ if (totalBytes > MAX_CONTEXT_TOTAL_BYTES) {
206
+ return yield* failure(`complete writer context exceeds ${String(MAX_CONTEXT_TOTAL_BYTES)} bytes; no context file was truncated`);
207
+ }
208
+ sources.push({ path, content });
209
+ }
210
+ return sources;
211
+ });
212
+ const makeSourceCatalog = Effect.fnUntraced(function* (input) {
213
+ const paths = [...new Set(input.paths)].sort();
214
+ const sources = [];
215
+ for (const path of paths) {
216
+ for (const phase of ["initial", "reference"]) {
217
+ const content = yield* readCitationContent({
218
+ citation: { commit: phase, path, startLine: 1, endLine: 1 },
219
+ snapshots: input.snapshots,
220
+ cache: input.cache
221
+ });
222
+ if (content === undefined)
223
+ continue;
224
+ sources.push({
225
+ sourceId: `spec-source-${checkpointDigestV1({ phase, path }).slice(0, 16)}`,
226
+ phase,
227
+ path,
228
+ content
229
+ });
230
+ }
231
+ }
232
+ return sources;
233
+ });
234
+ const reviewCitationValid = (evidence, sources) => {
235
+ const source = sources.find((candidate) => candidate.sourceId === evidence.sourceId && candidate.phase === "reference");
236
+ if (source === undefined ||
237
+ !Number.isSafeInteger(evidence.startLine) ||
238
+ !Number.isSafeInteger(evidence.endLine) ||
239
+ evidence.startLine < 1 ||
240
+ evidence.endLine < evidence.startLine) {
241
+ return false;
242
+ }
243
+ const lines = source.content.split("\n");
244
+ return (evidence.endLine <= lines.length &&
245
+ lines
246
+ .slice(evidence.startLine - 1, evidence.endLine)
247
+ .join("\n")
248
+ .trim().length > 0);
249
+ };
250
+ const validateReview = (input) => {
251
+ const findings = [];
252
+ const coverageIds = input.review.criticalBehaviorCoverage.map((entry) => entry.behaviorId);
253
+ if (coverageIds.length !== input.criticalBehaviorIds.size ||
254
+ new Set(coverageIds).size !== coverageIds.length ||
255
+ coverageIds.some((id) => !input.criticalBehaviorIds.has(id)) ||
256
+ input.review.criticalBehaviorCoverage.some((entry) => !nonEmpty(entry.detail))) {
257
+ findings.push({
258
+ kind: "contract",
259
+ message: "Return exactly one non-empty criticalBehaviorCoverage record for every critical behavior id."
260
+ });
261
+ }
262
+ const dimensionFit = input.review.dimensionFit;
263
+ if (dimensionFit.requestedDimension !== input.dimensionId ||
264
+ !nonEmpty(dimensionFit.detail) ||
265
+ !uniqueNonEmpty(dimensionFit.evidencePaths) ||
266
+ dimensionFit.evidencePaths.some((path) => !input.initial.files.includes(path))) {
267
+ findings.push({
268
+ kind: "contract",
269
+ message: "dimensionFit must address the exact supplied dimension id with a substantive explanation and existing initial-tree evidence paths."
270
+ });
271
+ }
272
+ const compatibility = input.review.referenceCompatibility;
273
+ const compatibilityIds = compatibility.scopeCoverage.map((entry) => entry.scopeId);
274
+ if (!nonEmpty(compatibility.detail) ||
275
+ compatibilityIds.length !== input.scopeIds.size ||
276
+ new Set(compatibilityIds).size !== compatibilityIds.length ||
277
+ compatibilityIds.some((id) => !input.scopeIds.has(id)) ||
278
+ compatibility.scopeCoverage.some((entry) => !nonEmpty(entry.detail) ||
279
+ entry.evidence.length === 0 ||
280
+ entry.evidence.some((evidence) => !reviewCitationValid(evidence, input.sources)))) {
281
+ findings.push({
282
+ kind: "contract",
283
+ message: "referenceCompatibility needs one substantive, valid reference-line-cited scopeCoverage record for every scope id."
284
+ });
285
+ }
286
+ if (!nonEmpty(input.review.detail) ||
287
+ input.review.findings.some((finding) => !nonEmpty(finding.detail))) {
288
+ findings.push({
289
+ kind: "contract",
290
+ message: "Review detail and finding detail must be non-empty."
291
+ });
292
+ }
293
+ if (input.review.verdict === "sufficient" &&
294
+ (dimensionFit.outcome !== "fit" ||
295
+ compatibility.outcome !== "compatible" ||
296
+ input.review.criticalBehaviorCoverage.some((entry) => entry.outcome !== "covered") ||
297
+ input.review.findings.some((finding) => finding.severity === "blocker"))) {
298
+ findings.push({
299
+ kind: "contract",
300
+ message: "A sufficient verdict requires fit, compatible reference evidence, complete critical coverage, and no blocker findings."
301
+ });
302
+ }
303
+ return findings;
304
+ };
305
+ const acceptedReview = (review) => review.verdict === "sufficient" &&
306
+ review.dimensionFit.outcome === "fit" &&
307
+ review.referenceCompatibility.outcome === "compatible" &&
308
+ review.criticalBehaviorCoverage.every((entry) => entry.outcome === "covered") &&
309
+ review.findings.every((finding) => finding.severity !== "blocker");
310
+ const publicReviewFeedback = (review) => [
311
+ review.detail,
312
+ review.dimensionFit.detail,
313
+ ...review.criticalBehaviorCoverage
314
+ .filter((entry) => entry.outcome !== "covered")
315
+ .map((entry) => entry.detail),
316
+ ...review.referenceCompatibility.scopeCoverage
317
+ .filter((entry) => entry.outcome !== "supported")
318
+ .map((entry) => entry.detail),
319
+ ...(review.referenceCompatibility.questionResolutions ?? [])
320
+ .filter((entry) => entry.outcome === "unresolved")
321
+ .map((entry) => entry.detail),
322
+ ...review.findings.map((finding) => finding.detail)
323
+ ].filter(nonEmpty);
324
+ const leakFindingsOf = (reviews) => reviews.flatMap((review) => review.findings
325
+ .filter((finding) => finding.axis === "hidden-answer-leakage")
326
+ .map((finding) => finding.detail));
327
+ const reviewOutputOf = (review) => Schema.decodeUnknownOption(PipelineSpecificationReviewOutputV1)({
328
+ verdict: review.verdict,
329
+ detail: review.detail,
330
+ criticalBehaviorCoverage: review.criticalBehaviorCoverage,
331
+ dimensionFit: review.dimensionFit,
332
+ referenceCompatibility: review.referenceCompatibility,
333
+ findings: review.findings
334
+ });
335
+ const checkpointLastReview = (checkpoint, parentDigest) => {
336
+ if (checkpoint === undefined ||
337
+ checkpoint.parentDigest !== parentDigest ||
338
+ checkpoint.reviews.length === 0) {
339
+ return undefined;
340
+ }
341
+ const decoded = reviewOutputOf(checkpoint.reviews.at(-1));
342
+ return Option.isSome(decoded) && !acceptedReview(decoded.value)
343
+ ? { checkpoint, review: decoded.value }
344
+ : undefined;
345
+ };
346
+ const publicBehaviorOf = (seed, scope) => seed.targetBehavior.map((behavior) => ({
347
+ id: behavior.id,
348
+ critical: behavior.critical,
349
+ description: scope
350
+ .filter((entry) => entry.behaviorIds.includes(behavior.id))
351
+ .map((entry) => entry.description)
352
+ .join(" ")
353
+ }));
354
+ /** Source-only authoring also accepts an unqualified draft seed. It never executes repository recipes. */
355
+ export const draftPipelineSpecificationV1 = Effect.fn("PipelineSpec.draft")(function* (input) {
356
+ const seed = input.seed;
357
+ const referenceCommit = seed.referenceCommit;
358
+ if (referenceCommit === undefined || referenceCommit === seed.initialState.commit) {
359
+ return yield* failure("spec stage requires distinct pinned initial and reference commits");
360
+ }
361
+ yield* reportFoundryStageV1(pipelineStageToProgressStageV1(STAGE), "grounding changed and preserved scope against pinned Git trees");
362
+ const languageModel = yield* RepositoryFoundryLanguageModel;
363
+ const [analystAssignment, writerAssignment, criticAssignment] = yield* Effect.all([
364
+ assignmentOf({ plan: input.context.modelPlan, role: "repository-analyst" }),
365
+ assignmentOf({ plan: input.context.modelPlan, role: "specification-writer" }),
366
+ assignmentOf({ plan: input.context.modelPlan, role: "specification-critic-b" })
367
+ ]);
368
+ const snapshots = {
369
+ initial: yield* captureGitTreeSnapshotV1({
370
+ repositoryRoot: input.context.repositoryRoot,
371
+ requestedRef: seed.initialState.commit
372
+ }),
373
+ reference: yield* captureGitTreeSnapshotV1({
374
+ repositoryRoot: input.context.repositoryRoot,
375
+ requestedRef: referenceCommit
376
+ })
377
+ };
378
+ const contentCache = new Map();
379
+ const behaviorIds = new Set(seed.targetBehavior.map((behavior) => behavior.id));
380
+ const criticalBehaviorIds = new Set(seed.targetBehavior.filter((behavior) => behavior.critical).map((behavior) => behavior.id));
381
+ const parentDigest = input.parentDigest;
382
+ const resumable = checkpointLastReview(input.checkpoints.spec, parentDigest);
383
+ let analysis;
384
+ let scope;
385
+ let contextSources;
386
+ let sourceCatalog;
387
+ const episode = input.map.historyEpisodes.find((candidate) => "changeEpisodeId" in seed.source && candidate.id === seed.source.changeEpisodeId);
388
+ const groundedSourcePaths = [
389
+ ...seed.capabilityEvidence.flatMap((evidence) => evidence.path === undefined ? [] : [evidence.path]),
390
+ ...seed.targetBehavior.flatMap((behavior) => behavior.evidence.flatMap((evidence) => (evidence.path === undefined ? [] : [evidence.path]))),
391
+ ...(episode?.changedPaths.flatMap((changed) => changed.previousPath === undefined ? [changed.path] : [changed.previousPath, changed.path]) ?? [])
392
+ ];
393
+ if (resumable === undefined) {
394
+ const analyst = yield* groundedStructuredGenerationV1({
395
+ checkpointStore: input.workCheckpointStore,
396
+ languageModel,
397
+ assignment: analystAssignment,
398
+ operationId: `${input.context.caseId}:spec:analyst`,
399
+ instructions: ANALYST_INSTRUCTIONS,
400
+ task: {
401
+ dimension: input.context.dimension,
402
+ seed: {
403
+ id: seed.id,
404
+ summary: seed.summary,
405
+ source: seed.source,
406
+ targetBehavior: seed.targetBehavior,
407
+ capabilityEvidence: seed.capabilityEvidence
408
+ },
409
+ repository: {
410
+ initialCommit: snapshots.initial.commit,
411
+ referenceCommit: snapshots.reference.commit
412
+ }
413
+ },
414
+ outputSchema: PipelineSpecificationAnalysisV1,
415
+ schemaName: "routekit_pipeline_spec_analysis_v1",
416
+ tools: {
417
+ repositoryRoot: input.context.repositoryRoot,
418
+ commits: { initial: snapshots.initial.commit, reference: snapshots.reference.commit }
419
+ },
420
+ validateSubmission: (candidate) => validateAnalysis({ analysis: candidate, behaviorIds, snapshots, cache: contentCache }),
421
+ maxTurns: Math.max(1, Math.trunc(input.context.budget.maxModelCalls) + 1),
422
+ maxToolTurnsBeforeSubmit: 3,
423
+ maximumOutputTokens: repositoryFoundryRoleOutputCeilingV1("repository-analyst")
424
+ });
425
+ contextSources = yield* loadContextSources({
426
+ initial: snapshots.initial,
427
+ paths: analyst.value.relevantPaths
428
+ });
429
+ sourceCatalog = yield* makeSourceCatalog({
430
+ paths: [...groundedSourcePaths, ...contextSources.map((source) => source.path)],
431
+ snapshots,
432
+ cache: contentCache
433
+ });
434
+ scope = analyst.value.scope.map(({ evidence: _evidence, ...entry }) => entry);
435
+ analysis = {
436
+ summary: analyst.value.summary,
437
+ userObservableBehaviors: analyst.value.userObservableBehaviors,
438
+ constraints: analyst.value.constraints,
439
+ risks: analyst.value.risks
440
+ };
441
+ }
442
+ else {
443
+ analysis = resumable.checkpoint.analysis;
444
+ scope = resumable.checkpoint.scope;
445
+ contextSources = resumable.checkpoint.contextSources;
446
+ sourceCatalog = yield* makeSourceCatalog({
447
+ paths: [...groundedSourcePaths, ...contextSources.map((source) => source.path)],
448
+ snapshots,
449
+ cache: contentCache
450
+ });
451
+ }
452
+ const scopeIds = new Set(scope.map((entry) => entry.id));
453
+ const publicTargetBehavior = publicBehaviorOf(seed, scope);
454
+ let previousVisible = resumable?.checkpoint.visible;
455
+ let priorReviewFeedback = resumable === undefined ? [] : publicReviewFeedback(resumable.review);
456
+ const reviews = [
457
+ ...(resumable?.checkpoint.reviews ?? [])
458
+ ];
459
+ let consecutiveDimensionMismatches = 0;
460
+ for (const prior of [...reviews].reverse()) {
461
+ const decoded = reviewOutputOf(prior);
462
+ if (Option.isNone(decoded) || decoded.value.dimensionFit.outcome !== "mismatch")
463
+ break;
464
+ consecutiveDimensionMismatches += 1;
465
+ }
466
+ let revisions = resumable === undefined ? 0 : resumable.checkpoint.revisions + 1;
467
+ const startingSequence = reviews.length;
468
+ for (let sequence = startingSequence;; sequence += 1) {
469
+ yield* reportFoundryStageV1(pipelineStageToProgressStageV1(STAGE), sequence === 0
470
+ ? "writing blind visible task"
471
+ : `revising visible task, round ${String(sequence)}`);
472
+ const writer = yield* generateWithFeedbackV1({
473
+ ...(input.workCheckpointStore === undefined ? {} : {
474
+ checkpoint: {
475
+ store: input.workCheckpointStore,
476
+ binding: { parentDigest, initialCommit: snapshots.initial.commit }
477
+ }
478
+ }),
479
+ languageModel,
480
+ assignment: writerAssignment,
481
+ operationId: `${input.context.caseId}:spec:writer:round-${String(sequence)}`,
482
+ instructions: WRITER_INSTRUCTIONS,
483
+ input: {
484
+ dimension: input.context.dimension,
485
+ targetBehavior: publicTargetBehavior,
486
+ analysis,
487
+ scope,
488
+ initialRepositoryContext: contextSources,
489
+ ...(previousVisible === undefined
490
+ ? {}
491
+ : { previousVisible, behavioralReviewFeedback: priorReviewFeedback })
492
+ },
493
+ schemaName: "routekit_pipeline_visible_task_v1",
494
+ outputSchema: PipelineVisibleTaskProposalV1,
495
+ maximumOutputTokens: repositoryFoundryRoleOutputCeilingV1("specification-writer"),
496
+ maxAttempts: Math.max(1, Math.trunc(input.context.budget.maxModelCalls) + 1),
497
+ validate: (proposal) => Effect.succeed(!nonEmpty(proposal.requestText) || proposal.constraints.some((entry) => !nonEmpty(entry))
498
+ ? [
499
+ {
500
+ kind: "contract",
501
+ message: "Visible request text and every supplied constraint must be non-empty."
502
+ }
503
+ ]
504
+ : [])
505
+ });
506
+ const visible = {
507
+ lane: "repository-agent",
508
+ id: input.context.caseId,
509
+ requestText: writer.value.requestText,
510
+ checkoutCommit: snapshots.initial.commit,
511
+ allowedTools: ["read", "search", "edit", "shell", "test"],
512
+ constraints: [
513
+ ...new Set([
514
+ ...writer.value.constraints,
515
+ "Do not weaken or delete tests to make the task pass.",
516
+ "Preserve unrelated public behavior."
517
+ ])
518
+ ]
519
+ };
520
+ yield* reportFoundryStageV1(pipelineStageToProgressStageV1(STAGE), `checking visible task against private reference, round ${String(sequence)}`);
521
+ const critic = yield* groundedStructuredGenerationV1({
522
+ checkpointStore: input.workCheckpointStore,
523
+ languageModel,
524
+ assignment: criticAssignment,
525
+ operationId: `${input.context.caseId}:spec:critic:round-${String(sequence)}`,
526
+ instructions: CRITIC_INSTRUCTIONS,
527
+ task: {
528
+ dimension: input.context.dimension,
529
+ targetBehavior: seed.targetBehavior,
530
+ analysis,
531
+ scope,
532
+ visible,
533
+ sourceCatalog: sourceCatalog.map(({ content: _content, ...source }) => source)
534
+ },
535
+ outputSchema: PipelineSpecificationReviewOutputV1,
536
+ schemaName: "routekit_pipeline_specification_review_v1",
537
+ tools: {
538
+ repositoryRoot: input.context.repositoryRoot,
539
+ commits: { initial: snapshots.initial.commit, reference: snapshots.reference.commit }
540
+ },
541
+ validateSubmission: (review) => Effect.succeed(validateReview({
542
+ review,
543
+ criticalBehaviorIds,
544
+ scopeIds,
545
+ initial: snapshots.initial,
546
+ dimensionId: input.context.dimension.id,
547
+ sources: sourceCatalog
548
+ })),
549
+ maxTurns: Math.max(1, Math.trunc(input.context.budget.maxModelCalls) + 1),
550
+ maxToolTurnsBeforeSubmit: 3,
551
+ maximumOutputTokens: repositoryFoundryRoleOutputCeilingV1("specification-critic-b")
552
+ });
553
+ const review = {
554
+ reviewerId: `${input.context.caseId}:spec:critic:round-${String(sequence)}`,
555
+ reviewerKind: "model-critic",
556
+ independentlyProduced: true,
557
+ ...critic.value
558
+ };
559
+ reviews.push(review);
560
+ const createdAt = new Date(yield* Clock.currentTimeMillis).toISOString();
561
+ const checkpoint = {
562
+ version: 1,
563
+ stage: STAGE,
564
+ parentDigest,
565
+ createdAt,
566
+ visible,
567
+ analysis,
568
+ scope,
569
+ contextSources,
570
+ reviews,
571
+ revisions,
572
+ leakFindings: leakFindingsOf(reviews)
573
+ };
574
+ yield* input.checkpoint(checkpoint);
575
+ if (acceptedReview(critic.value))
576
+ return checkpoint;
577
+ if (critic.value.dimensionFit.outcome === "mismatch") {
578
+ consecutiveDimensionMismatches += 1;
579
+ }
580
+ else {
581
+ consecutiveDimensionMismatches = 0;
582
+ }
583
+ if (consecutiveDimensionMismatches >= DIMENSION_MISMATCH_CONFIRMATIONS) {
584
+ return yield* new RepositoryFoundryError({
585
+ operation: "run-pipeline-stage",
586
+ detail: "specification cannot assess the requested dimension: repeated private grounded reviews established a dimension mismatch",
587
+ cause: new PipelineStageError({
588
+ stage: STAGE,
589
+ detail: "repeated private grounded reviews established that the authentic change does not fit the requested dimension",
590
+ terminal: true
591
+ }),
592
+ generationRejection: {
593
+ code: "specification-dimension-mismatch",
594
+ completedRevisions: revisions
595
+ }
596
+ });
597
+ }
598
+ // A bounded capability returns its real review/checkpoint to the orchestrator,
599
+ // not a fabricated acceptance or an unbounded hidden revision waterfall.
600
+ if (input.maximumReviewRounds !== undefined &&
601
+ sequence - startingSequence + 1 >= input.maximumReviewRounds) {
602
+ return checkpoint;
603
+ }
604
+ previousVisible = visible;
605
+ priorReviewFeedback = publicReviewFeedback(critic.value);
606
+ revisions += 1;
607
+ }
608
+ });
609
+ /** Legacy callers still require and preserve their qualified seed checkpoint. */
610
+ export const runPipelineSpecStageV1 = (input) => {
611
+ const seedCheckpoint = input.checkpoints.seed;
612
+ return seedCheckpoint === undefined
613
+ ? Effect.fail(failure("spec stage requires an accepted seed checkpoint"))
614
+ : draftPipelineSpecificationV1({
615
+ ...input,
616
+ seed: seedCheckpoint.seed,
617
+ parentDigest: checkpointDigestV1(seedCheckpoint)
618
+ });
619
+ };